Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libperfuse - Fix the confusion between fileno (opaque FU...



details:   https://anonhg.NetBSD.org/src/rev/05eea3ad8a1f
branches:  trunk
changeset: 770709:05eea3ad8a1f
user:      manu <manu%NetBSD.org@localhost>
date:      Sun Oct 30 05:11:37 2011 +0000

description:
- Fix the confusion between fileno (opaque FUSE reference) and inode
  numbers. fileno must be used when exchanging FUSE messages.
- Do not use kernel name cache anymore, as it caused modification from
  other machines to be invisible.
- Honour name and attribute cache directive from FUSE filesystem

diffstat:

 lib/libperfuse/ops.c          |  311 +++++++++++++++++++++++++++++------------
 lib/libperfuse/perfuse.c      |   14 +-
 lib/libperfuse/perfuse_if.h   |    5 +-
 lib/libperfuse/perfuse_priv.h |    6 +-
 lib/libperfuse/subr.c         |    4 +-
 5 files changed, 233 insertions(+), 107 deletions(-)

diffs (truncated from 750 to 300 lines):

diff -r 7eca6a009ece -r 05eea3ad8a1f lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c      Sun Oct 30 01:57:40 2011 +0000
+++ b/lib/libperfuse/ops.c      Sun Oct 30 05:11:37 2011 +0000
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.42 2011/09/10 10:06:10 tron Exp $ */
+/*  $NetBSD: ops.c,v 1.43 2011/10/30 05:11:37 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -44,6 +44,10 @@
 
 extern int perfuse_diagflags;
 
+static void set_expire(puffs_cookie_t, struct fuse_entry_out *, 
+   struct fuse_attr_out *);
+static int attr_expired(puffs_cookie_t);
+static int entry_expired(puffs_cookie_t);
 static int xchg_msg(struct puffs_usermount *, puffs_cookie_t, 
     perfuse_msg_t *, size_t, enum perfuse_xchg_pb_reply); 
 static int mode_access(puffs_cookie_t, const struct puffs_cred *, mode_t);
@@ -153,8 +157,8 @@
 
 #ifdef PERFUSE_DEBUG
        if (perfuse_diagflags & PDF_FH)
-               DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n",
-                        __func__, (void *)opc, pnd->pnd_ino, fri->fh);
+               DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
+                        __func__, (void *)opc, pnd->pnd_nodeid, fri->fh);
 #endif
 
        if ((error = xchg_msg(pu, opc, pm,
@@ -193,8 +197,9 @@
 
 #ifdef PERFUSE_DEBUG
        if ((perfuse_diagflags & PDF_FILENAME) && (opc != 0))
-               DPRINTF("file = \"%s\" flags = 0x%x\n", 
-                       perfuse_node_path(opc),
+               DPRINTF("file = \"%s\", ino = %"PRIu64" flags = 0x%x\n", 
+                       perfuse_node_path(opc), 
+                       ((struct puffs_node *)opc)->pn_va.va_fileid,
                        PERFUSE_NODE_DATA(opc)->pnd_flags);
 #endif
        if (pnd)
@@ -309,6 +314,74 @@
        return;
 }
 
+static void 
+set_expire(opc, feo, fao)
+       puffs_cookie_t opc;
+       struct fuse_entry_out *feo;
+       struct fuse_attr_out *fao;
+{
+       struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
+       struct timespec entry_ts;
+       struct timespec attr_ts;
+       struct timespec now;
+
+       if ((feo == NULL) && (fao == NULL))
+               DERRX(EX_SOFTWARE, "%s: feo and fao NULL", __func__);
+
+       if ((feo != NULL) && (fao != NULL))
+               DERRX(EX_SOFTWARE, "%s: feo and fao != NULL", __func__);
+
+       if (clock_gettime(CLOCK_REALTIME, &now) != 0)
+               DERR(EX_OSERR, "clock_gettime failed");
+
+       if (feo != NULL) {
+               entry_ts.tv_sec = (time_t)feo->entry_valid;
+               entry_ts.tv_nsec = (long)feo->entry_valid_nsec;
+
+               timespecadd(&now, &entry_ts, &pnd->pnd_entry_expire);
+
+               attr_ts.tv_sec = (time_t)feo->attr_valid;
+               attr_ts.tv_nsec = (long)feo->attr_valid_nsec;
+
+               timespecadd(&now, &attr_ts, &pnd->pnd_attr_expire);
+       } 
+
+       if (fao != NULL) {
+               attr_ts.tv_sec = (time_t)fao->attr_valid;
+               attr_ts.tv_nsec = (long)fao->attr_valid_nsec;
+
+               timespecadd(&now, &attr_ts, &pnd->pnd_attr_expire);
+       } 
+
+       return;
+}
+
+static int
+attr_expired(opc)
+       puffs_cookie_t opc;
+{
+       struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
+       struct timespec now;
+
+       if (clock_gettime(CLOCK_REALTIME, &now) != 0)
+               DERR(EX_OSERR, "clock_gettime failed");
+
+       return timespeccmp(&pnd->pnd_attr_expire, &now, <);
+}
+
+static int
+entry_expired(opc)
+       puffs_cookie_t opc;
+{
+       struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
+       struct timespec now;
+
+       if (clock_gettime(CLOCK_REALTIME, &now) != 0)
+               DERR(EX_OSERR, "clock_gettime failed");
+
+       return timespeccmp(&pnd->pnd_entry_expire, &now, <);
+}
+
 
 /* 
  * Lookup name in directory opc
@@ -323,12 +396,8 @@
        size_t namelen;
        struct puffs_node **pnp;
 {
-       char *path;
-       struct puffs_node *dpn = (struct puffs_node *)opc;
-       int error;
-
        /*
-        *  is easy as we already know it
+        * "dot" is easy as we already know it
         */
        if (strncmp(name, ".", namelen) == 0) {
                *pnp = (struct puffs_node *)opc;
@@ -336,22 +405,14 @@
        }
 
        /*
-        * For .. we just forget the name part
+        * "dotdot" is also known
         */
-       if (strncmp(name, "..", namelen) == 0)
-               namelen = 0;
-
-       namelen = PNPLEN(dpn) + 1 + namelen + 1;
-       if ((path = malloc(namelen)) == NULL)
-               DERR(EX_OSERR, "%s: malloc failed", __func__);
-       (void)snprintf(path, namelen, "%s/%s", 
-                      perfuse_node_path((puffs_cookie_t)dpn), name);
-
-       error = node_lookup_common(pu, opc, path, NULL, pnp);
-       
-       free(path);
-
-       return error;
+       if (strncmp(name, "..", namelen) == 0) {
+               *pnp = PERFUSE_NODE_DATA(opc)->pnd_parent;
+               return 0;
+       }
+
+       return node_lookup_common(pu, opc, name, NULL, pnp);
 }
 
 static int
@@ -363,13 +424,16 @@
        struct puffs_node **pnp;
 {
        struct perfuse_state *ps;
-       struct perfuse_node_data *pnd;
+       struct perfuse_node_data *oldpnd;
        perfuse_msg_t *pm;
        struct fuse_entry_out *feo;
        struct puffs_node *pn;
        size_t len;
        int error;
 
+       if (pnp == NULL)
+               DERRX(EX_SOFTWARE, "pnp must be != NULL");
+
        ps = puffs_getspecific(pu);
 
 #ifdef PERFUSE_DEBUG
@@ -380,24 +444,27 @@
        /*
         * 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))
+       TAILQ_FOREACH(oldpnd, &PERFUSE_NODE_DATA(opc)->pnd_children, pnd_next) {
+               if ((oldpnd->pnd_flags & PND_REMOVED) ||
+                   (strcmp(oldpnd->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",
+                               "cookie = %p, nodeid = 0x%"PRIx64" for \"%s\"\n",
                                __func__, (void *)opc, perfuse_node_path(opc), 
-                               (void *)pnd->pnd_pn, pnd->pnd_ino, path);
+                               (void *)oldpnd->pnd_pn, oldpnd->pnd_nodeid,     
+                               path);
 #endif
+               break;
+       }
+
+       /*
+        * Check for cached name
+        */
+       if ((oldpnd != NULL) && !entry_expired(oldpnd->pnd_pn)) {
+               *pnp = oldpnd->pnd_pn;
                return 0;
        }
 
@@ -406,26 +473,64 @@
        pm = ps->ps_new_msg(pu, opc, FUSE_LOOKUP, len, pcr);
        (void)strlcpy(_GET_INPAYLOAD(ps, pm, char *), path, len);
 
-       if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0)
+       error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply);
+
+       switch (error) {
+       case 0:
+               break;
+       case ENOENT:
+               if (oldpnd != NULL) {
+                       oldpnd->pnd_flags |= PND_REMOVED;
+#ifdef PERFUSE_DEBUG
+                       if (perfuse_diagflags & PDF_FILENAME)
+                               DPRINTF("%s: opc = %p nodeid = 0x%"PRIx64" "
+                                       "file = \"%s\" removed\n", __func__, 
+                                       oldpnd->pnd_pn, oldpnd->pnd_nodeid,
+                                       oldpnd->pnd_name);
+#endif
+               }
+               /* FALLTHROUGH */
+       default:
                goto out;
+               /* NOTREACHED */
+               break;
+       }
 
        feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
 
+       if (oldpnd != NULL) {
+               if (oldpnd->pnd_nodeid == feo->nodeid) {
+                       oldpnd->pnd_nlookup++;
+                       *pnp = oldpnd->pnd_pn;
+                       goto out;
+               } else {
+                       oldpnd->pnd_flags |= PND_REMOVED;
+#ifdef PERFUSE_DEBUG
+                       if (perfuse_diagflags & PDF_FILENAME)
+                               DPRINTF("%s: opc = %p nodeid = 0x%"PRIx64" "
+                                       "file = \"%s\" replaced\n", __func__, 
+                                       oldpnd->pnd_pn, oldpnd->pnd_nodeid,
+                                       oldpnd->pnd_name);
+#endif
+               }
+       }
+
        pn = perfuse_new_pn(pu, path, opc);
-       PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid;
+       PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
 
        fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
        pn->pn_va.va_gen = (u_long)(feo->generation);
-
-       if (pnp != NULL)
-               *pnp = pn;
+       set_expire((puffs_cookie_t)pn, feo, NULL);
+
+       *pnp = pn;
 
 #ifdef PERFUSE_DEBUG
        if (perfuse_diagflags & PDF_FILENAME)
-               DPRINTF("%s: opc = %p, looked up opc = %p, ino = %"PRId64" "
-                       "file = \"%s\"\n", __func__, (void *)opc, pn, 
-                       feo->nodeid, path);
+               DPRINTF("%s: opc = %p, looked up opc = %p, "
+                       "nodeid = 0x%"PRIx64" file = \"%s\"\n", __func__, 
+                       (void *)opc, pn, feo->nodeid, path);
 #endif
+       
 out: 
        ps->ps_destroy_msg(pm);
 
@@ -458,21 +563,22 @@
                goto out;
 
        feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
-       if (feo->nodeid == PERFUSE_UNKNOWN_INO)
-               DERRX(EX_SOFTWARE, "%s: no ino", __func__);
+       if (feo->nodeid == PERFUSE_UNKNOWN_NODEID)
+               DERRX(EX_SOFTWARE, "%s: no nodeid", __func__);



Home | Main Index | Thread Index | Old Index