mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-20 05:31:15 +00:00
NFS: create common routine for handling direct I/O completion
Factor out the common piece of completing an NFS direct I/O request. Test plan: Compile kernel with CONFIG_NFS and CONFIG_NFS_DIRECTIO enabled. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
93619e5989
commit
63ab46abc7
1 changed files with 26 additions and 20 deletions
|
@ -200,6 +200,30 @@ out:
|
||||||
return (ssize_t) result;
|
return (ssize_t) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We must hold a reference to all the pages in this direct read request
|
||||||
|
* until the RPCs complete. This could be long *after* we are woken up in
|
||||||
|
* nfs_direct_wait (for instance, if someone hits ^C on a slow server).
|
||||||
|
*
|
||||||
|
* In addition, synchronous I/O uses a stack-allocated iocb. Thus we
|
||||||
|
* can't trust the iocb is still valid here if this is a synchronous
|
||||||
|
* request. If the waiter is woken prematurely, the iocb is long gone.
|
||||||
|
*/
|
||||||
|
static void nfs_direct_complete(struct nfs_direct_req *dreq)
|
||||||
|
{
|
||||||
|
nfs_free_user_pages(dreq->pages, dreq->npages, 1);
|
||||||
|
|
||||||
|
if (dreq->iocb) {
|
||||||
|
long res = atomic_read(&dreq->error);
|
||||||
|
if (!res)
|
||||||
|
res = atomic_read(&dreq->count);
|
||||||
|
aio_complete(dreq->iocb, res, 0);
|
||||||
|
} else
|
||||||
|
wake_up(&dreq->wait);
|
||||||
|
|
||||||
|
kref_put(&dreq->kref, nfs_direct_req_release);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note we also set the number of requests we have in the dreq when we are
|
* Note we also set the number of requests we have in the dreq when we are
|
||||||
* done. This prevents races with I/O completion so we will always wait
|
* done. This prevents races with I/O completion so we will always wait
|
||||||
|
@ -245,15 +269,6 @@ static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, size_t rsize)
|
||||||
return dreq;
|
return dreq;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* We must hold a reference to all the pages in this direct read request
|
|
||||||
* until the RPCs complete. This could be long *after* we are woken up in
|
|
||||||
* nfs_direct_wait (for instance, if someone hits ^C on a slow server).
|
|
||||||
*
|
|
||||||
* In addition, synchronous I/O uses a stack-allocated iocb. Thus we
|
|
||||||
* can't trust the iocb is still valid here if this is a synchronous
|
|
||||||
* request. If the waiter is woken prematurely, the iocb is long gone.
|
|
||||||
*/
|
|
||||||
static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
|
static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
|
||||||
{
|
{
|
||||||
struct nfs_read_data *data = calldata;
|
struct nfs_read_data *data = calldata;
|
||||||
|
@ -266,17 +281,8 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
|
||||||
else
|
else
|
||||||
atomic_set(&dreq->error, task->tk_status);
|
atomic_set(&dreq->error, task->tk_status);
|
||||||
|
|
||||||
if (unlikely(atomic_dec_and_test(&dreq->complete))) {
|
if (unlikely(atomic_dec_and_test(&dreq->complete)))
|
||||||
nfs_free_user_pages(dreq->pages, dreq->npages, 1);
|
nfs_direct_complete(dreq);
|
||||||
if (dreq->iocb) {
|
|
||||||
long res = atomic_read(&dreq->error);
|
|
||||||
if (!res)
|
|
||||||
res = atomic_read(&dreq->count);
|
|
||||||
aio_complete(dreq->iocb, res, 0);
|
|
||||||
} else
|
|
||||||
wake_up(&dreq->wait);
|
|
||||||
kref_put(&dreq->kref, nfs_direct_req_release);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct rpc_call_ops nfs_read_direct_ops = {
|
static const struct rpc_call_ops nfs_read_direct_ops = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue