Patchwork [BUG:1756,4/4,v2] nfs: re-implement logic to perform fresh lookups when lookup revalidates fail

login
register
Submitter Anand Avati
Date 2010-10-12 06:52:28
Message ID <20101012065228.GA22035@dev.gluster.com>
Download mbox | patch
Permalink /patch/5461/
State Accepted
Headers show

Comments

Anand Avati - 2010-10-12 06:52:28
- implement lookup to pass via inode layer so that looked up entries make it to inode cache
- implement lookup revalidation failure check in the fop layer

Signed-off-by: Anand V. Avati <avati@blackhole.gluster.com>
---
 xlators/nfs/server/src/nfs-fops.c     |   52 ++++++++++++++++++++++++------
 xlators/nfs/server/src/nfs-fops.h     |    6 +++
 xlators/nfs/server/src/nfs-generics.c |    3 +-
 xlators/nfs/server/src/nfs-inodes.c   |   56 +++++++++++++++++++++++++++++++++
 xlators/nfs/server/src/nfs-inodes.h   |    2 +-
 5 files changed, 107 insertions(+), 12 deletions(-)

Patch

diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c
index 4928deb..1c5b4f5 100644
--- a/xlators/nfs/server/src/nfs-fops.c
+++ b/xlators/nfs/server/src/nfs-fops.c
@@ -74,6 +74,8 @@  nfs_fop_local_wipe (xlator_t *nfsx, struct nfs_fop_local *l)
         if (l->dictgfid)
                 dict_unref (l->dictgfid);
 
+        loc_wipe (&l->revalidate_loc);
+
         mem_put (nfs->foppool, l);
 
         return;
@@ -226,16 +228,21 @@  err:
         } while (0)                                                            \
 
 dict_t *
-nfs_gfid_dict ()
+nfs_gfid_dict (inode_t *inode)
 {
         uuid_t  newgfid = {0, };
         char    *dyngfid = NULL;
         dict_t  *dictgfid = NULL;
         int     ret = -1;
+        uuid_t  rootgfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
 
         dyngfid = GF_CALLOC (1, sizeof (uuid_t), gf_common_mt_char);
         uuid_generate (newgfid);
-        memcpy (dyngfid, newgfid, sizeof (uuid_t));
+
+        if (uuid_compare (inode->gfid, rootgfid) == 0)
+                memcpy (dyngfid, rootgfid, sizeof (uuid_t));
+        else
+                memcpy (dyngfid, newgfid, sizeof (uuid_t));
 
         dictgfid = dict_new ();
         if (!dictgfid) {
@@ -253,10 +260,10 @@  out:
         return dictgfid;
 }
 
-#define nfs_fop_gfid_setup(nflcl, retval, erlbl)                        \
+#define nfs_fop_gfid_setup(nflcl, inode, retval, erlbl)                 \
         do {                                                            \
                 if (nflcl) {                                            \
-                        (nflcl)->dictgfid = nfs_gfid_dict ();           \
+                        (nflcl)->dictgfid = nfs_gfid_dict (inode);      \
                                                                         \
                         if (!((nflcl)->dictgfid)) {                     \
                                 retval = -EFAULT;                       \
@@ -300,9 +307,29 @@  nfs_fop_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
 {
         struct nfs_fop_local    *local = NULL;
         fop_lookup_cbk_t        progcbk;
+        inode_table_t           *itable = NULL;
+        xlator_t                *xl = NULL;
 
-        nfl_to_prog_data (local, progcbk, frame);
+        xl = cookie;
+
+        local = frame->local;
         nfs_fop_restore_root_ino (local, buf, NULL, NULL, postparent);
+
+        if (op_ret == -1 && local->is_revalidate == 1) {
+                /* perform a fresh lookup if revalidate fails */
+                itable = local->revalidate_loc.inode->table;
+                inode_unref (local->revalidate_loc.inode);
+                local->revalidate_loc.inode = inode_new (itable);
+
+                local->is_revalidate = 2; /* prevent entering revalidate loops */
+
+                STACK_WIND_COOKIE (frame, nfs_fop_lookup_cbk, xl, xl,
+                                   xl->fops->lookup, &local->revalidate_loc,
+                                   local->dictgfid);
+                return 0;
+        }
+
+        nfl_to_prog_data (local, progcbk, frame);
         if (progcbk)
                 progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
                          xattr, postparent);
@@ -327,7 +354,12 @@  nfs_fop_lookup (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
         nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
         nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
         nfs_fop_save_root_ino (nfl, loc);
-        nfs_fop_gfid_setup (nfl, ret, err);
+        nfs_fop_gfid_setup (nfl, loc->inode, ret, err);
+
+        if (!uuid_is_null (loc->inode->gfid)) {
+                nfl->is_revalidate = 1;
+                loc_copy (&nfl->revalidate_loc, loc);
+        }
 
         STACK_WIND_COOKIE (frame, nfs_fop_lookup_cbk, xl, xl,
                            xl->fops->lookup, loc, nfl->dictgfid);
@@ -650,7 +682,7 @@  nfs_fop_create (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
         nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
         nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
         nfs_fop_save_root_ino (nfl, pathloc);
-        nfs_fop_gfid_setup (nfl, ret, err);
+        nfs_fop_gfid_setup (nfl, pathloc->inode, ret, err);
 
         STACK_WIND_COOKIE (frame, nfs_fop_create_cbk, xl, xl, xl->fops->create,
                            pathloc, flags, mode, fd, nfl->dictgfid);
@@ -748,7 +780,7 @@  nfs_fop_mkdir (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
         nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
         nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
         nfs_fop_save_root_ino (nfl, pathloc);
-        nfs_fop_gfid_setup (nfl, ret, err);
+        nfs_fop_gfid_setup (nfl, pathloc->inode, ret, err);
 
         STACK_WIND_COOKIE  (frame, nfs_fop_mkdir_cbk, xl, xl, xl->fops->mkdir,
                             pathloc, mode, nfl->dictgfid);
@@ -796,7 +828,7 @@  nfs_fop_symlink (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, char *target,
         nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
         nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
         nfs_fop_save_root_ino (nfl, pathloc);
-        nfs_fop_gfid_setup (nfl, ret, err);
+        nfs_fop_gfid_setup (nfl, pathloc->inode, ret, err);
 
         STACK_WIND_COOKIE  (frame, nfs_fop_symlink_cbk, xl, xl,
                             xl->fops->symlink, target, pathloc, nfl->dictgfid);
@@ -891,7 +923,7 @@  nfs_fop_mknod (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
         nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
         nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
         nfs_fop_save_root_ino (nfl, pathloc);
-        nfs_fop_gfid_setup (nfl, ret, err);
+        nfs_fop_gfid_setup (nfl, pathloc->inode, ret, err);
 
         STACK_WIND_COOKIE  (frame, nfs_fop_mknod_cbk, xl, xl, xl->fops->mknod,
                             pathloc, mode, dev, nfl->dictgfid);
diff --git a/xlators/nfs/server/src/nfs-fops.h b/xlators/nfs/server/src/nfs-fops.h
index d010db2..4feb916 100644
--- a/xlators/nfs/server/src/nfs-fops.h
+++ b/xlators/nfs/server/src/nfs-fops.h
@@ -100,6 +100,12 @@  struct nfs_fop_local {
         char            newpath[NFS_NAME_MAX];
         xlator_t        *nfsx;
         dict_t          *dictgfid;
+
+        /* Determine whether the call was a lookup revalidate in cases where
+         * lookup fails. Mangle the copied loc_t to perform a fresh lookup
+         */
+        int             is_revalidate;
+        loc_t           revalidate_loc;
 };
 
 extern struct nfs_fop_local *
diff --git a/xlators/nfs/server/src/nfs-generics.c b/xlators/nfs/server/src/nfs-generics.c
index 0ebba68..eb6dc58 100644
--- a/xlators/nfs/server/src/nfs-generics.c
+++ b/xlators/nfs/server/src/nfs-generics.c
@@ -83,7 +83,8 @@  nfs_lookup (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
         if ((!nfsx) || (!xl) || (!pathloc) || (!nfu))
                 return ret;
 
-        ret = nfs_fop_lookup (nfsx, xl, nfu, pathloc, cbk, local);
+        ret = nfs_inode_lookup (nfsx, xl, nfu, pathloc, cbk, local);
+
         return ret;
 }
 
diff --git a/xlators/nfs/server/src/nfs-inodes.c b/xlators/nfs/server/src/nfs-inodes.c
index cd33452..a69e1d7 100644
--- a/xlators/nfs/server/src/nfs-inodes.c
+++ b/xlators/nfs/server/src/nfs-inodes.c
@@ -336,6 +336,62 @@  err:
 
 
 int32_t
+nfs_inode_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+                      int32_t op_ret, int32_t op_errno, inode_t *inode,
+                      struct iatt *buf, dict_t *xattr,
+                      struct iatt *postparent)
+{
+        struct nfs_fop_local    *nfl = NULL;
+        fop_lookup_cbk_t         progcbk = NULL;
+        inode_t                 *linked_inode = NULL;
+        uuid_t                   rootgfid = {0, };
+
+        if (op_ret == -1)
+                goto do_not_link;
+
+        rootgfid[15] = 1;
+        if (uuid_compare (rootgfid, inode->gfid) == 0)
+                goto do_not_link;
+
+        nfl = frame->local;
+
+        linked_inode = inode_link (inode, nfl->newparent, nfl->path, buf);
+
+        if (linked_inode)
+                inode_unref (linked_inode);
+
+do_not_link:
+        inodes_nfl_to_prog_data (nfl, progcbk, frame);
+        if (progcbk)
+                progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
+                         xattr, postparent);
+        return 0;
+}
+
+
+int
+nfs_inode_lookup (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
+                  fop_lookup_cbk_t cbk, void *local)
+{
+        struct nfs_fop_local            *nfl = NULL;
+        int                             ret = -EFAULT;
+
+        if ((!nfsx) || (!xl) || (!loc) || (!nfu))
+                return -EFAULT;
+
+        nfs_fop_handle_local_init (NULL, nfsx, nfl, cbk, local, ret, err);
+        nfl_inodes_init (nfl, NULL, NULL, loc->parent, loc->name, NULL);
+        ret = nfs_fop_lookup (nfsx, xl, nfu, loc, nfs_inode_lookup_cbk, nfl);
+
+err:
+        if (ret < 0)
+                nfs_fop_local_wipe (xl, nfl);
+
+        return ret;
+}
+
+
+int32_t
 nfs_inode_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
                       int32_t op_ret, int32_t op_errno, struct iatt *preparent,
                       struct iatt *postparent)
diff --git a/xlators/nfs/server/src/nfs-inodes.h b/xlators/nfs/server/src/nfs-inodes.h
index ef79a11..a34a267 100644
--- a/xlators/nfs/server/src/nfs-inodes.h
+++ b/xlators/nfs/server/src/nfs-inodes.h
@@ -80,6 +80,6 @@  nfs_inode_mknod (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
                  mode_t mode, dev_t dev, fop_mknod_cbk_t cbk, void *local);
 
 extern int
-nfs_inode_lookup (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
+nfs_inode_lookup (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
                   fop_lookup_cbk_t cbk, void *local);
 #endif