diff options
| author | Shehjar Tikoo <shehjart@gluster.com> | 2010-11-25 00:17:08 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2010-11-25 06:35:19 -0800 | 
| commit | 26a8202550593232f941cd2251cfbeb304991808 (patch) | |
| tree | fb9f5a1d4a2977bea39edb76ddb98bd8e3c74101 /xlators/nfs/server/src | |
| parent | ac5e34ec840889bc3eaf07d2f7091432ff698fe2 (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/server/src')
| -rw-r--r-- | xlators/nfs/server/src/nfs3.c | 42 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3.h | 6 | 
2 files changed, 47 insertions, 1 deletions
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index ce59275202e..73293ed9fbe 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 a43fdc4af28..be570803a59 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. */  | 
