diff options
| -rw-r--r-- | xlators/nfs/server/src/nfs3-helpers.c | 47 | 
1 files changed, 40 insertions, 7 deletions
diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c index 653b6ecaf5c..c10954ab996 100644 --- a/xlators/nfs/server/src/nfs3-helpers.c +++ b/xlators/nfs/server/src/nfs3-helpers.c @@ -2753,6 +2753,42 @@ err:  } +/* Validate the depth of the dir such that we do not end up opening and + * reading directories beyond those that are needed for resolving the file + * handle. + * Returns 1 if fh resolution can continue, 0 otherwise. + */ +int +nfs3_fh_resolve_validate_dirdepth (nfs3_call_state_t *cs) +{ +        int     ret = 1; + +        if (!cs) +                return 0; + +        /* This condition will generally never be hit because the +         * hash-matching scheme will prevent us from going into a +         * directory that is not part of the hash-array. +         */ +        if (nfs3_fh_hash_index_is_beyond (&cs->resolvefh, cs->hashidx)) { +                gf_log (GF_NFS3, GF_LOG_TRACE, "Hash index is beyond: idx %d," +                        " fh idx: %d", cs->hashidx, cs->resolvefh.hashcount); +                ret = 0; +                goto out; +        } + +        if (cs->hashidx >= GF_NFSFH_MAXHASHES) { +                gf_log (GF_NFS3, GF_LOG_TRACE, "Hash index beyond max hashes:" +                        " hashidx %d, max: %d", cs->hashidx, +                        GF_NFSFH_MAXHASHES); +                ret = 0; +                goto out; +        } + +out: +        return ret; +} +  int  nfs3_fh_resolve_dir_hard (nfs3_call_state_t *cs, uint64_t ino, uint64_t gen, @@ -2766,9 +2802,8 @@ nfs3_fh_resolve_dir_hard (nfs3_call_state_t *cs, uint64_t ino, uint64_t gen,          cs->hashidx++;          nfs_loc_wipe (&cs->resolvedloc); -        if (nfs3_fh_hash_index_is_beyond (&cs->resolvefh, cs->hashidx)) { -                gf_log (GF_NFS3, GF_LOG_TRACE, "Hash index is beyond: idx %d, " -                        " fh idx: %d", cs->hashidx, cs->resolvefh.hashcount); +        if (!nfs3_fh_resolve_validate_dirdepth (cs)) { +                gf_log (GF_NFS3, GF_LOG_TRACE, "Dir depth validation failed");                  nfs3_call_resume_estale (cs);                  ret = 0;                  goto out; @@ -2920,10 +2955,8 @@ nfs3_fh_resolve_inode_hard (nfs3_call_state_t *cs)          cs->hashidx++;          nfs_loc_wipe (&cs->resolvedloc); -        if (nfs3_fh_hash_index_is_beyond (&cs->resolvefh, cs->hashidx)) { -                gf_log (GF_NFS3, GF_LOG_TRACE, "Hash index is beyond: idx %d, " -                        " fh hashcount: %d", cs->hashidx, -                        cs->resolvefh.hashcount); +        if (!nfs3_fh_resolve_validate_dirdepth (cs)) { +                gf_log (GF_NFS3, GF_LOG_TRACE, "Dir depth validation failed");                  nfs3_call_resume_estale (cs);                  ret = 0;                  goto out;  | 
