Commit eb582eba authored by Chuck Lever's avatar Chuck Lever Committed by Linus Torvalds

[PATCH] remove NFS client internal dependence on page->index

This makes the NFS client copy the page->index field into its read and
write request structures (struct nfs_page) when setting up I/O on a
page.  this makes it possible for NFS direct I/O support to reuse
existing NFS client subroutines, and helps eventually allow NFS I/O to
and from anonymous pages.  it is a prerequisite for NFS direct I/O
support.
parent 3a453bd4
...@@ -176,7 +176,7 @@ static int nfs_sync_page(struct page *page) ...@@ -176,7 +176,7 @@ static int nfs_sync_page(struct page *page)
{ {
struct address_space *mapping; struct address_space *mapping;
struct inode *inode; struct inode *inode;
unsigned long index = page_index(page); unsigned long index = page->index;
unsigned int rpages; unsigned int rpages;
int result; int result;
......
...@@ -103,6 +103,7 @@ nfs_create_request(struct rpc_cred *cred, struct inode *inode, ...@@ -103,6 +103,7 @@ nfs_create_request(struct rpc_cred *cred, struct inode *inode,
* long write-back delay. This will be adjusted in * long write-back delay. This will be adjusted in
* update_nfs_request below if the region is not locked. */ * update_nfs_request below if the region is not locked. */
req->wb_page = page; req->wb_page = page;
req->wb_index = page->index;
page_cache_get(page); page_cache_get(page);
req->wb_offset = offset; req->wb_offset = offset;
req->wb_bytes = count; req->wb_bytes = count;
...@@ -188,7 +189,6 @@ void ...@@ -188,7 +189,6 @@ void
nfs_list_add_request(struct nfs_page *req, struct list_head *head) nfs_list_add_request(struct nfs_page *req, struct list_head *head)
{ {
struct list_head *pos; struct list_head *pos;
unsigned long pg_idx = page_index(req->wb_page);
#ifdef NFS_PARANOIA #ifdef NFS_PARANOIA
if (!list_empty(&req->wb_list)) { if (!list_empty(&req->wb_list)) {
...@@ -198,7 +198,7 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head) ...@@ -198,7 +198,7 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
#endif #endif
list_for_each_prev(pos, head) { list_for_each_prev(pos, head) {
struct nfs_page *p = nfs_list_entry(pos); struct nfs_page *p = nfs_list_entry(pos);
if (page_index(p->wb_page) < pg_idx) if (p->wb_index < req->wb_index)
break; break;
} }
list_add(&req->wb_list, pos); list_add(&req->wb_list, pos);
...@@ -247,7 +247,7 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst, ...@@ -247,7 +247,7 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
if (prev) { if (prev) {
if (req->wb_cred != prev->wb_cred) if (req->wb_cred != prev->wb_cred)
break; break;
if (page_index(req->wb_page) != page_index(prev->wb_page)+1) if (req->wb_index != (prev->wb_index + 1))
break; break;
if (req->wb_offset != 0) if (req->wb_offset != 0)
...@@ -280,7 +280,7 @@ nfs_scan_forward(struct nfs_page *req, struct list_head *dst, int nmax) ...@@ -280,7 +280,7 @@ nfs_scan_forward(struct nfs_page *req, struct list_head *dst, int nmax)
struct nfs_server *server = NFS_SERVER(req->wb_inode); struct nfs_server *server = NFS_SERVER(req->wb_inode);
struct list_head *pos, *head = req->wb_list_head; struct list_head *pos, *head = req->wb_list_head;
struct rpc_cred *cred = req->wb_cred; struct rpc_cred *cred = req->wb_cred;
unsigned long idx = page_index(req->wb_page) + 1; unsigned long idx = req->wb_index + 1;
int npages = 0; int npages = 0;
for (pos = req->wb_list.next; nfs_lock_request(req); pos = pos->next) { for (pos = req->wb_list.next; nfs_lock_request(req); pos = pos->next) {
...@@ -296,7 +296,7 @@ nfs_scan_forward(struct nfs_page *req, struct list_head *dst, int nmax) ...@@ -296,7 +296,7 @@ nfs_scan_forward(struct nfs_page *req, struct list_head *dst, int nmax)
if (req->wb_offset + req->wb_bytes != PAGE_CACHE_SIZE) if (req->wb_offset + req->wb_bytes != PAGE_CACHE_SIZE)
break; break;
req = nfs_list_entry(pos); req = nfs_list_entry(pos);
if (page_index(req->wb_page) != idx++) if (req->wb_index != idx++)
break; break;
if (req->wb_offset != 0) if (req->wb_offset != 0)
break; break;
...@@ -393,17 +393,15 @@ nfs_scan_list(struct list_head *head, struct list_head *dst, ...@@ -393,17 +393,15 @@ nfs_scan_list(struct list_head *head, struct list_head *dst,
idx_end = idx_start + npages - 1; idx_end = idx_start + npages - 1;
list_for_each_safe(pos, tmp, head) { list_for_each_safe(pos, tmp, head) {
unsigned long pg_idx;
req = nfs_list_entry(pos); req = nfs_list_entry(pos);
if (file && req->wb_file != file) if (file && req->wb_file != file)
continue; continue;
pg_idx = page_index(req->wb_page); if (req->wb_index < idx_start)
if (pg_idx < idx_start)
continue; continue;
if (pg_idx > idx_end) if (req->wb_index > idx_end)
break; break;
if (!nfs_lock_request(req)) if (!nfs_lock_request(req))
......
...@@ -179,7 +179,7 @@ nfs_readpage_async(struct file *file, struct inode *inode, struct page *page) ...@@ -179,7 +179,7 @@ nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
nfs_mark_request_read(new); nfs_mark_request_read(new);
if (nfsi->nread >= NFS_SERVER(inode)->rpages || if (nfsi->nread >= NFS_SERVER(inode)->rpages ||
page_index(page) == (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) page->index == (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
nfs_pagein_inode(inode, 0, 0); nfs_pagein_inode(inode, 0, 0);
return 0; return 0;
} }
...@@ -207,7 +207,7 @@ nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data) ...@@ -207,7 +207,7 @@ nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data)
data->inode = req->wb_inode; data->inode = req->wb_inode;
data->cred = req->wb_cred; data->cred = req->wb_cred;
data->args.fh = NFS_FH(req->wb_inode); data->args.fh = NFS_FH(req->wb_inode);
data->args.offset = page_offset(req->wb_page) + req->wb_offset; data->args.offset = req_offset(req) + req->wb_offset;
data->args.pgbase = req->wb_offset; data->args.pgbase = req->wb_offset;
data->args.count = count; data->args.count = count;
data->res.fattr = &data->fattr; data->res.fattr = &data->fattr;
...@@ -441,7 +441,7 @@ nfs_readpage_result(struct rpc_task *task) ...@@ -441,7 +441,7 @@ nfs_readpage_result(struct rpc_task *task)
req->wb_inode->i_sb->s_id, req->wb_inode->i_sb->s_id,
(long long)NFS_FILEID(req->wb_inode), (long long)NFS_FILEID(req->wb_inode),
req->wb_bytes, req->wb_bytes,
(long long)(page_offset(page) + req->wb_offset)); (long long)(req_offset(req) + req->wb_offset));
nfs_clear_request(req); nfs_clear_request(req);
nfs_release_request(req); nfs_release_request(req);
nfs_unlock_request(req); nfs_unlock_request(req);
......
...@@ -291,7 +291,7 @@ region_locked(struct inode *inode, struct nfs_page *req) ...@@ -291,7 +291,7 @@ region_locked(struct inode *inode, struct nfs_page *req)
if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)
return 0; return 0;
rqstart = page_offset(req->wb_page) + req->wb_offset; rqstart = req_offset(req) + req->wb_offset;
rqend = rqstart + req->wb_bytes; rqend = rqstart + req->wb_bytes;
for (fl = inode->i_flock; fl; fl = fl->fl_next) { for (fl = inode->i_flock; fl; fl = fl->fl_next) {
if (fl->fl_owner == current->files && (fl->fl_flags & FL_POSIX) if (fl->fl_owner == current->files && (fl->fl_flags & FL_POSIX)
...@@ -357,7 +357,7 @@ nfs_inode_remove_request(struct nfs_page *req) ...@@ -357,7 +357,7 @@ nfs_inode_remove_request(struct nfs_page *req)
* Find a request * Find a request
*/ */
static inline struct nfs_page * static inline struct nfs_page *
_nfs_find_request(struct inode *inode, struct page *page) _nfs_find_request(struct inode *inode, unsigned long index)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
struct list_head *head, *next; struct list_head *head, *next;
...@@ -367,7 +367,7 @@ _nfs_find_request(struct inode *inode, struct page *page) ...@@ -367,7 +367,7 @@ _nfs_find_request(struct inode *inode, struct page *page)
while (next != head) { while (next != head) {
struct nfs_page *req = nfs_inode_wb_entry(next); struct nfs_page *req = nfs_inode_wb_entry(next);
next = next->next; next = next->next;
if (page_index(req->wb_page) != page_index(page)) if (req->wb_index != index)
continue; continue;
req->wb_count++; req->wb_count++;
return req; return req;
...@@ -376,12 +376,12 @@ _nfs_find_request(struct inode *inode, struct page *page) ...@@ -376,12 +376,12 @@ _nfs_find_request(struct inode *inode, struct page *page)
} }
static struct nfs_page * static struct nfs_page *
nfs_find_request(struct inode *inode, struct page *page) nfs_find_request(struct inode *inode, unsigned long index)
{ {
struct nfs_page *req; struct nfs_page *req;
spin_lock(&nfs_wreq_lock); spin_lock(&nfs_wreq_lock);
req = _nfs_find_request(inode, page); req = _nfs_find_request(inode, index);
spin_unlock(&nfs_wreq_lock); spin_unlock(&nfs_wreq_lock);
return req; return req;
} }
...@@ -457,7 +457,6 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s ...@@ -457,7 +457,6 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s
head = &nfsi->writeback; head = &nfsi->writeback;
p = head->next; p = head->next;
while (p != head) { while (p != head) {
unsigned long pg_idx;
struct nfs_page *req = nfs_inode_wb_entry(p); struct nfs_page *req = nfs_inode_wb_entry(p);
p = p->next; p = p->next;
...@@ -465,8 +464,7 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s ...@@ -465,8 +464,7 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s
if (file && req->wb_file != file) if (file && req->wb_file != file)
continue; continue;
pg_idx = page_index(req->wb_page); if (req->wb_index < idx_start || req->wb_index > idx_end)
if (pg_idx < idx_start || pg_idx > idx_end)
continue; continue;
if (!NFS_WBACK_BUSY(req)) if (!NFS_WBACK_BUSY(req))
...@@ -654,7 +652,7 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page, ...@@ -654,7 +652,7 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
* A request for the page we wish to update * A request for the page we wish to update
*/ */
spin_lock(&nfs_wreq_lock); spin_lock(&nfs_wreq_lock);
req = _nfs_find_request(inode, page); req = _nfs_find_request(inode, page->index);
if (req) { if (req) {
if (!nfs_lock_request_dontget(req)) { if (!nfs_lock_request_dontget(req)) {
int error; int error;
...@@ -776,7 +774,7 @@ nfs_flush_incompatible(struct file *file, struct page *page) ...@@ -776,7 +774,7 @@ nfs_flush_incompatible(struct file *file, struct page *page)
* Also do the same if we find a request from an existing * Also do the same if we find a request from an existing
* dropped page. * dropped page.
*/ */
req = nfs_find_request(inode,page); req = nfs_find_request(inode, page->index);
if (req) { if (req) {
if (req->wb_file != file || req->wb_cred != cred || req->wb_page != page) if (req->wb_file != file || req->wb_cred != cred || req->wb_page != page)
status = nfs_wb_page(inode, page); status = nfs_wb_page(inode, page);
...@@ -884,7 +882,7 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data) ...@@ -884,7 +882,7 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data)
data->inode = req->wb_inode; data->inode = req->wb_inode;
data->cred = req->wb_cred; data->cred = req->wb_cred;
data->args.fh = NFS_FH(req->wb_inode); data->args.fh = NFS_FH(req->wb_inode);
data->args.offset = page_offset(req->wb_page) + req->wb_offset; data->args.offset = req_offset(req) + req->wb_offset;
data->args.pgbase = req->wb_offset; data->args.pgbase = req->wb_offset;
data->args.count = count; data->args.count = count;
data->res.fattr = &data->fattr; data->res.fattr = &data->fattr;
...@@ -1072,7 +1070,7 @@ nfs_writeback_done(struct rpc_task *task) ...@@ -1072,7 +1070,7 @@ nfs_writeback_done(struct rpc_task *task)
req->wb_inode->i_sb->s_id, req->wb_inode->i_sb->s_id,
(long long)NFS_FILEID(req->wb_inode), (long long)NFS_FILEID(req->wb_inode),
req->wb_bytes, req->wb_bytes,
(long long)(page_offset(page) + req->wb_offset)); (long long)(req_offset(req) + req->wb_offset));
if (task->tk_status < 0) { if (task->tk_status < 0) {
ClearPageUptodate(page); ClearPageUptodate(page);
...@@ -1126,8 +1124,8 @@ nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data) ...@@ -1126,8 +1124,8 @@ nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data)
* Determine the offset range of requests in the COMMIT call. * Determine the offset range of requests in the COMMIT call.
* We rely on the fact that data->pages is an ordered list... * We rely on the fact that data->pages is an ordered list...
*/ */
start = page_offset(first->wb_page) + first->wb_offset; start = req_offset(first) + first->wb_offset;
end = page_offset(last->wb_page) + (last->wb_offset + last->wb_bytes); end = req_offset(last) + (last->wb_offset + last->wb_bytes);
len = end - start; len = end - start;
/* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */ /* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */
if (end >= inode->i_size || len < 0 || len > (~((u32)0) >> 1)) if (end >= inode->i_size || len < 0 || len > (~((u32)0) >> 1))
...@@ -1224,7 +1222,7 @@ nfs_commit_done(struct rpc_task *task) ...@@ -1224,7 +1222,7 @@ nfs_commit_done(struct rpc_task *task)
req->wb_inode->i_sb->s_id, req->wb_inode->i_sb->s_id,
(long long)NFS_FILEID(req->wb_inode), (long long)NFS_FILEID(req->wb_inode),
req->wb_bytes, req->wb_bytes,
(long long)(page_offset(req->wb_page) + req->wb_offset)); (long long)(req_offset(req) + req->wb_offset));
if (task->tk_status < 0) { if (task->tk_status < 0) {
if (req->wb_file) if (req->wb_file)
req->wb_file->f_error = task->tk_status; req->wb_file->f_error = task->tk_status;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/nfs.h> #include <linux/nfs.h>
#include <linux/nfs2.h> #include <linux/nfs2.h>
#include <linux/nfs3.h> #include <linux/nfs3.h>
#include <linux/nfs_page.h>
#include <linux/nfs_xdr.h> #include <linux/nfs_xdr.h>
/* /*
...@@ -243,9 +244,9 @@ loff_t page_offset(struct page *page) ...@@ -243,9 +244,9 @@ loff_t page_offset(struct page *page)
} }
static inline static inline
unsigned long page_index(struct page *page) loff_t req_offset(struct nfs_page *req)
{ {
return page->index; return ((loff_t)req->wb_index) << PAGE_CACHE_SHIFT;
} }
/* /*
...@@ -360,7 +361,8 @@ nfs_wb_all(struct inode *inode) ...@@ -360,7 +361,8 @@ nfs_wb_all(struct inode *inode)
static inline int static inline int
nfs_wb_page(struct inode *inode, struct page* page) nfs_wb_page(struct inode *inode, struct page* page)
{ {
int error = nfs_sync_file(inode, 0, page_index(page), 1, FLUSH_WAIT | FLUSH_STABLE); int error = nfs_sync_file(inode, 0, page->index, 1,
FLUSH_WAIT | FLUSH_STABLE);
return (error < 0) ? error : 0; return (error < 0) ? error : 0;
} }
......
...@@ -33,7 +33,8 @@ struct nfs_page { ...@@ -33,7 +33,8 @@ struct nfs_page {
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_timeout; /* when to read/write/commit */ unsigned long wb_timeout; /* when to read/write/commit */
unsigned int wb_offset, /* Offset of read/write */ unsigned long wb_index; /* Offset within mapping */
unsigned int wb_offset, /* Offset within page */
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