summaryrefslogtreecommitdiff
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-17 15:59:30 (GMT)
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-20 17:08:26 (GMT)
commit3b3be88d67cc17d0f0ab6edaf131516793fc947e (patch)
tree293bc2bcc7cf7a175786ec33a4e2aff8c5c7ebca /fs/nfs/write.c
parent5ae67c4fee869c9b3c87b727a9ea511b6326b834 (diff)
downloadlinux-3b3be88d67cc17d0f0ab6edaf131516793fc947e.tar.xz
NFS: Use cond_resched_lock() to reduce latencies in the commit scans
Ensure that we conditionally drop the inode->i_lock when it is safe to do so in the commit loops. We do so after locking the nfs_page, but before removing it from the commit list. We can then use list_safe_reset_next to recover the loop after the lock is retaken. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 628d9a6..bd93d40 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -561,7 +561,8 @@ nfs_need_commit(struct nfs_inode *nfsi)
/* i_lock held by caller */
static int
-nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max)
+nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max,
+ spinlock_t *lock)
{
struct nfs_page *req, *tmp;
int ret = 0;
@@ -569,6 +570,8 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max)
list_for_each_entry_safe(req, tmp, src, wb_list) {
if (!nfs_lock_request(req))
continue;
+ if (cond_resched_lock(lock))
+ list_safe_reset_next(req, tmp, wb_list);
nfs_request_remove_commit_list(req);
nfs_list_add_request(req, dst);
ret++;
@@ -596,8 +599,10 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst)
if (nfsi->ncommit > 0) {
const int max = INT_MAX;
- ret = nfs_scan_commit_list(&nfsi->commit_list, dst, max);
- ret += pnfs_scan_commit_lists(inode, max - ret);
+ ret = nfs_scan_commit_list(&nfsi->commit_list, dst, max,
+ &inode->i_lock);
+ ret += pnfs_scan_commit_lists(inode, max - ret,
+ &inode->i_lock);
}
spin_unlock(&inode->i_lock);
return ret;