Commit dbae4c73 authored by Trond Myklebust's avatar Trond Myklebust

NFS: Ensure that rpc_run_task() errors are propagated back to the caller

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent c9d8f89d
...@@ -347,8 +347,9 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, ...@@ -347,8 +347,9 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
NFS_PROTO(inode)->read_setup(data, &msg); NFS_PROTO(inode)->read_setup(data, &msg);
task = rpc_run_task(&task_setup_data); task = rpc_run_task(&task_setup_data);
if (!IS_ERR(task)) if (IS_ERR(task))
rpc_put_task(task); break;
rpc_put_task(task);
dprintk("NFS: %5u initiated direct read call " dprintk("NFS: %5u initiated direct read call "
"(req %s/%Ld, %zu bytes @ offset %Lu)\n", "(req %s/%Ld, %zu bytes @ offset %Lu)\n",
...@@ -763,8 +764,9 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, ...@@ -763,8 +764,9 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
NFS_PROTO(inode)->write_setup(data, &msg); NFS_PROTO(inode)->write_setup(data, &msg);
task = rpc_run_task(&task_setup_data); task = rpc_run_task(&task_setup_data);
if (!IS_ERR(task)) if (IS_ERR(task))
rpc_put_task(task); break;
rpc_put_task(task);
dprintk("NFS: %5u initiated direct write call " dprintk("NFS: %5u initiated direct write call "
"(req %s/%Ld, %zu bytes @ offset %Lu)\n", "(req %s/%Ld, %zu bytes @ offset %Lu)\n",
......
...@@ -153,7 +153,7 @@ static void nfs_readpage_release(struct nfs_page *req) ...@@ -153,7 +153,7 @@ static void nfs_readpage_release(struct nfs_page *req)
/* /*
* Set up the NFS read request struct * Set up the NFS read request struct
*/ */
static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
const struct rpc_call_ops *call_ops, const struct rpc_call_ops *call_ops,
unsigned int count, unsigned int offset) unsigned int count, unsigned int offset)
{ {
...@@ -202,8 +202,10 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, ...@@ -202,8 +202,10 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
(unsigned long long)data->args.offset); (unsigned long long)data->args.offset);
task = rpc_run_task(&task_setup_data); task = rpc_run_task(&task_setup_data);
if (!IS_ERR(task)) if (IS_ERR(task))
rpc_put_task(task); return PTR_ERR(task);
rpc_put_task(task);
return 0;
} }
static void static void
...@@ -240,6 +242,7 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne ...@@ -240,6 +242,7 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
size_t rsize = NFS_SERVER(inode)->rsize, nbytes; size_t rsize = NFS_SERVER(inode)->rsize, nbytes;
unsigned int offset; unsigned int offset;
int requests = 0; int requests = 0;
int ret = 0;
LIST_HEAD(list); LIST_HEAD(list);
nfs_list_remove_request(req); nfs_list_remove_request(req);
...@@ -261,6 +264,8 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne ...@@ -261,6 +264,8 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
offset = 0; offset = 0;
nbytes = count; nbytes = count;
do { do {
int ret2;
data = list_entry(list.next, struct nfs_read_data, pages); data = list_entry(list.next, struct nfs_read_data, pages);
list_del_init(&data->pages); list_del_init(&data->pages);
...@@ -268,13 +273,15 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne ...@@ -268,13 +273,15 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
if (nbytes < rsize) if (nbytes < rsize)
rsize = nbytes; rsize = nbytes;
nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, ret2 = nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
rsize, offset); rsize, offset);
if (ret == 0)
ret = ret2;
offset += rsize; offset += rsize;
nbytes -= rsize; nbytes -= rsize;
} while (nbytes != 0); } while (nbytes != 0);
return 0; return ret;
out_bad: out_bad:
while (!list_empty(&list)) { while (!list_empty(&list)) {
...@@ -292,6 +299,7 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned ...@@ -292,6 +299,7 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
struct nfs_page *req; struct nfs_page *req;
struct page **pages; struct page **pages;
struct nfs_read_data *data; struct nfs_read_data *data;
int ret = -ENOMEM;
data = nfs_readdata_alloc(npages); data = nfs_readdata_alloc(npages);
if (!data) if (!data)
...@@ -307,11 +315,10 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned ...@@ -307,11 +315,10 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
} }
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0); return nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
return 0;
out_bad: out_bad:
nfs_async_read_error(head); nfs_async_read_error(head);
return -ENOMEM; return ret;
} }
/* /*
......
...@@ -778,7 +778,7 @@ static int flush_task_priority(int how) ...@@ -778,7 +778,7 @@ static int flush_task_priority(int how)
/* /*
* Set up the argument/result storage required for the RPC call. * Set up the argument/result storage required for the RPC call.
*/ */
static void nfs_write_rpcsetup(struct nfs_page *req, static int nfs_write_rpcsetup(struct nfs_page *req,
struct nfs_write_data *data, struct nfs_write_data *data,
const struct rpc_call_ops *call_ops, const struct rpc_call_ops *call_ops,
unsigned int count, unsigned int offset, unsigned int count, unsigned int offset,
...@@ -841,8 +841,10 @@ static void nfs_write_rpcsetup(struct nfs_page *req, ...@@ -841,8 +841,10 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
(unsigned long long)data->args.offset); (unsigned long long)data->args.offset);
task = rpc_run_task(&task_setup_data); task = rpc_run_task(&task_setup_data);
if (!IS_ERR(task)) if (IS_ERR(task))
rpc_put_task(task); return PTR_ERR(task);
rpc_put_task(task);
return 0;
} }
/* If a nfs_flush_* function fails, it should remove reqs from @head and /* If a nfs_flush_* function fails, it should remove reqs from @head and
...@@ -868,6 +870,7 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned ...@@ -868,6 +870,7 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
size_t wsize = NFS_SERVER(inode)->wsize, nbytes; size_t wsize = NFS_SERVER(inode)->wsize, nbytes;
unsigned int offset; unsigned int offset;
int requests = 0; int requests = 0;
int ret = 0;
LIST_HEAD(list); LIST_HEAD(list);
nfs_list_remove_request(req); nfs_list_remove_request(req);
...@@ -889,6 +892,8 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned ...@@ -889,6 +892,8 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
offset = 0; offset = 0;
nbytes = count; nbytes = count;
do { do {
int ret2;
data = list_entry(list.next, struct nfs_write_data, pages); data = list_entry(list.next, struct nfs_write_data, pages);
list_del_init(&data->pages); list_del_init(&data->pages);
...@@ -896,13 +901,15 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned ...@@ -896,13 +901,15 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
if (nbytes < wsize) if (nbytes < wsize)
wsize = nbytes; wsize = nbytes;
nfs_write_rpcsetup(req, data, &nfs_write_partial_ops, ret2 = nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
wsize, offset, how); wsize, offset, how);
if (ret == 0)
ret = ret2;
offset += wsize; offset += wsize;
nbytes -= wsize; nbytes -= wsize;
} while (nbytes != 0); } while (nbytes != 0);
return 0; return ret;
out_bad: out_bad:
while (!list_empty(&list)) { while (!list_empty(&list)) {
...@@ -943,9 +950,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i ...@@ -943,9 +950,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
/* Set up the argument struct */ /* Set up the argument struct */
nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how); return nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
return 0;
out_bad: out_bad:
while (!list_empty(head)) { while (!list_empty(head)) {
req = nfs_list_entry(head->next); req = nfs_list_entry(head->next);
...@@ -1183,7 +1188,7 @@ void nfs_commitdata_release(void *data) ...@@ -1183,7 +1188,7 @@ void nfs_commitdata_release(void *data)
/* /*
* Set up the argument/result storage required for the RPC call. * Set up the argument/result storage required for the RPC call.
*/ */
static void nfs_commit_rpcsetup(struct list_head *head, static int nfs_commit_rpcsetup(struct list_head *head,
struct nfs_write_data *data, struct nfs_write_data *data,
int how) int how)
{ {
...@@ -1232,8 +1237,10 @@ static void nfs_commit_rpcsetup(struct list_head *head, ...@@ -1232,8 +1237,10 @@ static void nfs_commit_rpcsetup(struct list_head *head,
dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
task = rpc_run_task(&task_setup_data); task = rpc_run_task(&task_setup_data);
if (!IS_ERR(task)) if (IS_ERR(task))
rpc_put_task(task); return PTR_ERR(task);
rpc_put_task(task);
return 0;
} }
/* /*
...@@ -1251,9 +1258,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) ...@@ -1251,9 +1258,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
goto out_bad; goto out_bad;
/* Set up the argument struct */ /* Set up the argument struct */
nfs_commit_rpcsetup(head, data, how); return nfs_commit_rpcsetup(head, data, how);
return 0;
out_bad: out_bad:
while (!list_empty(head)) { while (!list_empty(head)) {
req = nfs_list_entry(head->next); req = nfs_list_entry(head->next);
......
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