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

Commit efc91ed0 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFS: Optimise append writes with holes



If a file is being extended, and we're creating a hole, we might as well
declare the entire page to be up to date.

This patch significantly improves the write performance for sparse files
in the case where lseek(SEEK_END) is used to append several non-contiguous
writes at intervals of < PAGE_SIZE.

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent b390c2b5
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -344,6 +344,26 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
	unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
	int status;

	/*
	 * Zero any uninitialised parts of the page, and then mark the page
	 * as up to date if it turns out that we're extending the file.
	 */
	if (!PageUptodate(page)) {
		unsigned pglen = nfs_page_length(page);
		unsigned end = offset + len;

		if (pglen == 0) {
			zero_user_segments(page, 0, offset,
					end, PAGE_CACHE_SIZE);
			SetPageUptodate(page);
		} else if (end >= pglen) {
			zero_user_segment(page, end, PAGE_CACHE_SIZE);
			if (offset == 0)
				SetPageUptodate(page);
		} else
			zero_user_segment(page, pglen, PAGE_CACHE_SIZE);
	}

	lock_kernel();
	status = nfs_updatepage(file, page, offset, copied);
	unlock_kernel();
+3 −9
Original line number Diff line number Diff line
@@ -616,7 +616,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
			spin_unlock(&inode->i_lock);
			radix_tree_preload_end();
			req = new;
			goto zero_page;
			goto out;
		}
		spin_unlock(&inode->i_lock);

@@ -649,19 +649,13 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
		req->wb_offset = offset;
		req->wb_pgbase = offset;
		req->wb_bytes = max(end, rqend) - req->wb_offset;
		goto zero_page;
		goto out;
	}

	if (end > rqend)
		req->wb_bytes = end - req->wb_offset;

	return req;
zero_page:
	/* If this page might potentially be marked as up to date,
	 * then we need to zero any uninitalised data. */
	if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE
			&& !PageUptodate(req->wb_page))
		zero_user_segment(req->wb_page, req->wb_bytes, PAGE_CACHE_SIZE);
out:
	return req;
}