diff options
-rw-r--r-- | libglusterfs/src/fd.c | 24 | ||||
-rw-r--r-- | libglusterfs/src/fd.h | 2 | ||||
-rw-r--r-- | xlators/nfs/server/src/nfs3.c | 18 |
3 files changed, 38 insertions, 6 deletions
diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index 9e91cdb8341..5e25b59cf91 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -499,6 +499,30 @@ fd_bind (fd_t *fd) return fd; } + +void +fd_unref_unbind (fd_t *fd) +{ + assert (fd->refcount); + + LOCK (&fd->inode->lock); + { + --fd->refcount; + /* Better know what you're doing with this function + * because it does not do what fd_destroy does when + * refcount goes to 0. + * Make sure you only call this when you know there are + * pending refs on the fd. + */ + assert (fd->refcount); + list_del_init (&fd->inode_list); + } + UNLOCK (&fd->inode->lock); + + return; +} + + fd_t * fd_create (inode_t *inode, pid_t pid) { diff --git a/libglusterfs/src/fd.h b/libglusterfs/src/fd.h index 4ea7fc165e3..48037b72267 100644 --- a/libglusterfs/src/fd.h +++ b/libglusterfs/src/fd.h @@ -170,4 +170,6 @@ _fd_ref (fd_t *fd); void fd_ctx_dump (fd_t *fd, char *prefix); +extern void +fd_unref_unbind (fd_t *fd); #endif /* _FD_H */ diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index 0a55e55c9c8..2d5df536937 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -3885,6 +3885,17 @@ nfs3svc_readdir_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, stat = NFS3_OK; nfs3err: + + /* On end-of-directory, unref the fd to have it removed from the cache + * and also unbind it from the fd so that any subsequent request on the + * on the directory do not get this fd when fd_lookup is called in + * dir open resume path. + */ + if (is_eof) { + gf_log (GF_NFS3, GF_LOG_TRACE, "EOF REF: %d", cs->fd->refcount); + fd_unref_unbind (cs->fd); + } + if (cs->maxcount == 0) { nfs3_log_readdir_res (nfs_rpcsvc_request_xid (cs->req), stat, op_errno, (uintptr_t)cs->fd, @@ -3902,11 +3913,6 @@ nfs3err: cs->maxcount, is_eof); } - if (is_eof) { - gf_log (GF_NFS3, GF_LOG_TRACE, "EOF REF: %d", cs->fd->refcount); - fd_unref (cs->fd); - } - gf_log (GF_NFS3, GF_LOG_TRACE, "CS WIPE REF: %d", cs->fd->refcount); nfs3_call_state_wipe (cs); return 0; @@ -3958,7 +3964,7 @@ err: * so that next time the dir is read, we'll get any changed directory * entries. */ - fd_unref (cs->fd); + fd_unref_unbind (cs->fd); nfs3_call_state_wipe (cs); ret: return 0; |