diff options
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f12cb31a41e5..f3ebabaa291d 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/iversion.h> | 26 | #include <linux/iversion.h> |
27 | 27 | ||
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/sched/mm.h> | ||
29 | 30 | ||
30 | #include "delegation.h" | 31 | #include "delegation.h" |
31 | #include "internal.h" | 32 | #include "internal.h" |
@@ -238,9 +239,9 @@ out: | |||
238 | } | 239 | } |
239 | 240 | ||
240 | /* A writeback failed: mark the page as bad, and invalidate the page cache */ | 241 | /* A writeback failed: mark the page as bad, and invalidate the page cache */ |
241 | static void nfs_set_pageerror(struct page *page) | 242 | static void nfs_set_pageerror(struct address_space *mapping) |
242 | { | 243 | { |
243 | nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page)); | 244 | nfs_zap_mapping(mapping->host, mapping); |
244 | } | 245 | } |
245 | 246 | ||
246 | /* | 247 | /* |
@@ -712,11 +713,13 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
712 | { | 713 | { |
713 | struct inode *inode = mapping->host; | 714 | struct inode *inode = mapping->host; |
714 | struct nfs_pageio_descriptor pgio; | 715 | struct nfs_pageio_descriptor pgio; |
715 | struct nfs_io_completion *ioc = nfs_io_completion_alloc(GFP_NOFS); | 716 | struct nfs_io_completion *ioc; |
717 | unsigned int pflags = memalloc_nofs_save(); | ||
716 | int err; | 718 | int err; |
717 | 719 | ||
718 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); | 720 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); |
719 | 721 | ||
722 | ioc = nfs_io_completion_alloc(GFP_NOFS); | ||
720 | if (ioc) | 723 | if (ioc) |
721 | nfs_io_completion_init(ioc, nfs_io_completion_commit, inode); | 724 | nfs_io_completion_init(ioc, nfs_io_completion_commit, inode); |
722 | 725 | ||
@@ -727,6 +730,8 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
727 | nfs_pageio_complete(&pgio); | 730 | nfs_pageio_complete(&pgio); |
728 | nfs_io_completion_put(ioc); | 731 | nfs_io_completion_put(ioc); |
729 | 732 | ||
733 | memalloc_nofs_restore(pflags); | ||
734 | |||
730 | if (err < 0) | 735 | if (err < 0) |
731 | goto out_err; | 736 | goto out_err; |
732 | err = pgio.pg_error; | 737 | err = pgio.pg_error; |
@@ -865,7 +870,6 @@ EXPORT_SYMBOL_GPL(nfs_request_add_commit_list_locked); | |||
865 | /** | 870 | /** |
866 | * nfs_request_add_commit_list - add request to a commit list | 871 | * nfs_request_add_commit_list - add request to a commit list |
867 | * @req: pointer to a struct nfs_page | 872 | * @req: pointer to a struct nfs_page |
868 | * @dst: commit list head | ||
869 | * @cinfo: holds list lock and accounting info | 873 | * @cinfo: holds list lock and accounting info |
870 | * | 874 | * |
871 | * This sets the PG_CLEAN bit, updates the cinfo count of | 875 | * This sets the PG_CLEAN bit, updates the cinfo count of |
@@ -994,7 +998,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr) | |||
994 | nfs_list_remove_request(req); | 998 | nfs_list_remove_request(req); |
995 | if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && | 999 | if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && |
996 | (hdr->good_bytes < bytes)) { | 1000 | (hdr->good_bytes < bytes)) { |
997 | nfs_set_pageerror(req->wb_page); | 1001 | nfs_set_pageerror(page_file_mapping(req->wb_page)); |
998 | nfs_context_set_write_error(req->wb_context, hdr->error); | 1002 | nfs_context_set_write_error(req->wb_context, hdr->error); |
999 | goto remove_req; | 1003 | goto remove_req; |
1000 | } | 1004 | } |
@@ -1348,7 +1352,8 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
1348 | unsigned int offset, unsigned int count) | 1352 | unsigned int offset, unsigned int count) |
1349 | { | 1353 | { |
1350 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 1354 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
1351 | struct inode *inode = page_file_mapping(page)->host; | 1355 | struct address_space *mapping = page_file_mapping(page); |
1356 | struct inode *inode = mapping->host; | ||
1352 | int status = 0; | 1357 | int status = 0; |
1353 | 1358 | ||
1354 | nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); | 1359 | nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); |
@@ -1366,7 +1371,7 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
1366 | 1371 | ||
1367 | status = nfs_writepage_setup(ctx, page, offset, count); | 1372 | status = nfs_writepage_setup(ctx, page, offset, count); |
1368 | if (status < 0) | 1373 | if (status < 0) |
1369 | nfs_set_pageerror(page); | 1374 | nfs_set_pageerror(mapping); |
1370 | else | 1375 | else |
1371 | __set_page_dirty_nobuffers(page); | 1376 | __set_page_dirty_nobuffers(page); |
1372 | out: | 1377 | out: |
@@ -1411,20 +1416,27 @@ static void nfs_redirty_request(struct nfs_page *req) | |||
1411 | nfs_release_request(req); | 1416 | nfs_release_request(req); |
1412 | } | 1417 | } |
1413 | 1418 | ||
1414 | static void nfs_async_write_error(struct list_head *head) | 1419 | static void nfs_async_write_error(struct list_head *head, int error) |
1415 | { | 1420 | { |
1416 | struct nfs_page *req; | 1421 | struct nfs_page *req; |
1417 | 1422 | ||
1418 | while (!list_empty(head)) { | 1423 | while (!list_empty(head)) { |
1419 | req = nfs_list_entry(head->next); | 1424 | req = nfs_list_entry(head->next); |
1420 | nfs_list_remove_request(req); | 1425 | nfs_list_remove_request(req); |
1426 | if (nfs_error_is_fatal(error)) { | ||
1427 | nfs_context_set_write_error(req->wb_context, error); | ||
1428 | if (nfs_error_is_fatal_on_server(error)) { | ||
1429 | nfs_write_error_remove_page(req); | ||
1430 | continue; | ||
1431 | } | ||
1432 | } | ||
1421 | nfs_redirty_request(req); | 1433 | nfs_redirty_request(req); |
1422 | } | 1434 | } |
1423 | } | 1435 | } |
1424 | 1436 | ||
1425 | static void nfs_async_write_reschedule_io(struct nfs_pgio_header *hdr) | 1437 | static void nfs_async_write_reschedule_io(struct nfs_pgio_header *hdr) |
1426 | { | 1438 | { |
1427 | nfs_async_write_error(&hdr->pages); | 1439 | nfs_async_write_error(&hdr->pages, 0); |
1428 | filemap_fdatawrite_range(hdr->inode->i_mapping, hdr->args.offset, | 1440 | filemap_fdatawrite_range(hdr->inode->i_mapping, hdr->args.offset, |
1429 | hdr->args.offset + hdr->args.count - 1); | 1441 | hdr->args.offset + hdr->args.count - 1); |
1430 | } | 1442 | } |