diff options
Diffstat (limited to 'fs/nfs/pagelist.c')
-rw-r--r-- | fs/nfs/pagelist.c | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index e54d899c1848..e9f39fa5964b 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -350,7 +350,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct page *page, | |||
350 | 350 | ||
351 | /** | 351 | /** |
352 | * nfs_unlock_request - Unlock request and wake up sleepers. | 352 | * nfs_unlock_request - Unlock request and wake up sleepers. |
353 | * @req: | 353 | * @req: pointer to request |
354 | */ | 354 | */ |
355 | void nfs_unlock_request(struct nfs_page *req) | 355 | void nfs_unlock_request(struct nfs_page *req) |
356 | { | 356 | { |
@@ -368,7 +368,7 @@ void nfs_unlock_request(struct nfs_page *req) | |||
368 | 368 | ||
369 | /** | 369 | /** |
370 | * nfs_unlock_and_release_request - Unlock request and release the nfs_page | 370 | * nfs_unlock_and_release_request - Unlock request and release the nfs_page |
371 | * @req: | 371 | * @req: pointer to request |
372 | */ | 372 | */ |
373 | void nfs_unlock_and_release_request(struct nfs_page *req) | 373 | void nfs_unlock_and_release_request(struct nfs_page *req) |
374 | { | 374 | { |
@@ -531,7 +531,6 @@ EXPORT_SYMBOL_GPL(nfs_pgio_header_free); | |||
531 | * nfs_pgio_rpcsetup - Set up arguments for a pageio call | 531 | * nfs_pgio_rpcsetup - Set up arguments for a pageio call |
532 | * @hdr: The pageio hdr | 532 | * @hdr: The pageio hdr |
533 | * @count: Number of bytes to read | 533 | * @count: Number of bytes to read |
534 | * @offset: Initial offset | ||
535 | * @how: How to commit data (writes only) | 534 | * @how: How to commit data (writes only) |
536 | * @cinfo: Commit information for the call (writes only) | 535 | * @cinfo: Commit information for the call (writes only) |
537 | */ | 536 | */ |
@@ -634,7 +633,6 @@ EXPORT_SYMBOL_GPL(nfs_initiate_pgio); | |||
634 | 633 | ||
635 | /** | 634 | /** |
636 | * nfs_pgio_error - Clean up from a pageio error | 635 | * nfs_pgio_error - Clean up from a pageio error |
637 | * @desc: IO descriptor | ||
638 | * @hdr: pageio header | 636 | * @hdr: pageio header |
639 | */ | 637 | */ |
640 | static void nfs_pgio_error(struct nfs_pgio_header *hdr) | 638 | static void nfs_pgio_error(struct nfs_pgio_header *hdr) |
@@ -768,8 +766,7 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, | |||
768 | pageused = 0; | 766 | pageused = 0; |
769 | while (!list_empty(head)) { | 767 | while (!list_empty(head)) { |
770 | req = nfs_list_entry(head->next); | 768 | req = nfs_list_entry(head->next); |
771 | nfs_list_remove_request(req); | 769 | nfs_list_move_request(req, &hdr->pages); |
772 | nfs_list_add_request(req, &hdr->pages); | ||
773 | 770 | ||
774 | if (!last_page || last_page != req->wb_page) { | 771 | if (!last_page || last_page != req->wb_page) { |
775 | pageused++; | 772 | pageused++; |
@@ -893,6 +890,7 @@ static bool nfs_match_lock_context(const struct nfs_lock_context *l1, | |||
893 | * nfs_can_coalesce_requests - test two requests for compatibility | 890 | * nfs_can_coalesce_requests - test two requests for compatibility |
894 | * @prev: pointer to nfs_page | 891 | * @prev: pointer to nfs_page |
895 | * @req: pointer to nfs_page | 892 | * @req: pointer to nfs_page |
893 | * @pgio: pointer to nfs_pagio_descriptor | ||
896 | * | 894 | * |
897 | * The nfs_page structures 'prev' and 'req' are compared to ensure that the | 895 | * The nfs_page structures 'prev' and 'req' are compared to ensure that the |
898 | * page data area they describe is contiguous, and that their RPC | 896 | * page data area they describe is contiguous, and that their RPC |
@@ -961,8 +959,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, | |||
961 | } | 959 | } |
962 | if (!nfs_can_coalesce_requests(prev, req, desc)) | 960 | if (!nfs_can_coalesce_requests(prev, req, desc)) |
963 | return 0; | 961 | return 0; |
964 | nfs_list_remove_request(req); | 962 | nfs_list_move_request(req, &mirror->pg_list); |
965 | nfs_list_add_request(req, &mirror->pg_list); | ||
966 | mirror->pg_count += req->wb_bytes; | 963 | mirror->pg_count += req->wb_bytes; |
967 | return 1; | 964 | return 1; |
968 | } | 965 | } |
@@ -988,6 +985,16 @@ static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc) | |||
988 | } | 985 | } |
989 | } | 986 | } |
990 | 987 | ||
988 | static void | ||
989 | nfs_pageio_cleanup_request(struct nfs_pageio_descriptor *desc, | ||
990 | struct nfs_page *req) | ||
991 | { | ||
992 | LIST_HEAD(head); | ||
993 | |||
994 | nfs_list_move_request(req, &head); | ||
995 | desc->pg_completion_ops->error_cleanup(&head, desc->pg_error); | ||
996 | } | ||
997 | |||
991 | /** | 998 | /** |
992 | * nfs_pageio_add_request - Attempt to coalesce a request into a page list. | 999 | * nfs_pageio_add_request - Attempt to coalesce a request into a page list. |
993 | * @desc: destination io descriptor | 1000 | * @desc: destination io descriptor |
@@ -1025,10 +1032,8 @@ static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, | |||
1025 | nfs_page_group_unlock(req); | 1032 | nfs_page_group_unlock(req); |
1026 | desc->pg_moreio = 1; | 1033 | desc->pg_moreio = 1; |
1027 | nfs_pageio_doio(desc); | 1034 | nfs_pageio_doio(desc); |
1028 | if (desc->pg_error < 0) | 1035 | if (desc->pg_error < 0 || mirror->pg_recoalesce) |
1029 | return 0; | 1036 | goto out_cleanup_subreq; |
1030 | if (mirror->pg_recoalesce) | ||
1031 | return 0; | ||
1032 | /* retry add_request for this subreq */ | 1037 | /* retry add_request for this subreq */ |
1033 | nfs_page_group_lock(req); | 1038 | nfs_page_group_lock(req); |
1034 | continue; | 1039 | continue; |
@@ -1061,6 +1066,10 @@ err_ptr: | |||
1061 | desc->pg_error = PTR_ERR(subreq); | 1066 | desc->pg_error = PTR_ERR(subreq); |
1062 | nfs_page_group_unlock(req); | 1067 | nfs_page_group_unlock(req); |
1063 | return 0; | 1068 | return 0; |
1069 | out_cleanup_subreq: | ||
1070 | if (req != subreq) | ||
1071 | nfs_pageio_cleanup_request(desc, subreq); | ||
1072 | return 0; | ||
1064 | } | 1073 | } |
1065 | 1074 | ||
1066 | static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc) | 1075 | static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc) |
@@ -1079,7 +1088,6 @@ static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc) | |||
1079 | struct nfs_page *req; | 1088 | struct nfs_page *req; |
1080 | 1089 | ||
1081 | req = list_first_entry(&head, struct nfs_page, wb_list); | 1090 | req = list_first_entry(&head, struct nfs_page, wb_list); |
1082 | nfs_list_remove_request(req); | ||
1083 | if (__nfs_pageio_add_request(desc, req)) | 1091 | if (__nfs_pageio_add_request(desc, req)) |
1084 | continue; | 1092 | continue; |
1085 | if (desc->pg_error < 0) { | 1093 | if (desc->pg_error < 0) { |
@@ -1120,7 +1128,8 @@ static void nfs_pageio_error_cleanup(struct nfs_pageio_descriptor *desc) | |||
1120 | 1128 | ||
1121 | for (midx = 0; midx < desc->pg_mirror_count; midx++) { | 1129 | for (midx = 0; midx < desc->pg_mirror_count; midx++) { |
1122 | mirror = &desc->pg_mirrors[midx]; | 1130 | mirror = &desc->pg_mirrors[midx]; |
1123 | desc->pg_completion_ops->error_cleanup(&mirror->pg_list); | 1131 | desc->pg_completion_ops->error_cleanup(&mirror->pg_list, |
1132 | desc->pg_error); | ||
1124 | } | 1133 | } |
1125 | } | 1134 | } |
1126 | 1135 | ||
@@ -1168,11 +1177,14 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, | |||
1168 | if (nfs_pgio_has_mirroring(desc)) | 1177 | if (nfs_pgio_has_mirroring(desc)) |
1169 | desc->pg_mirror_idx = midx; | 1178 | desc->pg_mirror_idx = midx; |
1170 | if (!nfs_pageio_add_request_mirror(desc, dupreq)) | 1179 | if (!nfs_pageio_add_request_mirror(desc, dupreq)) |
1171 | goto out_failed; | 1180 | goto out_cleanup_subreq; |
1172 | } | 1181 | } |
1173 | 1182 | ||
1174 | return 1; | 1183 | return 1; |
1175 | 1184 | ||
1185 | out_cleanup_subreq: | ||
1186 | if (req != dupreq) | ||
1187 | nfs_pageio_cleanup_request(desc, dupreq); | ||
1176 | out_failed: | 1188 | out_failed: |
1177 | nfs_pageio_error_cleanup(desc); | 1189 | nfs_pageio_error_cleanup(desc); |
1178 | return 0; | 1190 | return 0; |
@@ -1194,7 +1206,7 @@ static void nfs_pageio_complete_mirror(struct nfs_pageio_descriptor *desc, | |||
1194 | desc->pg_mirror_idx = mirror_idx; | 1206 | desc->pg_mirror_idx = mirror_idx; |
1195 | for (;;) { | 1207 | for (;;) { |
1196 | nfs_pageio_doio(desc); | 1208 | nfs_pageio_doio(desc); |
1197 | if (!mirror->pg_recoalesce) | 1209 | if (desc->pg_error < 0 || !mirror->pg_recoalesce) |
1198 | break; | 1210 | break; |
1199 | if (!nfs_do_recoalesce(desc)) | 1211 | if (!nfs_do_recoalesce(desc)) |
1200 | break; | 1212 | break; |
@@ -1222,9 +1234,8 @@ int nfs_pageio_resend(struct nfs_pageio_descriptor *desc, | |||
1222 | while (!list_empty(&hdr->pages)) { | 1234 | while (!list_empty(&hdr->pages)) { |
1223 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); | 1235 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); |
1224 | 1236 | ||
1225 | nfs_list_remove_request(req); | ||
1226 | if (!nfs_pageio_add_request(desc, req)) | 1237 | if (!nfs_pageio_add_request(desc, req)) |
1227 | nfs_list_add_request(req, &failed); | 1238 | nfs_list_move_request(req, &failed); |
1228 | } | 1239 | } |
1229 | nfs_pageio_complete(desc); | 1240 | nfs_pageio_complete(desc); |
1230 | if (!list_empty(&failed)) { | 1241 | if (!list_empty(&failed)) { |