Patchwork [BUG:885] nfs3: NULL fdentry check before removing from fdcache

login
register
Submitter Shehjar Tikoo
Date 2010-07-28 09:21:18
Message ID <1280308878-6450-1-git-send-email-shehjart@gluster.com>
Download mbox | patch
Permalink /patch/3941/
State Accepted
Delegated to: Anand Avati
Headers show

Comments

Shehjar Tikoo - 2010-07-28 09:21:18
From: Shehjar Tikoo <shehjart@gluster.com>

Suppose a file name 1 is created and some data is written to it. After this
another 512 files are newly created and written to. When the the 513th file is
created and an fd_t opened for it, it results in 1's fd_t being replaced in the
fd-lru with 513th file's fd_t. This is the correct behaviour resulting in all
refs getting unref from the fd_t of 1 and the fd and all related state being
freed.

But, in some workloads, some refs are still pending even after the fd_t is
removed from LRU, resulting in the fd still being bound to the inode. In
nfs3svc_remove_cbk, while removing the inode state, we also ensure that any
fd_ts in the cache for this inode are also removed. While removing the fd_t,
this situation where the fd_t has replaced with another, even while a ref
remains on the fd_t, results in a crash in the fdcache_remove path in
nfs3svc_remove_cbk. This happens because the fd_ctx_get results in a NULL value
because the ctx was already deleted when this fd_t was removed from fd-lru
earlier. This patch fixes the crash by introducing a NULL check.

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

Patch

diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c
index 699a290..4d4a253 100644
--- a/xlators/nfs/server/src/nfs3-helpers.c
+++ b/xlators/nfs/server/src/nfs3-helpers.c
@@ -1905,6 +1905,9 @@  nfs3_fdcache_update (struct nfs3_state *nfs3, fd_t *fd)
 int
 __nfs3_fdcache_remove_entry (struct nfs3_state *nfs3, struct nfs3_fd_entry *fde)
 {
+        if ((!fde) || (!nfs3))
+                return 0;
+
         gf_log (GF_NFS3, GF_LOG_TRACE, "Removing fd: 0x%lx: %d",
                 (long int)fde->cachedfd, fde->cachedfd->refcount);
         list_del (&fde->list);