aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2017-07-11 17:53:48 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2017-07-13 16:57:18 -0400
commit301bfa483016d48b7fb9cbad87c0a04a15c25b90 (patch)
tree1e86b94a773529cae5a3144e03ff7b35f7673188
parent00422483ad415d6267d36711f0e51f4bbbd653ed (diff)
NFS: Don't run wake_up_bit() when nobody is waiting...
"perf lock" shows fairly heavy contention for the bit waitqueue locks when doing an I/O heavy workload. Use a bit to tell whether or not there has been contention for a lock so that we can optimise away the bit waitqueue options in those cases. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--fs/nfs/pagelist.c17
-rw-r--r--include/linux/nfs_page.h2
2 files changed, 18 insertions, 1 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 8a23e2b40b04..de9066a92c0d 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -155,9 +155,12 @@ nfs_page_group_lock(struct nfs_page *req, bool nonblock)
155 if (!test_and_set_bit(PG_HEADLOCK, &head->wb_flags)) 155 if (!test_and_set_bit(PG_HEADLOCK, &head->wb_flags))
156 return 0; 156 return 0;
157 157
158 if (!nonblock) 158 if (!nonblock) {
159 set_bit(PG_CONTENDED1, &head->wb_flags);
160 smp_mb__after_atomic();
159 return wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK, 161 return wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK,
160 TASK_UNINTERRUPTIBLE); 162 TASK_UNINTERRUPTIBLE);
163 }
161 164
162 return -EAGAIN; 165 return -EAGAIN;
163} 166}
@@ -175,6 +178,10 @@ nfs_page_group_lock_wait(struct nfs_page *req)
175 178
176 WARN_ON_ONCE(head != head->wb_head); 179 WARN_ON_ONCE(head != head->wb_head);
177 180
181 if (!test_bit(PG_HEADLOCK, &head->wb_flags))
182 return;
183 set_bit(PG_CONTENDED1, &head->wb_flags);
184 smp_mb__after_atomic();
178 wait_on_bit(&head->wb_flags, PG_HEADLOCK, 185 wait_on_bit(&head->wb_flags, PG_HEADLOCK,
179 TASK_UNINTERRUPTIBLE); 186 TASK_UNINTERRUPTIBLE);
180} 187}
@@ -193,6 +200,8 @@ nfs_page_group_unlock(struct nfs_page *req)
193 smp_mb__before_atomic(); 200 smp_mb__before_atomic();
194 clear_bit(PG_HEADLOCK, &head->wb_flags); 201 clear_bit(PG_HEADLOCK, &head->wb_flags);
195 smp_mb__after_atomic(); 202 smp_mb__after_atomic();
203 if (!test_bit(PG_CONTENDED1, &head->wb_flags))
204 return;
196 wake_up_bit(&head->wb_flags, PG_HEADLOCK); 205 wake_up_bit(&head->wb_flags, PG_HEADLOCK);
197} 206}
198 207
@@ -383,6 +392,8 @@ void nfs_unlock_request(struct nfs_page *req)
383 smp_mb__before_atomic(); 392 smp_mb__before_atomic();
384 clear_bit(PG_BUSY, &req->wb_flags); 393 clear_bit(PG_BUSY, &req->wb_flags);
385 smp_mb__after_atomic(); 394 smp_mb__after_atomic();
395 if (!test_bit(PG_CONTENDED2, &req->wb_flags))
396 return;
386 wake_up_bit(&req->wb_flags, PG_BUSY); 397 wake_up_bit(&req->wb_flags, PG_BUSY);
387} 398}
388 399
@@ -465,6 +476,10 @@ void nfs_release_request(struct nfs_page *req)
465int 476int
466nfs_wait_on_request(struct nfs_page *req) 477nfs_wait_on_request(struct nfs_page *req)
467{ 478{
479 if (!test_bit(PG_BUSY, &req->wb_flags))
480 return 0;
481 set_bit(PG_CONTENDED2, &req->wb_flags);
482 smp_mb__after_atomic();
468 return wait_on_bit_io(&req->wb_flags, PG_BUSY, 483 return wait_on_bit_io(&req->wb_flags, PG_BUSY,
469 TASK_UNINTERRUPTIBLE); 484 TASK_UNINTERRUPTIBLE);
470} 485}
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index abbee2d15dce..d67b67ae6c8b 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -33,6 +33,8 @@ enum {
33 PG_UPTODATE, /* page group sync bit in read path */ 33 PG_UPTODATE, /* page group sync bit in read path */
34 PG_WB_END, /* page group sync bit in write path */ 34 PG_WB_END, /* page group sync bit in write path */
35 PG_REMOVE, /* page group sync bit in write path */ 35 PG_REMOVE, /* page group sync bit in write path */
36 PG_CONTENDED1, /* Is someone waiting for a lock? */
37 PG_CONTENDED2, /* Is someone waiting for a lock? */
36}; 38};
37 39
38struct nfs_inode; 40struct nfs_inode;