From patchwork Tue Apr 12 09:18:08 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 699521 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p3C9IgPb023224 for ; Tue, 12 Apr 2011 09:18:43 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753695Ab1DLJSV (ORCPT ); Tue, 12 Apr 2011 05:18:21 -0400 Received: from ipmail06.adl6.internode.on.net ([150.101.137.145]:52350 "EHLO ipmail06.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753303Ab1DLJSU (ORCPT ); Tue, 12 Apr 2011 05:18:20 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgQGACwYpE15LHHJgWdsb2JhbACZAo0cFQEBFiYlwXKFbgSUBw Received: from ppp121-44-113-201.lns20.syd6.internode.on.net (HELO dastard) ([121.44.113.201]) by ipmail06.adl6.internode.on.net with ESMTP; 12 Apr 2011 18:48:02 +0930 Received: from chute ([192.168.1.1] helo=disappointment) by dastard with esmtp (Exim 4.72) (envelope-from ) id 1Q9ZjV-0008Lu-Cy; Tue, 12 Apr 2011 19:18:01 +1000 Received: from dave by disappointment with local (Exim 4.72) (envelope-from ) id 1Q9Zjc-0005ab-UC; Tue, 12 Apr 2011 19:18:08 +1000 From: Dave Chinner To: torvalds@linux-foundation.org Cc: linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, simoneau@ele.uri.edu Subject: [PATCH] nfs: don't call __mark_inode_dirty while holding i_lock Date: Tue, 12 Apr 2011 19:18:08 +1000 Message-Id: <1302599888-21458-1-git-send-email-david@fromorbit.com> X-Mailer: git-send-email 1.7.2.3 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Tue, 12 Apr 2011 09:18:43 +0000 (UTC) From: Dave Chinner nfs_scan_commit() is called with the inode->i_lock held, but it then calls __mark_inode_dirty() while still holding the lock. This causes a deadlock. Push the inode->i_lock into nfs_scan_commit() so it can protect only the parts of the code it needs to and can be dropped before the call to __mark_inode_dirty() to avoid the deadlock. Signed-off-by: Dave Chinner Tested-by: Will Simoneau --- fs/nfs/write.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index af0c627..e4cbc11 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -542,11 +542,15 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, u if (!nfs_need_commit(nfsi)) return 0; + spin_lock(&inode->i_lock); ret = nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT); if (ret > 0) nfsi->ncommit -= ret; + spin_unlock(&inode->i_lock); + if (nfs_need_commit(NFS_I(inode))) __mark_inode_dirty(inode, I_DIRTY_DATASYNC); + return ret; } #else @@ -1483,9 +1487,7 @@ int nfs_commit_inode(struct inode *inode, int how) res = nfs_commit_set_lock(NFS_I(inode), may_wait); if (res <= 0) goto out_mark_dirty; - spin_lock(&inode->i_lock); res = nfs_scan_commit(inode, &head, 0, 0); - spin_unlock(&inode->i_lock); if (res) { int error;