Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b3be88d authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 5ae67c4f
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -936,7 +936,8 @@ static struct pnfs_layout_segment *find_only_write_lseg(struct inode *inode)
}

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 *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) {
		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);
		clear_bit(PG_COMMIT_TO_DS, &req->wb_flags);
		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.
 * 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 nfs4_filelayout_segment *fl;
@@ -972,7 +976,8 @@ static int filelayout_scan_commit_lists(struct inode *inode, int max)
	if (fl->commit_through_mds)
		goto out_done;
	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;
		rv += cnt;
	}
+4 −4
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ struct pnfs_layoutdriver_type {
	void (*mark_request_commit) (struct nfs_page *req,
					struct pnfs_layout_segment *lseg);
	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);

	/*
@@ -294,14 +294,14 @@ pnfs_clear_request_commit(struct nfs_page *req)
}

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;
	int ret;

	if (ld == NULL || ld->scan_commit_lists == NULL)
		return 0;
	ret = ld->scan_commit_lists(inode, max);
	ret = ld->scan_commit_lists(inode, max, lock);
	if (ret != 0)
		set_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags);
	return ret;
@@ -419,7 +419,7 @@ pnfs_clear_request_commit(struct nfs_page *req)
}

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;
}
+8 −3
Original line number Diff line number Diff line
@@ -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;