|
@@ -30,7 +30,7 @@
|
|
#include <linux/percpu-rwsem.h>
|
|
#include <linux/percpu-rwsem.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/delayed_call.h>
|
|
#include <linux/delayed_call.h>
|
|
-
|
|
|
|
|
|
+#include <linux/errseq.h>
|
|
#include <asm/byteorder.h>
|
|
#include <asm/byteorder.h>
|
|
#include <uapi/linux/fs.h>
|
|
#include <uapi/linux/fs.h>
|
|
|
|
|
|
@@ -392,6 +392,7 @@ struct address_space {
|
|
gfp_t gfp_mask; /* implicit gfp mask for allocations */
|
|
gfp_t gfp_mask; /* implicit gfp mask for allocations */
|
|
struct list_head private_list; /* ditto */
|
|
struct list_head private_list; /* ditto */
|
|
void *private_data; /* ditto */
|
|
void *private_data; /* ditto */
|
|
|
|
+ errseq_t wb_err;
|
|
} __attribute__((aligned(sizeof(long))));
|
|
} __attribute__((aligned(sizeof(long))));
|
|
/*
|
|
/*
|
|
* On most architectures that alignment is already the case; but
|
|
* On most architectures that alignment is already the case; but
|
|
@@ -868,6 +869,7 @@ struct file {
|
|
struct list_head f_tfile_llink;
|
|
struct list_head f_tfile_llink;
|
|
#endif /* #ifdef CONFIG_EPOLL */
|
|
#endif /* #ifdef CONFIG_EPOLL */
|
|
struct address_space *f_mapping;
|
|
struct address_space *f_mapping;
|
|
|
|
+ errseq_t f_wb_err;
|
|
} __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
|
|
} __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
|
|
|
|
|
|
struct file_handle {
|
|
struct file_handle {
|
|
@@ -2526,6 +2528,62 @@ extern int filemap_fdatawrite_range(struct address_space *mapping,
|
|
loff_t start, loff_t end);
|
|
loff_t start, loff_t end);
|
|
extern int filemap_check_errors(struct address_space *mapping);
|
|
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_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);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * filemap_set_wb_err - set a writeback error on an address_space
|
|
|
|
+ * @mapping: mapping in which to set writeback error
|
|
|
|
+ * @err: error to be set in mapping
|
|
|
|
+ *
|
|
|
|
+ * When writeback fails in some way, we must record that error so that
|
|
|
|
+ * userspace can be informed when fsync and the like are called. We endeavor
|
|
|
|
+ * to report errors on any file that was open at the time of the error. Some
|
|
|
|
+ * internal callers also need to know when writeback errors have occurred.
|
|
|
|
+ *
|
|
|
|
+ * When a writeback error occurs, most filesystems will want to call
|
|
|
|
+ * filemap_set_wb_err to record the error in the mapping so that it will be
|
|
|
|
+ * automatically reported whenever fsync is called on the file.
|
|
|
|
+ *
|
|
|
|
+ * FIXME: mention FS_* flag here?
|
|
|
|
+ */
|
|
|
|
+static inline void filemap_set_wb_err(struct address_space *mapping, int err)
|
|
|
|
+{
|
|
|
|
+ /* Fastpath for common case of no error */
|
|
|
|
+ if (unlikely(err))
|
|
|
|
+ __filemap_set_wb_err(mapping, err);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * filemap_check_wb_error - has an error occurred since the mark was sampled?
|
|
|
|
+ * @mapping: mapping to check for writeback errors
|
|
|
|
+ * @since: previously-sampled errseq_t
|
|
|
|
+ *
|
|
|
|
+ * Grab the errseq_t value from the mapping, and see if it has changed "since"
|
|
|
|
+ * the given value was sampled.
|
|
|
|
+ *
|
|
|
|
+ * If it has then report the latest error set, otherwise return 0.
|
|
|
|
+ */
|
|
|
|
+static inline int filemap_check_wb_err(struct address_space *mapping,
|
|
|
|
+ errseq_t since)
|
|
|
|
+{
|
|
|
|
+ return errseq_check(&mapping->wb_err, since);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * filemap_sample_wb_err - sample the current errseq_t to test for later errors
|
|
|
|
+ * @mapping: mapping to be sampled
|
|
|
|
+ *
|
|
|
|
+ * Writeback errors are always reported relative to a particular sample point
|
|
|
|
+ * in the past. This function provides those sample points.
|
|
|
|
+ */
|
|
|
|
+static inline errseq_t filemap_sample_wb_err(struct address_space *mapping)
|
|
|
|
+{
|
|
|
|
+ return errseq_sample(&mapping->wb_err);
|
|
|
|
+}
|
|
|
|
+
|
|
extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end,
|
|
extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end,
|
|
int datasync);
|
|
int datasync);
|
|
extern int vfs_fsync(struct file *file, int datasync);
|
|
extern int vfs_fsync(struct file *file, int datasync);
|