diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-09-17 17:12:15 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-09-28 16:03:06 -0400 |
| commit | a0b0a6e39bd1bb4a0922086feee73627cbd53ba4 (patch) | |
| tree | 51921888aee9b74c3d6ad62b3546c858434f8925 /fs | |
| parent | d19751e7b9bd8a01d00372325439589886674f79 (diff) | |
NFS: Clean up the pNFS layoutget interface
Ensure that we do return errors from nfs4_proc_layoutget() and that we
don't mark the layout as having failed if the error was due to a
signal or resource problem on the client side.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/nfs/nfs4proc.c | 14 | ||||
| -rw-r--r-- | fs/nfs/pnfs.c | 25 | ||||
| -rw-r--r-- | fs/nfs/pnfs.h | 4 |
3 files changed, 27 insertions, 16 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index cf2fd5d0c1b3..1c8656f8745c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -6286,7 +6286,8 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { | |||
| 6286 | .rpc_release = nfs4_layoutget_release, | 6286 | .rpc_release = nfs4_layoutget_release, |
| 6287 | }; | 6287 | }; |
| 6288 | 6288 | ||
| 6289 | void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | 6289 | struct pnfs_layout_segment * |
| 6290 | nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | ||
| 6290 | { | 6291 | { |
| 6291 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | 6292 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); |
| 6292 | size_t max_pages = max_response_pages(server); | 6293 | size_t max_pages = max_response_pages(server); |
| @@ -6303,6 +6304,7 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
| 6303 | .callback_data = lgp, | 6304 | .callback_data = lgp, |
| 6304 | .flags = RPC_TASK_ASYNC, | 6305 | .flags = RPC_TASK_ASYNC, |
| 6305 | }; | 6306 | }; |
| 6307 | struct pnfs_layout_segment *lseg = NULL; | ||
| 6306 | int status = 0; | 6308 | int status = 0; |
| 6307 | 6309 | ||
| 6308 | dprintk("--> %s\n", __func__); | 6310 | dprintk("--> %s\n", __func__); |
| @@ -6310,7 +6312,7 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
| 6310 | lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); | 6312 | lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); |
| 6311 | if (!lgp->args.layout.pages) { | 6313 | if (!lgp->args.layout.pages) { |
| 6312 | nfs4_layoutget_release(lgp); | 6314 | nfs4_layoutget_release(lgp); |
| 6313 | return; | 6315 | return ERR_PTR(-ENOMEM); |
| 6314 | } | 6316 | } |
| 6315 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; | 6317 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; |
| 6316 | 6318 | ||
| @@ -6319,15 +6321,17 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
| 6319 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); | 6321 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); |
| 6320 | task = rpc_run_task(&task_setup_data); | 6322 | task = rpc_run_task(&task_setup_data); |
| 6321 | if (IS_ERR(task)) | 6323 | if (IS_ERR(task)) |
| 6322 | return; | 6324 | return ERR_CAST(task); |
| 6323 | status = nfs4_wait_for_completion_rpc_task(task); | 6325 | status = nfs4_wait_for_completion_rpc_task(task); |
| 6324 | if (status == 0) | 6326 | if (status == 0) |
| 6325 | status = task->tk_status; | 6327 | status = task->tk_status; |
| 6326 | if (status == 0) | 6328 | if (status == 0) |
| 6327 | status = pnfs_layout_process(lgp); | 6329 | lseg = pnfs_layout_process(lgp); |
| 6328 | rpc_put_task(task); | 6330 | rpc_put_task(task); |
| 6329 | dprintk("<-- %s status=%d\n", __func__, status); | 6331 | dprintk("<-- %s status=%d\n", __func__, status); |
| 6330 | return; | 6332 | if (status) |
| 6333 | return ERR_PTR(status); | ||
| 6334 | return lseg; | ||
| 6331 | } | 6335 | } |
| 6332 | 6336 | ||
| 6333 | static void | 6337 | static void |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 2e00feacd4be..3a7ac97020df 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -582,7 +582,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
| 582 | struct inode *ino = lo->plh_inode; | 582 | struct inode *ino = lo->plh_inode; |
| 583 | struct nfs_server *server = NFS_SERVER(ino); | 583 | struct nfs_server *server = NFS_SERVER(ino); |
| 584 | struct nfs4_layoutget *lgp; | 584 | struct nfs4_layoutget *lgp; |
| 585 | struct pnfs_layout_segment *lseg = NULL; | 585 | struct pnfs_layout_segment *lseg; |
| 586 | 586 | ||
| 587 | dprintk("--> %s\n", __func__); | 587 | dprintk("--> %s\n", __func__); |
| 588 | 588 | ||
| @@ -599,16 +599,22 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
| 599 | lgp->args.type = server->pnfs_curr_ld->id; | 599 | lgp->args.type = server->pnfs_curr_ld->id; |
| 600 | lgp->args.inode = ino; | 600 | lgp->args.inode = ino; |
| 601 | lgp->args.ctx = get_nfs_open_context(ctx); | 601 | lgp->args.ctx = get_nfs_open_context(ctx); |
| 602 | lgp->lsegpp = &lseg; | ||
| 603 | lgp->gfp_flags = gfp_flags; | 602 | lgp->gfp_flags = gfp_flags; |
| 604 | 603 | ||
| 605 | /* Synchronously retrieve layout information from server and | 604 | /* Synchronously retrieve layout information from server and |
| 606 | * store in lseg. | 605 | * store in lseg. |
| 607 | */ | 606 | */ |
| 608 | nfs4_proc_layoutget(lgp, gfp_flags); | 607 | lseg = nfs4_proc_layoutget(lgp, gfp_flags); |
| 609 | if (!lseg) { | 608 | if (IS_ERR(lseg)) { |
| 610 | /* remember that LAYOUTGET failed and suspend trying */ | 609 | switch (PTR_ERR(lseg)) { |
| 611 | set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); | 610 | case -ENOMEM: |
| 611 | case -ERESTARTSYS: | ||
| 612 | break; | ||
| 613 | default: | ||
| 614 | /* remember that LAYOUTGET failed and suspend trying */ | ||
| 615 | set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); | ||
| 616 | } | ||
| 617 | return NULL; | ||
| 612 | } | 618 | } |
| 613 | 619 | ||
| 614 | return lseg; | 620 | return lseg; |
| @@ -1096,7 +1102,7 @@ out_unlock: | |||
| 1096 | } | 1102 | } |
| 1097 | EXPORT_SYMBOL_GPL(pnfs_update_layout); | 1103 | EXPORT_SYMBOL_GPL(pnfs_update_layout); |
| 1098 | 1104 | ||
| 1099 | int | 1105 | struct pnfs_layout_segment * |
| 1100 | pnfs_layout_process(struct nfs4_layoutget *lgp) | 1106 | pnfs_layout_process(struct nfs4_layoutget *lgp) |
| 1101 | { | 1107 | { |
| 1102 | struct pnfs_layout_hdr *lo = NFS_I(lgp->args.inode)->layout; | 1108 | struct pnfs_layout_hdr *lo = NFS_I(lgp->args.inode)->layout; |
| @@ -1129,7 +1135,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
| 1129 | } | 1135 | } |
| 1130 | init_lseg(lo, lseg); | 1136 | init_lseg(lo, lseg); |
| 1131 | lseg->pls_range = res->range; | 1137 | lseg->pls_range = res->range; |
| 1132 | *lgp->lsegpp = get_lseg(lseg); | 1138 | get_lseg(lseg); |
| 1133 | pnfs_insert_layout(lo, lseg); | 1139 | pnfs_insert_layout(lo, lseg); |
| 1134 | 1140 | ||
| 1135 | if (res->return_on_close) { | 1141 | if (res->return_on_close) { |
| @@ -1140,8 +1146,9 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
| 1140 | /* Done processing layoutget. Set the layout stateid */ | 1146 | /* Done processing layoutget. Set the layout stateid */ |
| 1141 | pnfs_set_layout_stateid(lo, &res->stateid, false); | 1147 | pnfs_set_layout_stateid(lo, &res->stateid, false); |
| 1142 | spin_unlock(&ino->i_lock); | 1148 | spin_unlock(&ino->i_lock); |
| 1149 | return lseg; | ||
| 1143 | out: | 1150 | out: |
| 1144 | return status; | 1151 | return ERR_PTR(status); |
| 1145 | 1152 | ||
| 1146 | out_forget_reply: | 1153 | out_forget_reply: |
| 1147 | spin_unlock(&ino->i_lock); | 1154 | spin_unlock(&ino->i_lock); |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 745aa1b39e7c..d51ef888e71b 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
| @@ -172,7 +172,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, | |||
| 172 | struct pnfs_devicelist *devlist); | 172 | struct pnfs_devicelist *devlist); |
| 173 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, | 173 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, |
| 174 | struct pnfs_device *dev); | 174 | struct pnfs_device *dev); |
| 175 | extern void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); | 175 | extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); |
| 176 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); | 176 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); |
| 177 | 177 | ||
| 178 | /* pnfs.c */ | 178 | /* pnfs.c */ |
| @@ -192,7 +192,7 @@ void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page | |||
| 192 | int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc); | 192 | int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc); |
| 193 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); | 193 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); |
| 194 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg); | 194 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg); |
| 195 | int pnfs_layout_process(struct nfs4_layoutget *lgp); | 195 | struct pnfs_layout_segment *pnfs_layout_process(struct nfs4_layoutget *lgp); |
| 196 | void pnfs_free_lseg_list(struct list_head *tmp_list); | 196 | void pnfs_free_lseg_list(struct list_head *tmp_list); |
| 197 | void pnfs_destroy_layout(struct nfs_inode *); | 197 | void pnfs_destroy_layout(struct nfs_inode *); |
| 198 | void pnfs_destroy_all_layouts(struct nfs_client *); | 198 | void pnfs_destroy_all_layouts(struct nfs_client *); |
