From a37a5a9e5e309f87db9497d187df41d0fede8d29 Mon Sep 17 00:00:00 2001 From: Andrew Perepechko Date: Thu, 25 Jun 2015 15:07:58 +0300 Subject: [PATCH] LU-6794 nfs: ASSERTION( atomic_read(&d->ld_ref) == 0 ) failed ll_iget_for_nfs() can call unbalanced iput() causing memory leaks. This patch removes this iput() call. Also, avoid unhashing disconnected dentries in d_lustre_invalidate(), which is another source of memory leaks. One of the symptoms of the leak is the following crash pattern: <0>LustreError: 14812:0:(lu_object.c:1251:lu_device_fini()) ASSERTION( atomic_read(&d->ld_ref) == 0 ) failed: Refcount is 1 <0>LustreError: 14812:0:(lu_object.c:1251:lu_device_fini()) LBUG <4>Pid: 14812, comm: umount <4> <4>Call Trace: <4> [] libcfs_debug_dumpstack+0x55/0x80 [libcfs] <4> [] lbug_with_loc+0x47/0xb0 [libcfs] <4> [] lu_device_fini+0xb8/0xc0 [obdclass] <4> [] lovsub_device_free+0x52/0x220 [lov] <4> [] lu_stack_fini+0x7e/0xc0 [obdclass] <4> [] cl_stack_fini+0xe/0x10 [obdclass] <4> [] lov_device_fini+0x58/0x120 [lov] <4> [] lu_stack_fini+0x49/0xc0 [obdclass] <4> [] cl_stack_fini+0xe/0x10 [obdclass] <4> [] cl_sb_fini+0x6d/0x190 [lustre] <4> [] ll_put_super+0x1bc/0x11e0 [lustre] <4> [] ? fsnotify_clear_marks_by_inode+0x32/0xf0 <4> [] ? destroy_inode+0x2f/0x60 <4> [] ? dispose_list+0xfc/0x120 <4> [] ? invalidate_inodes+0xf6/0x190 <4> [] generic_shutdown_super+0x5b/0xe0 <4> [] kill_anon_super+0x16/0x60 <4> [] lustre_kill_super+0x4a/0x60 [obdclass] <4> [] deactivate_super+0x57/0x80 <4> [] mntput_no_expire+0xbf/0x110 <4> [] sys_umount+0x7b/0x3a0 <4> [] system_call_fastpath+0x16/0x1b Xyratex-bug-id: MRP-2414 Signed-off-by: Andrew Perepechko Change-Id: Ie8bc428014f3897dc108568f55db9a9ed93c932b Reviewed-on: http://review.whamcloud.com/15480 Tested-by: Jenkins Reviewed-by: Lai Siyao Reviewed-by: Bobi Jam Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/llite/llite_internal.h | 10 +++++++++- lustre/llite/llite_nfs.c | 7 ++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 3d06c68..c393a38 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -1462,7 +1462,15 @@ static inline void d_lustre_invalidate(struct dentry *dentry, int nested) spin_lock_nested(&dentry->d_lock, nested ? DENTRY_D_LOCK_NESTED : DENTRY_D_LOCK_NORMAL); __d_lustre_invalidate(dentry); - if (ll_d_count(dentry) == 0) + /* + * We should be careful about dentries created by d_obtain_alias(). + * These dentries are not put in the dentry tree, instead they are + * linked to sb->s_anon through dentry->d_hash. + * shrink_dcache_for_umount() shrinks the tree and sb->s_anon list. + * If we unhashed such a dentry, unmount would not be able to find + * it and busy inodes would be reported. + */ + if (ll_d_count(dentry) == 0 && !(dentry->d_flags & DCACHE_DISCONNECTED)) __d_drop(dentry); spin_unlock(&dentry->d_lock); } diff --git a/lustre/llite/llite_nfs.c b/lustre/llite/llite_nfs.c index 38e2726..9e19e78 100644 --- a/lustre/llite/llite_nfs.c +++ b/lustre/llite/llite_nfs.c @@ -135,13 +135,10 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren RETURN(ERR_PTR(-ESTALE)); } + /* N.B. d_obtain_alias() drops inode ref on error */ result = d_obtain_alias(inode); - if (IS_ERR(result)) { - iput(inode); - RETURN(result); - } - RETURN(result); + RETURN(result); } #ifndef FILEID_INVALID -- 1.8.3.1