Module Name:    src
Committed By:   manu
Date:           Sun Oct  3 05:46:48 UTC 2010

Modified Files:
        src/lib/libperfuse: debug.c ops.c perfuse.c perfuse_priv.h subr.c

Log Message:
- Correctly handle rename whith overwritten destination
- Keep track of file name to avoid lookups when we can. This makes sure we
  do not have two cookies for the same inode, a situation that cause wreak
  havoc when we come to remove or rename a node.
- Do not use PUFFS_FLAG_BUILDPATH at all, since we now track file names
- In open, queue requests after checking for access, as there is no merit
  to queue a will-be-denied request while we can deny it immediatly
- request reclaim of removed nodes at inactive stage


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/lib/libperfuse/debug.c
cvs rdiff -u -r1.18 -r1.19 src/lib/libperfuse/ops.c
cvs rdiff -u -r1.9 -r1.10 src/lib/libperfuse/perfuse.c
cvs rdiff -u -r1.13 -r1.14 src/lib/libperfuse/perfuse_priv.h
cvs rdiff -u -r1.7 -r1.8 src/lib/libperfuse/subr.c

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.4 src/lib/libperfuse/debug.c:1.5
--- src/lib/libperfuse/debug.c:1.4	Wed Sep 29 08:01:10 2010
+++ src/lib/libperfuse/debug.c	Sun Oct  3 05:46:47 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: debug.c,v 1.4 2010/09/29 08:01:10 manu Exp $ */
+/*  $NetBSD: debug.c,v 1.5 2010/10/03 05:46:47 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -84,7 +84,7 @@
 	"READ",
 	"WRITE",
 	"AFTERWRITE",
-	"OPEN"
+	"OPEN",
 	"AFTERXCHG"
 };
 

Index: src/lib/libperfuse/ops.c
diff -u src/lib/libperfuse/ops.c:1.18 src/lib/libperfuse/ops.c:1.19
--- src/lib/libperfuse/ops.c:1.18	Wed Sep 29 08:01:10 2010
+++ src/lib/libperfuse/ops.c	Sun Oct  3 05:46:47 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.18 2010/09/29 08:01:10 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.19 2010/10/03 05:46:47 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -184,7 +184,7 @@
 #ifdef PERFUSE_DEBUG
 	if ((perfuse_diagflags & PDF_FILENAME) && (opc != 0))
 		DPRINTF("file = \"%s\" flags = 0x%x\n", 
-			(char *)PNPATH((struct puffs_node *)opc), 
+			perfuse_node_path(opc),
 			PERFUSE_NODE_DATA(opc)->pnd_flags);
 #endif
 	if (pnd)
@@ -209,6 +209,14 @@
 	struct puffs_node *pn;
 	struct vattr *va;
 
+	/*
+	 * pcr is NULL for self open through fsync or readdir.
+	 * In both case, access control is useless, as it was
+	 * done before, at open time.
+	 */
+	if (pcr == NULL)
+		return 0;
+
 	pn = (struct puffs_node *)opc;
 	va = puffs_pn_getvap(pn);
 
@@ -291,7 +299,8 @@
 	namelen = PNPLEN(dpn) + 1 + namelen + 1;
 	if ((path = malloc(namelen)) == NULL)
 		DERR(EX_OSERR, "malloc failed");
-	(void)snprintf(path, namelen, "%s/%s", (char *)PNPATH(dpn), name);
+	(void)snprintf(path, namelen, "%s/%s", 
+		       perfuse_node_path((puffs_cookie_t)dpn), name);
 
 	error = node_lookup_common(pu, opc, path, pnp);
 	
@@ -308,6 +317,7 @@
 	struct puffs_node **pnp;
 {
 	struct perfuse_state *ps;
+	struct perfuse_node_data *pnd;
 	perfuse_msg_t *pm;
 	struct fuse_entry_out *feo;
 	struct puffs_node *pn;
@@ -316,6 +326,35 @@
 
 	ps = puffs_getspecific(pu);
 
+#ifdef PERFUSE_DEBUG
+	if (perfuse_diagflags & PDF_FILENAME)
+		DPRINTF("%s: opc = %p, file = \"%s\" looking up \"%s\"\n",
+			__func__, (void *)opc, perfuse_node_path(opc), path);
+#endif
+	/*
+	 * Is the node already known?
+	 */
+	TAILQ_FOREACH(pnd, &PERFUSE_NODE_DATA(opc)->pnd_children, pnd_next) {
+		if ((pnd->pnd_flags & PND_REMOVED) ||
+		    (strcmp(pnd->pnd_name, path) != 0))
+			continue;
+
+		/*
+		 * We have a match
+		 */
+		if (pnp != NULL)
+			*pnp = (struct puffs_node *)(pnd->pnd_pn);
+
+#ifdef PERFUSE_DEBUG
+		if (perfuse_diagflags & PDF_FILENAME)
+			DPRINTF("%s: opc = %p, file = \"%s\" found "
+				"cookie = %p, ino = %"PRId64" for \"%s\"\n",
+				__func__, (void *)opc, perfuse_node_path(opc), 
+				(void *)pnd->pnd_pn, pnd->pnd_ino, path);
+#endif
+		return 0;
+	}
+
 	len = strlen(path) + 1;
 
 	pm = ps->ps_new_msg(pu, opc, FUSE_LOOKUP, len, NULL);
@@ -326,7 +365,7 @@
 
 	feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
 
-	pn = perfuse_new_pn(pu, opc);
+	pn = perfuse_new_pn(pu, path, opc);
 	PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid;
 
 	fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
@@ -376,13 +415,21 @@
 	if (feo->nodeid == PERFUSE_UNKNOWN_INO)
 		DERRX(EX_SOFTWARE, "%s: no ino", __func__);
 
-	pn = perfuse_new_pn(pu, opc);
+	pn = perfuse_new_pn(pu, pcn->pcn_name, opc);
 	PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid;
 
 	fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
 	puffs_newinfo_setcookie(pni, pn);
+
+#ifdef PERFUSE_DEBUG
+	if (perfuse_diagflags & PDF_FILENAME)
+		DPRINTF("%s: opc = %p, file = \"%s\", flags = 0x%x "
+			"ino = %"PRId64"\n",
+			__func__, (void *)pn, pcn->pcn_name,
+			PERFUSE_NODE_DATA(pn)->pnd_flags, feo->nodeid);
+#endif
 	ps->ps_destroy_msg(pm);
- 
+
 	/* 
 	 * Set owner and group
 	 */
@@ -406,6 +453,7 @@
 	 * The parent directory needs a sync
 	 */
 	PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
+
 out:
 	ps->ps_destroy_msg(pm);
 
@@ -995,7 +1043,7 @@
 	 * Save the file handle and inode in node private data 
 	 * so that we can reuse it later
 	 */
-	pn = perfuse_new_pn(pu, opc);
+	pn = perfuse_new_pn(pu, name, opc);
 	perfuse_new_fh((puffs_cookie_t)pn, foo->fh, FWRITE);
 	PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid;
 
@@ -1115,15 +1163,6 @@
 	if (pnd->pnd_flags & PND_REMOVED)
 		return ENOENT;
 
-	/*
-	 * Queue open on a node so that we do not open
-	 * twice. This would be better with read and
-	 * write distinguished.
-	 */
-	while (pnd->pnd_flags & PND_INOPEN)
-		requeue_request(pu, opc, PCQ_OPEN);
-	pnd->pnd_flags |= PND_INOPEN;
-
 	if (puffs_pn_getvap(pn)->va_type == VDIR) {
 		op = FUSE_OPENDIR;
 		pmode = PUFFS_VREAD|PUFFS_VEXEC;
@@ -1166,6 +1205,15 @@
 	}
 	
 	/*
+	 * Queue open on a node so that we do not open
+	 * twice. This would be better with read and
+	 * write distinguished.
+	 */
+	while (pnd->pnd_flags & PND_INOPEN)
+		requeue_request(pu, opc, PCQ_OPEN);
+	pnd->pnd_flags |= PND_INOPEN;
+
+	/*
 	 * Convert PUFFS mode to FUSE mode: convert FREAD/FWRITE
 	 * to O_RDONLY/O_WRONLY while perserving the other options.
 	 */
@@ -1192,8 +1240,7 @@
 	if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
 		DPRINTF("%s: opc = %p, file = \"%s\", "
 			"ino = %"PRId64", %s%sfh = 0x%"PRIx64"\n",
-			__func__, (void *)opc, 
-			(char *)PNPATH((struct puffs_node *)opc),
+			__func__, (void *)opc, perfuse_node_path(opc),
 			pnd->pnd_ino, mode & FREAD ? "r" : "",
 			mode & FWRITE ? "w" : "", foo->fh);
 #endif
@@ -1641,8 +1688,7 @@
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_SYNC)
 		DPRINTF("%s: TEST opc = %p, file = \"%s\" is %sdirty\n", 
-			__func__, (void*)opc,
-			(char *)PNPATH((struct puffs_node *)opc),
+			__func__, (void*)opc, perfuse_node_path(opc),
 			pnd->pnd_flags & PND_DIRTY ? "" : "not ");
 #endif
 	if (!(pnd->pnd_flags & PND_DIRTY))
@@ -1695,8 +1741,7 @@
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_SYNC)
 		DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n", 
-			__func__, (void*)opc,
-			(char *)PNPATH((struct puffs_node *)opc));
+			__func__, (void*)opc, perfuse_node_path(opc));
 #endif
 
 out:
@@ -1772,12 +1817,6 @@
 		DPRINTF("%s: opc = %p, remove opc = %p, file = \"%s\"\n",
 			__func__, (void *)opc, (void *)targ, pcn->pcn_name);
 #endif
-
-	ps = puffs_getspecific(pu);
-	pnd = PERFUSE_NODE_DATA(opc);
-	name = pcn->pcn_name;
-	len = pcn->pcn_namelen + 1;
-
 	/*
 	 * Await for all operations on the deleted node to drain, 
 	 * as the filesystem may be confused to have it deleted
@@ -1786,6 +1825,11 @@
 	while (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_INXCHG)
 		requeue_request(pu, targ, PCQ_AFTERXCHG);
 
+	ps = puffs_getspecific(pu);
+	pnd = PERFUSE_NODE_DATA(opc);
+	name = pcn->pcn_name;
+	len = pcn->pcn_namelen + 1;
+
 	pm = ps->ps_new_msg(pu, opc, FUSE_UNLINK, len, pcn->pcn_cred);
 	path = _GET_INPAYLOAD(ps, pm, char *);
 	(void)strlcpy(path, name, len);
@@ -1920,48 +1964,42 @@
 	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
 		goto out;
 
-	PERFUSE_NODE_DATA(opc)->pnd_childcount--;
-	PERFUSE_NODE_DATA(targ_dir)->pnd_childcount++;
+	if (opc != targ_dir) {
+		struct perfuse_node_data *srcdir_pnd;
+		struct perfuse_node_data *dstdir_pnd;
+		struct perfuse_node_data *src_pnd;
+		
+		srcdir_pnd = PERFUSE_NODE_DATA(opc);
+		dstdir_pnd = PERFUSE_NODE_DATA(targ_dir);
+		src_pnd = PERFUSE_NODE_DATA(src);
 
-	PERFUSE_NODE_DATA(src)->pnd_parent = targ_dir;
+		TAILQ_REMOVE(&srcdir_pnd->pnd_children, src_pnd, pnd_next);
+		TAILQ_INSERT_TAIL(&dstdir_pnd->pnd_children, src_pnd, pnd_next);
 
-	PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
-	PERFUSE_NODE_DATA(targ_dir)->pnd_flags |= PND_DIRTY;
+		srcdir_pnd->pnd_childcount--;
+		dstdir_pnd->pnd_childcount++;
 
-	if ((struct puffs_node *)targ != NULL) {
-		struct perfuse_node_data *targ_pnd;
-		struct perfuse_node_data *src_pnd;
+		src_pnd->pnd_parent = targ_dir;
 
-		/*
-		 * We overwrite a node. src must be freed, as it 
-		 * is associated in kernel with the old path. We
-		 * therefore have to transfer perfuse_node_data
-		 * from src to targ.
-		 * 
-		 * src cannot be destroyed here as setback is not
-		 * allowed in rename operation. The node is tagged
-		 * with PND_REMOVED, it will be disposed at inactive
-		 * time.
-		 */
-		targ_pnd = PERFUSE_NODE_DATA(targ);
-		src_pnd = PERFUSE_NODE_DATA(src);
-		puffs_pn_setpriv((struct puffs_node *)targ, src_pnd);
-		puffs_pn_setpriv((struct puffs_node *)src, targ_pnd);
-
-		PERFUSE_NODE_DATA(src)->pnd_flags |= PND_REMOVED;
+		PERFUSE_NODE_DATA(targ_dir)->pnd_flags |= PND_DIRTY;
 	}
 
+	(void)strlcpy(PERFUSE_NODE_DATA(src)->pnd_name, newname, MAXPATHLEN);
+
+	PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
+
+	if ((struct puffs_node *)targ != NULL)
+		PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED;
+
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_FILENAME)
 		DPRINTF("%s: nodeid = %"PRId64" file = \"%s\" renamed \"%s\" "
-			"from nodeid = %"PRId64" \"%s\" "
-			"to nodeid = %"PRId64" \"%s\"\n",
-	 		__func__, 
-			PERFUSE_NODE_DATA(src)->pnd_ino, pcn_src->pcn_name,
-			pcn_targ->pcn_name, PERFUSE_NODE_DATA(opc)->pnd_ino,
-			(char *)PNPATH((struct puffs_node *)targ_dir),
+			"nodeid = %"PRId64" -> nodeid = %"PRId64" \"%s\"\n",
+	 		__func__, PERFUSE_NODE_DATA(src)->pnd_ino,
+			pcn_src->pcn_name, pcn_targ->pcn_name,
+			PERFUSE_NODE_DATA(opc)->pnd_ino,
 			PERFUSE_NODE_DATA(targ_dir)->pnd_ino,
-			(char *)PNPATH((struct puffs_node *)opc));
+			perfuse_node_path(targ_dir));
 #endif
 
 out:
@@ -2044,7 +2082,6 @@
 	while (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_INXCHG)
 		requeue_request(pu, targ, PCQ_AFTERXCHG);
 
-
 	ps = puffs_getspecific(pu);
 	name = pcn->pcn_name;
 	len = pcn->pcn_namelen + 1;
@@ -2069,7 +2106,7 @@
 	if (perfuse_diagflags & PDF_FILENAME)
 		DPRINTF("%s: remove nodeid = %"PRId64" file = \"%s\"\n",
 			__func__, PERFUSE_NODE_DATA(targ)->pnd_ino,
-			(char *)PNPATH((struct puffs_node *)targ));
+			perfuse_node_path(targ));
 #endif
 out:
 	ps->ps_destroy_msg(pm);
@@ -2369,7 +2406,7 @@
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_RECLAIM)
 		DPRINTF("%s (nodeid %"PRId64") reclaimed\n", 
-		       (char *)PNPATH((struct puffs_node *)opc), pnd->pnd_ino);
+			perfuse_node_path(opc), pnd->pnd_ino);
 #endif
 
 	pn_root = puffs_getroot(pu);
@@ -2383,7 +2420,7 @@
 	if (perfuse_diagflags & PDF_RECLAIM)
 		DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, "
 			"has childcount %d %s%s%s%s, pending ops:%s%s%s\n", 
-		        (char *)PNPATH(pn), pnd->pnd_ino,
+		        perfuse_node_path((puffs_cookie_t)pn), pnd->pnd_ino,
 		        pnd->pnd_flags & PND_RECLAIMED ? "" : "not ",
 		        pnd->pnd_childcount,
 			pnd->pnd_flags & PND_OPEN ? "open " : "not open",
@@ -2440,8 +2477,10 @@
 	struct puffs_usermount *pu;
 	puffs_cookie_t opc;
 {
+	struct perfuse_state *ps;
 	struct perfuse_node_data *pnd;
 
+	ps = puffs_getspecific(pu);
 	pnd = PERFUSE_NODE_DATA(opc);
 
 	if (!(pnd->pnd_flags & (PND_OPEN|PND_REMOVED)))
@@ -2481,11 +2520,18 @@
 	if (pnd->pnd_flags & PND_RFH)
 		(void)perfuse_node_close_common(pu, opc, FREAD);
 
-	pnd->pnd_flags &= ~PND_INOPEN;
-
+	/*
+	 * This will cause a reclaim to be sent
+	 */
 	if (pnd->pnd_flags & PND_REMOVED)
 		puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1);
 
+	/*
+	 * Schedule awaiting operations
+	 */
+	pnd->pnd_flags &= ~PND_INOPEN;
+	(void)dequeue_requests(ps, opc, PCQ_OPEN, DEQUEUE_ALL);
+
 	return 0;
 }
 
@@ -2814,8 +2860,7 @@
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_SYNC)
 		DPRINTF("%s: DIRTY opc = %p, file = \"%s\"\n", 
-			__func__, (void*)opc,
-			(char *)PNPATH((struct puffs_node *)opc));
+			__func__, (void*)opc, perfuse_node_path(opc));
 #endif
 out:
 	if (pm != NULL)

Index: src/lib/libperfuse/perfuse.c
diff -u src/lib/libperfuse/perfuse.c:1.9 src/lib/libperfuse/perfuse.c:1.10
--- src/lib/libperfuse/perfuse.c:1.9	Wed Sep 29 08:01:10 2010
+++ src/lib/libperfuse/perfuse.c	Sun Oct  3 05:46:47 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse.c,v 1.9 2010/09/29 08:01:10 manu Exp $ */
+/*  $NetBSD: perfuse.c,v 1.10 2010/10/03 05:46:47 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -58,7 +58,6 @@
 	(void)memset(ps, 0, sizeof(*ps));
 	ps->ps_max_write = UINT_MAX;
 	ps->ps_max_readahead = UINT_MAX;
-	TAILQ_INIT(&ps->ps_pnd);
 	
 	return ps;
 }
@@ -411,9 +410,6 @@
 	if (perfuse_diagflags & PDF_PUFFS)
 		puffs_flags |= PUFFS_FLAG_OPDUMP;
 
-	if (perfuse_diagflags & PDF_FILENAME)
-		puffs_flags |= PUFFS_FLAG_BUILDPATH;
-
 	if ((pu = puffs_init(pops, _PATH_PUFFS, name, ps, puffs_flags)) == NULL)
 		DERR(EX_OSERR, "puffs_init failed");
 
@@ -422,7 +418,7 @@
 	/*
 	 * Setup filesystem root
 	 */
-	pn_root = perfuse_new_pn(pu, NULL);
+	pn_root = perfuse_new_pn(pu, "", NULL);
 	PERFUSE_NODE_DATA(pn_root)->pnd_ino = FUSE_ROOT_ID; 
 	PERFUSE_NODE_DATA(pn_root)->pnd_parent = pn_root;
 	puffs_setroot(pu, pn_root);

Index: src/lib/libperfuse/perfuse_priv.h
diff -u src/lib/libperfuse/perfuse_priv.h:1.13 src/lib/libperfuse/perfuse_priv.h:1.14
--- src/lib/libperfuse/perfuse_priv.h:1.13	Wed Sep 29 08:01:10 2010
+++ src/lib/libperfuse/perfuse_priv.h	Sun Oct  3 05:46:47 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse_priv.h,v 1.13 2010/09/29 08:01:10 manu Exp $ */
+/*  $NetBSD: perfuse_priv.h,v 1.14 2010/10/03 05:46:47 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -65,8 +65,6 @@
 	perfuse_get_inpayload_fn ps_get_inpayload;
 	perfuse_get_outhdr_fn ps_get_outhdr;
 	perfuse_get_outpayload_fn ps_get_outpayload;
-	TAILQ_HEAD(, perfuse_node_data) ps_pnd;
-	int ps_pnd_count;
 };
 
 
@@ -120,6 +118,8 @@
 	time_t pnd_timestamp;
 	TAILQ_ENTRY(perfuse_node_data) pnd_next;
 	puffs_cookie_t pnd_pn;
+	char pnd_name[MAXPATHLEN];	/* node name */
+	TAILQ_HEAD(,perfuse_node_data) pnd_children;
 };
 
 #define PERFUSE_NODE_DATA(opc)	\
@@ -140,13 +140,14 @@
 
 __BEGIN_DECLS
 
-struct puffs_node *perfuse_new_pn(struct puffs_usermount *, 
+struct puffs_node *perfuse_new_pn(struct puffs_usermount *, const char *,
     struct puffs_node *);
 void perfuse_destroy_pn(struct puffs_usermount *, struct puffs_node *);
 void perfuse_new_fh(puffs_cookie_t, uint64_t, int);
 void perfuse_destroy_fh(puffs_cookie_t, uint64_t);
 uint64_t perfuse_get_fh(puffs_cookie_t, int);
 uint64_t perfuse_next_unique(struct puffs_usermount *);
+char *perfuse_node_path(puffs_cookie_t);
 int perfuse_node_close_common(struct puffs_usermount *, puffs_cookie_t, int);
 
 char *perfuse_fs_mount(int, ssize_t);

Index: src/lib/libperfuse/subr.c
diff -u src/lib/libperfuse/subr.c:1.7 src/lib/libperfuse/subr.c:1.8
--- src/lib/libperfuse/subr.c:1.7	Wed Sep 29 08:01:10 2010
+++ src/lib/libperfuse/subr.c	Sun Oct  3 05:46:47 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: subr.c,v 1.7 2010/09/29 08:01:10 manu Exp $ */
+/*  $NetBSD: subr.c,v 1.8 2010/10/03 05:46:47 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -36,9 +36,12 @@
 
 #include "perfuse_priv.h"
 
+static size_t node_path(puffs_cookie_t, char *, size_t);
+
 struct puffs_node *
-perfuse_new_pn(pu, parent)
+perfuse_new_pn(pu, name, parent)
 	struct puffs_usermount *pu;
+	const char *name;
 	struct puffs_node *parent;
 {
 	struct perfuse_state *ps;
@@ -61,13 +64,18 @@
 	pnd->pnd_parent = parent;
 	pnd->pnd_timestamp = time(NULL);
 	pnd->pnd_pn = (puffs_cookie_t)pn;
+	(void)strlcpy(pnd->pnd_name, name, MAXPATHLEN);
 	TAILQ_INIT(&pnd->pnd_pcq);
+	TAILQ_INIT(&pnd->pnd_children);
+
+	if (parent != NULL) {
+		struct perfuse_node_data *parent_pnd;
 
-	TAILQ_INSERT_TAIL(&ps->ps_pnd, pnd, pnd_next);
-	ps->ps_pnd_count++;
+		parent_pnd = PERFUSE_NODE_DATA(parent);
+		TAILQ_INSERT_TAIL(&parent_pnd->pnd_children, pnd, pnd_next);
 
-	if (parent != NULL)
-		PERFUSE_NODE_DATA(parent)->pnd_childcount++;
+		parent_pnd->pnd_childcount++;
+	}
 
 	return pn;
 }
@@ -83,8 +91,12 @@
 	ps = puffs_getspecific(pu);
 	pnd = PERFUSE_NODE_DATA(pn);
 
-	TAILQ_REMOVE(&ps->ps_pnd, pnd, pnd_next);
-	ps->ps_pnd_count--;
+	if (pnd->pnd_parent != NULL) {
+		struct perfuse_node_data *parent_pnd;
+
+		parent_pnd = PERFUSE_NODE_DATA(pnd->pnd_parent);
+		TAILQ_REMOVE(&parent_pnd->pnd_children, pnd, pnd_next);
+	}
 
 	if ((pnd = puffs_pn_getpriv(pn)) != NULL) {
 		if (pnd->pnd_parent != NULL)
@@ -197,3 +209,34 @@
 	return FUSE_UNKNOWN_FH;
 }
 
+static size_t
+node_path(opc, buf, buflen)
+	puffs_cookie_t opc;
+	char *buf;
+	size_t buflen;
+{
+	struct perfuse_node_data *pnd;
+	size_t written;
+	
+	pnd = PERFUSE_NODE_DATA(opc);
+	if (pnd->pnd_parent == opc)
+		return 0;
+
+	written = node_path(pnd->pnd_parent, buf, buflen);
+	buf += written;
+	buflen -= written;
+	
+	return written + snprintf(buf, buflen, "/%s", pnd->pnd_name);
+}
+
+char *
+perfuse_node_path(opc)
+	puffs_cookie_t opc;
+{
+	static char buf[MAXPATHLEN + 1];
+
+	if (node_path(opc, buf, sizeof(buf)) == 0)
+		sprintf(buf, "/");
+
+	return buf;
+}

Reply via email to