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