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

login
register
Submitter Anand Avati
Date 2010-10-11 12:13:35
Message ID <20101011121335.GA9924@dev.gluster.com>
Download mbox | patch
Permalink /patch/5431/
State Accepted
Headers show

Comments

Anand Avati - 2010-10-11 12:13:35
- 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     |   25 ++++++++++++++++
 xlators/nfs/server/src/nfs-fops.h     |    6 ++++
 xlators/nfs/server/src/nfs-generics.c |    3 +-
 xlators/nfs/server/src/nfs-inodes.c   |   50 +++++++++++++++++++++++++++++++++
 xlators/nfs/server/src/nfs-inodes.h   |    2 +-
 5 files changed, 84 insertions(+), 2 deletions(-)

Patch

diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c
index 4928deb..f748c1f 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;
@@ -300,9 +302,27 @@  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;
 
+        xl = cookie;
         nfl_to_prog_data (local, progcbk, frame);
         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;
+        }
+
         if (progcbk)
                 progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
                          xattr, postparent);
@@ -329,6 +349,11 @@  nfs_fop_lookup (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
         nfs_fop_save_root_ino (nfl, loc);
         nfs_fop_gfid_setup (nfl, 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);
 
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..7f42103 100644
--- a/xlators/nfs/server/src/nfs-inodes.c
+++ b/xlators/nfs/server/src/nfs-inodes.c
@@ -336,6 +336,56 @@  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;
+
+        if (op_ret == -1)
+                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