aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-17 11:59:30 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-20 13:08:26 -0400
commit3b3be88d67cc17d0f0ab6edaf131516793fc947e (patch)
tree293bc2bcc7cf7a175786ec33a4e2aff8c5c7ebca
parent5ae67c4fee869c9b3c87b727a9ea511b6326b834 (diff)
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>
-rw-r--r--fs/nfs/nfs4filelayout.c11
-rw-r--r--fs/nfs/pnfs.h8
-rw-r--r--fs/nfs/write.c11
3 files changed, 20 insertions, 10 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index e0bdbf4fe454..634c0bcb4fd6 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -936,7 +936,8 @@ static struct pnfs_layout_segment *find_only_write_lseg(struct inode *inode)
936} 936}
937 937
938static int 938static int
939filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max) 939filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max,
940 spinlock_t *lock)
940{ 941{
941 struct list_head *src = &bucket->written; 942 struct list_head *src = &bucket->written;
942 struct list_head *dst = &bucket->committing; 943 struct list_head *dst = &bucket->committing;
@@ -946,6 +947,8 @@ filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max)
946 list_for_each_entry_safe(req, tmp, src, wb_list) { 947 list_for_each_entry_safe(req, tmp, src, wb_list) {
947 if (!nfs_lock_request(req)) 948 if (!nfs_lock_request(req))
948 continue; 949 continue;
950 if (cond_resched_lock(lock))
951 list_safe_reset_next(req, tmp, wb_list);
949 nfs_request_remove_commit_list(req); 952 nfs_request_remove_commit_list(req);
950 clear_bit(PG_COMMIT_TO_DS, &req->wb_flags); 953 clear_bit(PG_COMMIT_TO_DS, &req->wb_flags);
951 nfs_list_add_request(req, dst); 954 nfs_list_add_request(req, dst);
@@ -959,7 +962,8 @@ filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max)
959/* Move reqs from written to committing lists, returning count of number moved. 962/* Move reqs from written to committing lists, returning count of number moved.
960 * Note called with i_lock held. 963 * Note called with i_lock held.
961 */ 964 */
962static int filelayout_scan_commit_lists(struct inode *inode, int max) 965static int filelayout_scan_commit_lists(struct inode *inode, int max,
966 spinlock_t *lock)
963{ 967{
964 struct pnfs_layout_segment *lseg; 968 struct pnfs_layout_segment *lseg;
965 struct nfs4_filelayout_segment *fl; 969 struct nfs4_filelayout_segment *fl;
@@ -972,7 +976,8 @@ static int filelayout_scan_commit_lists(struct inode *inode, int max)
972 if (fl->commit_through_mds) 976 if (fl->commit_through_mds)
973 goto out_done; 977 goto out_done;
974 for (i = 0; i < fl->number_of_buckets && max != 0; i++) { 978 for (i = 0; i < fl->number_of_buckets && max != 0; i++) {
975 cnt = filelayout_scan_ds_commit_list(&fl->commit_buckets[i], max); 979 cnt = filelayout_scan_ds_commit_list(&fl->commit_buckets[i],
980 max, lock);
976 max -= cnt; 981 max -= cnt;
977 rv += cnt; 982 rv += cnt;
978 } 983 }
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index e98ff3027d3a..07802652f5a3 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -97,7 +97,7 @@ struct pnfs_layoutdriver_type {
97 void (*mark_request_commit) (struct nfs_page *req, 97 void (*mark_request_commit) (struct nfs_page *req,
98 struct pnfs_layout_segment *lseg); 98 struct pnfs_layout_segment *lseg);
99 void (*clear_request_commit) (struct nfs_page *req); 99 void (*clear_request_commit) (struct nfs_page *req);
100 int (*scan_commit_lists) (struct inode *inode, int max); 100 int (*scan_commit_lists) (struct inode *inode, int max, spinlock_t *lock);
101 int (*commit_pagelist)(struct inode *inode, struct list_head *mds_pages, int how); 101 int (*commit_pagelist)(struct inode *inode, struct list_head *mds_pages, int how);
102 102
103 /* 103 /*
@@ -294,14 +294,14 @@ pnfs_clear_request_commit(struct nfs_page *req)
294} 294}
295 295
296static inline int 296static inline int
297pnfs_scan_commit_lists(struct inode *inode, int max) 297pnfs_scan_commit_lists(struct inode *inode, int max, spinlock_t *lock)
298{ 298{
299 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld; 299 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
300 int ret; 300 int ret;
301 301
302 if (ld == NULL || ld->scan_commit_lists == NULL) 302 if (ld == NULL || ld->scan_commit_lists == NULL)
303 return 0; 303 return 0;
304 ret = ld->scan_commit_lists(inode, max); 304 ret = ld->scan_commit_lists(inode, max, lock);
305 if (ret != 0) 305 if (ret != 0)
306 set_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags); 306 set_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags);
307 return ret; 307 return ret;
@@ -419,7 +419,7 @@ pnfs_clear_request_commit(struct nfs_page *req)
419} 419}
420 420
421static inline int 421static inline int
422pnfs_scan_commit_lists(struct inode *inode, int max) 422pnfs_scan_commit_lists(struct inode *inode, int max, spinlock_t *lock)
423{ 423{
424 return 0; 424 return 0;
425} 425}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 628d9a69d0a2..bd93d40099f9 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -561,7 +561,8 @@ nfs_need_commit(struct nfs_inode *nfsi)
561 561
562/* i_lock held by caller */ 562/* i_lock held by caller */
563static int 563static int
564nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max) 564nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max,
565 spinlock_t *lock)
565{ 566{
566 struct nfs_page *req, *tmp; 567 struct nfs_page *req, *tmp;
567 int ret = 0; 568 int ret = 0;
@@ -569,6 +570,8 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max)
569 list_for_each_entry_safe(req, tmp, src, wb_list) { 570 list_for_each_entry_safe(req, tmp, src, wb_list) {
570 if (!nfs_lock_request(req)) 571 if (!nfs_lock_request(req))
571 continue; 572 continue;
573 if (cond_resched_lock(lock))
574 list_safe_reset_next(req, tmp, wb_list);
572 nfs_request_remove_commit_list(req); 575 nfs_request_remove_commit_list(req);
573 nfs_list_add_request(req, dst); 576 nfs_list_add_request(req, dst);
574 ret++; 577 ret++;
@@ -596,8 +599,10 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst)
596 if (nfsi->ncommit > 0) { 599 if (nfsi->ncommit > 0) {
597 const int max = INT_MAX; 600 const int max = INT_MAX;
598 601
599 ret = nfs_scan_commit_list(&nfsi->commit_list, dst, max); 602 ret = nfs_scan_commit_list(&nfsi->commit_list, dst, max,
600 ret += pnfs_scan_commit_lists(inode, max - ret); 603 &inode->i_lock);
604 ret += pnfs_scan_commit_lists(inode, max - ret,
605 &inode->i_lock);
601 } 606 }
602 spin_unlock(&inode->i_lock); 607 spin_unlock(&inode->i_lock);
603 return ret; 608 return ret;