Patchwork [BUG:1756,2/2] nfs3: Fresh inode lookup on failed revalidation

login
register
Submitter Shehjar Tikoo
Date 2010-11-25 05:47:08
Message ID <1290664028-11580-2-git-send-email-shehjart@gluster.com>
Download mbox | patch
Permalink /patch/5776/
State Accepted
Headers show

Comments

Shehjar Tikoo - 2010-11-25 05:47:08
From: Shehjar Tikoo <shehjart@gluster.com>

Brings in changes that were earlier introduced in commit:
f5afcc47f9f00472d6c2b3f48127e02332cd457a

but reverted because the patch was buggy and caused a seg-fault
due to extra inode_unrefs.

It fixes that extra inode_unref and cleans up the revalidation logic.

Signed-off-by: Shehjar Tikoo <shehjart@gluster.com>
---
 xlators/nfs/server/src/nfs3.c |   42 ++++++++++++++++++++++++++++++++++++++++-
 xlators/nfs/server/src/nfs3.h |    6 +++++
 2 files changed, 47 insertions(+), 1 deletions(-)

Patch

diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c
index ce59275..73293ed 100644
--- a/xlators/nfs/server/src/nfs3.c
+++ b/xlators/nfs/server/src/nfs3.c
@@ -1013,6 +1013,39 @@  nfs3_lookup_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *newfh,
                                      (nfs3_serializer)xdr_serialize_lookup3res);
 }
 
+int
+nfs3_lookup_resume (void *carg);
+
+
+int
+nfs3_fresh_lookup (nfs3_call_state_t *cs)
+{
+        int     ret = -EFAULT;
+        char    *oldresolventry = NULL;
+
+        if (!cs)
+                return -1;
+
+        gf_log (GF_NFS3, GF_LOG_DEBUG, "inode needs fresh lookup");
+        inode_unlink (cs->resolvedloc.inode, cs->resolvedloc.parent,
+                      cs->resolventry);
+        inode_unref (cs->resolvedloc.inode);
+        nfs_loc_wipe (&cs->resolvedloc);
+
+        /* Store pointer to currently allocated resolventry because it gets over
+         * written in fh_resolve_and_resume.
+         */
+        oldresolventry = cs->resolventry;
+        cs->lookuptype = GF_NFS3_FRESH;
+        ret = nfs3_fh_resolve_and_resume (cs, &cs->resolvefh, cs->resolventry,
+                                          nfs3_lookup_resume);
+        /* Allocated in the previous call to fh_resolve_and_resume using the
+         * same call_state.
+         */
+        GF_FREE (oldresolventry);
+
+        return ret;
+}
 
 int
 nfs3svc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
@@ -1032,11 +1065,17 @@  nfs3svc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
         nfs3_fh_build_child_fh (&cs->parent, buf, &newfh);
 
 xmit_res:
+        /* Only send fresh lookup if it was a revalidate that failed. */
+        if ((op_ret ==  -1) && (nfs3_is_revalidate_lookup (cs))) {
+                op_ret = nfs3_fresh_lookup (cs);
+                goto out;
+        }
+
         nfs3_log_newfh_res (nfs_rpcsvc_request_xid (cs->req), "LOOKUP", status,
                             op_errno, &newfh);
         nfs3_lookup_reply (cs->req, status, &newfh, buf, postparent);
         nfs3_call_state_wipe (cs);
-
+out:
         return 0;
 }
 
@@ -1213,6 +1252,7 @@  nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name)
         nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
         nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
 
+        cs->lookuptype = GF_NFS3_REVALIDATE;
         if (!nfs3_is_parentdir_entry (name))
                 ret = nfs3_fh_resolve_and_resume (cs, fh, name,
                                                   nfs3_lookup_resume);
diff --git a/xlators/nfs/server/src/nfs3.h b/xlators/nfs/server/src/nfs3.h
index a43fdc4..be57080 100644
--- a/xlators/nfs/server/src/nfs3.h
+++ b/xlators/nfs/server/src/nfs3.h
@@ -134,6 +134,10 @@  struct nfs3_state {
         int                     fdcount;
 };
 
+typedef enum nfs3_lookup_type {
+        GF_NFS3_REVALIDATE = 1,
+        GF_NFS3_FRESH,
+} nfs3_lookup_type_t;
 
 typedef int (*nfs3_resume_fn_t) (void *cs);
 /* Structure used to communicate state between a fop and its callback.
@@ -197,8 +201,10 @@  struct nfs3_local {
         int                     hashidx;
         fd_t                    *resolve_dir_fd;
         char                    *resolventry;
+        nfs3_lookup_type_t      lookuptype;
 };
 
+#define nfs3_is_revalidate_lookup(cst) ((cst)->lookuptype == GF_NFS3_REVALIDATE)
 typedef struct nfs3_local nfs3_call_state_t;
 
 /* Queue of ops waiting for open fop to return. */