summaryrefslogtreecommitdiffstats
path: root/xlators/nfs
diff options
context:
space:
mode:
authorShehjar Tikoo <shehjart@gluster.com>2010-11-25 00:17:08 +0000
committerAnand V. Avati <avati@dev.gluster.com>2010-11-25 06:35:19 -0800
commit26a8202550593232f941cd2251cfbeb304991808 (patch)
treefb9f5a1d4a2977bea39edb76ddb98bd8e3c74101 /xlators/nfs
parentac5e34ec840889bc3eaf07d2f7091432ff698fe2 (diff)
nfs3: Fresh inode lookup on failed revalidation
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> Signed-off-by: Anand V. Avati <avati@dev.gluster.com> BUG: 1756 (NFS must revalidate inode on first ESTALE on lookup) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1756
Diffstat (limited to 'xlators/nfs')
-rw-r--r--xlators/nfs/server/src/nfs3.c42
-rw-r--r--xlators/nfs/server/src/nfs3.h6
2 files changed, 47 insertions, 1 deletions
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c
index ce5927520..73293ed9f 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 a43fdc4af..be570803a 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. */