aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-05-01 12:07:22 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-05-01 13:48:13 -0400
commit25b11dcdbfcad69a5ec03265e2dce19e5eca936b (patch)
treef7f6ebbf62344f6cb6107815c489ce9918acd2c0 /fs/nfs
parent9146ab5055152bbacb5690c384df2fd610fb3c68 (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.c2
-rw-r--r--fs/nfs/read.c38
-rw-r--r--fs/nfs/write.c46
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
323static 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;
364out_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
374static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, 381static 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
1061static 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
1105out_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;
1158out: 1161 return 0;
1159 return ret;
1160} 1162}
1161 1163
1162int nfs_generic_flush(struct nfs_pageio_descriptor *desc, 1164int 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;