Module Name:    src
Committed By:   martin
Date:           Sun Feb 10 13:40:41 UTC 2019

Modified Files:
        src/lib/libperfuse [netbsd-8]: debug.c ops.c perfuse.c perfuse_priv.h

Log Message:
Pull up following revision(s) (requested by manu in ticket #1186):

        lib/libperfuse/perfuse.c: revision 1.41
        lib/libperfuse/perfuse_priv.h: revision 1.37
        lib/libperfuse/ops.c: revision 1.85
        lib/libperfuse/ops.c: revision 1.86
        lib/libperfuse/debug.c: revision 1.13

Use reclaim2 to fix reclaim/lookup race conditions

The PUFFS reclaim operation had a race condition with lookups: we could
be asked to lookup a node, then to reclaim it before lookup completion.

At lookup completion, we would then create a leaked node.

Enter the PUFFS reclaim2 operation, which features a nlookup argument.

That let us count how many lookups are pending and avoid the above
described scenario. It also makes the codes simplier.

 -

Fix directory filehandle usage with libufse. Fix lookup count
libfuse does not use filehandle the same way for directories and other
objects. As a result, filehandles obtained by OPENDIR should not be
sent on non-directory related operations like READ/WRITE/GETATTR...

While there, fix the lookup count sent to the FORGET operation, which
led to leaked nodes.


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.12.24.1 src/lib/libperfuse/debug.c
cvs rdiff -u -r1.84 -r1.84.8.1 src/lib/libperfuse/ops.c
cvs rdiff -u -r1.40 -r1.40.6.1 src/lib/libperfuse/perfuse.c
cvs rdiff -u -r1.36 -r1.36.8.1 src/lib/libperfuse/perfuse_priv.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libperfuse/debug.c
diff -u src/lib/libperfuse/debug.c:1.12 src/lib/libperfuse/debug.c:1.12.24.1
--- src/lib/libperfuse/debug.c:1.12	Sat Jul 21 05:49:42 2012
+++ src/lib/libperfuse/debug.c	Sun Feb 10 13:40:41 2019
@@ -1,4 +1,4 @@
-/*  $NetBSD: debug.c,v 1.12 2012/07/21 05:49:42 manu Exp $ */
+/*  $NetBSD: debug.c,v 1.12.24.1 2019/02/10 13:40:41 martin Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -270,7 +270,6 @@ perfuse_trace_dump(struct puffs_usermoun
 	fprintf(fp, "\n\nGlobal statistics\n");
 	fprintf(fp, "Nodes: %d\n", ps->ps_nodecount);
 	fprintf(fp, "Exchanges: %d\n", ps->ps_xchgcount);
-	fprintf(fp, "Nodes possibly leaked: %d\n", ps->ps_nodeleakcount);
 	
 	(void)fflush(fp);
 	return;

Index: src/lib/libperfuse/ops.c
diff -u src/lib/libperfuse/ops.c:1.84 src/lib/libperfuse/ops.c:1.84.8.1
--- src/lib/libperfuse/ops.c:1.84	Wed Jun  3 14:07:05 2015
+++ src/lib/libperfuse/ops.c	Sun Feb 10 13:40:41 2019
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.84 2015/06/03 14:07:05 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.84.8.1 2019/02/10 13:40:41 martin Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -105,6 +105,9 @@ const int vttoif_tab[9] = { 
 #define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12])
 #define VTTOIF(indx) (vttoif_tab[(int)(indx)])
 
+#define PN_ISDIR(opc) \
+	(puffs_pn_getvap((struct puffs_node *)opc)->va_type == VDIR)
+
 #if 0
 static void 
 print_node(const char *func, puffs_cookie_t opc)
@@ -141,7 +144,7 @@ perfuse_node_close_common(struct puffs_u
 	pn = (struct puffs_node *)opc;
 	pnd = PERFUSE_NODE_DATA(pn);
 
-	if (puffs_pn_getvap(pn)->va_type == VDIR) {
+	if (PN_ISDIR(opc)) {
 		op = FUSE_RELEASEDIR;
 		mode = FREAD;
 	} else {
@@ -479,13 +482,14 @@ node_lookup_common(struct puffs_usermoun
 	fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
 	pn->pn_va.va_gen = (u_long)(feo->generation);
 	PERFUSE_NODE_DATA(pn)->pnd_fuse_nlookup++;
+	PERFUSE_NODE_DATA(pn)->pnd_puffs_nlookup++;
 
 	*pnp = pn;
 
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_FILENAME)
 		DPRINTF("%s: opc = %p, looked up opc = %p, "
-			"nodeid = 0x%"PRIx64" file = \"%s\"\n", __func__, 
+			"nodeid = 0x%"PRIx64" file = \"%s\"\n", __func__,
 			(void *)opc, pn, feo->nodeid, path);
 #endif
 
@@ -500,11 +504,6 @@ node_lookup_common(struct puffs_usermoun
 		puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev);
 	}
 
-	if (PERFUSE_NODE_DATA(pn)->pnd_flags & PND_NODELEAK) {
-		PERFUSE_NODE_DATA(pn)->pnd_flags &= ~PND_NODELEAK;
-		ps->ps_nodeleakcount--;
-	}
-
 	ps->ps_destroy_msg(pm);
 
 	return 0;
@@ -538,6 +537,7 @@ node_mk_common(struct puffs_usermount *p
 
 	pn = perfuse_new_pn(pu, pcn->pcn_name, opc);
 	PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
+	PERFUSE_NODE_DATA(pn)->pnd_fuse_nlookup++;
 	PERFUSE_NODE_DATA(pn)->pnd_puffs_nlookup++;
 	perfuse_node_cache(ps, pn);
 
@@ -672,7 +672,7 @@ fuse_to_dirent(struct puffs_usermount *p
 					       "failed: %d", name, error);
 				} else {
 					fd->ino = pn->pn_va.va_fileid;
-					(void)perfuse_node_reclaim(pu, pn);
+					(void)perfuse_node_reclaim2(pu, pn, 1);
 				}
 			}
 		}
@@ -1135,7 +1135,7 @@ perfuse_node_lookup(struct puffs_usermou
 	case NAMEI_RENAME:
 		error = sticky_access(opc, pn, pcn->pcn_cred);
 		if (error != 0) {
-			(void)perfuse_node_reclaim(pu, pn);
+			(void)perfuse_node_reclaim2(pu, pn, 1);
 			goto out;
 		}
 		break;
@@ -1143,6 +1143,7 @@ perfuse_node_lookup(struct puffs_usermou
 		break;
 	}
 
+	PERFUSE_NODE_DATA(pn)->pnd_fuse_nlookup++;
 	PERFUSE_NODE_DATA(pn)->pnd_puffs_nlookup++;
 
 	error = 0;
@@ -1182,7 +1183,7 @@ perfuse_node_create(struct puffs_usermou
 		error = node_lookup_common(pu, opc, NULL, pcn->pcn_name,
 					   pcn->pcn_cred, &pn);
 		if (error == 0)	{
-			(void)perfuse_node_reclaim(pu, pn);
+			(void)perfuse_node_reclaim2(pu, pn, 1);
 			error = EEXIST;
 			goto out;
 		}
@@ -1252,6 +1253,7 @@ perfuse_node_create(struct puffs_usermou
 	pn = perfuse_new_pn(pu, name, opc);
 	perfuse_new_fh((puffs_cookie_t)pn, foo->fh, FWRITE);
 	PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
+	PERFUSE_NODE_DATA(pn)->pnd_fuse_nlookup++;
 	PERFUSE_NODE_DATA(pn)->pnd_puffs_nlookup++;
 	perfuse_node_cache(ps, pn);
 
@@ -1360,11 +1362,9 @@ perfuse_node_open2(struct puffs_usermoun
 	int op;
 	struct fuse_open_in *foi;
 	struct fuse_open_out *foo;
-	struct puffs_node *pn;
 	int error;
 	
 	ps = puffs_getspecific(pu);
-	pn = (struct puffs_node *)opc;
 	pnd = PERFUSE_NODE_DATA(opc);
 	error = 0;
 
@@ -1373,7 +1373,7 @@ perfuse_node_open2(struct puffs_usermoun
 
 	node_ref(opc);
 
-	if (puffs_pn_getvap(pn)->va_type == VDIR)
+	if (PN_ISDIR(opc))
 		op = FUSE_OPENDIR;
 	else
 		op = FUSE_OPEN;
@@ -1597,9 +1597,9 @@ perfuse_node_getattr_ttl(struct puffs_us
 	fgi = GET_INPAYLOAD(ps, pm, fuse_getattr_in);
 	fgi->getattr_flags = 0; 
 	fgi->dummy = 0;
-	fgi->fh = 0;
+	fgi->fh = FUSE_UNKNOWN_FH;
 
-	if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN) {
+	if (!PN_ISDIR(opc) && PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN) {
 		fgi->fh = perfuse_get_fh(opc, FREAD);
 		fgi->getattr_flags |= FUSE_GETATTR_FH;
 	}
@@ -1733,7 +1733,7 @@ perfuse_node_setattr_ttl(struct puffs_us
 	
 	node_ref(opc);
 	
-	if (pnd->pnd_flags & PND_WFH)
+	if (!PN_ISDIR(opc) && pnd->pnd_flags & PND_WFH)
 		fh = perfuse_get_fh(opc, FWRITE);
 	else
 		fh = FUSE_UNKNOWN_FH;
@@ -1959,7 +1959,7 @@ perfuse_node_poll(struct puffs_usermount
  	 */
 	pm = ps->ps_new_msg(pu, opc, FUSE_POLL, sizeof(*fpi), NULL);
 	fpi = GET_INPAYLOAD(ps, pm, fuse_poll_in);
-	fpi->fh = perfuse_get_fh(opc, FREAD);
+	fpi->fh = PN_ISDIR(opc) ? FUSE_UNKNOWN_FH : perfuse_get_fh(opc, FREAD);
 	fpi->kh = 0;
 	fpi->flags = 0;
 
@@ -2015,7 +2015,7 @@ perfuse_node_fsync(struct puffs_usermoun
 
 	node_ref(opc);
 
-	if (puffs_pn_getvap((struct puffs_node *)opc)->va_type == VDIR) 
+	if (PN_ISDIR(opc))
 		op = FUSE_FSYNCDIR;
 	else 		/* VREG but also other types such as VLNK */
 		op = FUSE_FSYNC;
@@ -2518,7 +2518,7 @@ perfuse_node_readdir(struct puffs_usermo
 			goto out;
 	}
 
-	fh = perfuse_get_fh(opc, FREAD);
+	fh = perfuse_get_fh(opc, FREAD); 
 
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_FH)
@@ -2682,17 +2682,22 @@ out:
 }
 
 int 
-perfuse_node_reclaim(struct puffs_usermount *pu, puffs_cookie_t opc)
+perfuse_node_reclaim2(struct puffs_usermount *pu,
+		      puffs_cookie_t opc, int nlookup)
 {
 	struct perfuse_state *ps;
 	perfuse_msg_t *pm;
 	struct perfuse_node_data *pnd;
 	struct fuse_forget_in *ffi;
-	int nlookup;
-	struct timespec now;
 	
-	if (opc == 0)
+#ifdef PERFUSE_DEBUG
+		if (perfuse_diagflags & PDF_RECLAIM)
+			DPRINTF("%s called with opc = %p, nlookup = %d\n",
+				__func__, (void *)opc, nlookup);
+#endif
+	if (opc == 0 || nlookup == 0) {
 		return 0;
+	}
 
 	ps = puffs_getspecific(pu);
 	pnd = PERFUSE_NODE_DATA(opc);
@@ -2703,43 +2708,23 @@ perfuse_node_reclaim(struct puffs_usermo
 	if (pnd->pnd_nodeid == FUSE_ROOT_ID)
 		return 0;
 
+#ifdef PERFUSE_DEBUG
+	if (perfuse_diagflags & PDF_RECLAIM)
+		DPRINTF("%s (nodeid %"PRId64") reclaimed, nlookup = %d/%d\n", 
+			perfuse_node_path(ps, opc), pnd->pnd_nodeid,
+			nlookup, pnd->pnd_puffs_nlookup);
+#endif
 	/*
-	 * There is a race condition between reclaim and lookup.
-	 * When looking up an already known node, the kernel cannot
-	 * hold a reference on the result until it gets the PUFFS
-	 * reply. It mayy therefore reclaim the node after the 
-	 * userland looked it up, and before it gets the reply. 
-	 * On rely, the kernel re-creates the node, but at that 
-	 * time the node has been reclaimed in userland.
-	 *
-	 * In order to avoid this, we refuse reclaiming nodes that
-	 * are too young since the last lookup - and that we do 
-	 * not have removed on our own, of course. 
-	 */
-	if (clock_gettime(CLOCK_REALTIME, &now) != 0)
-		DERR(EX_OSERR, "clock_gettime failed"); 
-
-	if (timespeccmp(&pnd->pnd_cn_expire, &now, >) && 
-	    !(pnd->pnd_flags & PND_REMOVED)) {
-		if (!(pnd->pnd_flags & PND_NODELEAK)) {
-			ps->ps_nodeleakcount++;
-			pnd->pnd_flags |= PND_NODELEAK;
-		}
-		DWARNX("possible leaked node:: opc = %p \"%s\"",
-		       opc, pnd->pnd_name);
+	 * The kernel tells us how many lookups it made, which allows
+	 * us to detect that we have an uncompleted lookup and that the
+	 * node should not dispear.
+	 */
+	pnd->pnd_puffs_nlookup -= nlookup;
+	if (pnd->pnd_puffs_nlookup > 0)
 		return 0;
-	}
 
 	node_ref(opc);
 	pnd->pnd_flags |= PND_RECLAIMED;
-	pnd->pnd_puffs_nlookup--;
-	nlookup = pnd->pnd_puffs_nlookup;
-
-#ifdef PERFUSE_DEBUG
-	if (perfuse_diagflags & PDF_RECLAIM)
-		DPRINTF("%s (nodeid %"PRId64") reclaimed\n", 
-			perfuse_node_path(ps, opc), pnd->pnd_nodeid);
-#endif
 
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_RECLAIM)
@@ -2751,7 +2736,7 @@ perfuse_node_reclaim(struct puffs_usermo
 			pnd->pnd_flags & PND_OPEN ? "open " : "not open",
 			pnd->pnd_flags & PND_RFH ? "r" : "",
 			pnd->pnd_flags & PND_WFH ? "w" : "",
-			pnd->pnd_flags & PND_BUSY ? "" : " none",
+			pnd->pnd_flags & PND_BUSY ? " busy" : "",
 			pnd->pnd_flags & PND_INREADDIR ? " readdir" : "",
 			pnd->pnd_flags & PND_INWRITE ? " write" : "",
 			pnd->pnd_flags & PND_INOPEN ? " open" : "");
@@ -2769,17 +2754,6 @@ perfuse_node_reclaim(struct puffs_usermo
 	while (pnd->pnd_ref > 1)
 		requeue_request(pu, opc, PCQ_REF);
 
-	/*
-	 * reclaim cancel?
-	 */
-	if (pnd->pnd_puffs_nlookup > nlookup) {
-		pnd->pnd_flags &= ~PND_RECLAIMED;
-		perfuse_node_cache(ps, opc);
-		node_rele(opc);
-		return 0;
-	}
-
-
 #ifdef PERFUSE_DEBUG
 	if ((pnd->pnd_flags & PND_OPEN) ||
 	       !TAILQ_EMPTY(&pnd->pnd_pcq))
@@ -2818,6 +2792,16 @@ perfuse_node_reclaim(struct puffs_usermo
 	return 0;
 }
 
+int
+perfuse_node_reclaim(struct puffs_usermount *pu, puffs_cookie_t opc)
+{
+#ifdef PERFUSE_DEBUG
+	if (perfuse_diagflags & PDF_RECLAIM)
+		DPRINTF("perfuse_node_reclaim called\n");
+#endif
+	return perfuse_node_reclaim2(pu, opc, 1);
+}
+
 int 
 perfuse_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc)
 {
@@ -2992,15 +2976,24 @@ perfuse_node_advlock(struct puffs_usermo
 	 * expect one. E.g.: if we provide none, GlusterFS logs an error
 	 * "0-glusterfs-fuse: xl is NULL"
 	 *
+	 * There is one exception with directories where filehandle
+	 * is not included, because libfuse uses different filehandle
+	 * in opendir/releasedir/readdir/fsyncdir compared to other 
+	 * operations. Who locks a directory anyway?
+	 *
 	 * We need the read file handle if the file is open read only,
 	 * in order to support shared locks on read-only files.
 	 * NB: The kernel always sends advlock for read-only
 	 * files at exit time when the process used lock, see
 	 * sys_exit -> exit1 -> fd_free -> fd_close -> VOP_ADVLOCK
 	 */
-	if ((fh = perfuse_get_fh(opc, FREAD)) == FUSE_UNKNOWN_FH) {
-		error = EBADF;
-		goto out;
+	if (!PN_ISDIR(opc)) {
+		if ((fh = perfuse_get_fh(opc, FREAD)) == FUSE_UNKNOWN_FH) {
+			error = EBADF;
+			goto out;
+		}
+	} else {
+		fh = FUSE_UNKNOWN_FH;
 	}
 
 	ps = puffs_getspecific(pu);
@@ -3097,6 +3090,7 @@ perfuse_node_read(struct puffs_usermount
 	struct perfuse_node_data *pnd;
 	const struct vattr *vap;
 	perfuse_msg_t *pm;
+	uint64_t fh;
 	struct fuse_read_in *fri;
 	struct fuse_out_header *foh;
 	size_t readen;
@@ -3113,6 +3107,8 @@ perfuse_node_read(struct puffs_usermount
 	if (vap->va_type == VDIR)
 		return EISDIR;
 
+	fh =  perfuse_get_fh(opc, FREAD); /* Cannot be VDIR */
+
 	do {
 		size_t max_read;
 
@@ -3123,7 +3119,7 @@ perfuse_node_read(struct puffs_usermount
 		 */
 		pm = ps->ps_new_msg(pu, opc, FUSE_READ, sizeof(*fri), pcr);
 		fri = GET_INPAYLOAD(ps, pm, fuse_read_in);
-		fri->fh = perfuse_get_fh(opc, FREAD);
+		fri->fh = fh;
 		fri->offset = offset;
 		fri->size = (uint32_t)MIN(*resid, max_read);
 		fri->read_flags = 0; /* XXX Unused by libfuse? */
@@ -3184,6 +3180,7 @@ perfuse_node_write2(struct puffs_usermou
 	struct perfuse_node_data *pnd;
 	struct vattr *vap;
 	perfuse_msg_t *pm;
+	uint64_t fh;
 	struct fuse_write_in *fwi;
 	struct fuse_write_out *fwo;
 	size_t data_len;
@@ -3239,6 +3236,8 @@ perfuse_node_write2(struct puffs_usermou
 			(void *)opc, vap->va_size);
 #endif
 
+	fh = perfuse_get_fh(opc, FWRITE); /* Cannot be VDIR */
+
 	do {
 		size_t max_write;
 		/*
@@ -3262,7 +3261,7 @@ perfuse_node_write2(struct puffs_usermou
 		 */
 		pm = ps->ps_new_msg(pu, opc, FUSE_WRITE, payload_len, pcr);
 		fwi = GET_INPAYLOAD(ps, pm, fuse_write_in);
-		fwi->fh = perfuse_get_fh(opc, FWRITE);
+		fwi->fh = fh;
 		fwi->offset = offset;
 		fwi->size = (uint32_t)data_len;
 		fwi->write_flags = (fwi->size % sysconf(_SC_PAGESIZE)) ? 0 : 1;
@@ -3276,7 +3275,7 @@ perfuse_node_write2(struct puffs_usermou
 #ifdef PERFUSE_DEBUG
 		if (perfuse_diagflags & PDF_FH)
 			DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", "
-				"fh = 0x%"PRIx64"\n", __func__, 
+				"fh = 0x%"PRIx64"\n", __func__,
 				(void *)opc, pnd->pnd_nodeid, fwi->fh);
 #endif
 		if ((error = xchg_msg(pu, opc, pm, 
@@ -3309,7 +3308,7 @@ out:
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_RESIZE) {
 		if (offset > (off_t)vap->va_size)
-			DPRINTF("<< %s %p %" PRIu64 " -> %lld\n", __func__, 
+			DPRINTF("<< %s %p %" PRIu64 " -> %lld\n", __func__,
 				(void *)opc, vap->va_size, (long long)offset);
 		else
 			DPRINTF("<< %s %p \n", __func__, (void *)opc);
@@ -3671,7 +3670,7 @@ perfuse_node_fallocate(struct puffs_user
 	pm = ps->ps_new_msg(pu, opc, FUSE_FALLOCATE, sizeof(*fai), NULL);
 
 	fai = GET_INPAYLOAD(ps, pm, fuse_fallocate_in);
-	fai->fh = perfuse_get_fh(opc, FWRITE);
+	fai->fh = PN_ISDIR(opc) ? FUSE_UNKNOWN_FH : perfuse_get_fh(opc, FWRITE);
 	fai->offset = off;
 	fai->length = len;
 	fai->mode = 0;

Index: src/lib/libperfuse/perfuse.c
diff -u src/lib/libperfuse/perfuse.c:1.40 src/lib/libperfuse/perfuse.c:1.40.6.1
--- src/lib/libperfuse/perfuse.c:1.40	Wed Oct 19 01:30:35 2016
+++ src/lib/libperfuse/perfuse.c	Sun Feb 10 13:40:41 2019
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse.c,v 1.40 2016/10/19 01:30:35 christos Exp $ */
+/*  $NetBSD: perfuse.c,v 1.40.6.1 2019/02/10 13:40:41 martin Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -512,6 +512,7 @@ perfuse_init(struct perfuse_callbacks *p
 	PUFFSOP_SET(pops, perfuse, node, readdir);
 	PUFFSOP_SET(pops, perfuse, node, readlink);
 	PUFFSOP_SET(pops, perfuse, node, reclaim);
+	PUFFSOP_SET(pops, perfuse, node, reclaim2);
 	PUFFSOP_SET(pops, perfuse, node, inactive);
 	PUFFSOP_SET(pops, perfuse, node, print);
 	PUFFSOP_SET(pops, perfuse, node, pathconf);

Index: src/lib/libperfuse/perfuse_priv.h
diff -u src/lib/libperfuse/perfuse_priv.h:1.36 src/lib/libperfuse/perfuse_priv.h:1.36.8.1
--- src/lib/libperfuse/perfuse_priv.h:1.36	Fri Oct 31 15:12:15 2014
+++ src/lib/libperfuse/perfuse_priv.h	Sun Feb 10 13:40:41 2019
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse_priv.h,v 1.36 2014/10/31 15:12:15 manu Exp $ */
+/*  $NetBSD: perfuse_priv.h,v 1.36.8.1 2019/02/10 13:40:41 martin Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -93,7 +93,6 @@ struct perfuse_state {
 	struct perfuse_node_hashlist *ps_nidhash;
 	int ps_nnidhash;
 	int ps_nodecount;
-	int ps_nodeleakcount;
 	int ps_xchgcount;
 };
 
@@ -145,7 +144,6 @@ struct perfuse_node_data {
 #define PND_REMOVED		0x020	/* Node was removed */
 #define PND_INWRITE		0x040	/* write in progress */
 #define PND_INOPEN		0x100	/* open in progress */
-#define PND_NODELEAK		0x200	/* node reclaim ignored */
 #define PND_INVALID		0x400	/* node freed, usage is a bug */
 #define PND_INRESIZE		0x800	/* resize in progress */
 
@@ -247,6 +245,7 @@ int perfuse_node_readdir(struct puffs_us
 int perfuse_node_readlink(struct puffs_usermount *,
     puffs_cookie_t, const struct puffs_cred *, char *, size_t *);
 int perfuse_node_reclaim(struct puffs_usermount *, puffs_cookie_t);
+int perfuse_node_reclaim2(struct puffs_usermount *, puffs_cookie_t, int);
 int perfuse_node_inactive(struct puffs_usermount *, puffs_cookie_t);
 int perfuse_node_print(struct puffs_usermount *, puffs_cookie_t);
 int perfuse_node_pathconf(struct puffs_usermount *,

Reply via email to