From: Peter Zijlstra while doing a kernel make modules_install install over an NFS mount. ( ============================================= [ INFO: possible recursive locking detected ] --------------------------------------------- nfsd/9550 is trying to acquire lock: (&inode->i_mutex){--..}, at: [] mutex_lock+0x1c/0x1f but task is already holding lock: (&inode->i_mutex){--..}, at: [] mutex_lock+0x1c/0x1f other info that might help us debug this: 2 locks held by nfsd/9550: #0: (hash_sem){..--}, at: [] exp_readlock+0xd/0xf [nfsd] #1: (&inode->i_mutex){--..}, at: [] mutex_lock+0x1c/0x1f stack backtrace: [] show_trace_log_lvl+0x58/0x152 [] show_trace+0xd/0x10 [] dump_stack+0x19/0x1b [] __lock_acquire+0x77a/0x9a3 [] lock_acquire+0x60/0x80 [] __mutex_lock_slowpath+0xa7/0x20e [] mutex_lock+0x1c/0x1f [] vfs_unlink+0x34/0x8a [] nfsd_unlink+0x18f/0x1e2 [nfsd] [] nfsd3_proc_remove+0x95/0xa2 [nfsd] [] nfsd_dispatch+0xc0/0x178 [nfsd] [] svc_process+0x3a5/0x5ed [] nfsd+0x1a7/0x305 [nfsd] [] kernel_thread_helper+0x5/0xb DWARF2 unwinder stuck at kernel_thread_helper+0x5/0xb Leftover inexact backtrace: [] show_trace+0xd/0x10 [] dump_stack+0x19/0x1b [] __lock_acquire+0x77a/0x9a3 [] lock_acquire+0x60/0x80 [] __mutex_lock_slowpath+0xa7/0x20e [] mutex_lock+0x1c/0x1f [] vfs_unlink+0x34/0x8a [] nfsd_unlink+0x18f/0x1e2 [nfsd] [] nfsd3_proc_remove+0x95/0xa2 [nfsd] [] nfsd_dispatch+0xc0/0x178 [nfsd] [] svc_process+0x3a5/0x5ed [] nfsd+0x1a7/0x305 [nfsd] [] kernel_thread_helper+0x5/0xb ============================================= [ INFO: possible recursive locking detected ] --------------------------------------------- nfsd/9580 is trying to acquire lock: (&inode->i_mutex){--..}, at: [] mutex_lock+0x1c/0x1f but task is already holding lock: (&inode->i_mutex){--..}, at: [] mutex_lock+0x1c/0x1f other info that might help us debug this: 2 locks held by nfsd/9580: #0: (hash_sem){..--}, at: [] exp_readlock+0xd/0xf [nfsd] #1: (&inode->i_mutex){--..}, at: [] mutex_lock+0x1c/0x1f stack backtrace: [] show_trace_log_lvl+0x58/0x152 [] show_trace+0xd/0x10 [] dump_stack+0x19/0x1b [] __lock_acquire+0x77a/0x9a3 [] lock_acquire+0x60/0x80 [] __mutex_lock_slowpath+0xa7/0x20e [] mutex_lock+0x1c/0x1f [] nfsd_setattr+0x2c8/0x499 [nfsd] [] nfsd_create_v3+0x31b/0x4ac [nfsd] [] nfsd3_proc_create+0x128/0x138 [nfsd] [] nfsd_dispatch+0xc0/0x178 [nfsd] [] svc_process+0x3a5/0x5ed [] nfsd+0x1a7/0x305 [nfsd] [] kernel_thread_helper+0x5/0xb DWARF2 unwinder stuck at kernel_thread_helper+0x5/0xb Leftover inexact backtrace: [] show_trace+0xd/0x10 [] dump_stack+0x19/0x1b [] __lock_acquire+0x77a/0x9a3 [] lock_acquire+0x60/0x80 [] __mutex_lock_slowpath+0xa7/0x20e [] mutex_lock+0x1c/0x1f [] nfsd_setattr+0x2c8/0x499 [nfsd] [] nfsd_create_v3+0x31b/0x4ac [nfsd] [] nfsd3_proc_create+0x128/0x138 [nfsd] [] nfsd_dispatch+0xc0/0x178 [nfsd] [] svc_process+0x3a5/0x5ed [] nfsd+0x1a7/0x305 [nfsd] [] kernel_thread_helper+0x5/0xb Signed-off-by: Peter Zijlstra Cc: Neil Brown Cc: Ingo Molnar Cc: Arjan van de Ven Signed-off-by: Andrew Morton --- fs/nfsd/vfs.c | 8 ++++---- include/linux/nfsd/nfsfh.h | 11 +++++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff -puN fs/nfsd/vfs.c~nfsd-lockdep-annotation fs/nfsd/vfs.c --- a/fs/nfsd/vfs.c~nfsd-lockdep-annotation +++ a/fs/nfsd/vfs.c @@ -1114,7 +1114,7 @@ nfsd_create(struct svc_rqst *rqstp, stru */ if (!resfhp->fh_dentry) { /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ - fh_lock(fhp); + fh_lock_nested(fhp, I_MUTEX_PARENT); dchild = lookup_one_len(fname, dentry, flen); err = PTR_ERR(dchild); if (IS_ERR(dchild)) @@ -1240,7 +1240,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, s err = nfserr_notdir; if(!dirp->i_op || !dirp->i_op->lookup) goto out; - fh_lock(fhp); + fh_lock_nested(fhp, I_MUTEX_PARENT); /* * Compose the response file handle. @@ -1494,7 +1494,7 @@ nfsd_link(struct svc_rqst *rqstp, struct if (isdotent(name, len)) goto out; - fh_lock(ffhp); + fh_lock_nested(ffhp, I_MUTEX_PARENT); ddir = ffhp->fh_dentry; dirp = ddir->d_inode; @@ -1644,7 +1644,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru if (err) goto out; - fh_lock(fhp); + fh_lock_nested(fhp, I_MUTEX_PARENT); dentry = fhp->fh_dentry; dirp = dentry->d_inode; diff -puN include/linux/nfsd/nfsfh.h~nfsd-lockdep-annotation include/linux/nfsd/nfsfh.h --- a/include/linux/nfsd/nfsfh.h~nfsd-lockdep-annotation +++ a/include/linux/nfsd/nfsfh.h @@ -290,8 +290,9 @@ fill_post_wcc(struct svc_fh *fhp) * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once * so, any changes here should be reflected there. */ + static inline void -fh_lock(struct svc_fh *fhp) +fh_lock_nested(struct svc_fh *fhp, unsigned int subclass) { struct dentry *dentry = fhp->fh_dentry; struct inode *inode; @@ -310,11 +311,17 @@ fh_lock(struct svc_fh *fhp) } inode = dentry->d_inode; - mutex_lock(&inode->i_mutex); + mutex_lock_nested(&inode->i_mutex, subclass); fill_pre_wcc(fhp); fhp->fh_locked = 1; } +static inline void +fh_lock(struct svc_fh *fhp) +{ + fh_lock_nested(fhp, I_MUTEX_NORMAL); +} + /* * Unlock a file handle/inode */ _