diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-01 12:07:22 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-01 13:48:13 -0400 |
commit | 25b11dcdbfcad69a5ec03265e2dce19e5eca936b (patch) | |
tree | f7f6ebbf62344f6cb6107815c489ce9918acd2c0 /fs/nfs | |
parent | 9146ab5055152bbacb5690c384df2fd610fb3c68 (diff) |
NFS: Clean up nfs read and write error paths
Move the error handling for nfs_generic_pagein() into a single function.
Ditto for nfs_generic_flush().
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: Fred Isaman <iisaman@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/pnfs.c | 2 | ||||
-rw-r--r-- | fs/nfs/read.c | 38 | ||||
-rw-r--r-- | fs/nfs/write.c | 46 |
3 files changed, 44 insertions, 42 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 39cbac548730..6fdeca2fbc2a 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1321,7 +1321,6 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | |||
1321 | if (ret != 0) { | 1321 | if (ret != 0) { |
1322 | put_lseg(desc->pg_lseg); | 1322 | put_lseg(desc->pg_lseg); |
1323 | desc->pg_lseg = NULL; | 1323 | desc->pg_lseg = NULL; |
1324 | set_bit(NFS_IOHDR_REDO, &hdr->flags); | ||
1325 | } else | 1324 | } else |
1326 | pnfs_do_multiple_writes(desc, &hdr->rpc_list, desc->pg_ioflags); | 1325 | pnfs_do_multiple_writes(desc, &hdr->rpc_list, desc->pg_ioflags); |
1327 | if (atomic_dec_and_test(&hdr->refcnt)) | 1326 | if (atomic_dec_and_test(&hdr->refcnt)) |
@@ -1476,7 +1475,6 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | |||
1476 | if (ret != 0) { | 1475 | if (ret != 0) { |
1477 | put_lseg(desc->pg_lseg); | 1476 | put_lseg(desc->pg_lseg); |
1478 | desc->pg_lseg = NULL; | 1477 | desc->pg_lseg = NULL; |
1479 | set_bit(NFS_IOHDR_REDO, &hdr->flags); | ||
1480 | } else | 1478 | } else |
1481 | pnfs_do_multiple_reads(desc, &hdr->rpc_list); | 1479 | pnfs_do_multiple_reads(desc, &hdr->rpc_list); |
1482 | if (atomic_dec_and_test(&hdr->refcnt)) | 1480 | if (atomic_dec_and_test(&hdr->refcnt)) |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 20a029324060..1961a192f1cb 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -320,6 +320,19 @@ static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops = { | |||
320 | .completion = nfs_read_completion, | 320 | .completion = nfs_read_completion, |
321 | }; | 321 | }; |
322 | 322 | ||
323 | static void nfs_pagein_error(struct nfs_pageio_descriptor *desc, | ||
324 | struct nfs_pgio_header *hdr) | ||
325 | { | ||
326 | set_bit(NFS_IOHDR_REDO, &hdr->flags); | ||
327 | while (!list_empty(&hdr->rpc_list)) { | ||
328 | struct nfs_read_data *data = list_first_entry(&hdr->rpc_list, | ||
329 | struct nfs_read_data, list); | ||
330 | list_del(&data->list); | ||
331 | nfs_readdata_release(data); | ||
332 | } | ||
333 | desc->pg_completion_ops->error_cleanup(&desc->pg_list); | ||
334 | } | ||
335 | |||
323 | /* | 336 | /* |
324 | * Generate multiple requests to fill a single page. | 337 | * Generate multiple requests to fill a single page. |
325 | * | 338 | * |
@@ -342,33 +355,27 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc, | |||
342 | size_t rsize = desc->pg_bsize, nbytes; | 355 | size_t rsize = desc->pg_bsize, nbytes; |
343 | unsigned int offset; | 356 | unsigned int offset; |
344 | 357 | ||
345 | nfs_list_remove_request(req); | ||
346 | nfs_list_add_request(req, &hdr->pages); | ||
347 | |||
348 | offset = 0; | 358 | offset = 0; |
349 | nbytes = desc->pg_count; | 359 | nbytes = desc->pg_count; |
350 | do { | 360 | do { |
351 | size_t len = min(nbytes,rsize); | 361 | size_t len = min(nbytes,rsize); |
352 | 362 | ||
353 | data = nfs_readdata_alloc(hdr, 1); | 363 | data = nfs_readdata_alloc(hdr, 1); |
354 | if (!data) | 364 | if (!data) { |
355 | goto out_bad; | 365 | nfs_pagein_error(desc, hdr); |
366 | return -ENOMEM; | ||
367 | } | ||
356 | data->pages.pagevec[0] = page; | 368 | data->pages.pagevec[0] = page; |
357 | nfs_read_rpcsetup(data, len, offset); | 369 | nfs_read_rpcsetup(data, len, offset); |
358 | list_add(&data->list, &hdr->rpc_list); | 370 | list_add(&data->list, &hdr->rpc_list); |
359 | nbytes -= len; | 371 | nbytes -= len; |
360 | offset += len; | 372 | offset += len; |
361 | } while (nbytes != 0); | 373 | } while (nbytes != 0); |
374 | |||
375 | nfs_list_remove_request(req); | ||
376 | nfs_list_add_request(req, &hdr->pages); | ||
362 | desc->pg_rpc_callops = &nfs_read_common_ops; | 377 | desc->pg_rpc_callops = &nfs_read_common_ops; |
363 | return 0; | 378 | return 0; |
364 | out_bad: | ||
365 | while (!list_empty(&hdr->rpc_list)) { | ||
366 | data = list_first_entry(&hdr->rpc_list, struct nfs_read_data, list); | ||
367 | list_del(&data->list); | ||
368 | nfs_readdata_release(data); | ||
369 | } | ||
370 | desc->pg_completion_ops->error_cleanup(&hdr->pages); | ||
371 | return -ENOMEM; | ||
372 | } | 379 | } |
373 | 380 | ||
374 | static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, | 381 | static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, |
@@ -378,12 +385,11 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, | |||
378 | struct page **pages; | 385 | struct page **pages; |
379 | struct nfs_read_data *data; | 386 | struct nfs_read_data *data; |
380 | struct list_head *head = &desc->pg_list; | 387 | struct list_head *head = &desc->pg_list; |
381 | int ret = 0; | ||
382 | 388 | ||
383 | data = nfs_readdata_alloc(hdr, nfs_page_array_len(desc->pg_base, | 389 | data = nfs_readdata_alloc(hdr, nfs_page_array_len(desc->pg_base, |
384 | desc->pg_count)); | 390 | desc->pg_count)); |
385 | if (!data) { | 391 | if (!data) { |
386 | desc->pg_completion_ops->error_cleanup(head); | 392 | nfs_pagein_error(desc, hdr); |
387 | return -ENOMEM; | 393 | return -ENOMEM; |
388 | } | 394 | } |
389 | 395 | ||
@@ -427,8 +433,6 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | |||
427 | if (ret == 0) | 433 | if (ret == 0) |
428 | ret = nfs_do_multiple_reads(&hdr->rpc_list, | 434 | ret = nfs_do_multiple_reads(&hdr->rpc_list, |
429 | desc->pg_rpc_callops); | 435 | desc->pg_rpc_callops); |
430 | else | ||
431 | set_bit(NFS_IOHDR_REDO, &hdr->flags); | ||
432 | if (atomic_dec_and_test(&hdr->refcnt)) | 436 | if (atomic_dec_and_test(&hdr->refcnt)) |
433 | hdr->completion_ops->completion(hdr); | 437 | hdr->completion_ops->completion(hdr); |
434 | return ret; | 438 | return ret; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 2f80aa50d967..d1e4f81ba057 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1058,6 +1058,19 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = { | |||
1058 | .completion = nfs_write_completion, | 1058 | .completion = nfs_write_completion, |
1059 | }; | 1059 | }; |
1060 | 1060 | ||
1061 | static void nfs_flush_error(struct nfs_pageio_descriptor *desc, | ||
1062 | struct nfs_pgio_header *hdr) | ||
1063 | { | ||
1064 | set_bit(NFS_IOHDR_REDO, &hdr->flags); | ||
1065 | while (!list_empty(&hdr->rpc_list)) { | ||
1066 | struct nfs_write_data *data = list_first_entry(&hdr->rpc_list, | ||
1067 | struct nfs_write_data, list); | ||
1068 | list_del(&data->list); | ||
1069 | nfs_writedata_release(data); | ||
1070 | } | ||
1071 | desc->pg_completion_ops->error_cleanup(&desc->pg_list); | ||
1072 | } | ||
1073 | |||
1061 | /* | 1074 | /* |
1062 | * Generate multiple small requests to write out a single | 1075 | * Generate multiple small requests to write out a single |
1063 | * contiguous dirty area on one page. | 1076 | * contiguous dirty area on one page. |
@@ -1071,12 +1084,9 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, | |||
1071 | size_t wsize = desc->pg_bsize, nbytes; | 1084 | size_t wsize = desc->pg_bsize, nbytes; |
1072 | unsigned int offset; | 1085 | unsigned int offset; |
1073 | int requests = 0; | 1086 | int requests = 0; |
1074 | int ret = 0; | ||
1075 | struct nfs_commit_info cinfo; | 1087 | struct nfs_commit_info cinfo; |
1076 | 1088 | ||
1077 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); | 1089 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); |
1078 | nfs_list_remove_request(req); | ||
1079 | nfs_list_add_request(req, &hdr->pages); | ||
1080 | 1090 | ||
1081 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | 1091 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && |
1082 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo) || | 1092 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo) || |
@@ -1090,8 +1100,10 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, | |||
1090 | size_t len = min(nbytes, wsize); | 1100 | size_t len = min(nbytes, wsize); |
1091 | 1101 | ||
1092 | data = nfs_writedata_alloc(hdr, 1); | 1102 | data = nfs_writedata_alloc(hdr, 1); |
1093 | if (!data) | 1103 | if (!data) { |
1094 | goto out_bad; | 1104 | nfs_flush_error(desc, hdr); |
1105 | return -ENOMEM; | ||
1106 | } | ||
1095 | data->pages.pagevec[0] = page; | 1107 | data->pages.pagevec[0] = page; |
1096 | nfs_write_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo); | 1108 | nfs_write_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo); |
1097 | list_add(&data->list, &hdr->rpc_list); | 1109 | list_add(&data->list, &hdr->rpc_list); |
@@ -1099,17 +1111,10 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, | |||
1099 | nbytes -= len; | 1111 | nbytes -= len; |
1100 | offset += len; | 1112 | offset += len; |
1101 | } while (nbytes != 0); | 1113 | } while (nbytes != 0); |
1114 | nfs_list_remove_request(req); | ||
1115 | nfs_list_add_request(req, &hdr->pages); | ||
1102 | desc->pg_rpc_callops = &nfs_write_common_ops; | 1116 | desc->pg_rpc_callops = &nfs_write_common_ops; |
1103 | return ret; | 1117 | return 0; |
1104 | |||
1105 | out_bad: | ||
1106 | while (!list_empty(&hdr->rpc_list)) { | ||
1107 | data = list_first_entry(&hdr->rpc_list, struct nfs_write_data, list); | ||
1108 | list_del(&data->list); | ||
1109 | nfs_writedata_release(data); | ||
1110 | } | ||
1111 | desc->pg_completion_ops->error_cleanup(&hdr->pages); | ||
1112 | return -ENOMEM; | ||
1113 | } | 1118 | } |
1114 | 1119 | ||
1115 | /* | 1120 | /* |
@@ -1127,15 +1132,13 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc, | |||
1127 | struct page **pages; | 1132 | struct page **pages; |
1128 | struct nfs_write_data *data; | 1133 | struct nfs_write_data *data; |
1129 | struct list_head *head = &desc->pg_list; | 1134 | struct list_head *head = &desc->pg_list; |
1130 | int ret = 0; | ||
1131 | struct nfs_commit_info cinfo; | 1135 | struct nfs_commit_info cinfo; |
1132 | 1136 | ||
1133 | data = nfs_writedata_alloc(hdr, nfs_page_array_len(desc->pg_base, | 1137 | data = nfs_writedata_alloc(hdr, nfs_page_array_len(desc->pg_base, |
1134 | desc->pg_count)); | 1138 | desc->pg_count)); |
1135 | if (!data) { | 1139 | if (!data) { |
1136 | desc->pg_completion_ops->error_cleanup(head); | 1140 | nfs_flush_error(desc, hdr); |
1137 | ret = -ENOMEM; | 1141 | return -ENOMEM; |
1138 | goto out; | ||
1139 | } | 1142 | } |
1140 | 1143 | ||
1141 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); | 1144 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); |
@@ -1155,8 +1158,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc, | |||
1155 | nfs_write_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo); | 1158 | nfs_write_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo); |
1156 | list_add(&data->list, &hdr->rpc_list); | 1159 | list_add(&data->list, &hdr->rpc_list); |
1157 | desc->pg_rpc_callops = &nfs_write_common_ops; | 1160 | desc->pg_rpc_callops = &nfs_write_common_ops; |
1158 | out: | 1161 | return 0; |
1159 | return ret; | ||
1160 | } | 1162 | } |
1161 | 1163 | ||
1162 | int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | 1164 | int nfs_generic_flush(struct nfs_pageio_descriptor *desc, |
@@ -1186,8 +1188,6 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | |||
1186 | ret = nfs_do_multiple_writes(&hdr->rpc_list, | 1188 | ret = nfs_do_multiple_writes(&hdr->rpc_list, |
1187 | desc->pg_rpc_callops, | 1189 | desc->pg_rpc_callops, |
1188 | desc->pg_ioflags); | 1190 | desc->pg_ioflags); |
1189 | else | ||
1190 | set_bit(NFS_IOHDR_REDO, &hdr->flags); | ||
1191 | if (atomic_dec_and_test(&hdr->refcnt)) | 1191 | if (atomic_dec_and_test(&hdr->refcnt)) |
1192 | hdr->completion_ops->completion(hdr); | 1192 | hdr->completion_ops->completion(hdr); |
1193 | return ret; | 1193 | return ret; |