summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShehjar Tikoo <shehjart@gluster.com>2010-08-31 06:50:28 +0000
committerVijay Bellur <vijay@dev.gluster.com>2010-08-31 07:44:21 -0700
commit217fb3e2acbb221668ad5d54ef4067a2bac47c4a (patch)
tree0509f4e58839d6af059c5aaf4279e3454fb4f83a
parente1422d796fefd6a3ae599507e71efdb922eede02 (diff)
nfs3: Unref dir fd once usage ends in hard fh resolution
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> Signed-off-by: Vijay Bellur <vijay@dev.gluster.com> BUG: 1397 (Cached dir fd_ts are a leakin') URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1397
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c
index dae2d6a61..35dd0ae02 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;