aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c30
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 */
241static void nfs_set_pageerror(struct page *page) 242static 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);
1372out: 1377out:
@@ -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
1414static void nfs_async_write_error(struct list_head *head) 1419static 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
1425static void nfs_async_write_reschedule_io(struct nfs_pgio_header *hdr) 1437static 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}