From b2b6281e3487d3d797ab7974df69790a28c443c9 Mon Sep 17 00:00:00 2001 From: Shehjar Tikoo Date: Wed, 28 Jul 2010 03:51:18 +0000 Subject: nfs3: NULL fdentry check before removing from fdcache 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 Signed-off-by: Anand V. Avati BUG: 885 ([NFS Xlator] Crash in nfs3_fdcache_update) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=885 --- xlators/nfs/server/src/nfs3-helpers.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'xlators/nfs/server') diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c index fa0e751c7..d41bd1815 100644 --- a/xlators/nfs/server/src/nfs3-helpers.c +++ b/xlators/nfs/server/src/nfs3-helpers.c @@ -1908,6 +1908,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); -- cgit