From: Srinivasa Ds Date: Fri, 3 Nov 2006 06:07:12 +0000 (-0800) Subject: [PATCH] NFS4: fix for recursive locking problem X-Git-Tag: v2.6.19-rc5~45 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ef55b8a05c02db7c07d81827c69fe8f124e8654;p=linux-2.6 [PATCH] NFS4: fix for recursive locking problem When I was performing some operations on NFS, I got below error on server side. ============================================= [ INFO: possible recursive locking detected ] 2.6.19-prep #1 --------------------------------------------- nfsd4/3525 is trying to acquire lock: (&inode->i_mutex){--..}, at: [] mutex_lock+0x21/0x24 but task is already holding lock: (&inode->i_mutex){--..}, at: [] mutex_lock+0x21/0x24 other info that might help us debug this: 2 locks held by nfsd4/3525: #0: (client_mutex){--..}, at: [] mutex_lock+0x21/0x24 #1: (&inode->i_mutex){--..}, at: [] mutex_lock+0x21/0x24 stack backtrace: [] show_trace_log_lvl+0x58/0x16a [] show_trace+0xd/0x10 [] dump_stack+0x19/0x1b [] __lock_acquire+0x778/0x99c [] lock_acquire+0x4b/0x6d [] __mutex_lock_slowpath+0xbc/0x20a [] mutex_lock+0x21/0x24 [] vfs_rmdir+0x76/0xf8 [] nfsd4_clear_clid_dir+0x2c/0x41 [nfsd] [] nfsd4_remove_clid_dir+0xb1/0xe8 [nfsd] [] laundromat_main+0x9b/0x1c3 [nfsd] [] run_workqueue+0x7a/0xbb [] worker_thread+0xd2/0x107 [] kthread+0xc3/0xf2 [] kernel_thread_helper+0x5/0xb =================================================================== Cause for this problem was,2 successive mutex_lock calls on 2 diffrent inodes ,as shown below static int nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry) { int status; /* For now this directory should already be empty, but we empty it of * any regular files anyway, just in case the directory was created by * a kernel from the future.... */ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); mutex_lock(&dir->d_inode->i_mutex); status = vfs_rmdir(dir->d_inode, dentry); ... int vfs_rmdir(struct inode *dir, struct dentry *dentry) { int error = may_delete(dir, dentry, 1); if (error) return error; if (!dir->i_op || !dir->i_op->rmdir) return -EPERM; DQUOT_INIT(dir); mutex_lock(&dentry->d_inode->i_mutex); ... So I have developed the patch to overcome this problem. Signed-off-by: Srinivasa DS Cc: Neil Brown Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index e9d0770468..81b8565d38 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -274,7 +274,7 @@ nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry) * any regular files anyway, just in case the directory was created by * a kernel from the future.... */ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); - mutex_lock(&dir->d_inode->i_mutex); + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); status = vfs_rmdir(dir->d_inode, dentry); mutex_unlock(&dir->d_inode->i_mutex); return status;