Commit 33198c16 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-v4.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux

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()
parents 3ea4fcc5 0f41074a
...@@ -72,7 +72,7 @@ static int exofs_commit_chunk(struct page *page, loff_t pos, unsigned len) ...@@ -72,7 +72,7 @@ static int exofs_commit_chunk(struct page *page, loff_t pos, unsigned len)
set_page_dirty(page); set_page_dirty(page);
if (IS_DIRSYNC(dir)) if (IS_DIRSYNC(dir))
err = write_one_page(page, 1); err = write_one_page(page);
else else
unlock_page(page); unlock_page(page);
......
...@@ -100,7 +100,7 @@ static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len) ...@@ -100,7 +100,7 @@ static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
} }
if (IS_DIRSYNC(dir)) { if (IS_DIRSYNC(dir)) {
err = write_one_page(page, 1); err = write_one_page(page);
if (!err) if (!err)
err = sync_inode_metadata(dir, 1); err = sync_inode_metadata(dir, 1);
} else { } else {
......
...@@ -664,6 +664,7 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, ...@@ -664,6 +664,7 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
INCREMENT(mpStat.pagealloc); INCREMENT(mpStat.pagealloc);
mp = alloc_metapage(GFP_NOFS); mp = alloc_metapage(GFP_NOFS);
mp->page = page; mp->page = page;
mp->sb = inode->i_sb;
mp->flag = 0; mp->flag = 0;
mp->xflag = COMMIT_PAGE; mp->xflag = COMMIT_PAGE;
mp->count = 1; mp->count = 1;
...@@ -711,7 +712,8 @@ void force_metapage(struct metapage *mp) ...@@ -711,7 +712,8 @@ void force_metapage(struct metapage *mp)
get_page(page); get_page(page);
lock_page(page); lock_page(page);
set_page_dirty(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); clear_bit(META_forcewrite, &mp->flag);
put_page(page); put_page(page);
} }
...@@ -756,7 +758,8 @@ void release_metapage(struct metapage * mp) ...@@ -756,7 +758,8 @@ void release_metapage(struct metapage * mp)
set_page_dirty(page); set_page_dirty(page);
if (test_bit(META_sync, &mp->flag)) { if (test_bit(META_sync, &mp->flag)) {
clear_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 */ lock_page(page); /* write_one_page unlocks the page */
} }
} else if (mp->lsn) /* discard_metapage doesn't remove it */ } else if (mp->lsn) /* discard_metapage doesn't remove it */
......
...@@ -38,6 +38,7 @@ struct metapage { ...@@ -38,6 +38,7 @@ struct metapage {
/* implementation */ /* implementation */
struct page *page; struct page *page;
struct super_block *sb;
unsigned int logical_size; unsigned int logical_size;
/* Journal management */ /* Journal management */
......
...@@ -57,7 +57,7 @@ static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len) ...@@ -57,7 +57,7 @@ static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
mark_inode_dirty(dir); mark_inode_dirty(dir);
} }
if (IS_DIRSYNC(dir)) if (IS_DIRSYNC(dir))
err = write_one_page(page, 1); err = write_one_page(page);
else else
unlock_page(page); unlock_page(page);
return err; return err;
......
...@@ -192,7 +192,7 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) ...@@ -192,7 +192,7 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
mark_inode_dirty_sync(inode); 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); EXPORT_SYMBOL(vfs_fsync_range);
......
...@@ -45,7 +45,7 @@ static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len) ...@@ -45,7 +45,7 @@ static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
mark_inode_dirty(dir); mark_inode_dirty(dir);
} }
if (IS_DIRSYNC(dir)) if (IS_DIRSYNC(dir))
err = write_one_page(page, 1); err = write_one_page(page);
else else
unlock_page(page); unlock_page(page);
return err; return err;
......
...@@ -53,7 +53,7 @@ static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len) ...@@ -53,7 +53,7 @@ static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len)
mark_inode_dirty(dir); mark_inode_dirty(dir);
} }
if (IS_DIRSYNC(dir)) if (IS_DIRSYNC(dir))
err = write_one_page(page, 1); err = write_one_page(page);
else else
unlock_page(page); unlock_page(page);
return err; return err;
......
...@@ -1748,12 +1748,6 @@ static inline int call_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1748,12 +1748,6 @@ static inline int call_mmap(struct file *file, struct vm_area_struct *vma)
return file->f_op->mmap(file, 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, ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
unsigned long nr_segs, unsigned long fast_segs, unsigned long nr_segs, unsigned long fast_segs,
struct iovec *fast_pointer, struct iovec *fast_pointer,
......
...@@ -2171,7 +2171,7 @@ extern void filemap_map_pages(struct vm_fault *vmf, ...@@ -2171,7 +2171,7 @@ extern void filemap_map_pages(struct vm_fault *vmf,
extern int filemap_page_mkwrite(struct vm_fault *vmf); extern int filemap_page_mkwrite(struct vm_fault *vmf);
/* mm/page-writeback.c */ /* 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); void task_dirty_inc(struct task_struct *tsk);
/* readahead.c */ /* readahead.c */
......
...@@ -452,7 +452,7 @@ static int shm_fsync(struct file *file, loff_t start, loff_t end, int datasync) ...@@ -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) if (!sfd->file->f_op->fsync)
return -EINVAL; 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, static long shm_fallocate(struct file *file, int mode, loff_t offset,
......
...@@ -2366,15 +2366,15 @@ int do_writepages(struct address_space *mapping, struct writeback_control *wbc) ...@@ -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 * @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. * 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; struct address_space *mapping = page->mapping;
int ret = 0; int ret = 0;
...@@ -2385,21 +2385,20 @@ int write_one_page(struct page *page, int wait) ...@@ -2385,21 +2385,20 @@ int write_one_page(struct page *page, int wait)
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
if (wait) wait_on_page_writeback(page);
wait_on_page_writeback(page);
if (clear_page_dirty_for_io(page)) { if (clear_page_dirty_for_io(page)) {
get_page(page); get_page(page);
ret = mapping->a_ops->writepage(page, &wbc); ret = mapping->a_ops->writepage(page, &wbc);
if (ret == 0 && wait) { if (ret == 0)
wait_on_page_writeback(page); wait_on_page_writeback(page);
if (PageError(page))
ret = -EIO;
}
put_page(page); put_page(page);
} else { } else {
unlock_page(page); unlock_page(page);
} }
if (!ret)
ret = filemap_check_errors(mapping);
return ret; return ret;
} }
EXPORT_SYMBOL(write_one_page); EXPORT_SYMBOL(write_one_page);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment