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>
This commit is contained in:
parent
5ae67c4fee
commit
3b3be88d67
3 changed files with 20 additions and 10 deletions
|
@ -936,7 +936,8 @@ static struct pnfs_layout_segment *find_only_write_lseg(struct inode *inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max)
|
filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max,
|
||||||
|
spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct list_head *src = &bucket->written;
|
struct list_head *src = &bucket->written;
|
||||||
struct list_head *dst = &bucket->committing;
|
struct list_head *dst = &bucket->committing;
|
||||||
|
@ -946,6 +947,8 @@ filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max)
|
||||||
list_for_each_entry_safe(req, tmp, src, wb_list) {
|
list_for_each_entry_safe(req, tmp, src, wb_list) {
|
||||||
if (!nfs_lock_request(req))
|
if (!nfs_lock_request(req))
|
||||||
continue;
|
continue;
|
||||||
|
if (cond_resched_lock(lock))
|
||||||
|
list_safe_reset_next(req, tmp, wb_list);
|
||||||
nfs_request_remove_commit_list(req);
|
nfs_request_remove_commit_list(req);
|
||||||
clear_bit(PG_COMMIT_TO_DS, &req->wb_flags);
|
clear_bit(PG_COMMIT_TO_DS, &req->wb_flags);
|
||||||
nfs_list_add_request(req, dst);
|
nfs_list_add_request(req, dst);
|
||||||
|
@ -959,7 +962,8 @@ filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max)
|
||||||
/* Move reqs from written to committing lists, returning count of number moved.
|
/* Move reqs from written to committing lists, returning count of number moved.
|
||||||
* Note called with i_lock held.
|
* Note called with i_lock held.
|
||||||
*/
|
*/
|
||||||
static int filelayout_scan_commit_lists(struct inode *inode, int max)
|
static int filelayout_scan_commit_lists(struct inode *inode, int max,
|
||||||
|
spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct pnfs_layout_segment *lseg;
|
struct pnfs_layout_segment *lseg;
|
||||||
struct nfs4_filelayout_segment *fl;
|
struct nfs4_filelayout_segment *fl;
|
||||||
|
@ -972,7 +976,8 @@ static int filelayout_scan_commit_lists(struct inode *inode, int max)
|
||||||
if (fl->commit_through_mds)
|
if (fl->commit_through_mds)
|
||||||
goto out_done;
|
goto out_done;
|
||||||
for (i = 0; i < fl->number_of_buckets && max != 0; i++) {
|
for (i = 0; i < fl->number_of_buckets && max != 0; i++) {
|
||||||
cnt = filelayout_scan_ds_commit_list(&fl->commit_buckets[i], max);
|
cnt = filelayout_scan_ds_commit_list(&fl->commit_buckets[i],
|
||||||
|
max, lock);
|
||||||
max -= cnt;
|
max -= cnt;
|
||||||
rv += cnt;
|
rv += cnt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ struct pnfs_layoutdriver_type {
|
||||||
void (*mark_request_commit) (struct nfs_page *req,
|
void (*mark_request_commit) (struct nfs_page *req,
|
||||||
struct pnfs_layout_segment *lseg);
|
struct pnfs_layout_segment *lseg);
|
||||||
void (*clear_request_commit) (struct nfs_page *req);
|
void (*clear_request_commit) (struct nfs_page *req);
|
||||||
int (*scan_commit_lists) (struct inode *inode, int max);
|
int (*scan_commit_lists) (struct inode *inode, int max, spinlock_t *lock);
|
||||||
int (*commit_pagelist)(struct inode *inode, struct list_head *mds_pages, int how);
|
int (*commit_pagelist)(struct inode *inode, struct list_head *mds_pages, int how);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -294,14 +294,14 @@ pnfs_clear_request_commit(struct nfs_page *req)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
pnfs_scan_commit_lists(struct inode *inode, int max)
|
pnfs_scan_commit_lists(struct inode *inode, int max, spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
|
struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ld == NULL || ld->scan_commit_lists == NULL)
|
if (ld == NULL || ld->scan_commit_lists == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
ret = ld->scan_commit_lists(inode, max);
|
ret = ld->scan_commit_lists(inode, max, lock);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
set_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags);
|
set_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -419,7 +419,7 @@ pnfs_clear_request_commit(struct nfs_page *req)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
pnfs_scan_commit_lists(struct inode *inode, int max)
|
pnfs_scan_commit_lists(struct inode *inode, int max, spinlock_t *lock)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -561,7 +561,8 @@ nfs_need_commit(struct nfs_inode *nfsi)
|
||||||
|
|
||||||
/* i_lock held by caller */
|
/* i_lock held by caller */
|
||||||
static int
|
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;
|
struct nfs_page *req, *tmp;
|
||||||
int ret = 0;
|
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) {
|
list_for_each_entry_safe(req, tmp, src, wb_list) {
|
||||||
if (!nfs_lock_request(req))
|
if (!nfs_lock_request(req))
|
||||||
continue;
|
continue;
|
||||||
|
if (cond_resched_lock(lock))
|
||||||
|
list_safe_reset_next(req, tmp, wb_list);
|
||||||
nfs_request_remove_commit_list(req);
|
nfs_request_remove_commit_list(req);
|
||||||
nfs_list_add_request(req, dst);
|
nfs_list_add_request(req, dst);
|
||||||
ret++;
|
ret++;
|
||||||
|
@ -596,8 +599,10 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst)
|
||||||
if (nfsi->ncommit > 0) {
|
if (nfsi->ncommit > 0) {
|
||||||
const int max = INT_MAX;
|
const int max = INT_MAX;
|
||||||
|
|
||||||
ret = nfs_scan_commit_list(&nfsi->commit_list, dst, max);
|
ret = nfs_scan_commit_list(&nfsi->commit_list, dst, max,
|
||||||
ret += pnfs_scan_commit_lists(inode, max - ret);
|
&inode->i_lock);
|
||||||
|
ret += pnfs_scan_commit_lists(inode, max - ret,
|
||||||
|
&inode->i_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue