diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-28 14:49:41 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-28 14:49:41 -0500 |
commit | 58baac0ac7cc13a690f6f7cea23accaf84e843a0 (patch) | |
tree | f73c2f68d4a43ad95b75de646ad7e39c90d42c64 /fs/nfs | |
parent | 8d0ed0ca6381fea4a97f3b0f085cb1dfa0a50ec0 (diff) | |
parent | 4d0ac22109740c36174c5aac630876b2af0f6943 (diff) |
Merge branch 'flexfiles'
* flexfiles:
pNFS/flexfiles: Ensure we record layoutstats even if RPC is terminated early
pNFS: Add flag to track if we've called nfs4_ff_layout_stat_io_start_read/write
pNFS/flexfiles: Fix a statistics gathering imbalance
pNFS/flexfiles: Don't mark the entire layout as failed, when returning it
pNFS/flexfiles: Don't prevent flexfiles client from retrying LAYOUTGET
pnfs/flexfiles: count io stat in rpc_count_stats callback
pnfs/flexfiles: do not mark delay-like status as DS failure
NFS41: map NFS4ERR_LAYOUTUNAVAILABLE to ENODATA
nfs: only remove page from mapping if launder_page fails
nfs: handle request add failure properly
nfs: centralize pgio error cleanup
nfs: clean up rest of reqs when failing to add one
NFS41: pop some layoutget errors to application
pNFS/flexfiles: Support server-supplied layoutstats sampling period
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/direct.c | 15 | ||||
-rw-r--r-- | fs/nfs/file.c | 2 | ||||
-rw-r--r-- | fs/nfs/filelayout/filelayout.c | 18 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 190 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.h | 1 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayoutdev.c | 16 | ||||
-rw-r--r-- | fs/nfs/inode.c | 6 | ||||
-rw-r--r-- | fs/nfs/internal.h | 14 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 9 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 69 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 62 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 21 | ||||
-rw-r--r-- | fs/nfs/read.c | 43 | ||||
-rw-r--r-- | fs/nfs/write.c | 47 |
14 files changed, 339 insertions, 174 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 4b1d08f56aba..2e7142bcb4c8 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -670,6 +670,10 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
670 | 670 | ||
671 | req = nfs_list_entry(reqs.next); | 671 | req = nfs_list_entry(reqs.next); |
672 | nfs_direct_setup_mirroring(dreq, &desc, req); | 672 | nfs_direct_setup_mirroring(dreq, &desc, req); |
673 | if (desc.pg_error < 0) { | ||
674 | list_splice_init(&reqs, &failed); | ||
675 | goto out_failed; | ||
676 | } | ||
673 | 677 | ||
674 | list_for_each_entry_safe(req, tmp, &reqs, wb_list) { | 678 | list_for_each_entry_safe(req, tmp, &reqs, wb_list) { |
675 | if (!nfs_pageio_add_request(&desc, req)) { | 679 | if (!nfs_pageio_add_request(&desc, req)) { |
@@ -677,13 +681,17 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
677 | nfs_list_add_request(req, &failed); | 681 | nfs_list_add_request(req, &failed); |
678 | spin_lock(cinfo.lock); | 682 | spin_lock(cinfo.lock); |
679 | dreq->flags = 0; | 683 | dreq->flags = 0; |
680 | dreq->error = -EIO; | 684 | if (desc.pg_error < 0) |
685 | dreq->error = desc.pg_error; | ||
686 | else | ||
687 | dreq->error = -EIO; | ||
681 | spin_unlock(cinfo.lock); | 688 | spin_unlock(cinfo.lock); |
682 | } | 689 | } |
683 | nfs_release_request(req); | 690 | nfs_release_request(req); |
684 | } | 691 | } |
685 | nfs_pageio_complete(&desc); | 692 | nfs_pageio_complete(&desc); |
686 | 693 | ||
694 | out_failed: | ||
687 | while (!list_empty(&failed)) { | 695 | while (!list_empty(&failed)) { |
688 | req = nfs_list_entry(failed.next); | 696 | req = nfs_list_entry(failed.next); |
689 | nfs_list_remove_request(req); | 697 | nfs_list_remove_request(req); |
@@ -900,6 +908,11 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
900 | } | 908 | } |
901 | 909 | ||
902 | nfs_direct_setup_mirroring(dreq, &desc, req); | 910 | nfs_direct_setup_mirroring(dreq, &desc, req); |
911 | if (desc.pg_error < 0) { | ||
912 | nfs_free_request(req); | ||
913 | result = desc.pg_error; | ||
914 | break; | ||
915 | } | ||
903 | 916 | ||
904 | nfs_lock_request(req); | 917 | nfs_lock_request(req); |
905 | req->wb_index = pos >> PAGE_SHIFT; | 918 | req->wb_index = pos >> PAGE_SHIFT; |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 93e236429c5d..f188dd071dfc 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -545,7 +545,7 @@ static int nfs_launder_page(struct page *page) | |||
545 | inode->i_ino, (long long)page_offset(page)); | 545 | inode->i_ino, (long long)page_offset(page)); |
546 | 546 | ||
547 | nfs_fscache_wait_on_page_write(nfsi, page); | 547 | nfs_fscache_wait_on_page_write(nfsi, page); |
548 | return nfs_wb_page(inode, page); | 548 | return nfs_wb_launder_page(inode, page); |
549 | } | 549 | } |
550 | 550 | ||
551 | static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file, | 551 | static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file, |
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 02ec07973bc4..bb1f4e7a3270 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -202,6 +202,7 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
202 | task->tk_status); | 202 | task->tk_status); |
203 | nfs4_mark_deviceid_unavailable(devid); | 203 | nfs4_mark_deviceid_unavailable(devid); |
204 | pnfs_error_mark_layout_for_return(inode, lseg); | 204 | pnfs_error_mark_layout_for_return(inode, lseg); |
205 | pnfs_set_lo_fail(lseg); | ||
205 | rpc_wake_up(&tbl->slot_tbl_waitq); | 206 | rpc_wake_up(&tbl->slot_tbl_waitq); |
206 | /* fall through */ | 207 | /* fall through */ |
207 | default: | 208 | default: |
@@ -883,13 +884,19 @@ static void | |||
883 | filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, | 884 | filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, |
884 | struct nfs_page *req) | 885 | struct nfs_page *req) |
885 | { | 886 | { |
886 | if (!pgio->pg_lseg) | 887 | if (!pgio->pg_lseg) { |
887 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 888 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
888 | req->wb_context, | 889 | req->wb_context, |
889 | 0, | 890 | 0, |
890 | NFS4_MAX_UINT64, | 891 | NFS4_MAX_UINT64, |
891 | IOMODE_READ, | 892 | IOMODE_READ, |
892 | GFP_KERNEL); | 893 | GFP_KERNEL); |
894 | if (IS_ERR(pgio->pg_lseg)) { | ||
895 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | ||
896 | pgio->pg_lseg = NULL; | ||
897 | return; | ||
898 | } | ||
899 | } | ||
893 | /* If no lseg, fall back to read through mds */ | 900 | /* If no lseg, fall back to read through mds */ |
894 | if (pgio->pg_lseg == NULL) | 901 | if (pgio->pg_lseg == NULL) |
895 | nfs_pageio_reset_read_mds(pgio); | 902 | nfs_pageio_reset_read_mds(pgio); |
@@ -902,13 +909,20 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
902 | struct nfs_commit_info cinfo; | 909 | struct nfs_commit_info cinfo; |
903 | int status; | 910 | int status; |
904 | 911 | ||
905 | if (!pgio->pg_lseg) | 912 | if (!pgio->pg_lseg) { |
906 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 913 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
907 | req->wb_context, | 914 | req->wb_context, |
908 | 0, | 915 | 0, |
909 | NFS4_MAX_UINT64, | 916 | NFS4_MAX_UINT64, |
910 | IOMODE_RW, | 917 | IOMODE_RW, |
911 | GFP_NOFS); | 918 | GFP_NOFS); |
919 | if (IS_ERR(pgio->pg_lseg)) { | ||
920 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | ||
921 | pgio->pg_lseg = NULL; | ||
922 | return; | ||
923 | } | ||
924 | } | ||
925 | |||
912 | /* If no lseg, fall back to write through mds */ | 926 | /* If no lseg, fall back to write through mds */ |
913 | if (pgio->pg_lseg == NULL) | 927 | if (pgio->pg_lseg == NULL) |
914 | goto out_mds; | 928 | goto out_mds; |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 03516c80855a..2981cd190bfd 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
@@ -505,9 +505,17 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, | |||
505 | } | 505 | } |
506 | 506 | ||
507 | p = xdr_inline_decode(&stream, 4); | 507 | p = xdr_inline_decode(&stream, 4); |
508 | if (p) | 508 | if (!p) |
509 | fls->flags = be32_to_cpup(p); | 509 | goto out_sort_mirrors; |
510 | fls->flags = be32_to_cpup(p); | ||
511 | |||
512 | p = xdr_inline_decode(&stream, 4); | ||
513 | if (!p) | ||
514 | goto out_sort_mirrors; | ||
515 | for (i=0; i < fls->mirror_array_cnt; i++) | ||
516 | fls->mirror_array[i]->report_interval = be32_to_cpup(p); | ||
510 | 517 | ||
518 | out_sort_mirrors: | ||
511 | ff_layout_sort_mirrors(fls); | 519 | ff_layout_sort_mirrors(fls); |
512 | rc = ff_layout_check_layout(lgr); | 520 | rc = ff_layout_check_layout(lgr); |
513 | if (rc) | 521 | if (rc) |
@@ -603,7 +611,9 @@ nfs4_ff_layoutstat_start_io(struct nfs4_ff_layout_mirror *mirror, | |||
603 | mirror->start_time = now; | 611 | mirror->start_time = now; |
604 | if (ktime_equal(mirror->last_report_time, notime)) | 612 | if (ktime_equal(mirror->last_report_time, notime)) |
605 | mirror->last_report_time = now; | 613 | mirror->last_report_time = now; |
606 | if (layoutstats_timer != 0) | 614 | if (mirror->report_interval != 0) |
615 | report_interval = (s64)mirror->report_interval * 1000LL; | ||
616 | else if (layoutstats_timer != 0) | ||
607 | report_interval = (s64)layoutstats_timer * 1000LL; | 617 | report_interval = (s64)layoutstats_timer * 1000LL; |
608 | if (ktime_to_ms(ktime_sub(now, mirror->last_report_time)) >= | 618 | if (ktime_to_ms(ktime_sub(now, mirror->last_report_time)) >= |
609 | report_interval) { | 619 | report_interval) { |
@@ -785,13 +795,19 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, | |||
785 | int ds_idx; | 795 | int ds_idx; |
786 | 796 | ||
787 | /* Use full layout for now */ | 797 | /* Use full layout for now */ |
788 | if (!pgio->pg_lseg) | 798 | if (!pgio->pg_lseg) { |
789 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 799 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
790 | req->wb_context, | 800 | req->wb_context, |
791 | 0, | 801 | 0, |
792 | NFS4_MAX_UINT64, | 802 | NFS4_MAX_UINT64, |
793 | IOMODE_READ, | 803 | IOMODE_READ, |
794 | GFP_KERNEL); | 804 | GFP_KERNEL); |
805 | if (IS_ERR(pgio->pg_lseg)) { | ||
806 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | ||
807 | pgio->pg_lseg = NULL; | ||
808 | return; | ||
809 | } | ||
810 | } | ||
795 | /* If no lseg, fall back to read through mds */ | 811 | /* If no lseg, fall back to read through mds */ |
796 | if (pgio->pg_lseg == NULL) | 812 | if (pgio->pg_lseg == NULL) |
797 | goto out_mds; | 813 | goto out_mds; |
@@ -825,13 +841,19 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
825 | int i; | 841 | int i; |
826 | int status; | 842 | int status; |
827 | 843 | ||
828 | if (!pgio->pg_lseg) | 844 | if (!pgio->pg_lseg) { |
829 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 845 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
830 | req->wb_context, | 846 | req->wb_context, |
831 | 0, | 847 | 0, |
832 | NFS4_MAX_UINT64, | 848 | NFS4_MAX_UINT64, |
833 | IOMODE_RW, | 849 | IOMODE_RW, |
834 | GFP_NOFS); | 850 | GFP_NOFS); |
851 | if (IS_ERR(pgio->pg_lseg)) { | ||
852 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | ||
853 | pgio->pg_lseg = NULL; | ||
854 | return; | ||
855 | } | ||
856 | } | ||
835 | /* If no lseg, fall back to write through mds */ | 857 | /* If no lseg, fall back to write through mds */ |
836 | if (pgio->pg_lseg == NULL) | 858 | if (pgio->pg_lseg == NULL) |
837 | goto out_mds; | 859 | goto out_mds; |
@@ -867,18 +889,25 @@ static unsigned int | |||
867 | ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio, | 889 | ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio, |
868 | struct nfs_page *req) | 890 | struct nfs_page *req) |
869 | { | 891 | { |
870 | if (!pgio->pg_lseg) | 892 | if (!pgio->pg_lseg) { |
871 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 893 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
872 | req->wb_context, | 894 | req->wb_context, |
873 | 0, | 895 | 0, |
874 | NFS4_MAX_UINT64, | 896 | NFS4_MAX_UINT64, |
875 | IOMODE_RW, | 897 | IOMODE_RW, |
876 | GFP_NOFS); | 898 | GFP_NOFS); |
899 | if (IS_ERR(pgio->pg_lseg)) { | ||
900 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | ||
901 | pgio->pg_lseg = NULL; | ||
902 | goto out; | ||
903 | } | ||
904 | } | ||
877 | if (pgio->pg_lseg) | 905 | if (pgio->pg_lseg) |
878 | return FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg); | 906 | return FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg); |
879 | 907 | ||
880 | /* no lseg means that pnfs is not in use, so no mirroring here */ | 908 | /* no lseg means that pnfs is not in use, so no mirroring here */ |
881 | nfs_pageio_reset_write_mds(pgio); | 909 | nfs_pageio_reset_write_mds(pgio); |
910 | out: | ||
882 | return 1; | 911 | return 1; |
883 | } | 912 | } |
884 | 913 | ||
@@ -1101,7 +1130,7 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task, | |||
1101 | return -NFS4ERR_RESET_TO_PNFS; | 1130 | return -NFS4ERR_RESET_TO_PNFS; |
1102 | out_retry: | 1131 | out_retry: |
1103 | task->tk_status = 0; | 1132 | task->tk_status = 0; |
1104 | rpc_restart_call(task); | 1133 | rpc_restart_call_prepare(task); |
1105 | rpc_delay(task, NFS_JUKEBOX_RETRY_TIME); | 1134 | rpc_delay(task, NFS_JUKEBOX_RETRY_TIME); |
1106 | return -EAGAIN; | 1135 | return -EAGAIN; |
1107 | } | 1136 | } |
@@ -1159,6 +1188,14 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, | |||
1159 | } | 1188 | } |
1160 | } | 1189 | } |
1161 | 1190 | ||
1191 | switch (status) { | ||
1192 | case NFS4ERR_DELAY: | ||
1193 | case NFS4ERR_GRACE: | ||
1194 | return; | ||
1195 | default: | ||
1196 | break; | ||
1197 | } | ||
1198 | |||
1162 | mirror = FF_LAYOUT_COMP(lseg, idx); | 1199 | mirror = FF_LAYOUT_COMP(lseg, idx); |
1163 | err = ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout), | 1200 | err = ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout), |
1164 | mirror, offset, length, status, opnum, | 1201 | mirror, offset, length, status, opnum, |
@@ -1242,14 +1279,31 @@ ff_layout_reset_to_mds(struct pnfs_layout_segment *lseg, int idx) | |||
1242 | return ff_layout_test_devid_unavailable(node); | 1279 | return ff_layout_test_devid_unavailable(node); |
1243 | } | 1280 | } |
1244 | 1281 | ||
1245 | static int ff_layout_read_prepare_common(struct rpc_task *task, | 1282 | static void ff_layout_read_record_layoutstats_start(struct rpc_task *task, |
1246 | struct nfs_pgio_header *hdr) | 1283 | struct nfs_pgio_header *hdr) |
1247 | { | 1284 | { |
1285 | if (test_and_set_bit(NFS_IOHDR_STAT, &hdr->flags)) | ||
1286 | return; | ||
1248 | nfs4_ff_layout_stat_io_start_read(hdr->inode, | 1287 | nfs4_ff_layout_stat_io_start_read(hdr->inode, |
1249 | FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), | 1288 | FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), |
1250 | hdr->args.count, | 1289 | hdr->args.count, |
1251 | task->tk_start); | 1290 | task->tk_start); |
1291 | } | ||
1252 | 1292 | ||
1293 | static void ff_layout_read_record_layoutstats_done(struct rpc_task *task, | ||
1294 | struct nfs_pgio_header *hdr) | ||
1295 | { | ||
1296 | if (!test_and_clear_bit(NFS_IOHDR_STAT, &hdr->flags)) | ||
1297 | return; | ||
1298 | nfs4_ff_layout_stat_io_end_read(task, | ||
1299 | FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), | ||
1300 | hdr->args.count, | ||
1301 | hdr->res.count); | ||
1302 | } | ||
1303 | |||
1304 | static int ff_layout_read_prepare_common(struct rpc_task *task, | ||
1305 | struct nfs_pgio_header *hdr) | ||
1306 | { | ||
1253 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { | 1307 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { |
1254 | rpc_exit(task, -EIO); | 1308 | rpc_exit(task, -EIO); |
1255 | return -EIO; | 1309 | return -EIO; |
@@ -1265,6 +1319,7 @@ static int ff_layout_read_prepare_common(struct rpc_task *task, | |||
1265 | } | 1319 | } |
1266 | hdr->pgio_done_cb = ff_layout_read_done_cb; | 1320 | hdr->pgio_done_cb = ff_layout_read_done_cb; |
1267 | 1321 | ||
1322 | ff_layout_read_record_layoutstats_start(task, hdr); | ||
1268 | return 0; | 1323 | return 0; |
1269 | } | 1324 | } |
1270 | 1325 | ||
@@ -1323,10 +1378,6 @@ static void ff_layout_read_call_done(struct rpc_task *task, void *data) | |||
1323 | 1378 | ||
1324 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); | 1379 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); |
1325 | 1380 | ||
1326 | nfs4_ff_layout_stat_io_end_read(task, | ||
1327 | FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), | ||
1328 | hdr->args.count, hdr->res.count); | ||
1329 | |||
1330 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && | 1381 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && |
1331 | task->tk_status == 0) { | 1382 | task->tk_status == 0) { |
1332 | nfs4_sequence_done(task, &hdr->res.seq_res); | 1383 | nfs4_sequence_done(task, &hdr->res.seq_res); |
@@ -1341,10 +1392,20 @@ static void ff_layout_read_count_stats(struct rpc_task *task, void *data) | |||
1341 | { | 1392 | { |
1342 | struct nfs_pgio_header *hdr = data; | 1393 | struct nfs_pgio_header *hdr = data; |
1343 | 1394 | ||
1395 | ff_layout_read_record_layoutstats_done(task, hdr); | ||
1344 | rpc_count_iostats_metrics(task, | 1396 | rpc_count_iostats_metrics(task, |
1345 | &NFS_CLIENT(hdr->inode)->cl_metrics[NFSPROC4_CLNT_READ]); | 1397 | &NFS_CLIENT(hdr->inode)->cl_metrics[NFSPROC4_CLNT_READ]); |
1346 | } | 1398 | } |
1347 | 1399 | ||
1400 | static void ff_layout_read_release(void *data) | ||
1401 | { | ||
1402 | struct nfs_pgio_header *hdr = data; | ||
1403 | |||
1404 | ff_layout_read_record_layoutstats_done(&hdr->task, hdr); | ||
1405 | pnfs_generic_rw_release(data); | ||
1406 | } | ||
1407 | |||
1408 | |||
1348 | static int ff_layout_write_done_cb(struct rpc_task *task, | 1409 | static int ff_layout_write_done_cb(struct rpc_task *task, |
1349 | struct nfs_pgio_header *hdr) | 1410 | struct nfs_pgio_header *hdr) |
1350 | { | 1411 | { |
@@ -1362,15 +1423,12 @@ static int ff_layout_write_done_cb(struct rpc_task *task, | |||
1362 | 1423 | ||
1363 | switch (err) { | 1424 | switch (err) { |
1364 | case -NFS4ERR_RESET_TO_PNFS: | 1425 | case -NFS4ERR_RESET_TO_PNFS: |
1365 | pnfs_set_retry_layoutget(hdr->lseg->pls_layout); | ||
1366 | ff_layout_reset_write(hdr, true); | 1426 | ff_layout_reset_write(hdr, true); |
1367 | return task->tk_status; | 1427 | return task->tk_status; |
1368 | case -NFS4ERR_RESET_TO_MDS: | 1428 | case -NFS4ERR_RESET_TO_MDS: |
1369 | pnfs_clear_retry_layoutget(hdr->lseg->pls_layout); | ||
1370 | ff_layout_reset_write(hdr, false); | 1429 | ff_layout_reset_write(hdr, false); |
1371 | return task->tk_status; | 1430 | return task->tk_status; |
1372 | case -EAGAIN: | 1431 | case -EAGAIN: |
1373 | rpc_restart_call_prepare(task); | ||
1374 | return -EAGAIN; | 1432 | return -EAGAIN; |
1375 | } | 1433 | } |
1376 | 1434 | ||
@@ -1402,11 +1460,9 @@ static int ff_layout_commit_done_cb(struct rpc_task *task, | |||
1402 | 1460 | ||
1403 | switch (err) { | 1461 | switch (err) { |
1404 | case -NFS4ERR_RESET_TO_PNFS: | 1462 | case -NFS4ERR_RESET_TO_PNFS: |
1405 | pnfs_set_retry_layoutget(data->lseg->pls_layout); | ||
1406 | pnfs_generic_prepare_to_resend_writes(data); | 1463 | pnfs_generic_prepare_to_resend_writes(data); |
1407 | return -EAGAIN; | 1464 | return -EAGAIN; |
1408 | case -NFS4ERR_RESET_TO_MDS: | 1465 | case -NFS4ERR_RESET_TO_MDS: |
1409 | pnfs_clear_retry_layoutget(data->lseg->pls_layout); | ||
1410 | pnfs_generic_prepare_to_resend_writes(data); | 1466 | pnfs_generic_prepare_to_resend_writes(data); |
1411 | return -EAGAIN; | 1467 | return -EAGAIN; |
1412 | case -EAGAIN: | 1468 | case -EAGAIN: |
@@ -1421,14 +1477,31 @@ static int ff_layout_commit_done_cb(struct rpc_task *task, | |||
1421 | return 0; | 1477 | return 0; |
1422 | } | 1478 | } |
1423 | 1479 | ||
1424 | static int ff_layout_write_prepare_common(struct rpc_task *task, | 1480 | static void ff_layout_write_record_layoutstats_start(struct rpc_task *task, |
1425 | struct nfs_pgio_header *hdr) | 1481 | struct nfs_pgio_header *hdr) |
1426 | { | 1482 | { |
1483 | if (test_and_set_bit(NFS_IOHDR_STAT, &hdr->flags)) | ||
1484 | return; | ||
1427 | nfs4_ff_layout_stat_io_start_write(hdr->inode, | 1485 | nfs4_ff_layout_stat_io_start_write(hdr->inode, |
1428 | FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), | 1486 | FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), |
1429 | hdr->args.count, | 1487 | hdr->args.count, |
1430 | task->tk_start); | 1488 | task->tk_start); |
1489 | } | ||
1490 | |||
1491 | static void ff_layout_write_record_layoutstats_done(struct rpc_task *task, | ||
1492 | struct nfs_pgio_header *hdr) | ||
1493 | { | ||
1494 | if (!test_and_clear_bit(NFS_IOHDR_STAT, &hdr->flags)) | ||
1495 | return; | ||
1496 | nfs4_ff_layout_stat_io_end_write(task, | ||
1497 | FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), | ||
1498 | hdr->args.count, hdr->res.count, | ||
1499 | hdr->res.verf->committed); | ||
1500 | } | ||
1431 | 1501 | ||
1502 | static int ff_layout_write_prepare_common(struct rpc_task *task, | ||
1503 | struct nfs_pgio_header *hdr) | ||
1504 | { | ||
1432 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { | 1505 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { |
1433 | rpc_exit(task, -EIO); | 1506 | rpc_exit(task, -EIO); |
1434 | return -EIO; | 1507 | return -EIO; |
@@ -1445,6 +1518,7 @@ static int ff_layout_write_prepare_common(struct rpc_task *task, | |||
1445 | return -EAGAIN; | 1518 | return -EAGAIN; |
1446 | } | 1519 | } |
1447 | 1520 | ||
1521 | ff_layout_write_record_layoutstats_start(task, hdr); | ||
1448 | return 0; | 1522 | return 0; |
1449 | } | 1523 | } |
1450 | 1524 | ||
@@ -1480,11 +1554,6 @@ static void ff_layout_write_call_done(struct rpc_task *task, void *data) | |||
1480 | { | 1554 | { |
1481 | struct nfs_pgio_header *hdr = data; | 1555 | struct nfs_pgio_header *hdr = data; |
1482 | 1556 | ||
1483 | nfs4_ff_layout_stat_io_end_write(task, | ||
1484 | FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), | ||
1485 | hdr->args.count, hdr->res.count, | ||
1486 | hdr->res.verf->committed); | ||
1487 | |||
1488 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && | 1557 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && |
1489 | task->tk_status == 0) { | 1558 | task->tk_status == 0) { |
1490 | nfs4_sequence_done(task, &hdr->res.seq_res); | 1559 | nfs4_sequence_done(task, &hdr->res.seq_res); |
@@ -1499,18 +1568,53 @@ static void ff_layout_write_count_stats(struct rpc_task *task, void *data) | |||
1499 | { | 1568 | { |
1500 | struct nfs_pgio_header *hdr = data; | 1569 | struct nfs_pgio_header *hdr = data; |
1501 | 1570 | ||
1571 | ff_layout_write_record_layoutstats_done(task, hdr); | ||
1502 | rpc_count_iostats_metrics(task, | 1572 | rpc_count_iostats_metrics(task, |
1503 | &NFS_CLIENT(hdr->inode)->cl_metrics[NFSPROC4_CLNT_WRITE]); | 1573 | &NFS_CLIENT(hdr->inode)->cl_metrics[NFSPROC4_CLNT_WRITE]); |
1504 | } | 1574 | } |
1505 | 1575 | ||
1506 | static void ff_layout_commit_prepare_common(struct rpc_task *task, | 1576 | static void ff_layout_write_release(void *data) |
1577 | { | ||
1578 | struct nfs_pgio_header *hdr = data; | ||
1579 | |||
1580 | ff_layout_write_record_layoutstats_done(&hdr->task, hdr); | ||
1581 | pnfs_generic_rw_release(data); | ||
1582 | } | ||
1583 | |||
1584 | static void ff_layout_commit_record_layoutstats_start(struct rpc_task *task, | ||
1507 | struct nfs_commit_data *cdata) | 1585 | struct nfs_commit_data *cdata) |
1508 | { | 1586 | { |
1587 | if (test_and_set_bit(NFS_IOHDR_STAT, &cdata->flags)) | ||
1588 | return; | ||
1509 | nfs4_ff_layout_stat_io_start_write(cdata->inode, | 1589 | nfs4_ff_layout_stat_io_start_write(cdata->inode, |
1510 | FF_LAYOUT_COMP(cdata->lseg, cdata->ds_commit_index), | 1590 | FF_LAYOUT_COMP(cdata->lseg, cdata->ds_commit_index), |
1511 | 0, task->tk_start); | 1591 | 0, task->tk_start); |
1512 | } | 1592 | } |
1513 | 1593 | ||
1594 | static void ff_layout_commit_record_layoutstats_done(struct rpc_task *task, | ||
1595 | struct nfs_commit_data *cdata) | ||
1596 | { | ||
1597 | struct nfs_page *req; | ||
1598 | __u64 count = 0; | ||
1599 | |||
1600 | if (!test_and_clear_bit(NFS_IOHDR_STAT, &cdata->flags)) | ||
1601 | return; | ||
1602 | |||
1603 | if (task->tk_status == 0) { | ||
1604 | list_for_each_entry(req, &cdata->pages, wb_list) | ||
1605 | count += req->wb_bytes; | ||
1606 | } | ||
1607 | nfs4_ff_layout_stat_io_end_write(task, | ||
1608 | FF_LAYOUT_COMP(cdata->lseg, cdata->ds_commit_index), | ||
1609 | count, count, NFS_FILE_SYNC); | ||
1610 | } | ||
1611 | |||
1612 | static void ff_layout_commit_prepare_common(struct rpc_task *task, | ||
1613 | struct nfs_commit_data *cdata) | ||
1614 | { | ||
1615 | ff_layout_commit_record_layoutstats_start(task, cdata); | ||
1616 | } | ||
1617 | |||
1514 | static void ff_layout_commit_prepare_v3(struct rpc_task *task, void *data) | 1618 | static void ff_layout_commit_prepare_v3(struct rpc_task *task, void *data) |
1515 | { | 1619 | { |
1516 | ff_layout_commit_prepare_common(task, data); | 1620 | ff_layout_commit_prepare_common(task, data); |
@@ -1531,19 +1635,6 @@ static void ff_layout_commit_prepare_v4(struct rpc_task *task, void *data) | |||
1531 | 1635 | ||
1532 | static void ff_layout_commit_done(struct rpc_task *task, void *data) | 1636 | static void ff_layout_commit_done(struct rpc_task *task, void *data) |
1533 | { | 1637 | { |
1534 | struct nfs_commit_data *cdata = data; | ||
1535 | struct nfs_page *req; | ||
1536 | __u64 count = 0; | ||
1537 | |||
1538 | if (task->tk_status == 0) { | ||
1539 | list_for_each_entry(req, &cdata->pages, wb_list) | ||
1540 | count += req->wb_bytes; | ||
1541 | } | ||
1542 | |||
1543 | nfs4_ff_layout_stat_io_end_write(task, | ||
1544 | FF_LAYOUT_COMP(cdata->lseg, cdata->ds_commit_index), | ||
1545 | count, count, NFS_FILE_SYNC); | ||
1546 | |||
1547 | pnfs_generic_write_commit_done(task, data); | 1638 | pnfs_generic_write_commit_done(task, data); |
1548 | } | 1639 | } |
1549 | 1640 | ||
@@ -1551,50 +1642,59 @@ static void ff_layout_commit_count_stats(struct rpc_task *task, void *data) | |||
1551 | { | 1642 | { |
1552 | struct nfs_commit_data *cdata = data; | 1643 | struct nfs_commit_data *cdata = data; |
1553 | 1644 | ||
1645 | ff_layout_commit_record_layoutstats_done(task, cdata); | ||
1554 | rpc_count_iostats_metrics(task, | 1646 | rpc_count_iostats_metrics(task, |
1555 | &NFS_CLIENT(cdata->inode)->cl_metrics[NFSPROC4_CLNT_COMMIT]); | 1647 | &NFS_CLIENT(cdata->inode)->cl_metrics[NFSPROC4_CLNT_COMMIT]); |
1556 | } | 1648 | } |
1557 | 1649 | ||
1650 | static void ff_layout_commit_release(void *data) | ||
1651 | { | ||
1652 | struct nfs_commit_data *cdata = data; | ||
1653 | |||
1654 | ff_layout_commit_record_layoutstats_done(&cdata->task, cdata); | ||
1655 | pnfs_generic_commit_release(data); | ||
1656 | } | ||
1657 | |||
1558 | static const struct rpc_call_ops ff_layout_read_call_ops_v3 = { | 1658 | static const struct rpc_call_ops ff_layout_read_call_ops_v3 = { |
1559 | .rpc_call_prepare = ff_layout_read_prepare_v3, | 1659 | .rpc_call_prepare = ff_layout_read_prepare_v3, |
1560 | .rpc_call_done = ff_layout_read_call_done, | 1660 | .rpc_call_done = ff_layout_read_call_done, |
1561 | .rpc_count_stats = ff_layout_read_count_stats, | 1661 | .rpc_count_stats = ff_layout_read_count_stats, |
1562 | .rpc_release = pnfs_generic_rw_release, | 1662 | .rpc_release = ff_layout_read_release, |
1563 | }; | 1663 | }; |
1564 | 1664 | ||
1565 | static const struct rpc_call_ops ff_layout_read_call_ops_v4 = { | 1665 | static const struct rpc_call_ops ff_layout_read_call_ops_v4 = { |
1566 | .rpc_call_prepare = ff_layout_read_prepare_v4, | 1666 | .rpc_call_prepare = ff_layout_read_prepare_v4, |
1567 | .rpc_call_done = ff_layout_read_call_done, | 1667 | .rpc_call_done = ff_layout_read_call_done, |
1568 | .rpc_count_stats = ff_layout_read_count_stats, | 1668 | .rpc_count_stats = ff_layout_read_count_stats, |
1569 | .rpc_release = pnfs_generic_rw_release, | 1669 | .rpc_release = ff_layout_read_release, |
1570 | }; | 1670 | }; |
1571 | 1671 | ||
1572 | static const struct rpc_call_ops ff_layout_write_call_ops_v3 = { | 1672 | static const struct rpc_call_ops ff_layout_write_call_ops_v3 = { |
1573 | .rpc_call_prepare = ff_layout_write_prepare_v3, | 1673 | .rpc_call_prepare = ff_layout_write_prepare_v3, |
1574 | .rpc_call_done = ff_layout_write_call_done, | 1674 | .rpc_call_done = ff_layout_write_call_done, |
1575 | .rpc_count_stats = ff_layout_write_count_stats, | 1675 | .rpc_count_stats = ff_layout_write_count_stats, |
1576 | .rpc_release = pnfs_generic_rw_release, | 1676 | .rpc_release = ff_layout_write_release, |
1577 | }; | 1677 | }; |
1578 | 1678 | ||
1579 | static const struct rpc_call_ops ff_layout_write_call_ops_v4 = { | 1679 | static const struct rpc_call_ops ff_layout_write_call_ops_v4 = { |
1580 | .rpc_call_prepare = ff_layout_write_prepare_v4, | 1680 | .rpc_call_prepare = ff_layout_write_prepare_v4, |
1581 | .rpc_call_done = ff_layout_write_call_done, | 1681 | .rpc_call_done = ff_layout_write_call_done, |
1582 | .rpc_count_stats = ff_layout_write_count_stats, | 1682 | .rpc_count_stats = ff_layout_write_count_stats, |
1583 | .rpc_release = pnfs_generic_rw_release, | 1683 | .rpc_release = ff_layout_write_release, |
1584 | }; | 1684 | }; |
1585 | 1685 | ||
1586 | static const struct rpc_call_ops ff_layout_commit_call_ops_v3 = { | 1686 | static const struct rpc_call_ops ff_layout_commit_call_ops_v3 = { |
1587 | .rpc_call_prepare = ff_layout_commit_prepare_v3, | 1687 | .rpc_call_prepare = ff_layout_commit_prepare_v3, |
1588 | .rpc_call_done = ff_layout_commit_done, | 1688 | .rpc_call_done = ff_layout_commit_done, |
1589 | .rpc_count_stats = ff_layout_commit_count_stats, | 1689 | .rpc_count_stats = ff_layout_commit_count_stats, |
1590 | .rpc_release = pnfs_generic_commit_release, | 1690 | .rpc_release = ff_layout_commit_release, |
1591 | }; | 1691 | }; |
1592 | 1692 | ||
1593 | static const struct rpc_call_ops ff_layout_commit_call_ops_v4 = { | 1693 | static const struct rpc_call_ops ff_layout_commit_call_ops_v4 = { |
1594 | .rpc_call_prepare = ff_layout_commit_prepare_v4, | 1694 | .rpc_call_prepare = ff_layout_commit_prepare_v4, |
1595 | .rpc_call_done = ff_layout_commit_done, | 1695 | .rpc_call_done = ff_layout_commit_done, |
1596 | .rpc_count_stats = ff_layout_commit_count_stats, | 1696 | .rpc_count_stats = ff_layout_commit_count_stats, |
1597 | .rpc_release = pnfs_generic_commit_release, | 1697 | .rpc_release = ff_layout_commit_release, |
1598 | }; | 1698 | }; |
1599 | 1699 | ||
1600 | static enum pnfs_try_status | 1700 | static enum pnfs_try_status |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.h b/fs/nfs/flexfilelayout/flexfilelayout.h index 2bb08bc6aaf0..dd353bb7dc0a 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.h +++ b/fs/nfs/flexfilelayout/flexfilelayout.h | |||
@@ -85,6 +85,7 @@ struct nfs4_ff_layout_mirror { | |||
85 | struct nfs4_ff_layoutstat write_stat; | 85 | struct nfs4_ff_layoutstat write_stat; |
86 | ktime_t start_time; | 86 | ktime_t start_time; |
87 | ktime_t last_report_time; | 87 | ktime_t last_report_time; |
88 | u32 report_interval; | ||
88 | }; | 89 | }; |
89 | 90 | ||
90 | struct nfs4_ff_layout_segment { | 91 | struct nfs4_ff_layout_segment { |
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c index e125e55de86d..bd0327541366 100644 --- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c +++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c | |||
@@ -429,22 +429,14 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx, | |||
429 | mirror, lseg->pls_range.offset, | 429 | mirror, lseg->pls_range.offset, |
430 | lseg->pls_range.length, NFS4ERR_NXIO, | 430 | lseg->pls_range.length, NFS4ERR_NXIO, |
431 | OP_ILLEGAL, GFP_NOIO); | 431 | OP_ILLEGAL, GFP_NOIO); |
432 | if (fail_return) { | 432 | if (!fail_return) { |
433 | pnfs_error_mark_layout_for_return(ino, lseg); | ||
434 | if (ff_layout_has_available_ds(lseg)) | ||
435 | pnfs_set_retry_layoutget(lseg->pls_layout); | ||
436 | else | ||
437 | pnfs_clear_retry_layoutget(lseg->pls_layout); | ||
438 | |||
439 | } else { | ||
440 | if (ff_layout_has_available_ds(lseg)) | 433 | if (ff_layout_has_available_ds(lseg)) |
441 | set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, | 434 | set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, |
442 | &lseg->pls_layout->plh_flags); | 435 | &lseg->pls_layout->plh_flags); |
443 | else { | 436 | else |
444 | pnfs_error_mark_layout_for_return(ino, lseg); | 437 | pnfs_error_mark_layout_for_return(ino, lseg); |
445 | pnfs_clear_retry_layoutget(lseg->pls_layout); | 438 | } else |
446 | } | 439 | pnfs_error_mark_layout_for_return(ino, lseg); |
447 | } | ||
448 | } | 440 | } |
449 | out_update_creds: | 441 | out_update_creds: |
450 | if (ff_layout_update_mirror_cred(mirror, ds)) | 442 | if (ff_layout_update_mirror_cred(mirror, ds)) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c7e8b87da5b2..74fb1223c2f5 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -912,6 +912,12 @@ void nfs_file_clear_open_context(struct file *filp) | |||
912 | if (ctx) { | 912 | if (ctx) { |
913 | struct inode *inode = d_inode(ctx->dentry); | 913 | struct inode *inode = d_inode(ctx->dentry); |
914 | 914 | ||
915 | /* | ||
916 | * We fatal error on write before. Try to writeback | ||
917 | * every page again. | ||
918 | */ | ||
919 | if (ctx->error < 0) | ||
920 | invalidate_inode_pages2(inode->i_mapping); | ||
915 | filp->private_data = NULL; | 921 | filp->private_data = NULL; |
916 | spin_lock(&inode->i_lock); | 922 | spin_lock(&inode->i_lock); |
917 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); | 923 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 313d55402238..68f773dc226e 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -711,3 +711,17 @@ static inline u32 nfs_stateid_hash(nfs4_stateid *stateid) | |||
711 | return 0; | 711 | return 0; |
712 | } | 712 | } |
713 | #endif | 713 | #endif |
714 | |||
715 | static inline bool nfs_error_is_fatal(int err) | ||
716 | { | ||
717 | switch (err) { | ||
718 | case -ERESTARTSYS: | ||
719 | case -EIO: | ||
720 | case -ENOSPC: | ||
721 | case -EROFS: | ||
722 | case -E2BIG: | ||
723 | return true; | ||
724 | default: | ||
725 | return false; | ||
726 | } | ||
727 | } | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a7d564a83665..adae525edec4 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -7811,6 +7811,15 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
7811 | switch (task->tk_status) { | 7811 | switch (task->tk_status) { |
7812 | case 0: | 7812 | case 0: |
7813 | goto out; | 7813 | goto out; |
7814 | |||
7815 | /* | ||
7816 | * NFS4ERR_LAYOUTUNAVAILABLE means we are not supposed to use pnfs | ||
7817 | * on the file. set tk_status to -ENODATA to tell upper layer to | ||
7818 | * retry go inband. | ||
7819 | */ | ||
7820 | case -NFS4ERR_LAYOUTUNAVAILABLE: | ||
7821 | task->tk_status = -ENODATA; | ||
7822 | goto out; | ||
7814 | /* | 7823 | /* |
7815 | * NFS4ERR_BADLAYOUT means the MDS cannot return a layout of | 7824 | * NFS4ERR_BADLAYOUT means the MDS cannot return a layout of |
7816 | * length lgp->args.minlength != 0 (see RFC5661 section 18.43.3). | 7825 | * length lgp->args.minlength != 0 (see RFC5661 section 18.43.3). |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 452a011ba0d8..7c71b71016b5 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -664,22 +664,11 @@ EXPORT_SYMBOL_GPL(nfs_initiate_pgio); | |||
664 | * @desc: IO descriptor | 664 | * @desc: IO descriptor |
665 | * @hdr: pageio header | 665 | * @hdr: pageio header |
666 | */ | 666 | */ |
667 | static int nfs_pgio_error(struct nfs_pageio_descriptor *desc, | 667 | static void nfs_pgio_error(struct nfs_pgio_header *hdr) |
668 | struct nfs_pgio_header *hdr) | ||
669 | { | 668 | { |
670 | struct nfs_pgio_mirror *mirror; | ||
671 | u32 midx; | ||
672 | |||
673 | set_bit(NFS_IOHDR_REDO, &hdr->flags); | 669 | set_bit(NFS_IOHDR_REDO, &hdr->flags); |
674 | nfs_pgio_data_destroy(hdr); | 670 | nfs_pgio_data_destroy(hdr); |
675 | hdr->completion_ops->completion(hdr); | 671 | hdr->completion_ops->completion(hdr); |
676 | /* TODO: Make sure it's right to clean up all mirrors here | ||
677 | * and not just hdr->pgio_mirror_idx */ | ||
678 | for (midx = 0; midx < desc->pg_mirror_count; midx++) { | ||
679 | mirror = &desc->pg_mirrors[midx]; | ||
680 | desc->pg_completion_ops->error_cleanup(&mirror->pg_list); | ||
681 | } | ||
682 | return -ENOMEM; | ||
683 | } | 672 | } |
684 | 673 | ||
685 | /** | 674 | /** |
@@ -800,8 +789,11 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, | |||
800 | unsigned int pagecount, pageused; | 789 | unsigned int pagecount, pageused; |
801 | 790 | ||
802 | pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count); | 791 | pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count); |
803 | if (!nfs_pgarray_set(&hdr->page_array, pagecount)) | 792 | if (!nfs_pgarray_set(&hdr->page_array, pagecount)) { |
804 | return nfs_pgio_error(desc, hdr); | 793 | nfs_pgio_error(hdr); |
794 | desc->pg_error = -ENOMEM; | ||
795 | return desc->pg_error; | ||
796 | } | ||
805 | 797 | ||
806 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); | 798 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); |
807 | pages = hdr->page_array.pagevec; | 799 | pages = hdr->page_array.pagevec; |
@@ -819,8 +811,11 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, | |||
819 | *pages++ = last_page = req->wb_page; | 811 | *pages++ = last_page = req->wb_page; |
820 | } | 812 | } |
821 | } | 813 | } |
822 | if (WARN_ON_ONCE(pageused != pagecount)) | 814 | if (WARN_ON_ONCE(pageused != pagecount)) { |
823 | return nfs_pgio_error(desc, hdr); | 815 | nfs_pgio_error(hdr); |
816 | desc->pg_error = -EINVAL; | ||
817 | return desc->pg_error; | ||
818 | } | ||
824 | 819 | ||
825 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | 820 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && |
826 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo))) | 821 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo))) |
@@ -843,10 +838,8 @@ static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc) | |||
843 | 838 | ||
844 | hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); | 839 | hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); |
845 | if (!hdr) { | 840 | if (!hdr) { |
846 | /* TODO: make sure this is right with mirroring - or | 841 | desc->pg_error = -ENOMEM; |
847 | * should it back out all mirrors? */ | 842 | return desc->pg_error; |
848 | desc->pg_completion_ops->error_cleanup(&mirror->pg_list); | ||
849 | return -ENOMEM; | ||
850 | } | 843 | } |
851 | nfs_pgheader_init(desc, hdr, nfs_pgio_header_free); | 844 | nfs_pgheader_init(desc, hdr, nfs_pgio_header_free); |
852 | ret = nfs_generic_pgio(desc, hdr); | 845 | ret = nfs_generic_pgio(desc, hdr); |
@@ -874,6 +867,9 @@ static int nfs_pageio_setup_mirroring(struct nfs_pageio_descriptor *pgio, | |||
874 | 867 | ||
875 | mirror_count = pgio->pg_ops->pg_get_mirror_count(pgio, req); | 868 | mirror_count = pgio->pg_ops->pg_get_mirror_count(pgio, req); |
876 | 869 | ||
870 | if (pgio->pg_error < 0) | ||
871 | return pgio->pg_error; | ||
872 | |||
877 | if (!mirror_count || mirror_count > NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX) | 873 | if (!mirror_count || mirror_count > NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX) |
878 | return -EINVAL; | 874 | return -EINVAL; |
879 | 875 | ||
@@ -982,6 +978,8 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, | |||
982 | } else { | 978 | } else { |
983 | if (desc->pg_ops->pg_init) | 979 | if (desc->pg_ops->pg_init) |
984 | desc->pg_ops->pg_init(desc, req); | 980 | desc->pg_ops->pg_init(desc, req); |
981 | if (desc->pg_error < 0) | ||
982 | return 0; | ||
985 | mirror->pg_base = req->wb_pgbase; | 983 | mirror->pg_base = req->wb_pgbase; |
986 | } | 984 | } |
987 | if (!nfs_can_coalesce_requests(prev, req, desc)) | 985 | if (!nfs_can_coalesce_requests(prev, req, desc)) |
@@ -1147,6 +1145,8 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, | |||
1147 | bytes = req->wb_bytes; | 1145 | bytes = req->wb_bytes; |
1148 | 1146 | ||
1149 | nfs_pageio_setup_mirroring(desc, req); | 1147 | nfs_pageio_setup_mirroring(desc, req); |
1148 | if (desc->pg_error < 0) | ||
1149 | goto out_failed; | ||
1150 | 1150 | ||
1151 | for (midx = 0; midx < desc->pg_mirror_count; midx++) { | 1151 | for (midx = 0; midx < desc->pg_mirror_count; midx++) { |
1152 | if (midx) { | 1152 | if (midx) { |
@@ -1163,7 +1163,8 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, | |||
1163 | 1163 | ||
1164 | if (IS_ERR(dupreq)) { | 1164 | if (IS_ERR(dupreq)) { |
1165 | nfs_page_group_unlock(req); | 1165 | nfs_page_group_unlock(req); |
1166 | return 0; | 1166 | desc->pg_error = PTR_ERR(dupreq); |
1167 | goto out_failed; | ||
1167 | } | 1168 | } |
1168 | 1169 | ||
1169 | nfs_lock_request(dupreq); | 1170 | nfs_lock_request(dupreq); |
@@ -1176,10 +1177,32 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, | |||
1176 | if (nfs_pgio_has_mirroring(desc)) | 1177 | if (nfs_pgio_has_mirroring(desc)) |
1177 | desc->pg_mirror_idx = midx; | 1178 | desc->pg_mirror_idx = midx; |
1178 | if (!nfs_pageio_add_request_mirror(desc, dupreq)) | 1179 | if (!nfs_pageio_add_request_mirror(desc, dupreq)) |
1179 | return 0; | 1180 | goto out_failed; |
1180 | } | 1181 | } |
1181 | 1182 | ||
1182 | return 1; | 1183 | return 1; |
1184 | |||
1185 | out_failed: | ||
1186 | /* | ||
1187 | * We might have failed before sending any reqs over wire. | ||
1188 | * Clean up rest of the reqs in mirror pg_list. | ||
1189 | */ | ||
1190 | if (desc->pg_error) { | ||
1191 | struct nfs_pgio_mirror *mirror; | ||
1192 | void (*func)(struct list_head *); | ||
1193 | |||
1194 | /* remember fatal errors */ | ||
1195 | if (nfs_error_is_fatal(desc->pg_error)) | ||
1196 | mapping_set_error(desc->pg_inode->i_mapping, | ||
1197 | desc->pg_error); | ||
1198 | |||
1199 | func = desc->pg_completion_ops->error_cleanup; | ||
1200 | for (midx = 0; midx < desc->pg_mirror_count; midx++) { | ||
1201 | mirror = &desc->pg_mirrors[midx]; | ||
1202 | func(&mirror->pg_list); | ||
1203 | } | ||
1204 | } | ||
1205 | return 0; | ||
1183 | } | 1206 | } |
1184 | 1207 | ||
1185 | /* | 1208 | /* |
@@ -1232,7 +1255,7 @@ int nfs_pageio_resend(struct nfs_pageio_descriptor *desc, | |||
1232 | nfs_pageio_complete(desc); | 1255 | nfs_pageio_complete(desc); |
1233 | if (!list_empty(&failed)) { | 1256 | if (!list_empty(&failed)) { |
1234 | list_move(&failed, &hdr->pages); | 1257 | list_move(&failed, &hdr->pages); |
1235 | return -EIO; | 1258 | return desc->pg_error < 0 ? desc->pg_error : -EIO; |
1236 | } | 1259 | } |
1237 | return 0; | 1260 | return 0; |
1238 | } | 1261 | } |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 6095a8d42766..113c3b327e24 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -618,7 +618,6 @@ pnfs_destroy_layout(struct nfs_inode *nfsi) | |||
618 | pnfs_get_layout_hdr(lo); | 618 | pnfs_get_layout_hdr(lo); |
619 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED); | 619 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED); |
620 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED); | 620 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED); |
621 | pnfs_clear_retry_layoutget(lo); | ||
622 | spin_unlock(&nfsi->vfs_inode.i_lock); | 621 | spin_unlock(&nfsi->vfs_inode.i_lock); |
623 | pnfs_free_lseg_list(&tmp_list); | 622 | pnfs_free_lseg_list(&tmp_list); |
624 | pnfs_put_layout_hdr(lo); | 623 | pnfs_put_layout_hdr(lo); |
@@ -904,17 +903,9 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
904 | lseg = nfs4_proc_layoutget(lgp, gfp_flags); | 903 | lseg = nfs4_proc_layoutget(lgp, gfp_flags); |
905 | } while (lseg == ERR_PTR(-EAGAIN)); | 904 | } while (lseg == ERR_PTR(-EAGAIN)); |
906 | 905 | ||
907 | if (IS_ERR(lseg)) { | 906 | if (IS_ERR(lseg) && !nfs_error_is_fatal(PTR_ERR(lseg))) |
908 | switch (PTR_ERR(lseg)) { | 907 | lseg = NULL; |
909 | case -ENOMEM: | 908 | else |
910 | case -ERESTARTSYS: | ||
911 | break; | ||
912 | default: | ||
913 | /* remember that LAYOUTGET failed and suspend trying */ | ||
914 | pnfs_layout_io_set_failed(lo, range->iomode); | ||
915 | } | ||
916 | return NULL; | ||
917 | } else | ||
918 | pnfs_layout_clear_fail_bit(lo, | 909 | pnfs_layout_clear_fail_bit(lo, |
919 | pnfs_iomode_to_fail_bit(range->iomode)); | 910 | pnfs_iomode_to_fail_bit(range->iomode)); |
920 | 911 | ||
@@ -1102,7 +1093,6 @@ bool pnfs_roc(struct inode *ino) | |||
1102 | &lo->plh_flags)) | 1093 | &lo->plh_flags)) |
1103 | layoutreturn = pnfs_prepare_layoutreturn(lo); | 1094 | layoutreturn = pnfs_prepare_layoutreturn(lo); |
1104 | 1095 | ||
1105 | pnfs_clear_retry_layoutget(lo); | ||
1106 | list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) | 1096 | list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) |
1107 | /* If we are sending layoutreturn, invalidate all valid lsegs */ | 1097 | /* If we are sending layoutreturn, invalidate all valid lsegs */ |
1108 | if (layoutreturn || test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { | 1098 | if (layoutreturn || test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { |
@@ -1465,25 +1455,15 @@ static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx, | |||
1465 | return ret; | 1455 | return ret; |
1466 | } | 1456 | } |
1467 | 1457 | ||
1468 | /* stop waiting if someone clears NFS_LAYOUT_RETRY_LAYOUTGET bit. */ | ||
1469 | static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key, int mode) | ||
1470 | { | ||
1471 | if (!test_bit(NFS_LAYOUT_RETRY_LAYOUTGET, key->flags)) | ||
1472 | return 1; | ||
1473 | return nfs_wait_bit_killable(key, mode); | ||
1474 | } | ||
1475 | |||
1476 | static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo) | 1458 | static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo) |
1477 | { | 1459 | { |
1478 | if (!pnfs_should_retry_layoutget(lo)) | ||
1479 | return false; | ||
1480 | /* | 1460 | /* |
1481 | * send layoutcommit as it can hold up layoutreturn due to lseg | 1461 | * send layoutcommit as it can hold up layoutreturn due to lseg |
1482 | * reference | 1462 | * reference |
1483 | */ | 1463 | */ |
1484 | pnfs_layoutcommit_inode(lo->plh_inode, false); | 1464 | pnfs_layoutcommit_inode(lo->plh_inode, false); |
1485 | return !wait_on_bit_action(&lo->plh_flags, NFS_LAYOUT_RETURN, | 1465 | return !wait_on_bit_action(&lo->plh_flags, NFS_LAYOUT_RETURN, |
1486 | pnfs_layoutget_retry_bit_wait, | 1466 | nfs_wait_bit_killable, |
1487 | TASK_UNINTERRUPTIBLE); | 1467 | TASK_UNINTERRUPTIBLE); |
1488 | } | 1468 | } |
1489 | 1469 | ||
@@ -1558,8 +1538,7 @@ lookup_again: | |||
1558 | } | 1538 | } |
1559 | 1539 | ||
1560 | /* if LAYOUTGET already failed once we don't try again */ | 1540 | /* if LAYOUTGET already failed once we don't try again */ |
1561 | if (pnfs_layout_io_test_failed(lo, iomode) && | 1541 | if (pnfs_layout_io_test_failed(lo, iomode)) { |
1562 | !pnfs_should_retry_layoutget(lo)) { | ||
1563 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, | 1542 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, |
1564 | PNFS_UPDATE_LAYOUT_IO_TEST_FAIL); | 1543 | PNFS_UPDATE_LAYOUT_IO_TEST_FAIL); |
1565 | goto out_unlock; | 1544 | goto out_unlock; |
@@ -1636,7 +1615,6 @@ lookup_again: | |||
1636 | arg.length = PAGE_CACHE_ALIGN(arg.length); | 1615 | arg.length = PAGE_CACHE_ALIGN(arg.length); |
1637 | 1616 | ||
1638 | lseg = send_layoutget(lo, ctx, &arg, gfp_flags); | 1617 | lseg = send_layoutget(lo, ctx, &arg, gfp_flags); |
1639 | pnfs_clear_retry_layoutget(lo); | ||
1640 | atomic_dec(&lo->plh_outstanding); | 1618 | atomic_dec(&lo->plh_outstanding); |
1641 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, | 1619 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, |
1642 | PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET); | 1620 | PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET); |
@@ -1649,7 +1627,7 @@ out: | |||
1649 | "(%s, offset: %llu, length: %llu)\n", | 1627 | "(%s, offset: %llu, length: %llu)\n", |
1650 | __func__, ino->i_sb->s_id, | 1628 | __func__, ino->i_sb->s_id, |
1651 | (unsigned long long)NFS_FILEID(ino), | 1629 | (unsigned long long)NFS_FILEID(ino), |
1652 | lseg == NULL ? "not found" : "found", | 1630 | IS_ERR_OR_NULL(lseg) ? "not found" : "found", |
1653 | iomode==IOMODE_RW ? "read/write" : "read-only", | 1631 | iomode==IOMODE_RW ? "read/write" : "read-only", |
1654 | (unsigned long long)pos, | 1632 | (unsigned long long)pos, |
1655 | (unsigned long long)count); | 1633 | (unsigned long long)count); |
@@ -1785,7 +1763,6 @@ void pnfs_error_mark_layout_for_return(struct inode *inode, | |||
1785 | struct pnfs_layout_segment *lseg) | 1763 | struct pnfs_layout_segment *lseg) |
1786 | { | 1764 | { |
1787 | struct pnfs_layout_hdr *lo = NFS_I(inode)->layout; | 1765 | struct pnfs_layout_hdr *lo = NFS_I(inode)->layout; |
1788 | int iomode = pnfs_iomode_to_fail_bit(lseg->pls_range.iomode); | ||
1789 | struct pnfs_layout_range range = { | 1766 | struct pnfs_layout_range range = { |
1790 | .iomode = lseg->pls_range.iomode, | 1767 | .iomode = lseg->pls_range.iomode, |
1791 | .offset = 0, | 1768 | .offset = 0, |
@@ -1794,8 +1771,6 @@ void pnfs_error_mark_layout_for_return(struct inode *inode, | |||
1794 | LIST_HEAD(free_me); | 1771 | LIST_HEAD(free_me); |
1795 | 1772 | ||
1796 | spin_lock(&inode->i_lock); | 1773 | spin_lock(&inode->i_lock); |
1797 | /* set failure bit so that pnfs path will be retried later */ | ||
1798 | pnfs_layout_set_fail_bit(lo, iomode); | ||
1799 | if (lo->plh_return_iomode == 0) | 1774 | if (lo->plh_return_iomode == 0) |
1800 | lo->plh_return_iomode = range.iomode; | 1775 | lo->plh_return_iomode = range.iomode; |
1801 | else if (lo->plh_return_iomode != range.iomode) | 1776 | else if (lo->plh_return_iomode != range.iomode) |
@@ -1828,6 +1803,11 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r | |||
1828 | rd_size, | 1803 | rd_size, |
1829 | IOMODE_READ, | 1804 | IOMODE_READ, |
1830 | GFP_KERNEL); | 1805 | GFP_KERNEL); |
1806 | if (IS_ERR(pgio->pg_lseg)) { | ||
1807 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | ||
1808 | pgio->pg_lseg = NULL; | ||
1809 | return; | ||
1810 | } | ||
1831 | } | 1811 | } |
1832 | /* If no lseg, fall back to read through mds */ | 1812 | /* If no lseg, fall back to read through mds */ |
1833 | if (pgio->pg_lseg == NULL) | 1813 | if (pgio->pg_lseg == NULL) |
@@ -1840,13 +1820,19 @@ void | |||
1840 | pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, | 1820 | pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, |
1841 | struct nfs_page *req, u64 wb_size) | 1821 | struct nfs_page *req, u64 wb_size) |
1842 | { | 1822 | { |
1843 | if (pgio->pg_lseg == NULL) | 1823 | if (pgio->pg_lseg == NULL) { |
1844 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 1824 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
1845 | req->wb_context, | 1825 | req->wb_context, |
1846 | req_offset(req), | 1826 | req_offset(req), |
1847 | wb_size, | 1827 | wb_size, |
1848 | IOMODE_RW, | 1828 | IOMODE_RW, |
1849 | GFP_NOFS); | 1829 | GFP_NOFS); |
1830 | if (IS_ERR(pgio->pg_lseg)) { | ||
1831 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | ||
1832 | pgio->pg_lseg = NULL; | ||
1833 | return; | ||
1834 | } | ||
1835 | } | ||
1850 | /* If no lseg, fall back to write through mds */ | 1836 | /* If no lseg, fall back to write through mds */ |
1851 | if (pgio->pg_lseg == NULL) | 1837 | if (pgio->pg_lseg == NULL) |
1852 | nfs_pageio_reset_write_mds(pgio); | 1838 | nfs_pageio_reset_write_mds(pgio); |
@@ -2014,15 +2000,13 @@ static void pnfs_writehdr_free(struct nfs_pgio_header *hdr) | |||
2014 | int | 2000 | int |
2015 | pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | 2001 | pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) |
2016 | { | 2002 | { |
2017 | struct nfs_pgio_mirror *mirror = nfs_pgio_current_mirror(desc); | ||
2018 | |||
2019 | struct nfs_pgio_header *hdr; | 2003 | struct nfs_pgio_header *hdr; |
2020 | int ret; | 2004 | int ret; |
2021 | 2005 | ||
2022 | hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); | 2006 | hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); |
2023 | if (!hdr) { | 2007 | if (!hdr) { |
2024 | desc->pg_completion_ops->error_cleanup(&mirror->pg_list); | 2008 | desc->pg_error = -ENOMEM; |
2025 | return -ENOMEM; | 2009 | return desc->pg_error; |
2026 | } | 2010 | } |
2027 | nfs_pgheader_init(desc, hdr, pnfs_writehdr_free); | 2011 | nfs_pgheader_init(desc, hdr, pnfs_writehdr_free); |
2028 | 2012 | ||
@@ -2145,15 +2129,13 @@ static void pnfs_readhdr_free(struct nfs_pgio_header *hdr) | |||
2145 | int | 2129 | int |
2146 | pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | 2130 | pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) |
2147 | { | 2131 | { |
2148 | struct nfs_pgio_mirror *mirror = nfs_pgio_current_mirror(desc); | ||
2149 | |||
2150 | struct nfs_pgio_header *hdr; | 2132 | struct nfs_pgio_header *hdr; |
2151 | int ret; | 2133 | int ret; |
2152 | 2134 | ||
2153 | hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); | 2135 | hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); |
2154 | if (!hdr) { | 2136 | if (!hdr) { |
2155 | desc->pg_completion_ops->error_cleanup(&mirror->pg_list); | 2137 | desc->pg_error = -ENOMEM; |
2156 | return -ENOMEM; | 2138 | return desc->pg_error; |
2157 | } | 2139 | } |
2158 | nfs_pgheader_init(desc, hdr, pnfs_readhdr_free); | 2140 | nfs_pgheader_init(desc, hdr, pnfs_readhdr_free); |
2159 | hdr->lseg = pnfs_get_lseg(desc->pg_lseg); | 2141 | hdr->lseg = pnfs_get_lseg(desc->pg_lseg); |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index d1990e90e7a0..6916ff4e86f9 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -98,7 +98,6 @@ enum { | |||
98 | NFS_LAYOUT_RETURN_BEFORE_CLOSE, /* Return this layout before close */ | 98 | NFS_LAYOUT_RETURN_BEFORE_CLOSE, /* Return this layout before close */ |
99 | NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */ | 99 | NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */ |
100 | NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */ | 100 | NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */ |
101 | NFS_LAYOUT_RETRY_LAYOUTGET, /* Retry layoutget */ | ||
102 | }; | 101 | }; |
103 | 102 | ||
104 | enum layoutdriver_policy_flags { | 103 | enum layoutdriver_policy_flags { |
@@ -379,26 +378,6 @@ nfs4_get_deviceid(struct nfs4_deviceid_node *d) | |||
379 | return d; | 378 | return d; |
380 | } | 379 | } |
381 | 380 | ||
382 | static inline void pnfs_set_retry_layoutget(struct pnfs_layout_hdr *lo) | ||
383 | { | ||
384 | if (!test_and_set_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags)) | ||
385 | atomic_inc(&lo->plh_refcount); | ||
386 | } | ||
387 | |||
388 | static inline void pnfs_clear_retry_layoutget(struct pnfs_layout_hdr *lo) | ||
389 | { | ||
390 | if (test_and_clear_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags)) { | ||
391 | atomic_dec(&lo->plh_refcount); | ||
392 | /* wake up waiters for LAYOUTRETURN as that is not needed */ | ||
393 | wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | static inline bool pnfs_should_retry_layoutget(struct pnfs_layout_hdr *lo) | ||
398 | { | ||
399 | return test_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags); | ||
400 | } | ||
401 | |||
402 | static inline struct pnfs_layout_segment * | 381 | static inline struct pnfs_layout_segment * |
403 | pnfs_get_lseg(struct pnfs_layout_segment *lseg) | 382 | pnfs_get_lseg(struct pnfs_layout_segment *lseg) |
404 | { | 383 | { |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 0a5e33f33b5c..eb31e23e7def 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -85,6 +85,23 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio) | |||
85 | } | 85 | } |
86 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); | 86 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); |
87 | 87 | ||
88 | static void nfs_readpage_release(struct nfs_page *req) | ||
89 | { | ||
90 | struct inode *inode = d_inode(req->wb_context->dentry); | ||
91 | |||
92 | dprintk("NFS: read done (%s/%llu %d@%lld)\n", inode->i_sb->s_id, | ||
93 | (unsigned long long)NFS_FILEID(inode), req->wb_bytes, | ||
94 | (long long)req_offset(req)); | ||
95 | |||
96 | if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) { | ||
97 | if (PageUptodate(req->wb_page)) | ||
98 | nfs_readpage_to_fscache(inode, req->wb_page, 0); | ||
99 | |||
100 | unlock_page(req->wb_page); | ||
101 | } | ||
102 | nfs_release_request(req); | ||
103 | } | ||
104 | |||
88 | int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | 105 | int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, |
89 | struct page *page) | 106 | struct page *page) |
90 | { | 107 | { |
@@ -106,7 +123,10 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | |||
106 | 123 | ||
107 | nfs_pageio_init_read(&pgio, inode, false, | 124 | nfs_pageio_init_read(&pgio, inode, false, |
108 | &nfs_async_read_completion_ops); | 125 | &nfs_async_read_completion_ops); |
109 | nfs_pageio_add_request(&pgio, new); | 126 | if (!nfs_pageio_add_request(&pgio, new)) { |
127 | nfs_list_remove_request(new); | ||
128 | nfs_readpage_release(new); | ||
129 | } | ||
110 | nfs_pageio_complete(&pgio); | 130 | nfs_pageio_complete(&pgio); |
111 | 131 | ||
112 | /* It doesn't make sense to do mirrored reads! */ | 132 | /* It doesn't make sense to do mirrored reads! */ |
@@ -115,24 +135,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | |||
115 | pgm = &pgio.pg_mirrors[0]; | 135 | pgm = &pgio.pg_mirrors[0]; |
116 | NFS_I(inode)->read_io += pgm->pg_bytes_written; | 136 | NFS_I(inode)->read_io += pgm->pg_bytes_written; |
117 | 137 | ||
118 | return 0; | 138 | return pgio.pg_error < 0 ? pgio.pg_error : 0; |
119 | } | ||
120 | |||
121 | static void nfs_readpage_release(struct nfs_page *req) | ||
122 | { | ||
123 | struct inode *inode = d_inode(req->wb_context->dentry); | ||
124 | |||
125 | dprintk("NFS: read done (%s/%llu %d@%lld)\n", inode->i_sb->s_id, | ||
126 | (unsigned long long)NFS_FILEID(inode), req->wb_bytes, | ||
127 | (long long)req_offset(req)); | ||
128 | |||
129 | if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) { | ||
130 | if (PageUptodate(req->wb_page)) | ||
131 | nfs_readpage_to_fscache(inode, req->wb_page, 0); | ||
132 | |||
133 | unlock_page(req->wb_page); | ||
134 | } | ||
135 | nfs_release_request(req); | ||
136 | } | 139 | } |
137 | 140 | ||
138 | static void nfs_page_group_set_uptodate(struct nfs_page *req) | 141 | static void nfs_page_group_set_uptodate(struct nfs_page *req) |
@@ -361,6 +364,8 @@ readpage_async_filler(void *data, struct page *page) | |||
361 | if (len < PAGE_CACHE_SIZE) | 364 | if (len < PAGE_CACHE_SIZE) |
362 | zero_user_segment(page, len, PAGE_CACHE_SIZE); | 365 | zero_user_segment(page, len, PAGE_CACHE_SIZE); |
363 | if (!nfs_pageio_add_request(desc->pgio, new)) { | 366 | if (!nfs_pageio_add_request(desc->pgio, new)) { |
367 | nfs_list_remove_request(new); | ||
368 | nfs_readpage_release(new); | ||
364 | error = desc->pgio->pg_error; | 369 | error = desc->pgio->pg_error; |
365 | goto out_unlock; | 370 | goto out_unlock; |
366 | } | 371 | } |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 7b9316406930..4d254232d728 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -545,12 +545,22 @@ try_again: | |||
545 | return head; | 545 | return head; |
546 | } | 546 | } |
547 | 547 | ||
548 | static void nfs_write_error_remove_page(struct nfs_page *req) | ||
549 | { | ||
550 | nfs_unlock_request(req); | ||
551 | nfs_end_page_writeback(req); | ||
552 | nfs_release_request(req); | ||
553 | generic_error_remove_page(page_file_mapping(req->wb_page), | ||
554 | req->wb_page); | ||
555 | } | ||
556 | |||
548 | /* | 557 | /* |
549 | * Find an associated nfs write request, and prepare to flush it out | 558 | * Find an associated nfs write request, and prepare to flush it out |
550 | * May return an error if the user signalled nfs_wait_on_request(). | 559 | * May return an error if the user signalled nfs_wait_on_request(). |
551 | */ | 560 | */ |
552 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | 561 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, |
553 | struct page *page, bool nonblock) | 562 | struct page *page, bool nonblock, |
563 | bool launder) | ||
554 | { | 564 | { |
555 | struct nfs_page *req; | 565 | struct nfs_page *req; |
556 | int ret = 0; | 566 | int ret = 0; |
@@ -567,8 +577,21 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
567 | 577 | ||
568 | ret = 0; | 578 | ret = 0; |
569 | if (!nfs_pageio_add_request(pgio, req)) { | 579 | if (!nfs_pageio_add_request(pgio, req)) { |
570 | nfs_redirty_request(req); | ||
571 | ret = pgio->pg_error; | 580 | ret = pgio->pg_error; |
581 | /* | ||
582 | * Remove the problematic req upon fatal errors | ||
583 | * in launder case, while other dirty pages can | ||
584 | * still be around until they get flushed. | ||
585 | */ | ||
586 | if (nfs_error_is_fatal(ret)) { | ||
587 | nfs_context_set_write_error(req->wb_context, ret); | ||
588 | if (launder) { | ||
589 | nfs_write_error_remove_page(req); | ||
590 | goto out; | ||
591 | } | ||
592 | } | ||
593 | nfs_redirty_request(req); | ||
594 | ret = -EAGAIN; | ||
572 | } else | 595 | } else |
573 | nfs_add_stats(page_file_mapping(page)->host, | 596 | nfs_add_stats(page_file_mapping(page)->host, |
574 | NFSIOS_WRITEPAGES, 1); | 597 | NFSIOS_WRITEPAGES, 1); |
@@ -576,12 +599,14 @@ out: | |||
576 | return ret; | 599 | return ret; |
577 | } | 600 | } |
578 | 601 | ||
579 | static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) | 602 | static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, |
603 | struct nfs_pageio_descriptor *pgio, bool launder) | ||
580 | { | 604 | { |
581 | int ret; | 605 | int ret; |
582 | 606 | ||
583 | nfs_pageio_cond_complete(pgio, page_file_index(page)); | 607 | nfs_pageio_cond_complete(pgio, page_file_index(page)); |
584 | ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE); | 608 | ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE, |
609 | launder); | ||
585 | if (ret == -EAGAIN) { | 610 | if (ret == -EAGAIN) { |
586 | redirty_page_for_writepage(wbc, page); | 611 | redirty_page_for_writepage(wbc, page); |
587 | ret = 0; | 612 | ret = 0; |
@@ -592,7 +617,9 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, st | |||
592 | /* | 617 | /* |
593 | * Write an mmapped page to the server. | 618 | * Write an mmapped page to the server. |
594 | */ | 619 | */ |
595 | static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc) | 620 | static int nfs_writepage_locked(struct page *page, |
621 | struct writeback_control *wbc, | ||
622 | bool launder) | ||
596 | { | 623 | { |
597 | struct nfs_pageio_descriptor pgio; | 624 | struct nfs_pageio_descriptor pgio; |
598 | struct inode *inode = page_file_mapping(page)->host; | 625 | struct inode *inode = page_file_mapping(page)->host; |
@@ -601,7 +628,7 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc | |||
601 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); | 628 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); |
602 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc), | 629 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc), |
603 | false, &nfs_async_write_completion_ops); | 630 | false, &nfs_async_write_completion_ops); |
604 | err = nfs_do_writepage(page, wbc, &pgio); | 631 | err = nfs_do_writepage(page, wbc, &pgio, launder); |
605 | nfs_pageio_complete(&pgio); | 632 | nfs_pageio_complete(&pgio); |
606 | if (err < 0) | 633 | if (err < 0) |
607 | return err; | 634 | return err; |
@@ -614,7 +641,7 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) | |||
614 | { | 641 | { |
615 | int ret; | 642 | int ret; |
616 | 643 | ||
617 | ret = nfs_writepage_locked(page, wbc); | 644 | ret = nfs_writepage_locked(page, wbc, false); |
618 | unlock_page(page); | 645 | unlock_page(page); |
619 | return ret; | 646 | return ret; |
620 | } | 647 | } |
@@ -623,7 +650,7 @@ static int nfs_writepages_callback(struct page *page, struct writeback_control * | |||
623 | { | 650 | { |
624 | int ret; | 651 | int ret; |
625 | 652 | ||
626 | ret = nfs_do_writepage(page, wbc, data); | 653 | ret = nfs_do_writepage(page, wbc, data, false); |
627 | unlock_page(page); | 654 | unlock_page(page); |
628 | return ret; | 655 | return ret; |
629 | } | 656 | } |
@@ -1911,7 +1938,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) | |||
1911 | /* | 1938 | /* |
1912 | * Write back all requests on one page - we do this before reading it. | 1939 | * Write back all requests on one page - we do this before reading it. |
1913 | */ | 1940 | */ |
1914 | int nfs_wb_page(struct inode *inode, struct page *page) | 1941 | int nfs_wb_single_page(struct inode *inode, struct page *page, bool launder) |
1915 | { | 1942 | { |
1916 | loff_t range_start = page_file_offset(page); | 1943 | loff_t range_start = page_file_offset(page); |
1917 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); | 1944 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); |
@@ -1928,7 +1955,7 @@ int nfs_wb_page(struct inode *inode, struct page *page) | |||
1928 | for (;;) { | 1955 | for (;;) { |
1929 | wait_on_page_writeback(page); | 1956 | wait_on_page_writeback(page); |
1930 | if (clear_page_dirty_for_io(page)) { | 1957 | if (clear_page_dirty_for_io(page)) { |
1931 | ret = nfs_writepage_locked(page, &wbc); | 1958 | ret = nfs_writepage_locked(page, &wbc, launder); |
1932 | if (ret < 0) | 1959 | if (ret < 0) |
1933 | goto out_error; | 1960 | goto out_error; |
1934 | continue; | 1961 | continue; |