Merge tag 'for-linus-v4.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayto...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Jul 2017 01:39:15 +0000 (18:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Jul 2017 01:39:15 +0000 (18:39 -0700)
Pull Writeback error handling fixes from Jeff Layton:
 "The main rationale for all of these changes is to tighten up writeback
  error reporting to userland. There are many ways now that writeback
  errors can be lost, such that fsync/fdatasync/msync return 0 when
  writeback actually failed.

  This pile contains a small set of cleanups and writeback error
  handling fixes that I was able to break off from the main pile (#2).

  Two of the patches in this pile are trivial. The exceptions are the
  patch to fix up error handling in write_one_page, and the patch to
  make JFS pay attention to write_one_page errors"

* tag 'for-linus-v4.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux:
  fs: remove call_fsync helper function
  mm: clean up error handling in write_one_page
  JFS: do not ignore return code from write_one_page()
  mm: drop "wait" parameter from write_one_page()

12 files changed:
fs/exofs/dir.c
fs/ext2/dir.c
fs/jfs/jfs_metapage.c
fs/jfs/jfs_metapage.h
fs/minix/dir.c
fs/sync.c
fs/sysv/dir.c
fs/ufs/dir.c
include/linux/fs.h
include/linux/mm.h
ipc/shm.c
mm/page-writeback.c

index 8eeb694332fe811e820ed342ebbecc25bb678a1f..98233a97b7b87fb43ccb2584f35e38309be978b7 100644 (file)
@@ -72,7 +72,7 @@ static int exofs_commit_chunk(struct page *page, loff_t pos, unsigned len)
        set_page_dirty(page);
 
        if (IS_DIRSYNC(dir))
-               err = write_one_page(page, 1);
+               err = write_one_page(page);
        else
                unlock_page(page);
 
index d9650c9508e4de549788e85210039b36032ec5a0..e2709695b1772bb6684b697dd8965366d7698fe0 100644 (file)
@@ -100,7 +100,7 @@ static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
        }
 
        if (IS_DIRSYNC(dir)) {
-               err = write_one_page(page, 1);
+               err = write_one_page(page);
                if (!err)
                        err = sync_inode_metadata(dir, 1);
        } else {
index ce93db3aef3c450990ecec5c4daac05c9d1c066e..65120a4717290ae3ec109cb116172e7f091f9f79 100644 (file)
@@ -664,6 +664,7 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
                INCREMENT(mpStat.pagealloc);
                mp = alloc_metapage(GFP_NOFS);
                mp->page = page;
+               mp->sb = inode->i_sb;
                mp->flag = 0;
                mp->xflag = COMMIT_PAGE;
                mp->count = 1;
@@ -711,7 +712,8 @@ void force_metapage(struct metapage *mp)
        get_page(page);
        lock_page(page);
        set_page_dirty(page);
-       write_one_page(page, 1);
+       if (write_one_page(page))
+               jfs_error(mp->sb, "write_one_page() failed\n");
        clear_bit(META_forcewrite, &mp->flag);
        put_page(page);
 }
@@ -756,7 +758,8 @@ void release_metapage(struct metapage * mp)
                set_page_dirty(page);
                if (test_bit(META_sync, &mp->flag)) {
                        clear_bit(META_sync, &mp->flag);
-                       write_one_page(page, 1);
+                       if (write_one_page(page))
+                               jfs_error(mp->sb, "write_one_page() failed\n");
                        lock_page(page); /* write_one_page unlocks the page */
                }
        } else if (mp->lsn)     /* discard_metapage doesn't remove it */
index a869fb4a20d66d160ea9e10468d081ec79495114..8b0ee514eb84933c6bb6b233449cfb54ec940954 100644 (file)
@@ -38,6 +38,7 @@ struct metapage {
 
        /* implementation */
        struct page *page;
+       struct super_block *sb;
        unsigned int logical_size;
 
        /* Journal management */
index 7edc9b3957009ee1c3bbbf3193bcb4b54395d499..baa9721f1299c2306e2e614a6dea37cf8bc2ff70 100644 (file)
@@ -57,7 +57,7 @@ static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
                mark_inode_dirty(dir);
        }
        if (IS_DIRSYNC(dir))
-               err = write_one_page(page, 1);
+               err = write_one_page(page);
        else
                unlock_page(page);
        return err;
index 11ba023434b14bb0075a130a9837426a5fc57b90..2a54c1f2203595823df1bd97680b9a1fb163e400 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -192,7 +192,7 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
                spin_unlock(&inode->i_lock);
                mark_inode_dirty_sync(inode);
        }
-       return call_fsync(file, start, end, datasync);
+       return file->f_op->fsync(file, start, end, datasync);
 }
 EXPORT_SYMBOL(vfs_fsync_range);
 
index 5bdae85ceef7d6ae9e7c560cb23e9bb1c09ea098..f5191cb2c947a3abdc4e77d0ee84ade3a15d133c 100644 (file)
@@ -45,7 +45,7 @@ static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
                mark_inode_dirty(dir);
        }
        if (IS_DIRSYNC(dir))
-               err = write_one_page(page, 1);
+               err = write_one_page(page);
        else
                unlock_page(page);
        return err;
index de01b8f2aa78b00cdb4360e142b24abc83fdae72..48609f1d95803742656b74933fb6490548144354 100644 (file)
@@ -53,7 +53,7 @@ static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len)
                mark_inode_dirty(dir);
        }
        if (IS_DIRSYNC(dir))
-               err = write_one_page(page, 1);
+               err = write_one_page(page);
        else
                unlock_page(page);
        return err;
index 818568c8e5ed270fa843eefa727822a69a2661a1..978fb5966a2517b060bf9e64a9e2d7c6350da2c0 100644 (file)
@@ -1748,12 +1748,6 @@ static inline int call_mmap(struct file *file, struct vm_area_struct *vma)
        return file->f_op->mmap(file, vma);
 }
 
-static inline int call_fsync(struct file *file, loff_t start, loff_t end,
-                            int datasync)
-{
-       return file->f_op->fsync(file, start, end, datasync);
-}
-
 ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
                              unsigned long nr_segs, unsigned long fast_segs,
                              struct iovec *fast_pointer,
index 6f543a47fc92ecc89cdd49c00f4c0e9acf0ea2eb..46b9ac5e856923ec77125cf5c468585167bf0ff6 100644 (file)
@@ -2171,7 +2171,7 @@ extern void filemap_map_pages(struct vm_fault *vmf,
 extern int filemap_page_mkwrite(struct vm_fault *vmf);
 
 /* mm/page-writeback.c */
-int write_one_page(struct page *page, int wait);
+int __must_check write_one_page(struct page *page);
 void task_dirty_inc(struct task_struct *tsk);
 
 /* readahead.c */
index 34c4344e8d4b2f00206208f1d2c8d48e85dd0e48..f45c7959b26407f6b59559e653fdb0172fddf56c 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -452,7 +452,7 @@ static int shm_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 
        if (!sfd->file->f_op->fsync)
                return -EINVAL;
-       return call_fsync(sfd->file, start, end, datasync);
+       return sfd->file->f_op->fsync(sfd->file, start, end, datasync);
 }
 
 static long shm_fallocate(struct file *file, int mode, loff_t offset,
index 8989eada0ef7e40397e24383af2c2acd40b3c2d7..0b60cc7ddac2b1a63ce71ed17c02a64cb6370e1c 100644 (file)
@@ -2366,15 +2366,15 @@ int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
 }
 
 /**
- * write_one_page - write out a single page and optionally wait on I/O
+ * write_one_page - write out a single page and wait on I/O
  * @page: the page to write
- * @wait: if true, wait on writeout
  *
  * The page must be locked by the caller and will be unlocked upon return.
  *
- * write_one_page() returns a negative error code if I/O failed.
+ * Note that the mapping's AS_EIO/AS_ENOSPC flags will be cleared when this
+ * function returns.
  */
-int write_one_page(struct page *page, int wait)
+int write_one_page(struct page *page)
 {
        struct address_space *mapping = page->mapping;
        int ret = 0;
@@ -2385,21 +2385,20 @@ int write_one_page(struct page *page, int wait)
 
        BUG_ON(!PageLocked(page));
 
-       if (wait)
-               wait_on_page_writeback(page);
+       wait_on_page_writeback(page);
 
        if (clear_page_dirty_for_io(page)) {
                get_page(page);
                ret = mapping->a_ops->writepage(page, &wbc);
-               if (ret == 0 && wait) {
+               if (ret == 0)
                        wait_on_page_writeback(page);
-                       if (PageError(page))
-                               ret = -EIO;
-               }
                put_page(page);
        } else {
                unlock_page(page);
        }
+
+       if (!ret)
+               ret = filemap_check_errors(mapping);
        return ret;
 }
 EXPORT_SYMBOL(write_one_page);