Patchwork [BUG:1397,03/12] nfs3: Unref dir fd once usage ends in hard fh resolution

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

Comments

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

There are three conditions when a dir fd_t needs to be unrefed
when:

a. the inode being searched is found as the candidate entry,
b. we have exhausted all the entries in the current dir,
c. we decide to step into a child directory because of a hash
match.

This decision is made in nfs3_fh_resolve_check_response.

Signed-off-by: Shehjar Tikoo <shehjart@gluster.com>
---
 xlators/nfs/server/src/nfs3-helpers.c |   32 +++++++++++++++++++++++++++++---
 1 files changed, 29 insertions(+), 3 deletions(-)

Patch

diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c
index dae2d6a..35dd0ae 100644
--- a/xlators/nfs/server/src/nfs3-helpers.c
+++ b/xlators/nfs/server/src/nfs3-helpers.c
@@ -2797,6 +2797,23 @@  out:
 }
 
 
+/*
+ * Called in a recursive code path, so if another
+ * directory was opened in an earlier call during fh resolution, we must unref
+ * through this reference before opening another fd_t.
+ */
+#define nfs3_fh_resolve_close_cwd(cst)                                  \
+        do {                                                            \
+                if ((cst)->resolve_dir_fd) {                            \
+                        gf_log (GF_NFS3, GF_LOG_TRACE, "resolve fd "    \
+                                "unrefing: 0x%lx, ref: %d",             \
+                                (long)(cst)->resolve_dir_fd,            \
+                                (cst)->resolve_dir_fd->refcount);       \
+                                fd_unref ((cst)->resolve_dir_fd);       \
+                }                                                       \
+        } while (0)                                                     \
+
+
 int
 nfs3_fh_resolve_check_response (nfs3_call_state_t *cs, gf_dirent_t *candidate,
                                 int response, off_t last_offt)
@@ -2812,16 +2829,25 @@  nfs3_fh_resolve_check_response (nfs3_call_state_t *cs, gf_dirent_t *candidate,
         dirino = cs->resolvedloc.inode->ino;
         dirgen = cs->resolvedloc.inode->generation;
 
-        if (response == GF_NFS3_FHRESOLVE_DIRFOUND)
+        switch (response) {
+
+        case GF_NFS3_FHRESOLVE_DIRFOUND:
+                nfs3_fh_resolve_close_cwd (cs);
                 nfs3_fh_resolve_dir_hard (cs, dirino, dirgen,
                                           candidate->d_name);
-        else if (response == GF_NFS3_FHRESOLVE_FOUND)
+                break;
+
+        case GF_NFS3_FHRESOLVE_FOUND:
+                nfs3_fh_resolve_close_cwd (cs);
                 nfs3_fh_resolve_found (cs, candidate);
-        else if (response == GF_NFS3_FHRESOLVE_NOTFOUND) {
+                break;
+
+        case GF_NFS3_FHRESOLVE_NOTFOUND:
                 nfs_user_root_create (&nfu);
                 nfs_readdirp (cs->nfsx, cs->vol, &nfu, cs->resolve_dir_fd,
                               GF_NFS3_DTPREF, last_offt,
                               nfs3_fh_resolve_readdir_cbk, cs);
+                break;
         }
 
         return 0;