From 83e7543be0bf8941cb6383c7e23b9bc0f54e67ba Mon Sep 17 00:00:00 2001 From: Shehjar Tikoo Date: Tue, 31 Aug 2010 06:50:31 +0000 Subject: nfs3: Return ESTALE when going beyond fh-hashcount or max-hashes During fh resolution, if we go beyond the max hashes support by gnfs or if we go beyond the dir depth specified in the filehandle, then return ESTALE. Signed-off-by: Shehjar Tikoo Signed-off-by: Vijay Bellur BUG: 1378 (Deep directory creation crashes gnfs) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1378 --- xlators/nfs/server/src/nfs3-helpers.c | 47 +++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-) (limited to 'xlators') diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c index 653b6ecaf..c10954ab9 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; -- cgit