diff options
author | Shehjar Tikoo <shehjart@gluster.com> | 2010-08-31 06:50:28 +0000 |
---|---|---|
committer | Vijay Bellur <vijay@dev.gluster.com> | 2010-08-31 07:44:21 -0700 |
commit | 217fb3e2acbb221668ad5d54ef4067a2bac47c4a (patch) | |
tree | 0509f4e58839d6af059c5aaf4279e3454fb4f83a | |
parent | e1422d796fefd6a3ae599507e71efdb922eede02 (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.c | 32 |
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; |