diff options
Diffstat (limited to 'xlators/nfs/server/src/nfs3.c')
| -rw-r--r-- | xlators/nfs/server/src/nfs3.c | 32 | 
1 files changed, 32 insertions, 0 deletions
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index 1c379997266..7c01d0301ba 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -32,6 +32,7 @@  #include "nfs3.h"  #include "mem-pool.h"  #include "logging.h" +#include "nfs-common.h"  #include "nfs-fops.h"  #include "nfs-inodes.h"  #include "nfs-generics.h" @@ -692,12 +693,21 @@ nfs3svc_getattr_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          cs = frame->local; +        /* +         * Somewhat counter-intuitively, we don't need to look for sh-failed +         * here. Failing this getattr will generate a new lookup from the +         * client, and nfs_fop_lookup_cbk will detect any self-heal failures. +         */ +          if (op_ret == -1) {                  gf_log (GF_NFS, GF_LOG_WARNING,                          "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),                          cs->resolvedloc.path, strerror (op_errno));                  status = nfs3_errno_to_nfsstat3 (op_errno);          } +        else { +                nfs_fix_generation(this,inode); +        }          nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_GETATTR,                               status, op_errno); @@ -743,6 +753,9 @@ nfs3_getattr_resume (void *carg)          int                             ret = -EFAULT;          nfs_user_t                      nfu = {0, };          nfs3_call_state_t               *cs = NULL; +        uint64_t                         raw_ctx = 0; +        struct nfs_inode_ctx            *ictx = NULL; +        struct nfs_state                *priv = NULL;          if (!carg)                  return ret; @@ -769,9 +782,28 @@ nfs3_getattr_resume (void *carg)  		goto nfs3err;  	} +        /* +         * If brick state changed, we need to force a proper lookup cycle (as +         * would happen in native protocol) to do self-heal checks. We detect +         * this by comparing the generation number for the last successful +         * creation/lookup on the inode to the current number, so inodes that +         * haven't been validated since the state change are affected. +         */ +        if (inode_ctx_get(cs->resolvedloc.inode,cs->nfsx,&raw_ctx) == 0) { +                ictx = (struct nfs_inode_ctx *)raw_ctx; +                priv = cs->nfsx->private; +                if (ictx->generation != priv->generation) { +                        ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, +                                          &cs->resolvedloc, +                                          nfs3svc_getattr_lookup_cbk, cs); +                        goto check_err; +                } +        } +          ret = nfs_stat (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,                          nfs3svc_getattr_stat_cbk, cs); +check_err:          if (ret < 0) {                  gf_log (GF_NFS3, GF_LOG_ERROR, "Stat fop failed: %s: %s",                          cs->oploc.path, strerror (-ret));  | 
