From: Jeff Layton <jlay...@redhat.com>

Some filesystem fsync routines will need these.

Signed-off-by: Jeff Layton <jlay...@redhat.com>
---
 include/linux/fs.h |  7 ++++++-
 mm/filemap.c       | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 21e7df1ad613..bc57a79294f0 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2544,6 +2544,8 @@ extern int filemap_fdatawait_range(struct address_space 
*, loff_t lstart,
                                   loff_t lend);
 extern bool filemap_range_has_page(struct address_space *, loff_t lstart,
                                  loff_t lend);
+extern int __must_check file_fdatawait_range(struct file *file, loff_t lstart,
+                                               loff_t lend);
 extern int filemap_write_and_wait(struct address_space *mapping);
 extern int filemap_write_and_wait_range(struct address_space *mapping,
                                        loff_t lstart, loff_t lend);
@@ -2552,11 +2554,14 @@ extern int __filemap_fdatawrite_range(struct 
address_space *mapping,
 extern int filemap_fdatawrite_range(struct address_space *mapping,
                                loff_t start, loff_t end);
 extern int filemap_check_errors(struct address_space *mapping);
-
 extern void __filemap_set_wb_err(struct address_space *mapping, int err);
+
+extern int __must_check file_fdatawait_range(struct file *file, loff_t lstart,
+                                               loff_t lend);
 extern int __must_check file_check_and_advance_wb_err(struct file *file);
 extern int __must_check file_write_and_wait_range(struct file *file,
                                                loff_t start, loff_t end);
+extern int __must_check file_write_and_wait(struct file *file);
 
 /**
  * filemap_set_wb_err - set a writeback error on an address_space
diff --git a/mm/filemap.c b/mm/filemap.c
index 72e46e6f0d9a..b904a8dfa43d 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -476,6 +476,29 @@ int filemap_fdatawait_range(struct address_space *mapping, 
loff_t start_byte,
 EXPORT_SYMBOL(filemap_fdatawait_range);
 
 /**
+ * file_fdatawait_range - wait for writeback to complete
+ * @file:              file pointing to address space structure to wait for
+ * @start_byte:                offset in bytes where the range starts
+ * @end_byte:          offset in bytes where the range ends (inclusive)
+ *
+ * Walk the list of under-writeback pages of the address space that file
+ * refers to, in the given range and wait for all of them.  Check error
+ * status of the address space vs. the file->f_wb_err cursor and return it.
+ *
+ * Since the error status of the file is advanced by this function,
+ * callers are responsible for checking the return value and handling and/or
+ * reporting the error.
+ */
+int file_fdatawait_range(struct file *file, loff_t start_byte, loff_t end_byte)
+{
+       struct address_space *mapping = file->f_mapping;
+
+       __filemap_fdatawait_range(mapping, start_byte, end_byte);
+       return file_check_and_advance_wb_err(file);
+}
+EXPORT_SYMBOL(file_fdatawait_range);
+
+/**
  * filemap_fdatawait_keep_errors - wait for writeback without clearing errors
  * @mapping: address space structure to wait for
  *
@@ -675,6 +698,39 @@ int file_write_and_wait_range(struct file *file, loff_t 
lstart, loff_t lend)
 EXPORT_SYMBOL(file_write_and_wait_range);
 
 /**
+ * file_write_and_wait - write out whole file and wait on it and return any
+ *                      writeback errors since we last checked
+ * @file: file to write back and wait on
+ *
+ * Write back the whole file and wait on its mapping. Afterward, check for
+ * errors that may have occurred since our file->f_wb_err cursor was last
+ * updated.
+ */
+int file_write_and_wait(struct file *file)
+{
+       int err = 0, err2;
+       struct address_space *mapping = file->f_mapping;
+
+       if ((!dax_mapping(mapping) && mapping->nrpages) ||
+           (dax_mapping(mapping) && mapping->nrexceptional)) {
+               err = filemap_fdatawrite(mapping);
+               /* See comment of filemap_write_and_wait() */
+               if (err != -EIO) {
+                       loff_t i_size = i_size_read(mapping->host);
+
+                       if (i_size != 0)
+                               __filemap_fdatawait_range(mapping, 0,
+                                                         i_size - 1);
+               }
+       }
+       err2 = file_check_and_advance_wb_err(file);
+       if (!err)
+               err = err2;
+       return err;
+}
+EXPORT_SYMBOL(file_write_and_wait);
+
+/**
  * replace_page_cache_page - replace a pagecache page with a new one
  * @old:       page to be replaced
  * @new:       page to replace with
-- 
2.13.3

Reply via email to