Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libperfuse - Correctly handle rename whith overwritten d...
details: https://anonhg.NetBSD.org/src/rev/d9c47efa3ed0
branches: trunk
changeset: 757912:d9c47efa3ed0
user: manu <manu%NetBSD.org@localhost>
date: Sun Oct 03 05:46:47 2010 +0000
description:
- 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
diffstat:
lib/libperfuse/debug.c | 4 +-
lib/libperfuse/ops.c | 187 ++++++++++++++++++++++++++---------------
lib/libperfuse/perfuse.c | 8 +-
lib/libperfuse/perfuse_priv.h | 9 +-
lib/libperfuse/subr.c | 59 +++++++++++-
5 files changed, 176 insertions(+), 91 deletions(-)
diffs (truncated from 572 to 300 lines):
diff -r 4aefbb7519d9 -r d9c47efa3ed0 lib/libperfuse/debug.c
--- a/lib/libperfuse/debug.c Sat Oct 02 23:54:03 2010 +0000
+++ b/lib/libperfuse/debug.c Sun Oct 03 05:46:47 2010 +0000
@@ -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"
};
diff -r 4aefbb7519d9 -r d9c47efa3ed0 lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c Sat Oct 02 23:54:03 2010 +0000
+++ b/lib/libperfuse/ops.c Sun Oct 03 05:46:47 2010 +0000
@@ -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++;
-
- PERFUSE_NODE_DATA(src)->pnd_parent = targ_dir;
+ 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);
+
+ TAILQ_REMOVE(&srcdir_pnd->pnd_children, src_pnd, pnd_next);
+ TAILQ_INSERT_TAIL(&dstdir_pnd->pnd_children, src_pnd, pnd_next);
+
+ srcdir_pnd->pnd_childcount--;
+ dstdir_pnd->pnd_childcount++;
+
+ src_pnd->pnd_parent = targ_dir;
+
+ 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;
- PERFUSE_NODE_DATA(targ_dir)->pnd_flags |= PND_DIRTY;
-
- if ((struct puffs_node *)targ != NULL) {
- struct perfuse_node_data *targ_pnd;
- struct perfuse_node_data *src_pnd;
-
- /*
- * 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;
- }
+
+ if ((struct puffs_node *)targ != NULL)
+ PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED;
Home |
Main Index |
Thread Index |
Old Index