summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.c47
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;