Patchwork [BUG:1378,06/12] nfs3: Return ESTALE when going beyond fh-hashcount or max-hashes

login
register
Submitter Shehjar Tikoo
Date 2010-08-31 12:20:31
Message ID <1283257237-18659-6-git-send-email-shehjart@gluster.com>
Download mbox | patch
Permalink /patch/4421/
State Accepted
Delegated to: Anand Avati
Headers show

Comments

Shehjar Tikoo - 2010-08-31 12:20:31
From: Shehjar Tikoo <shehjart@gluster.com>

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 <shehjart@gluster.com>
---
 xlators/nfs/server/src/nfs3-helpers.c |   47 ++++++++++++++++++++++++++++-----
 1 files changed, 40 insertions(+), 7 deletions(-)

Patch

diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c
index 653b6ec..c10954a 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;