Commit 0c5bb195 authored by Trond Myklebust's avatar Trond Myklebust

[PATCH] allow arbitrary alignment of NFS read/write requests

Patch by Chuck Lever to add a new field called wb_pgbase to the
nfs_page struct. This separates the concept of file page offset from
buffer page offset, allowing NFS to specify read and write requests
into buffers at offsets that are independent of the file page
offset. It is a prequisite for direct I/O in NFS.
parent 8701dd18
...@@ -731,7 +731,7 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count) ...@@ -731,7 +731,7 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count)
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
data->args.fh = NFS_FH(inode); data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req); data->args.offset = req_offset(req);
data->args.pgbase = req->wb_offset; data->args.pgbase = req->wb_pgbase;
data->args.pages = data->pagevec; data->args.pages = data->pagevec;
data->args.count = count; data->args.count = count;
data->res.fattr = &data->fattr; data->res.fattr = &data->fattr;
...@@ -788,7 +788,7 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -788,7 +788,7 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
data->args.fh = NFS_FH(inode); data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req); data->args.offset = req_offset(req);
data->args.pgbase = req->wb_offset; data->args.pgbase = req->wb_pgbase;
data->args.count = count; data->args.count = count;
data->args.stable = stable; data->args.stable = stable;
data->args.pages = data->pagevec; data->args.pages = data->pagevec;
......
...@@ -1372,7 +1372,7 @@ nfs4_proc_read_setup(struct nfs_read_data *data, unsigned int count) ...@@ -1372,7 +1372,7 @@ nfs4_proc_read_setup(struct nfs_read_data *data, unsigned int count)
data->args.fh = NFS_FH(inode); data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req); data->args.offset = req_offset(req);
data->args.pgbase = req->wb_offset; data->args.pgbase = req->wb_pgbase;
data->args.pages = data->pagevec; data->args.pages = data->pagevec;
data->args.count = count; data->args.count = count;
data->res.fattr = &data->fattr; data->res.fattr = &data->fattr;
...@@ -1445,7 +1445,7 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -1445,7 +1445,7 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
data->args.fh = NFS_FH(inode); data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req); data->args.offset = req_offset(req);
data->args.pgbase = req->wb_offset; data->args.pgbase = req->wb_pgbase;
data->args.count = count; data->args.count = count;
data->args.stable = stable; data->args.stable = stable;
data->args.pages = data->pagevec; data->args.pages = data->pagevec;
......
...@@ -91,6 +91,7 @@ nfs_create_request(struct rpc_cred *cred, struct inode *inode, ...@@ -91,6 +91,7 @@ nfs_create_request(struct rpc_cred *cred, struct inode *inode,
req->wb_index = page->index; req->wb_index = page->index;
page_cache_get(page); page_cache_get(page);
req->wb_offset = offset; req->wb_offset = offset;
req->wb_pgbase = offset;
req->wb_bytes = count; req->wb_bytes = count;
if (cred) if (cred)
...@@ -278,13 +279,13 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst, ...@@ -278,13 +279,13 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
if (req->wb_index != (prev->wb_index + 1)) if (req->wb_index != (prev->wb_index + 1))
break; break;
if (req->wb_offset != 0) if (req->wb_pgbase != 0)
break; break;
} }
nfs_list_remove_request(req); nfs_list_remove_request(req);
nfs_list_add_request(req, dst); nfs_list_add_request(req, dst);
npages++; npages++;
if (req->wb_offset + req->wb_bytes != PAGE_CACHE_SIZE) if (req->wb_pgbase + req->wb_bytes != PAGE_CACHE_SIZE)
break; break;
if (npages >= nmax) if (npages >= nmax)
break; break;
......
...@@ -564,7 +564,7 @@ nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count) ...@@ -564,7 +564,7 @@ nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count)
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
data->args.fh = NFS_FH(inode); data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req); data->args.offset = req_offset(req);
data->args.pgbase = req->wb_offset; data->args.pgbase = req->wb_pgbase;
data->args.pages = data->pagevec; data->args.pages = data->pagevec;
data->args.count = count; data->args.count = count;
data->res.fattr = &data->fattr; data->res.fattr = &data->fattr;
...@@ -612,7 +612,7 @@ nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -612,7 +612,7 @@ nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
data->args.fh = NFS_FH(inode); data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req); data->args.offset = req_offset(req);
data->args.pgbase = req->wb_offset; data->args.pgbase = req->wb_pgbase;
data->args.count = count; data->args.count = count;
data->args.stable = NFS_FILE_SYNC; data->args.stable = NFS_FILE_SYNC;
data->args.pages = data->pagevec; data->args.pages = data->pagevec;
......
...@@ -267,7 +267,7 @@ nfs_readpage_result(struct rpc_task *task) ...@@ -267,7 +267,7 @@ nfs_readpage_result(struct rpc_task *task)
if (task->tk_status >= 0) { if (task->tk_status >= 0) {
if (count < PAGE_CACHE_SIZE) { if (count < PAGE_CACHE_SIZE) {
memclear_highpage_flush(page, memclear_highpage_flush(page,
req->wb_offset + count, req->wb_pgbase + count,
req->wb_bytes - count); req->wb_bytes - count);
if (data->res.eof || if (data->res.eof ||
......
...@@ -568,6 +568,7 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page, ...@@ -568,6 +568,7 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
/* Okay, the request matches. Update the region */ /* Okay, the request matches. Update the region */
if (offset < req->wb_offset) { if (offset < req->wb_offset) {
req->wb_offset = offset; req->wb_offset = offset;
req->wb_pgbase = offset;
req->wb_bytes = rqend - req->wb_offset; req->wb_bytes = rqend - req->wb_offset;
} }
...@@ -700,7 +701,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsign ...@@ -700,7 +701,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsign
* Call the strategy routine so it can send out a bunch * Call the strategy routine so it can send out a bunch
* of requests. * of requests.
*/ */
if (req->wb_offset == 0 && req->wb_bytes == PAGE_CACHE_SIZE) { if (req->wb_pgbase == 0 && req->wb_bytes == PAGE_CACHE_SIZE) {
SetPageUptodate(page); SetPageUptodate(page);
nfs_unlock_request(req); nfs_unlock_request(req);
nfs_strategy(inode); nfs_strategy(inode);
......
...@@ -30,8 +30,9 @@ struct nfs_page { ...@@ -30,8 +30,9 @@ struct nfs_page {
struct rpc_cred *wb_cred; struct rpc_cred *wb_cred;
struct page *wb_page; /* page to read in/write out */ struct page *wb_page; /* page to read in/write out */
wait_queue_head_t wb_wait; /* wait queue */ wait_queue_head_t wb_wait; /* wait queue */
unsigned long wb_index; /* Offset within mapping */ unsigned long wb_index; /* Offset >> PAGE_CACHE_SHIFT */
unsigned int wb_offset, /* Offset within page */ unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */
wb_pgbase, /* Start of page data */
wb_bytes, /* Length of request */ wb_bytes, /* Length of request */
wb_count; /* reference count */ wb_count; /* reference count */
unsigned long wb_flags; unsigned long wb_flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment