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>
This commit is contained in:
parent
00422483ad
commit
301bfa4830
|
@ -155,9 +155,12 @@ nfs_page_group_lock(struct nfs_page *req, bool nonblock)
|
||||||
if (!test_and_set_bit(PG_HEADLOCK, &head->wb_flags))
|
if (!test_and_set_bit(PG_HEADLOCK, &head->wb_flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!nonblock)
|
if (!nonblock) {
|
||||||
|
set_bit(PG_CONTENDED1, &head->wb_flags);
|
||||||
|
smp_mb__after_atomic();
|
||||||
return wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK,
|
return wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK,
|
||||||
TASK_UNINTERRUPTIBLE);
|
TASK_UNINTERRUPTIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
@ -175,6 +178,10 @@ nfs_page_group_lock_wait(struct nfs_page *req)
|
||||||
|
|
||||||
WARN_ON_ONCE(head != head->wb_head);
|
WARN_ON_ONCE(head != head->wb_head);
|
||||||
|
|
||||||
|
if (!test_bit(PG_HEADLOCK, &head->wb_flags))
|
||||||
|
return;
|
||||||
|
set_bit(PG_CONTENDED1, &head->wb_flags);
|
||||||
|
smp_mb__after_atomic();
|
||||||
wait_on_bit(&head->wb_flags, PG_HEADLOCK,
|
wait_on_bit(&head->wb_flags, PG_HEADLOCK,
|
||||||
TASK_UNINTERRUPTIBLE);
|
TASK_UNINTERRUPTIBLE);
|
||||||
}
|
}
|
||||||
|
@ -193,6 +200,8 @@ nfs_page_group_unlock(struct nfs_page *req)
|
||||||
smp_mb__before_atomic();
|
smp_mb__before_atomic();
|
||||||
clear_bit(PG_HEADLOCK, &head->wb_flags);
|
clear_bit(PG_HEADLOCK, &head->wb_flags);
|
||||||
smp_mb__after_atomic();
|
smp_mb__after_atomic();
|
||||||
|
if (!test_bit(PG_CONTENDED1, &head->wb_flags))
|
||||||
|
return;
|
||||||
wake_up_bit(&head->wb_flags, PG_HEADLOCK);
|
wake_up_bit(&head->wb_flags, PG_HEADLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +392,8 @@ void nfs_unlock_request(struct nfs_page *req)
|
||||||
smp_mb__before_atomic();
|
smp_mb__before_atomic();
|
||||||
clear_bit(PG_BUSY, &req->wb_flags);
|
clear_bit(PG_BUSY, &req->wb_flags);
|
||||||
smp_mb__after_atomic();
|
smp_mb__after_atomic();
|
||||||
|
if (!test_bit(PG_CONTENDED2, &req->wb_flags))
|
||||||
|
return;
|
||||||
wake_up_bit(&req->wb_flags, PG_BUSY);
|
wake_up_bit(&req->wb_flags, PG_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,6 +476,10 @@ void nfs_release_request(struct nfs_page *req)
|
||||||
int
|
int
|
||||||
nfs_wait_on_request(struct nfs_page *req)
|
nfs_wait_on_request(struct nfs_page *req)
|
||||||
{
|
{
|
||||||
|
if (!test_bit(PG_BUSY, &req->wb_flags))
|
||||||
|
return 0;
|
||||||
|
set_bit(PG_CONTENDED2, &req->wb_flags);
|
||||||
|
smp_mb__after_atomic();
|
||||||
return wait_on_bit_io(&req->wb_flags, PG_BUSY,
|
return wait_on_bit_io(&req->wb_flags, PG_BUSY,
|
||||||
TASK_UNINTERRUPTIBLE);
|
TASK_UNINTERRUPTIBLE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ enum {
|
||||||
PG_UPTODATE, /* page group sync bit in read path */
|
PG_UPTODATE, /* page group sync bit in read path */
|
||||||
PG_WB_END, /* page group sync bit in write path */
|
PG_WB_END, /* page group sync bit in write path */
|
||||||
PG_REMOVE, /* page group sync bit in write path */
|
PG_REMOVE, /* page group sync bit in write path */
|
||||||
|
PG_CONTENDED1, /* Is someone waiting for a lock? */
|
||||||
|
PG_CONTENDED2, /* Is someone waiting for a lock? */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nfs_inode;
|
struct nfs_inode;
|
||||||
|
|
Loading…
Reference in New Issue