diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:27 -0500 | 
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:27 -0500 | 
| commit | ec06c096edec0755534c7126f4caded69de131c2 (patch) | |
| tree | 1f5b219c09dea1d9886cefe3ea3f7cef560a5e9a /fs/nfs/read.c | |
| parent | 788e7a89a03e364855583c0ab4649b94925efbb9 (diff) | |
NFS: Cleanup of NFS read code
Same callback hierarchy inversion as for the NFS write calls. This patch is
not strictly speaking needed by the O_DIRECT code, but avoids confusing
differences between the asynchronous read and write code.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/read.c')
| -rw-r--r-- | fs/nfs/read.c | 58 | 
1 files changed, 41 insertions, 17 deletions
| diff --git a/fs/nfs/read.c b/fs/nfs/read.c index ae3ddd24cf8f..2da255f0247f 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -36,8 +36,8 @@  #define NFSDBG_FACILITY		NFSDBG_PAGECACHE  static int nfs_pagein_one(struct list_head *, struct inode *); -static void nfs_readpage_result_partial(struct nfs_read_data *, int); -static void nfs_readpage_result_full(struct nfs_read_data *, int); +static const struct rpc_call_ops nfs_read_partial_ops; +static const struct rpc_call_ops nfs_read_full_ops;  static kmem_cache_t *nfs_rdata_cachep;  mempool_t *nfs_rdata_mempool; @@ -200,9 +200,11 @@ static void nfs_readpage_release(struct nfs_page *req)   * Set up the NFS read request struct   */  static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, +		const struct rpc_call_ops *call_ops,  		unsigned int count, unsigned int offset)  {  	struct inode		*inode; +	int flags;  	data->req	  = req;  	data->inode	  = inode = req->wb_context->dentry->d_inode; @@ -220,6 +222,9 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,  	data->res.eof     = 0;  	nfs_fattr_init(&data->fattr); +	/* Set up the initial task struct. */ +	flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); +	rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data);  	NFS_PROTO(inode)->read_setup(data);  	data->task.tk_cookie = (unsigned long)inode; @@ -307,14 +312,15 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)  		list_del_init(&data->pages);  		data->pagevec[0] = page; -		data->complete = nfs_readpage_result_partial;  		if (nbytes > rsize) { -			nfs_read_rpcsetup(req, data, rsize, offset); +			nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, +					rsize, offset);  			offset += rsize;  			nbytes -= rsize;  		} else { -			nfs_read_rpcsetup(req, data, nbytes, offset); +			nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, +					nbytes, offset);  			nbytes = 0;  		}  		nfs_execute_read(data); @@ -360,8 +366,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode)  	}  	req = nfs_list_entry(data->pages.next); -	data->complete = nfs_readpage_result_full; -	nfs_read_rpcsetup(req, data, count, 0); +	nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);  	nfs_execute_read(data);  	return 0; @@ -395,12 +400,15 @@ nfs_pagein_list(struct list_head *head, int rpages)  /*   * Handle a read reply that fills part of a page.   */ -static void nfs_readpage_result_partial(struct nfs_read_data *data, int status) +static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata)  { +	struct nfs_read_data *data = calldata;  	struct nfs_page *req = data->req;  	struct page *page = req->wb_page; -	if (status >= 0) { +	if (nfs_readpage_result(task, data) != 0) +		return; +	if (task->tk_status >= 0) {  		unsigned int request = data->args.count;  		unsigned int result = data->res.count; @@ -419,20 +427,28 @@ static void nfs_readpage_result_partial(struct nfs_read_data *data, int status)  	}  } +static const struct rpc_call_ops nfs_read_partial_ops = { +	.rpc_call_done = nfs_readpage_result_partial, +	.rpc_release = nfs_readdata_release, +}; +  /*   * This is the callback from RPC telling us whether a reply was   * received or some error occurred (timeout or socket shutdown).   */ -static void nfs_readpage_result_full(struct nfs_read_data *data, int status) +static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)  { +	struct nfs_read_data *data = calldata;  	unsigned int count = data->res.count; +	if (nfs_readpage_result(task, data) != 0) +		return;  	while (!list_empty(&data->pages)) {  		struct nfs_page *req = nfs_list_entry(data->pages.next);  		struct page *page = req->wb_page;  		nfs_list_remove_request(req); -		if (status >= 0) { +		if (task->tk_status >= 0) {  			if (count < PAGE_CACHE_SIZE) {  				if (count < req->wb_bytes)  					memclear_highpage_flush(page, @@ -448,19 +464,27 @@ static void nfs_readpage_result_full(struct nfs_read_data *data, int status)  	}  } +static const struct rpc_call_ops nfs_read_full_ops = { +	.rpc_call_done = nfs_readpage_result_full, +	.rpc_release = nfs_readdata_release, +}; +  /*   * This is the callback from RPC telling us whether a reply was   * received or some error occurred (timeout or socket shutdown).   */ -void nfs_readpage_result(struct rpc_task *task, void *calldata) +int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)  { -	struct nfs_read_data *data = calldata;  	struct nfs_readargs *argp = &data->args;  	struct nfs_readres *resp = &data->res; -	int status = task->tk_status; +	int status;  	dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", -		task->tk_pid, status); +		task->tk_pid, task->tk_status); + +	status = NFS_PROTO(data->inode)->read_done(task, data); +	if (status != 0) +		return status;  	nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count); @@ -474,14 +498,14 @@ void nfs_readpage_result(struct rpc_task *task, void *calldata)  			argp->pgbase += resp->count;  			argp->count -= resp->count;  			rpc_restart_call(task); -			return; +			return -EAGAIN;  		}  		task->tk_status = -EIO;  	}  	spin_lock(&data->inode->i_lock);  	NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME;  	spin_unlock(&data->inode->i_lock); -	data->complete(data, status); +	return 0;  }  /* | 
