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 | |
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>
-rw-r--r-- | fs/nfs/nfs4proc.c | 14 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 25 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 4 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 1 |
4 files changed, 27 insertions, 17 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index cf2fd5d0c1b..1c8656f8745 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 2e00feacd4b..3a7ac97020d 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 745aa1b39e7..d51ef888e71 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 *); |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index be9cf3c7e79..5da789fdf25 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -251,7 +251,6 @@ struct nfs4_layoutget_res { | |||
251 | struct nfs4_layoutget { | 251 | struct nfs4_layoutget { |
252 | struct nfs4_layoutget_args args; | 252 | struct nfs4_layoutget_args args; |
253 | struct nfs4_layoutget_res res; | 253 | struct nfs4_layoutget_res res; |
254 | struct pnfs_layout_segment **lsegpp; | ||
255 | gfp_t gfp_flags; | 254 | gfp_t gfp_flags; |
256 | }; | 255 | }; |
257 | 256 | ||