Thu Mar 8 14:58:58 2012 UTC ()
The kernel can lookup the same node multiple time and will reclaim as
many times it looked up. All reclaims but the last one must be ignored,
otherwise we discard a node which will still get operations. We therefore
have to keep track of lookup/reclaim count and hnour reclaims only when
the count reaches zero.


(manu)
diff -r1.50 -r1.51 src/lib/libperfuse/ops.c
diff -r1.25 -r1.26 src/lib/libperfuse/perfuse_priv.h
diff -r1.15 -r1.16 src/lib/libperfuse/subr.c

cvs diff -r1.50 -r1.51 src/lib/libperfuse/ops.c (expand / switch to unified diff)

--- src/lib/libperfuse/ops.c 2012/01/29 06:22:02 1.50
+++ src/lib/libperfuse/ops.c 2012/03/08 14:58:57 1.51
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ops.c,v 1.50 2012/01/29 06:22:02 manu Exp $ */ 1/* $NetBSD: ops.c,v 1.51 2012/03/08 14:58:57 manu Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved. 4 * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
5 *  5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 *  14 *
@@ -504,26 +504,27 @@ node_lookup_common(pu, opc, path, pcr, p @@ -504,26 +504,27 @@ node_lookup_common(pu, opc, path, pcr, p
504 "cookie = %p, nodeid = 0x%"PRIx64" " 504 "cookie = %p, nodeid = 0x%"PRIx64" "
505 "for \"%s\"\n", __func__,  505 "for \"%s\"\n", __func__,
506 (void *)opc, perfuse_node_path(opc),  506 (void *)opc, perfuse_node_path(opc),
507 (void *)oldpnd->pnd_pn, oldpnd->pnd_nodeid,  507 (void *)oldpnd->pnd_pn, oldpnd->pnd_nodeid,
508 path); 508 path);
509#endif 509#endif
510 break; 510 break;
511 } 511 }
512 512
513 /* 513 /*
514 * Check for cached name 514 * Check for cached name
515 */ 515 */
516 if ((oldpnd != NULL) && !entry_expired(oldpnd->pnd_pn)) { 516 if ((oldpnd != NULL) && !entry_expired(oldpnd->pnd_pn)) {
 517 oldpnd->pnd_puffs_nlookup++;
517 *pnp = oldpnd->pnd_pn; 518 *pnp = oldpnd->pnd_pn;
518 return 0; 519 return 0;
519 } 520 }
520 521
521 len = strlen(path) + 1; 522 len = strlen(path) + 1;
522 523
523 pm = ps->ps_new_msg(pu, opc, FUSE_LOOKUP, len, pcr); 524 pm = ps->ps_new_msg(pu, opc, FUSE_LOOKUP, len, pcr);
524 (void)strlcpy(_GET_INPAYLOAD(ps, pm, char *), path, len); 525 (void)strlcpy(_GET_INPAYLOAD(ps, pm, char *), path, len);
525 526
526 error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply); 527 error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply);
527 528
528 switch (error) { 529 switch (error) {
529 case 0: 530 case 0:
@@ -540,27 +541,28 @@ node_lookup_common(pu, opc, path, pcr, p @@ -540,27 +541,28 @@ node_lookup_common(pu, opc, path, pcr, p
540#endif 541#endif
541 } 542 }
542 /* FALLTHROUGH */ 543 /* FALLTHROUGH */
543 default: 544 default:
544 return error; 545 return error;
545 /* NOTREACHED */ 546 /* NOTREACHED */
546 break; 547 break;
547 } 548 }
548 549
549 feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); 550 feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
550 551
551 if (oldpnd != NULL) { 552 if (oldpnd != NULL) {
552 if (oldpnd->pnd_nodeid == feo->nodeid) { 553 if (oldpnd->pnd_nodeid == feo->nodeid) {
553 oldpnd->pnd_nlookup++; 554 oldpnd->pnd_fuse_nlookup++;
 555 oldpnd->pnd_puffs_nlookup++;
554 *pnp = oldpnd->pnd_pn; 556 *pnp = oldpnd->pnd_pn;
555 557
556 ps->ps_destroy_msg(pm); 558 ps->ps_destroy_msg(pm);
557 return 0; 559 return 0;
558 } else { 560 } else {
559 oldpnd->pnd_flags |= PND_REMOVED; 561 oldpnd->pnd_flags |= PND_REMOVED;
560#ifdef PERFUSE_DEBUG 562#ifdef PERFUSE_DEBUG
561 if (perfuse_diagflags & PDF_FILENAME) 563 if (perfuse_diagflags & PDF_FILENAME)
562 DPRINTF("%s: opc = %p nodeid = 0x%"PRIx64" " 564 DPRINTF("%s: opc = %p nodeid = 0x%"PRIx64" "
563 "file = \"%s\" replaced\n", __func__,  565 "file = \"%s\" replaced\n", __func__,
564 oldpnd->pnd_pn, oldpnd->pnd_nodeid, 566 oldpnd->pnd_pn, oldpnd->pnd_nodeid,
565 oldpnd->pnd_name); 567 oldpnd->pnd_name);
566#endif 568#endif
@@ -2692,83 +2694,84 @@ perfuse_node_reclaim(pu, opc) @@ -2692,83 +2694,84 @@ perfuse_node_reclaim(pu, opc)
2692 struct puffs_node *pn; 2694 struct puffs_node *pn;
2693 struct puffs_node *pn_root; 2695 struct puffs_node *pn_root;
2694  2696
2695 ps = puffs_getspecific(pu); 2697 ps = puffs_getspecific(pu);
2696 pnd = PERFUSE_NODE_DATA(opc); 2698 pnd = PERFUSE_NODE_DATA(opc);
2697 2699
2698 /* 2700 /*
2699 * Never forget the root. 2701 * Never forget the root.
2700 */ 2702 */
2701 if (pnd->pnd_nodeid == FUSE_ROOT_ID) 2703 if (pnd->pnd_nodeid == FUSE_ROOT_ID)
2702 return 0; 2704 return 0;
2703 2705
2704 pnd->pnd_flags |= PND_RECLAIMED; 2706 pnd->pnd_flags |= PND_RECLAIMED;
 2707 pnd->pnd_puffs_nlookup--;
2705 2708
2706#ifdef PERFUSE_DEBUG 2709#ifdef PERFUSE_DEBUG
2707 if (perfuse_diagflags & PDF_RECLAIM) 2710 if (perfuse_diagflags & PDF_RECLAIM)
2708 DPRINTF("%s (nodeid %"PRId64") reclaimed\n",  2711 DPRINTF("%s (nodeid %"PRId64") reclaimed\n",
2709 perfuse_node_path(opc), pnd->pnd_nodeid); 2712 perfuse_node_path(opc), pnd->pnd_nodeid);
2710#endif 2713#endif
2711 2714
2712 pn_root = puffs_getroot(pu); 2715 pn_root = puffs_getroot(pu);
2713 pn = (struct puffs_node *)opc; 2716 pn = (struct puffs_node *)opc;
2714 while (pn != pn_root) { 2717 while (pn != pn_root) {
2715 struct puffs_node *parent_pn; 2718 struct puffs_node *parent_pn;
2716  2719
2717 pnd = PERFUSE_NODE_DATA(pn); 2720 pnd = PERFUSE_NODE_DATA(pn);
2718 2721
2719#ifdef PERFUSE_DEBUG 2722#ifdef PERFUSE_DEBUG
2720 if (perfuse_diagflags & PDF_RECLAIM) 2723 if (perfuse_diagflags & PDF_RECLAIM)
2721 DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, " 2724 DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, nlookup = %d "
2722 "has childcount %d %s%s%s%s, pending ops:%s%s%s\n",  2725 "has childcount %d %s%s%s%s, pending ops:%s%s%s\n",
2723 perfuse_node_path((puffs_cookie_t)pn), pnd->pnd_nodeid, 2726 perfuse_node_path((puffs_cookie_t)pn), pnd->pnd_nodeid,
2724 pnd->pnd_flags & PND_RECLAIMED ? "" : "not ", 2727 pnd->pnd_flags & PND_RECLAIMED ? "" : "not ",
2725 pnd->pnd_childcount, 2728 pnd->pnd_puffs_nlookup, pnd->pnd_childcount,
2726 pnd->pnd_flags & PND_OPEN ? "open " : "not open", 2729 pnd->pnd_flags & PND_OPEN ? "open " : "not open",
2727 pnd->pnd_flags & PND_RFH ? "r" : "", 2730 pnd->pnd_flags & PND_RFH ? "r" : "",
2728 pnd->pnd_flags & PND_WFH ? "w" : "", 2731 pnd->pnd_flags & PND_WFH ? "w" : "",
2729 pnd->pnd_flags & PND_BUSY ? "" : " none", 2732 pnd->pnd_flags & PND_BUSY ? "" : " none",
2730 pnd->pnd_flags & PND_INREADDIR ? " readdir" : "", 2733 pnd->pnd_flags & PND_INREADDIR ? " readdir" : "",
2731 pnd->pnd_flags & PND_INWRITE ? " write" : "", 2734 pnd->pnd_flags & PND_INWRITE ? " write" : "",
2732 pnd->pnd_flags & PND_INOPEN ? " open" : ""); 2735 pnd->pnd_flags & PND_INOPEN ? " open" : "");
2733#endif 2736#endif
2734 
2735 if (!(pnd->pnd_flags & PND_RECLAIMED) || 2737 if (!(pnd->pnd_flags & PND_RECLAIMED) ||
 2738 (pnd->pnd_puffs_nlookup != 0) ||
2736 (pnd->pnd_childcount != 0)) 2739 (pnd->pnd_childcount != 0))
2737 return 0; 2740 return 0;
2738 2741
2739#ifdef PERFUSE_DEBUG 2742#ifdef PERFUSE_DEBUG
2740 if ((pnd->pnd_flags & PND_OPEN) || 2743 if ((pnd->pnd_flags & PND_OPEN) ||
2741 !TAILQ_EMPTY(&pnd->pnd_pcq)) 2744 !TAILQ_EMPTY(&pnd->pnd_pcq))
2742 DERRX(EX_SOFTWARE, "%s: opc = %p: still open", 2745 DERRX(EX_SOFTWARE, "%s: opc = %p: still open",
2743 __func__, (void *)opc); 2746 __func__, (void *)opc);
2744 2747
2745 if ((pnd->pnd_flags & PND_BUSY) || 2748 if ((pnd->pnd_flags & PND_BUSY) ||
2746 !TAILQ_EMPTY(&pnd->pnd_pcq)) 2749 !TAILQ_EMPTY(&pnd->pnd_pcq))
2747 DERRX(EX_SOFTWARE, "%s: opc = %p: ongoing operations", 2750 DERRX(EX_SOFTWARE, "%s: opc = %p: ongoing operations",
2748 __func__, (void *)opc); 2751 __func__, (void *)opc);
2749#endif 2752#endif
2750 2753
2751 /* 2754 /*
2752 * Send the FORGET message 2755 * Send the FORGET message
2753 * 2756 *
2754 * ps_new_msg() is called with NULL creds, which will 2757 * ps_new_msg() is called with NULL creds, which will
2755 * be interpreted as FUSE superuser. This is obviously 2758 * be interpreted as FUSE superuser. This is obviously
2756 * fine since we operate with kernel creds here. 2759 * fine since we operate with kernel creds here.
2757 */ 2760 */
2758 pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn, FUSE_FORGET,  2761 pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn, FUSE_FORGET,
2759 sizeof(*ffi), NULL); 2762 sizeof(*ffi), NULL);
2760 ffi = GET_INPAYLOAD(ps, pm, fuse_forget_in); 2763 ffi = GET_INPAYLOAD(ps, pm, fuse_forget_in);
2761 ffi->nlookup = pnd->pnd_nlookup; 2764 ffi->nlookup = pnd->pnd_fuse_nlookup;
2762 2765
2763 /* 2766 /*
2764 * No reply is expected, pm is freed in xchg_msg 2767 * No reply is expected, pm is freed in xchg_msg
2765 */ 2768 */
2766 (void)xchg_msg(pu, (puffs_cookie_t)pn,  2769 (void)xchg_msg(pu, (puffs_cookie_t)pn,
2767 pm, UNSPEC_REPLY_LEN, no_reply); 2770 pm, UNSPEC_REPLY_LEN, no_reply);
2768 2771
2769 parent_pn = pnd->pnd_parent; 2772 parent_pn = pnd->pnd_parent;
2770 2773
2771 perfuse_destroy_pn(pn); 2774 perfuse_destroy_pn(pn);
2772 2775
2773 pn = parent_pn; 2776 pn = parent_pn;
2774 } 2777 }

cvs diff -r1.25 -r1.26 src/lib/libperfuse/perfuse_priv.h (expand / switch to unified diff)

--- src/lib/libperfuse/perfuse_priv.h 2012/01/29 06:22:02 1.25
+++ src/lib/libperfuse/perfuse_priv.h 2012/03/08 14:58:57 1.26
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: perfuse_priv.h,v 1.25 2012/01/29 06:22:02 manu Exp $ */ 1/* $NetBSD: perfuse_priv.h,v 1.26 2012/03/08 14:58:57 manu Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved. 4 * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
5 *  5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 *  14 *
@@ -98,27 +98,28 @@ enum perfuse_qtype {  @@ -98,27 +98,28 @@ enum perfuse_qtype {
98extern const char *perfuse_qtypestr[]; 98extern const char *perfuse_qtypestr[];
99#endif 99#endif
100 100
101struct perfuse_cc_queue { 101struct perfuse_cc_queue {
102 enum perfuse_qtype pcq_type; 102 enum perfuse_qtype pcq_type;
103 struct puffs_cc *pcq_cc; 103 struct puffs_cc *pcq_cc;
104 TAILQ_ENTRY(perfuse_cc_queue) pcq_next; 104 TAILQ_ENTRY(perfuse_cc_queue) pcq_next;
105}; 105};
106 106
107struct perfuse_node_data { 107struct perfuse_node_data {
108 uint64_t pnd_rfh; 108 uint64_t pnd_rfh;
109 uint64_t pnd_wfh; 109 uint64_t pnd_wfh;
110 uint64_t pnd_nodeid; /* nodeid, this is not inode */ 110 uint64_t pnd_nodeid; /* nodeid, this is not inode */
111 uint64_t pnd_nlookup; /* vnode refcount */ 111 uint64_t pnd_fuse_nlookup; /* vnode refcount */
 112 int pnd_puffs_nlookup; /* vnode refcount */
112 uint64_t pnd_lock_owner; 113 uint64_t pnd_lock_owner;
113 struct dirent *pnd_dirent; /* native buffer for readdir */ 114 struct dirent *pnd_dirent; /* native buffer for readdir */
114 off_t pnd_dirent_len; 115 off_t pnd_dirent_len;
115 struct fuse_dirent *pnd_all_fd; /* FUSE buffer for readdir */ 116 struct fuse_dirent *pnd_all_fd; /* FUSE buffer for readdir */
116 size_t pnd_all_fd_len; 117 size_t pnd_all_fd_len;
117 uint64_t pnd_fd_cookie; /* opaque readdir ref from fs */ 118 uint64_t pnd_fd_cookie; /* opaque readdir ref from fs */
118 TAILQ_HEAD(,perfuse_cc_queue) pnd_pcq; /* queued requests */ 119 TAILQ_HEAD(,perfuse_cc_queue) pnd_pcq; /* queued requests */
119 int pnd_flags; 120 int pnd_flags;
120#define PND_RECLAIMED 0x001 /* reclaim pending */ 121#define PND_RECLAIMED 0x001 /* reclaim pending */
121#define PND_INREADDIR 0x002 /* readdir in progress */ 122#define PND_INREADDIR 0x002 /* readdir in progress */
122#define PND_DIRTY 0x004 /* There is some data to sync */ 123#define PND_DIRTY 0x004 /* There is some data to sync */
123#define PND_RFH 0x008 /* Read FH allocated */ 124#define PND_RFH 0x008 /* Read FH allocated */
124#define PND_WFH 0x010 /* Write FH allocated */ 125#define PND_WFH 0x010 /* Write FH allocated */

cvs diff -r1.15 -r1.16 src/lib/libperfuse/subr.c (expand / switch to unified diff)

--- src/lib/libperfuse/subr.c 2012/01/29 06:22:02 1.15
+++ src/lib/libperfuse/subr.c 2012/03/08 14:58:57 1.16
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: subr.c,v 1.15 2012/01/29 06:22:02 manu Exp $ */ 1/* $NetBSD: subr.c,v 1.16 2012/03/08 14:58:57 manu Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved. 4 * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
5 *  5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 *  14 *
@@ -57,27 +57,28 @@ perfuse_new_pn(pu, name, parent) @@ -57,27 +57,28 @@ perfuse_new_pn(pu, name, parent)
57 struct puffs_node *pn; 57 struct puffs_node *pn;
58 struct perfuse_node_data *pnd; 58 struct perfuse_node_data *pnd;
59 59
60 if ((pnd = malloc(sizeof(*pnd))) == NULL) 60 if ((pnd = malloc(sizeof(*pnd))) == NULL)
61 DERR(EX_OSERR, "%s: malloc failed", __func__); 61 DERR(EX_OSERR, "%s: malloc failed", __func__);
62 62
63 if ((pn = puffs_pn_new(pu, pnd)) == NULL) 63 if ((pn = puffs_pn_new(pu, pnd)) == NULL)
64 DERR(EX_SOFTWARE, "%s: puffs_pn_new failed", __func__); 64 DERR(EX_SOFTWARE, "%s: puffs_pn_new failed", __func__);
65 65
66 (void)memset(pnd, 0, sizeof(*pnd)); 66 (void)memset(pnd, 0, sizeof(*pnd));
67 pnd->pnd_rfh = FUSE_UNKNOWN_FH; 67 pnd->pnd_rfh = FUSE_UNKNOWN_FH;
68 pnd->pnd_wfh = FUSE_UNKNOWN_FH; 68 pnd->pnd_wfh = FUSE_UNKNOWN_FH;
69 pnd->pnd_nodeid = PERFUSE_UNKNOWN_NODEID; 69 pnd->pnd_nodeid = PERFUSE_UNKNOWN_NODEID;
70 pnd->pnd_nlookup = 1; 70 pnd->pnd_fuse_nlookup = 1;
 71 pnd->pnd_puffs_nlookup = 1;
71 pnd->pnd_parent = parent; 72 pnd->pnd_parent = parent;
72 pnd->pnd_pn = (puffs_cookie_t)pn; 73 pnd->pnd_pn = (puffs_cookie_t)pn;
73 (void)strlcpy(pnd->pnd_name, name, MAXPATHLEN); 74 (void)strlcpy(pnd->pnd_name, name, MAXPATHLEN);
74 TAILQ_INIT(&pnd->pnd_pcq); 75 TAILQ_INIT(&pnd->pnd_pcq);
75 TAILQ_INIT(&pnd->pnd_children); 76 TAILQ_INIT(&pnd->pnd_children);
76 77
77 if (parent != NULL) { 78 if (parent != NULL) {
78 struct perfuse_node_data *parent_pnd; 79 struct perfuse_node_data *parent_pnd;
79 80
80 parent_pnd = PERFUSE_NODE_DATA(parent); 81 parent_pnd = PERFUSE_NODE_DATA(parent);
81 TAILQ_INSERT_TAIL(&parent_pnd->pnd_children, pnd, pnd_next); 82 TAILQ_INSERT_TAIL(&parent_pnd->pnd_children, pnd, pnd_next);
82 83
83 parent_pnd->pnd_childcount++; 84 parent_pnd->pnd_childcount++;