* [PATCH v4 14/27] fs: new infrastructure for writeback error handling and reporting
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
Most filesystems currently use mapping_set_error and
filemap_check_errors for setting and reporting/clearing writeback errors
at the mapping level. filemap_check_errors is indirectly called from
most of the filemap_fdatawait_* functions and from
filemap_write_and_wait*. These functions are called from all sorts of
contexts to wait on writeback to finish -- e.g. mostly in fsync, but
also in truncate calls, getattr, etc.
The non-fsync callers are problematic. We should be reporting writeback
errors during fsync, but many places spread over the tree clear out
errors before they can be properly reported, or report errors at
nonsensical times.
If I get -EIO on a stat() call, there is no reason for me to assume that
it is because some previous writeback failed. The fact that it also
clears out the error such that a subsequent fsync returns 0 is a bug,
and a nasty one since that's potentially silent data corruption.
This patch adds a small bit of new infrastructure for setting and
reporting errors during address_space writeback. While the above was my
original impetus for adding this, I think it's also the case that
current fsync semantics are just problematic for userland. Most
applications that call fsync do so to ensure that the data they wrote
has hit the backing store.
In the case where there are multiple writers to the file at the same
time, this is really hard to determine. The first one to call fsync will
see any stored error, and the rest get back 0. The processes with open
fds may not be associated with one another in any way. They could even
be in different containers, so ensuring coordination between all fsync
callers is not really an option.
One way to remedy this would be to track what file descriptor was used
to dirty the file, but that's rather cumbersome and would likely be
slow. However, there is a simpler way to improve the semantics here
without incurring too much overhead.
This set adds an errseq_t to struct address_space, and a corresponding
one is added to struct file. Writeback errors are recorded in the
mapping's errseq_t, and the one in struct file is used as the "since"
value.
This changes the semantics of the Linux fsync implementation such that
applications can now use it to determine whether there were any
writeback errors since fsync(fd) was last called (or since the file was
opened in the case of fsync having never been called).
Note that those writeback errors may have occurred when writing data
that was dirtied via an entirely different fd, but that's the case now
with the current mapping_set_error/filemap_check_error infrastructure.
This will at least prevent you from getting a false report of success.
The new behavior is still consistent with the POSIX spec, and is more
reliable for application developers. This patch just adds some basic
infrastructure for doing this. Later patches will change the existing
code to use this new infrastructure.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
Documentation/filesystems/vfs.txt | 10 +++++++++-
drivers/dax/dax.c | 1 +
fs/block_dev.c | 1 +
fs/file_table.c | 1 +
fs/open.c | 3 +++
include/linux/fs.h | 24 ++++++++++++++++++++++++
mm/filemap.c | 38 ++++++++++++++++++++++++++++++++++++++
7 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 94dd27ef4a76..ed06fb39822b 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -576,6 +576,11 @@ should clear PG_Dirty and set PG_Writeback. It can be actually
written at any point after PG_Dirty is clear. Once it is known to be
safe, PG_Writeback is cleared.
+If there is an error during writeback, then the address_space should be
+marked with an error (typically using filemap_set_wb_error), in order to
+ensure that the error can later be reported to the application when an
+fsync is issued.
+
Writeback makes use of a writeback_control structure...
struct address_space_operations
@@ -888,7 +893,10 @@ otherwise noted.
release: called when the last reference to an open file is closed
- fsync: called by the fsync(2) system call
+ fsync: called by the fsync(2) system call. Filesystems that use the
+ pagecache should call filemap_report_wb_error before returning
+ to ensure that any errors that occurred during writeback are
+ reported and the file's error sequence advanced.
fasync: called by the fcntl(2) system call when asynchronous
(non-blocking) mode is enabled for a file
diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c
index 806f180c80d8..984d6ec35dda 100644
--- a/drivers/dax/dax.c
+++ b/drivers/dax/dax.c
@@ -668,6 +668,7 @@ static int dax_open(struct inode *inode, struct file *filp)
inode->i_mapping = dax_dev->inode->i_mapping;
inode->i_mapping->host = dax_dev->inode;
filp->f_mapping = inode->i_mapping;
+ filp->f_wb_err = filemap_sample_wb_error(filp->f_mapping);
filp->private_data = dax_dev;
inode->i_flags = S_DAX;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 2eca00ec4370..daab40c2e8af 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1857,6 +1857,7 @@ static int blkdev_open(struct inode * inode, struct file * filp)
return -ENOMEM;
filp->f_mapping = bdev->bd_inode->i_mapping;
+ filp->f_wb_err = filemap_sample_wb_error(filp->f_mapping);
return blkdev_get(bdev, filp->f_mode, filp);
}
diff --git a/fs/file_table.c b/fs/file_table.c
index 954d510b765a..d6138b6411ff 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -168,6 +168,7 @@ struct file *alloc_file(const struct path *path, fmode_t mode,
file->f_path = *path;
file->f_inode = path->dentry->d_inode;
file->f_mapping = path->dentry->d_inode->i_mapping;
+ file->f_wb_err = filemap_sample_wb_error(file->f_mapping);
if ((mode & FMODE_READ) &&
likely(fop->read || fop->read_iter))
mode |= FMODE_CAN_READ;
diff --git a/fs/open.c b/fs/open.c
index 949cef29c3bb..88bfed8d3c88 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -709,6 +709,9 @@ static int do_dentry_open(struct file *f,
f->f_inode = inode;
f->f_mapping = inode->i_mapping;
+ /* Ensure that we skip any errors that predate opening of the file */
+ f->f_wb_err = filemap_sample_wb_error(f->f_mapping);
+
if (unlikely(f->f_flags & O_PATH)) {
f->f_mode = FMODE_PATH;
f->f_op = &empty_fops;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 38adefd8e2a0..bab3333e8671 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -31,6 +31,7 @@
#include <linux/workqueue.h>
#include <linux/percpu-rwsem.h>
#include <linux/delayed_call.h>
+#include <linux/errseq.h>
#include <asm/byteorder.h>
#include <uapi/linux/fs.h>
@@ -394,6 +395,7 @@ struct address_space {
gfp_t gfp_mask; /* implicit gfp mask for allocations */
struct list_head private_list; /* ditto */
void *private_data; /* ditto */
+ errseq_t wb_err;
} __attribute__((aligned(sizeof(long))));
/*
* On most architectures that alignment is already the case; but
@@ -846,6 +848,7 @@ struct file {
* Must not be taken from IRQ context.
*/
spinlock_t f_lock;
+ errseq_t f_wb_err;
atomic_long_t f_count;
unsigned int f_flags;
fmode_t f_mode;
@@ -2519,6 +2522,27 @@ 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 int __must_check filemap_report_wb_error(struct file *file);
+
+/**
+ * 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_error(struct address_space *mapping, errseq_t since)
+{
+ return errseq_check(&mapping->wb_err, since);
+}
+
+static inline errseq_t filemap_sample_wb_error(struct address_space *mapping)
+{
+ return errseq_sample(&mapping->wb_err);
+}
extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end,
int datasync);
diff --git a/mm/filemap.c b/mm/filemap.c
index 1694623a6289..ee1a798acfc1 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -546,6 +546,44 @@ int filemap_write_and_wait_range(struct address_space *mapping,
EXPORT_SYMBOL(filemap_write_and_wait_range);
/**
+ * filemap_report_wb_error - report wb error (if any) that was previously set
+ * @file: struct file on which the error is being reported
+ *
+ * When userland calls fsync (or something like nfsd does the equivalent), we
+ * want to report any writeback errors that occurred since the last fsync (or
+ * since the file was opened if there haven't been any).
+ *
+ * Grab the wb_err from the mapping. If it matches what we have in the file,
+ * then just quickly return 0. The file is all caught up.
+ *
+ * If it doesn't match, then take the mapping value, set the "seen" flag in
+ * it and try to swap it into place. If it works, or another task beat us
+ * to it with the new value, then update the f_wb_err and return the error
+ * portion. The error at this point must be reported via proper channels
+ * (a'la fsync, or NFS COMMIT operation, etc.).
+ *
+ * While we handle mapping->wb_err with atomic operations, the f_wb_err
+ * value is protected by the f_lock since we must ensure that it reflects
+ * the latest value swapped in for this file descriptor.
+ */
+int filemap_report_wb_error(struct file *file)
+{
+ int err = 0;
+ struct address_space *mapping = file->f_mapping;
+
+ /* Locklessly handle the common case where nothing has changed */
+ if (errseq_check(&mapping->wb_err, READ_ONCE(file->f_wb_err))) {
+ /* Something changed, must use slow path */
+ spin_lock(&file->f_lock);
+ err = errseq_check_and_advance(&mapping->wb_err,
+ &file->f_wb_err);
+ spin_unlock(&file->f_lock);
+ }
+ return err;
+}
+EXPORT_SYMBOL(filemap_report_wb_error);
+
+/**
* replace_page_cache_page - replace a pagecache page with a new one
* @old: page to be replaced
* @new: page to replace with
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 15/27] fs: retrofit old error reporting API onto new infrastructure
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
Now that we have a better way to store and report errors that occur
during writeback, we need to convert the existing codebase to use it. We
could just adapt all of the filesystem code and related infrastructure
to the new API, but that's a lot of churn.
When it comes to setting errors in the mapping, filemap_set_wb_error is
a drop-in replacement for mapping_set_error. Turn that function into a
simple wrapper around the new one.
Because we want to ensure that writeback errors are always reported at
fsync time, inject filemap_report_wb_error calls much closer to the
syscall boundary, in call_fsync.
For fsync calls (and things like the nfsd equivalent), we either return
the error that the fsync operation returns, or the one returned by
filemap_report_wb_error. In both cases, we advance the file->f_wb_err to
the latest value. This allows us to provide new fsync semantics that
will return errors that may have occurred previously and been viewed
via other file descriptors.
The final piece of the puzzle is what to do about filemap_check_errors
calls that are being called directly or via filemap_* functions. Here,
we must take a little "creative license".
Since we now handle advancing the file->f_wb_err value at the generic
filesystem layer, we no longer need those callers to clear errors out
of the mapping or advance an errseq_t.
A lot of the existing codebase relies on being getting an error back
from those functions when there is a writeback problem, so we do still
want to have them report writeback errors somehow.
When reporting writeback errors, we will always report errors that have
occurred since a particular point in time. With the old writeback error
reporting, the time we used was "since it was last tested/cleared" which
is entirely arbitrary and potentially racy. Now, we can at least report
the latest error that has occurred since an arbitrary point in time
(represented as a sampled errseq_t value).
In the case where we don't have a struct file to work with, this patch
just has the wrappers sample the current mapping->wb_err value, and use
that as an arbitrary point from which to check for errors.
That's probably not "correct" in all cases, particularly in the case of
something like filemap_fdatawait, but I'm not sure it's any worse than
what we already have, and this gives us a basis from which to work.
A lot of those callers will likely want to change to a model where they
sample the errseq_t much earlier (perhaps when starting a transaction),
store it in an appropriate place and then use that value later when
checking to see if an error occurred.
That will almost certainly take some involvement from other subsystem
maintainers. I'm quite open to adding new API functions to help enable
this if that would be helpful, but I don't really want to do that until
I better understand what's needed.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
Documentation/filesystems/vfs.txt | 9 +++----
fs/btrfs/file.c | 10 ++------
fs/btrfs/tree-log.c | 9 ++-----
fs/f2fs/file.c | 3 +++
fs/f2fs/node.c | 6 +----
fs/fuse/file.c | 7 ++++--
fs/libfs.c | 6 +++--
include/linux/fs.h | 19 +++++++++------
include/linux/pagemap.h | 8 ++----
mm/filemap.c | 51 +++++++++++++++++----------------------
10 files changed, 57 insertions(+), 71 deletions(-)
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index ed06fb39822b..f201a77873f7 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -577,7 +577,7 @@ written at any point after PG_Dirty is clear. Once it is known to be
safe, PG_Writeback is cleared.
If there is an error during writeback, then the address_space should be
-marked with an error (typically using filemap_set_wb_error), in order to
+marked with an error (typically using mapping_set_error), in order to
ensure that the error can later be reported to the application when an
fsync is issued.
@@ -893,10 +893,9 @@ otherwise noted.
release: called when the last reference to an open file is closed
- fsync: called by the fsync(2) system call. Filesystems that use the
- pagecache should call filemap_report_wb_error before returning
- to ensure that any errors that occurred during writeback are
- reported and the file's error sequence advanced.
+ fsync: called by the fsync(2) system call. Errors that were previously
+ recorded using mapping_set_error will automatically be returned to
+ the application and the file's error sequence advanced.
fasync: called by the fcntl(2) system call when asynchronous
(non-blocking) mode is enabled for a file
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 520cb7230b2d..e15faf240b51 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1962,6 +1962,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
int ret = 0;
bool full_sync = 0;
u64 len;
+ errseq_t wb_since = READ_ONCE(file->f_wb_err);
/*
* The range length can be represented by u64, we have to do the typecasts
@@ -2079,14 +2080,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
*/
clear_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
&BTRFS_I(inode)->runtime_flags);
- /*
- * An ordered extent might have started before and completed
- * already with io errors, in which case the inode was not
- * updated and we end up here. So check the inode's mapping
- * flags for any errors that might have happened while doing
- * writeback of file data.
- */
- ret = filemap_check_errors(inode->i_mapping);
+ ret = filemap_check_wb_error(inode->i_mapping, wb_since);
inode_unlock(inode);
goto out;
}
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index a59674c3e69e..d0a123dbb199 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -3972,12 +3972,6 @@ static int wait_ordered_extents(struct btrfs_trans_handle *trans,
test_bit(BTRFS_ORDERED_IOERR, &ordered->flags)));
if (test_bit(BTRFS_ORDERED_IOERR, &ordered->flags)) {
- /*
- * Clear the AS_EIO/AS_ENOSPC flags from the inode's
- * i_mapping flags, so that the next fsync won't get
- * an outdated io error too.
- */
- filemap_check_errors(inode->i_mapping);
*ordered_io_error = true;
break;
}
@@ -4171,6 +4165,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
u64 test_gen;
int ret = 0;
int num = 0;
+ errseq_t since = filemap_sample_wb_error(inode->vfs_inode.i_mapping);
INIT_LIST_HEAD(&extents);
@@ -4214,7 +4209,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
* without writing to the log tree and the fsync must report the
* file data write error and not commit the current transaction.
*/
- ret = filemap_check_errors(inode->vfs_inode.i_mapping);
+ ret = filemap_check_wb_error(inode->vfs_inode.i_mapping, since);
if (ret)
ctx->io_err = ret;
process:
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 5f7317875a67..7ce13281925f 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -187,6 +187,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
.nr_to_write = LONG_MAX,
.for_reclaim = 0,
};
+ errseq_t since = READ_ONCE(file->f_wb_err);
if (unlikely(f2fs_readonly(inode->i_sb)))
return 0;
@@ -265,6 +266,8 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
}
ret = wait_on_node_pages_writeback(sbi, ino);
+ if (ret == 0)
+ ret = filemap_check_wb_error(NODE_MAPPING(sbi), since);
if (ret)
goto out;
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 481aa8dc79f4..b3ef9504fd8b 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1630,7 +1630,7 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
{
pgoff_t index = 0, end = ULONG_MAX;
struct pagevec pvec;
- int ret2, ret = 0;
+ int ret = 0;
pagevec_init(&pvec, 0);
@@ -1658,10 +1658,6 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
pagevec_release(&pvec);
cond_resched();
}
-
- ret2 = filemap_check_errors(NODE_MAPPING(sbi));
- if (!ret)
- ret = ret2;
return ret;
}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 07d0efcb050c..e1ced9cfb090 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -398,6 +398,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
struct fuse_req *req;
struct fuse_flush_in inarg;
int err;
+ errseq_t since = READ_ONCE(file->f_wb_err);
if (is_bad_inode(inode))
return -EIO;
@@ -413,7 +414,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
fuse_sync_writes(inode);
inode_unlock(inode);
- err = filemap_check_errors(file->f_mapping);
+ err = filemap_check_wb_error(file->f_mapping, since);
if (err)
return err;
@@ -446,6 +447,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
FUSE_ARGS(args);
struct fuse_fsync_in inarg;
int err;
+ errseq_t since;
if (is_bad_inode(inode))
return -EIO;
@@ -461,6 +463,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
if (err)
goto out;
+ since = READ_ONCE(file->f_wb_err);
fuse_sync_writes(inode);
/*
@@ -468,7 +471,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
* filemap_write_and_wait_range() does not catch errors.
* We have to do this directly after fuse_sync_writes()
*/
- err = filemap_check_errors(file->f_mapping);
+ err = filemap_check_wb_error(file->f_mapping, since);
if (err)
goto out;
diff --git a/fs/libfs.c b/fs/libfs.c
index efd23040ab25..23319d74fa42 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -991,8 +991,10 @@ int __generic_file_fsync(struct file *file, loff_t start, loff_t end,
out:
inode_unlock(inode);
- err = filemap_check_errors(inode->i_mapping);
- return ret ? ret : err;
+ if (!ret)
+ ret = filemap_check_wb_error(inode->i_mapping,
+ READ_ONCE(file->f_wb_err));
+ return ret;
}
EXPORT_SYMBOL(__generic_file_fsync);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index bab3333e8671..e3068f3f69be 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1739,12 +1739,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,
@@ -2512,6 +2506,8 @@ extern int filemap_fdatawrite(struct address_space *);
extern int filemap_flush(struct address_space *);
extern int filemap_fdatawait(struct address_space *);
extern void filemap_fdatawait_keep_errors(struct address_space *);
+extern int filemap_fdatawait_range_since(struct address_space *, loff_t lstart,
+ loff_t lend, errseq_t since);
extern int filemap_fdatawait_range(struct address_space *, loff_t lstart,
loff_t lend);
extern int filemap_write_and_wait(struct address_space *mapping);
@@ -2521,7 +2517,6 @@ extern int __filemap_fdatawrite_range(struct address_space *mapping,
loff_t start, loff_t end, int sync_mode);
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 int __must_check filemap_report_wb_error(struct file *file);
/**
@@ -2544,6 +2539,16 @@ static inline errseq_t filemap_sample_wb_error(struct address_space *mapping)
return errseq_sample(&mapping->wb_err);
}
+static inline int call_fsync(struct file *file, loff_t start, loff_t end,
+ int datasync)
+{
+ int ret, ret2;
+
+ ret = file->f_op->fsync(file, start, end, datasync);
+ ret2 = filemap_report_wb_error(file);
+ return ret ? ret : ret2;
+}
+
extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end,
int datasync);
extern int vfs_fsync(struct file *file, int datasync);
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 84943e8057ef..32512ffc15fa 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -14,6 +14,7 @@
#include <linux/bitops.h>
#include <linux/hardirq.h> /* for in_interrupt() */
#include <linux/hugetlb_inline.h>
+#include <linux/errseq.h>
/*
* Bits in mapping->flags.
@@ -30,12 +31,7 @@ enum mapping_flags {
static inline void mapping_set_error(struct address_space *mapping, int error)
{
- if (unlikely(error)) {
- if (error == -ENOSPC)
- set_bit(AS_ENOSPC, &mapping->flags);
- else
- set_bit(AS_EIO, &mapping->flags);
- }
+ return errseq_set(&mapping->wb_err, error);
}
static inline void mapping_set_unevictable(struct address_space *mapping)
diff --git a/mm/filemap.c b/mm/filemap.c
index ee1a798acfc1..eaec849ec8e5 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -36,6 +36,7 @@
#include <linux/memcontrol.h>
#include <linux/cleancache.h>
#include <linux/rmap.h>
+#include <linux/errseq.h>
#include "internal.h"
#define CREATE_TRACE_POINTS
@@ -295,20 +296,6 @@ void delete_from_page_cache(struct page *page)
}
EXPORT_SYMBOL(delete_from_page_cache);
-int filemap_check_errors(struct address_space *mapping)
-{
- int ret = 0;
- /* Check for outstanding write errors */
- if (test_bit(AS_ENOSPC, &mapping->flags) &&
- test_and_clear_bit(AS_ENOSPC, &mapping->flags))
- ret = -ENOSPC;
- if (test_bit(AS_EIO, &mapping->flags) &&
- test_and_clear_bit(AS_EIO, &mapping->flags))
- ret = -EIO;
- return ret;
-}
-EXPORT_SYMBOL(filemap_check_errors);
-
/**
* __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
* @mapping: address space structure to write
@@ -418,27 +405,32 @@ static int __filemap_fdatawait_range(struct address_space *mapping,
* @mapping: 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)
+ * @since: check for errors since this errseq_t
*
* Walk the list of under-writeback pages of the given address space
* in the given range and wait for all of them. Check error status of
- * the address space and return it.
- *
- * Since the error status of the address space is cleared by this function,
- * callers are responsible for checking the return value and handling and/or
- * reporting the error.
+ * the address space vs. the since value and return it.
*/
-int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte,
- loff_t end_byte)
+int filemap_fdatawait_range_since(struct address_space *mapping,
+ loff_t start_byte, loff_t end_byte, errseq_t since)
{
int ret, ret2;
ret = __filemap_fdatawait_range(mapping, start_byte, end_byte);
- ret2 = filemap_check_errors(mapping);
+ ret2 = filemap_check_wb_error(mapping, since);
if (!ret)
ret = ret2;
return ret;
}
+EXPORT_SYMBOL(filemap_fdatawait_range_since);
+
+int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte,
+ loff_t end_byte)
+{
+ return filemap_fdatawait_range_since(mapping, start_byte, end_byte,
+ filemap_sample_wb_error(mapping));
+}
EXPORT_SYMBOL(filemap_fdatawait_range);
/**
@@ -489,6 +481,7 @@ EXPORT_SYMBOL(filemap_fdatawait);
int filemap_write_and_wait(struct address_space *mapping)
{
int err = 0;
+ errseq_t since = filemap_sample_wb_error(mapping);
if ((!dax_mapping(mapping) && mapping->nrpages) ||
(dax_mapping(mapping) && mapping->nrexceptional)) {
@@ -500,12 +493,12 @@ int filemap_write_and_wait(struct address_space *mapping)
* thing (e.g. bug) happened, so we avoid waiting for it.
*/
if (err != -EIO) {
- int err2 = filemap_fdatawait(mapping);
+ filemap_fdatawait_keep_errors(mapping);
if (!err)
- err = err2;
+ err = filemap_check_wb_error(mapping, since);
}
} else {
- err = filemap_check_errors(mapping);
+ err = filemap_check_wb_error(mapping, since);
}
return err;
}
@@ -526,6 +519,7 @@ int filemap_write_and_wait_range(struct address_space *mapping,
loff_t lstart, loff_t lend)
{
int err = 0;
+ errseq_t since = filemap_sample_wb_error(mapping);
if ((!dax_mapping(mapping) && mapping->nrpages) ||
(dax_mapping(mapping) && mapping->nrexceptional)) {
@@ -533,13 +527,12 @@ int filemap_write_and_wait_range(struct address_space *mapping,
WB_SYNC_ALL);
/* See comment of filemap_write_and_wait() */
if (err != -EIO) {
- int err2 = filemap_fdatawait_range(mapping,
- lstart, lend);
+ __filemap_fdatawait_range(mapping, lstart, lend);
if (!err)
- err = err2;
+ err = filemap_check_wb_error(mapping, since);
}
} else {
- err = filemap_check_errors(mapping);
+ err = filemap_check_wb_error(mapping, since);
}
return err;
}
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 16/27] fs: adapt sync_file_range to new reporting infrastructure
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
Since it returns errors in a way similar to fsync, have it use the same
method for returning previously-reported writeback errors.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/sync.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/fs/sync.c b/fs/sync.c
index 11ba023434b1..89a03b5252d2 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -271,8 +271,11 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
*
*
* SYNC_FILE_RANGE_WAIT_BEFORE and SYNC_FILE_RANGE_WAIT_AFTER will detect any
- * I/O errors or ENOSPC conditions and will return those to the caller, after
- * clearing the EIO and ENOSPC flags in the address_space.
+ * error condition that occurred prior to or after writeback, and will return
+ * that to the caller, while advancing the file's errseq_t cursor. Note that
+ * any errors returned here may have occurred in an area of the file that is
+ * not covered by the given range as most filesystems track writeback errors
+ * on a per-address_space basis
*
* It should be noted that none of these operations write out the file's
* metadata. So unless the application is strictly performing overwrites of
@@ -282,7 +285,7 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes,
unsigned int, flags)
{
- int ret;
+ int ret, ret2;
struct fd f;
struct address_space *mapping;
loff_t endbyte; /* inclusive */
@@ -356,7 +359,9 @@ SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes,
if (flags & SYNC_FILE_RANGE_WAIT_AFTER)
ret = filemap_fdatawait_range(mapping, offset, endbyte);
-
+ ret2 = filemap_report_wb_error(f.file);
+ if (!ret)
+ ret = ret2;
out_put:
fdput(f);
out:
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 17/27] mm: remove AS_EIO and AS_ENOSPC flags
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
They're no longer used.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
include/linux/pagemap.h | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 32512ffc15fa..9593eac41499 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -20,13 +20,11 @@
* Bits in mapping->flags.
*/
enum mapping_flags {
- AS_EIO = 0, /* IO error on async write */
- AS_ENOSPC = 1, /* ENOSPC on async write */
- AS_MM_ALL_LOCKS = 2, /* under mm_take_all_locks() */
- AS_UNEVICTABLE = 3, /* e.g., ramdisk, SHM_LOCK */
- AS_EXITING = 4, /* final truncate in progress */
+ AS_MM_ALL_LOCKS = 0, /* under mm_take_all_locks() */
+ AS_UNEVICTABLE = 1, /* e.g., ramdisk, SHM_LOCK */
+ AS_EXITING = 2, /* final truncate in progress */
/* writeback related tags are not used */
- AS_NO_WRITEBACK_TAGS = 5,
+ AS_NO_WRITEBACK_TAGS = 3,
};
static inline void mapping_set_error(struct address_space *mapping, int error)
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 18/27] mm: don't TestClearPageError in __filemap_fdatawait_range
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
The -EIO returned here can end up overriding whatever error is marked in
the address space, and be returned at fsync time, even when there is a
more appropriate error stored in the mapping.
Read errors are also sometimes tracked on a per-page level using
PG_error. Suppose we have a read error on a page, and then that page is
subsequently dirtied by overwriting the whole page. Writeback doesn't
clear PG_error, so we can then end up successfully writing back that
page and still return -EIO on fsync.
Worse yet, PG_error is cleared during a sync() syscall, but the -EIO
return from that is silently discarded. Any subsystem that is relying on
PG_error to report errors during fsync can easily lose writeback errors
due to this. All you need is a stray sync() call to wait for writeback
to complete and you've lost the error.
Since the handling of the PG_error flag is somewhat inconsistent across
subsystems, let's just rely on marking the address space when there are
writeback errors. Change the TestClearPageError call to ClearPageError,
and make __filemap_fdatawait_range a void return function.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
mm/filemap.c | 20 +++++---------------
1 file changed, 5 insertions(+), 15 deletions(-)
diff --git a/mm/filemap.c b/mm/filemap.c
index eaec849ec8e5..ffdc21762e2f 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -363,17 +363,16 @@ int filemap_flush(struct address_space *mapping)
}
EXPORT_SYMBOL(filemap_flush);
-static int __filemap_fdatawait_range(struct address_space *mapping,
+static void __filemap_fdatawait_range(struct address_space *mapping,
loff_t start_byte, loff_t end_byte)
{
pgoff_t index = start_byte >> PAGE_SHIFT;
pgoff_t end = end_byte >> PAGE_SHIFT;
struct pagevec pvec;
int nr_pages;
- int ret = 0;
if (end_byte < start_byte)
- goto out;
+ return;
pagevec_init(&pvec, 0);
while ((index <= end) &&
@@ -390,14 +389,11 @@ static int __filemap_fdatawait_range(struct address_space *mapping,
continue;
wait_on_page_writeback(page);
- if (TestClearPageError(page))
- ret = -EIO;
+ ClearPageError(page);
}
pagevec_release(&pvec);
cond_resched();
}
-out:
- return ret;
}
/**
@@ -414,14 +410,8 @@ static int __filemap_fdatawait_range(struct address_space *mapping,
int filemap_fdatawait_range_since(struct address_space *mapping,
loff_t start_byte, loff_t end_byte, errseq_t since)
{
- int ret, ret2;
-
- ret = __filemap_fdatawait_range(mapping, start_byte, end_byte);
- ret2 = filemap_check_wb_error(mapping, since);
- if (!ret)
- ret = ret2;
-
- return ret;
+ __filemap_fdatawait_range(mapping, start_byte, end_byte);
+ return filemap_check_wb_error(mapping, since);
}
EXPORT_SYMBOL(filemap_fdatawait_range_since);
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 19/27] buffer: set errors in mapping at the time that the error occurs
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
I noticed on xfs that I could still sometimes get back an error on fsync
on a fd that was opened after the error condition had been cleared.
The problem is that the buffer code sets the write_io_error flag and
then later checks that flag to set the error in the mapping. That flag
perisists for quite a while however. If the file is later opened with
O_TRUNC, the buffers will then be invalidated and the mapping's error
set such that a subsequent fsync will return error. I think this is
incorrect, as there was no writeback between the open and fsync.
Add a new mark_buffer_write_io_error operation that sets the flag and
the error in the mapping at the same time. Replace all calls to
set_buffer_write_io_error with mark_buffer_write_io_error, and remove
the places that check this flag in order to set the error in the
mapping.
This sets the error in the mapping earlier, at the time that it's first
detected.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/buffer.c | 19 +++++++++++++------
fs/gfs2/lops.c | 2 +-
include/linux/buffer_head.h | 1 +
3 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 70638941066d..1b566cf3f4e4 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -179,7 +179,7 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate)
set_buffer_uptodate(bh);
} else {
buffer_io_error(bh, ", lost sync page write");
- set_buffer_write_io_error(bh);
+ mark_buffer_write_io_error(bh);
clear_buffer_uptodate(bh);
}
unlock_buffer(bh);
@@ -354,7 +354,7 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate)
} else {
buffer_io_error(bh, ", lost async page write");
mapping_set_error(page->mapping, -EIO);
- set_buffer_write_io_error(bh);
+ mark_buffer_write_io_error(bh);
clear_buffer_uptodate(bh);
SetPageError(page);
}
@@ -482,8 +482,6 @@ static void __remove_assoc_queue(struct buffer_head *bh)
{
list_del_init(&bh->b_assoc_buffers);
WARN_ON(!bh->b_assoc_map);
- if (buffer_write_io_error(bh))
- mapping_set_error(bh->b_assoc_map, -EIO);
bh->b_assoc_map = NULL;
}
@@ -1182,6 +1180,17 @@ void mark_buffer_dirty(struct buffer_head *bh)
}
EXPORT_SYMBOL(mark_buffer_dirty);
+void mark_buffer_write_io_error(struct buffer_head *bh)
+{
+ set_buffer_write_io_error(bh);
+ /* FIXME: do we need to set this in both places? */
+ if (bh->b_page && bh->b_page->mapping)
+ mapping_set_error(bh->b_page->mapping, -EIO);
+ if (bh->b_assoc_map)
+ mapping_set_error(bh->b_assoc_map, -EIO);
+}
+EXPORT_SYMBOL(mark_buffer_write_io_error);
+
/*
* Decrement a buffer_head's reference count. If all buffers against a page
* have zero reference count, are clean and unlocked, and if the page is clean
@@ -3291,8 +3300,6 @@ drop_buffers(struct page *page, struct buffer_head **buffers_to_free)
bh = head;
do {
- if (buffer_write_io_error(bh) && page->mapping)
- mapping_set_error(page->mapping, -EIO);
if (buffer_busy(bh))
goto failed;
bh = bh->b_this_page;
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index b1f9144b42c7..cd7857ab1a6a 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -182,7 +182,7 @@ static void gfs2_end_log_write_bh(struct gfs2_sbd *sdp, struct bio_vec *bvec,
bh = bh->b_this_page;
do {
if (error)
- set_buffer_write_io_error(bh);
+ mark_buffer_write_io_error(bh);
unlock_buffer(bh);
next = bh->b_this_page;
size -= bh->b_size;
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 79591c3660cc..db6256fb1692 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -149,6 +149,7 @@ void buffer_check_dirty_writeback(struct page *page,
*/
void mark_buffer_dirty(struct buffer_head *bh);
+void mark_buffer_write_io_error(struct buffer_head *bh);
void init_buffer(struct buffer_head *, bh_end_io_t *, void *);
void touch_buffer(struct buffer_head *bh);
void set_bh_page(struct buffer_head *bh,
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 20/27] cifs: cleanup writeback handling errors and comments
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
Now that writeback errors are handled on a per-file basis using the new
sequence counter method at the vfs layer, we no longer need to re-set
errors in the mapping after doing writeback in non-fsync codepaths.
Also, fix up some bogus comments.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/cifsfs.c | 4 +---
fs/cifs/file.c | 7 ++-----
fs/cifs/inode.c | 22 +++++++---------------
3 files changed, 10 insertions(+), 23 deletions(-)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index dd3f5fabfdf6..017a2d1d02c7 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -829,10 +829,8 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int whence)
if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
inode->i_mapping->nrpages != 0) {
rc = filemap_fdatawait(inode->i_mapping);
- if (rc) {
- mapping_set_error(inode->i_mapping, rc);
+ if (rc)
return rc;
- }
}
/*
* Some applications poll for the file length in this strange
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 0bee7f8d91ad..9825d892716e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -722,9 +722,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
cinode = CIFS_I(inode);
if (can_flush) {
- rc = filemap_write_and_wait(inode->i_mapping);
- mapping_set_error(inode->i_mapping, rc);
-
+ filemap_write_and_wait(inode->i_mapping);
if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path,
inode->i_sb, xid);
@@ -3906,8 +3904,7 @@ void cifs_oplock_break(struct work_struct *work)
break_lease(inode, O_WRONLY);
rc = filemap_fdatawrite(inode->i_mapping);
if (!CIFS_CACHE_READ(cinode)) {
- rc = filemap_fdatawait(inode->i_mapping);
- mapping_set_error(inode->i_mapping, rc);
+ filemap_fdatawait(inode->i_mapping);
cifs_zap_mapping(inode);
}
cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index b261db34103c..a58e605240fc 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -2008,10 +2008,8 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
inode->i_mapping->nrpages != 0) {
rc = filemap_fdatawait(inode->i_mapping);
- if (rc) {
- mapping_set_error(inode->i_mapping, rc);
+ if (rc)
return rc;
- }
}
rc = cifs_revalidate_dentry_attr(dentry);
@@ -2171,15 +2169,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
* Attempt to flush data before changing attributes. We need to do
* this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
* ownership or mode then we may also need to do this. Here, we take
- * the safe way out and just do the flush on all setattr requests. If
- * the flush returns error, store it to report later and continue.
+ * the safe way out and just do the flush on all setattr requests.
*
* BB: This should be smarter. Why bother flushing pages that
- * will be truncated anyway? Also, should we error out here if
- * the flush returns error?
+ * will be truncated anyway?
*/
- rc = filemap_write_and_wait(inode->i_mapping);
- mapping_set_error(inode->i_mapping, rc);
+ filemap_write_and_wait(inode->i_mapping);
rc = 0;
if (attrs->ia_valid & ATTR_SIZE) {
@@ -2314,15 +2309,12 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
* Attempt to flush data before changing attributes. We need to do
* this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
* ownership or mode then we may also need to do this. Here, we take
- * the safe way out and just do the flush on all setattr requests. If
- * the flush returns error, store it to report later and continue.
+ * the safe way out and just do the flush on all setattr requests.
*
* BB: This should be smarter. Why bother flushing pages that
- * will be truncated anyway? Also, should we error out here if
- * the flush returns error?
+ * will be truncated anyway?
*/
- rc = filemap_write_and_wait(inode->i_mapping);
- mapping_set_error(inode->i_mapping, rc);
+ filemap_write_and_wait(inode->i_mapping);
rc = 0;
if (attrs->ia_valid & ATTR_SIZE) {
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 21/27] mm: clean up error handling in write_one_page
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
Don't try to check PageError since that's potentially racy and not
necessarily going to be set after writepage errors out.
Instead, sample the mapping error early on, and use that value to tell
us whether we got a writeback error since then.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
mm/page-writeback.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index de0dbf12e2c1..1643456881b4 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2373,11 +2373,12 @@ int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
int write_one_page(struct page *page)
{
struct address_space *mapping = page->mapping;
- int ret = 0;
+ int ret = 0, ret2;
struct writeback_control wbc = {
.sync_mode = WB_SYNC_ALL,
.nr_to_write = 1,
};
+ errseq_t since = filemap_sample_wb_error(mapping);
BUG_ON(!PageLocked(page));
@@ -2386,16 +2387,14 @@ int write_one_page(struct page *page)
if (clear_page_dirty_for_io(page)) {
get_page(page);
ret = mapping->a_ops->writepage(page, &wbc);
- if (ret == 0) {
+ if (ret == 0)
wait_on_page_writeback(page);
- if (PageError(page))
- ret = -EIO;
- }
put_page(page);
} else {
unlock_page(page);
}
- return ret;
+ ret2 = filemap_check_wb_error(mapping, since);
+ return ret ? : ret2;
}
EXPORT_SYMBOL(write_one_page);
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 23/27] gfs2: clean up some filemap_* calls
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
In some places, it's trying to reset the mapping error after calling
filemap_fdatawait. That's no longer required. Also, turn several
filemap_fdatawrite+filemap_fdatawait calls into filemap_write_and_wait.
That will at least return writeback errors that occur during the write
phase.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/gfs2/glops.c | 17 ++++-------------
fs/gfs2/lops.c | 4 +---
fs/gfs2/super.c | 6 ++----
3 files changed, 7 insertions(+), 20 deletions(-)
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 5db59d444838..18ab54e351d6 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -145,7 +145,6 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct address_space *mapping = &sdp->sd_aspace;
struct gfs2_rgrpd *rgd;
- int error;
spin_lock(&gl->gl_lockref.lock);
rgd = gl->gl_object;
@@ -158,9 +157,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
gfs2_log_flush(sdp, gl, NORMAL_FLUSH);
- filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
- error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
- mapping_set_error(mapping, error);
+ filemap_write_and_wait_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
gfs2_ail_empty_gl(gl);
spin_lock(&gl->gl_lockref.lock);
@@ -207,7 +204,6 @@ static void inode_go_sync(struct gfs2_glock *gl)
{
struct gfs2_inode *ip = gl->gl_object;
struct address_space *metamapping = gfs2_glock2aspace(gl);
- int error;
if (ip && !S_ISREG(ip->i_inode.i_mode))
ip = NULL;
@@ -223,14 +219,9 @@ static void inode_go_sync(struct gfs2_glock *gl)
gfs2_log_flush(gl->gl_name.ln_sbd, gl, NORMAL_FLUSH);
filemap_fdatawrite(metamapping);
- if (ip) {
- struct address_space *mapping = ip->i_inode.i_mapping;
- filemap_fdatawrite(mapping);
- error = filemap_fdatawait(mapping);
- mapping_set_error(mapping, error);
- }
- error = filemap_fdatawait(metamapping);
- mapping_set_error(metamapping, error);
+ if (ip)
+ filemap_write_and_wait(ip->i_inode.i_mapping);
+ filemap_fdatawait(metamapping);
gfs2_ail_empty_gl(gl);
/*
* Writeback of the data mapping may cause the dirty flag to be set
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index cd7857ab1a6a..614bb974b927 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -586,9 +586,7 @@ static void gfs2_meta_sync(struct gfs2_glock *gl)
if (mapping == NULL)
mapping = &sdp->sd_aspace;
- filemap_fdatawrite(mapping);
- error = filemap_fdatawait(mapping);
-
+ error = filemap_write_and_wait(mapping);
if (error)
gfs2_io_error(gl->gl_name.ln_sbd);
}
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 361796a84fce..675c39566ea1 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1593,10 +1593,8 @@ static void gfs2_evict_inode(struct inode *inode)
out_truncate:
gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
metamapping = gfs2_glock2aspace(ip->i_gl);
- if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) {
- filemap_fdatawrite(metamapping);
- filemap_fdatawait(metamapping);
- }
+ if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags))
+ filemap_write_and_wait(metamapping);
write_inode_now(inode, 1);
gfs2_ail_flush(ip->i_gl, 0);
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 24/27][RFC] nfs: convert to new errseq_t based error tracking for writeback errors
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
Drop the ERROR_WRITE flag and convert the error field in the context to
a errseq_t. Add a new wb_err_cursor to track the reporting of the
errseq_t. In principle, we could use the f_wb_err field in struct file
for that, but that's problematic with the stock reporting in call_fsync.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/nfs/file.c | 19 +++++++++++--------
fs/nfs/inode.c | 5 +++--
fs/nfs/write.c | 2 +-
include/linux/nfs_fs.h | 3 ++-
4 files changed, 17 insertions(+), 12 deletions(-)
I did this on a lark to see how it would be, but I don't think this is
really better than what's there already. There may be a better way to
provide the right semantics without using an errseq_t here.
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 668213984d68..fd4d2b381d4b 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -212,21 +212,24 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
{
struct nfs_open_context *ctx = nfs_file_open_context(file);
struct inode *inode = file_inode(file);
- int have_error, do_resend, status;
- int ret = 0;
+ int do_resend, status;
+ int ret;
dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync);
nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
- have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
+ clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
status = nfs_commit_inode(inode, FLUSH_SYNC);
- have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
- if (have_error) {
- ret = xchg(&ctx->error, 0);
- if (ret)
- goto out;
+ ret = errseq_check(&ctx->wb_err, READ_ONCE(ctx->wb_err_cursor));
+ if (ret) {
+ /* Use f_lock to serialize changes to wb_err_cursor */
+ spin_lock(&file->f_lock);
+ ret = errseq_check_and_advance(&ctx->wb_err, &ctx->wb_err_cursor);
+ spin_unlock(&file->f_lock);
}
+ if (ret)
+ goto out;
if (status < 0) {
ret = status;
goto out;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f489a5a71bd5..ca85f6b39e3b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -869,7 +869,8 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry,
ctx->state = NULL;
ctx->mode = f_mode;
ctx->flags = 0;
- ctx->error = 0;
+ ctx->wb_err = 0;
+ ctx->wb_err_cursor = 0;
ctx->flock_owner = (fl_owner_t)filp;
nfs_init_lock_context(&ctx->lock_context);
ctx->lock_context.open_context = ctx;
@@ -978,7 +979,7 @@ void nfs_file_clear_open_context(struct file *filp)
* We fatal error on write before. Try to writeback
* every page again.
*/
- if (ctx->error < 0)
+ if (errseq_check(&ctx->wb_err, ctx->wb_err_cursor))
invalidate_inode_pages2(inode->i_mapping);
filp->private_data = NULL;
spin_lock(&inode->i_lock);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index abb2c8a3be42..95a5b4ac6714 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -94,7 +94,7 @@ static void nfs_writehdr_free(struct nfs_pgio_header *hdr)
static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
{
- ctx->error = error;
+ errseq_set(&ctx->wb_err, error);
smp_wmb();
set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
}
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 287f34161086..336adf1a38f7 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -76,7 +76,8 @@ struct nfs_open_context {
#define NFS_CONTEXT_ERROR_WRITE (0)
#define NFS_CONTEXT_RESEND_WRITES (1)
#define NFS_CONTEXT_BAD (2)
- int error;
+ errseq_t wb_err; /* where wb errors are tracked */
+ errseq_t wb_err_cursor; /* reporting cursor */
struct list_head list;
struct nfs4_threshold *mdsthreshold;
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 22/27] jbd2: don't reset error in journal_finish_inode_data_buffers
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
Now that we don't clear writeback errors after fetching them, there is
no need to reset them. This is also potentially racy.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/jbd2/commit.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index b6b194ec1b4f..4c6262652028 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -264,17 +264,8 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
jinode->i_flags |= JI_COMMIT_RUNNING;
spin_unlock(&journal->j_list_lock);
err = filemap_fdatawait(jinode->i_vfs_inode->i_mapping);
- if (err) {
- /*
- * Because AS_EIO is cleared by
- * filemap_fdatawait_range(), set it again so
- * that user process can get -EIO from fsync().
- */
- mapping_set_error(jinode->i_vfs_inode->i_mapping, -EIO);
-
- if (!ret)
- ret = err;
- }
+ if (err && !ret)
+ ret = err;
spin_lock(&journal->j_list_lock);
jinode->i_flags &= ~JI_COMMIT_RUNNING;
smp_mb();
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 25/27] Documentation: flesh out the section in vfs.txt on storing and reporting writeback errors
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
I waxed a little loquacious here, but I figured that more detail was
better, and writeback error handling is so hard to get right.
Cc: Jan Kara <jack@suse.cz>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
Documentation/filesystems/vfs.txt | 54 ++++++++++++++++++++++++++++++++-------
1 file changed, 45 insertions(+), 9 deletions(-)
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index f201a77873f7..382190a872e5 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -576,12 +576,46 @@ should clear PG_Dirty and set PG_Writeback. It can be actually
written at any point after PG_Dirty is clear. Once it is known to be
safe, PG_Writeback is cleared.
-If there is an error during writeback, then the address_space should be
-marked with an error (typically using mapping_set_error), in order to
-ensure that the error can later be reported to the application when an
-fsync is issued.
-
-Writeback makes use of a writeback_control structure...
+Writeback makes use of a writeback_control structure to direct the
+operations. This gives the the writepage and writepages operations some
+information about the nature of and reason for the writeback request,
+and the constraints under which it is being done. It is also used to
+return information back to the caller about the result of a writepage or
+writepages request.
+
+Handling errors during writeback
+--------------------------------
+Most applications that utilize the pagecache will periodically call
+fsync to ensure that data written has made it to the backing store.
+When there is an error during writeback, that error should be reported
+when fsync is called. After an error has been reported to fsync,
+subsequent fsync calls on the same file descriptor should return 0,
+unless further writeback errors have occurred since the previous fsync.
+
+Ideally, the kernel would report it only on file descriptions on which
+writes were done that subsequently failed to be written back. The
+generic pagecache infrastructure does not track the file descriptions
+that have dirtied each individual page however, so determining which
+file descriptors should get back an error is not possible.
+
+Instead, the generic writeback error tracking infrastructure in the
+kernel settles for reporting errors to fsync on all file descriptions
+that were open at the time that the error occurred. In a situation with
+multiple writers, all of them will get back an error on a subsequent fsync,
+even if all of the writes done through that particular file descriptor
+succeeded (or even if there were no writes on that file descriptor at all).
+
+Filesystems that wish to use this infrastructure should call
+mapping_set_error to record the error in the address_space when it
+occurs. The generic vfs code will then handle reporting the error when
+fsync is called, even if the fsync file operation returned 0.
+
+Filesystems are free to track errors internally if they choose (i.e. if
+they do keep track of how the pages were dirtied), but they should aim
+to provide the same (or better) error reporting semantics for when there
+are multiple writers. Those filesystems should avoid calling
+mapping_set_error in order to ensure that errors stored in the mapping
+aren't improperly reported by the generic filesystem code.
struct address_space_operations
-------------------------------
@@ -810,7 +844,8 @@ struct address_space_operations {
The File Object
===============
-A file object represents a file opened by a process.
+A file object represents a file opened by a process. This is also known
+as an "open file description" in POSIX parlance.
struct file_operations
@@ -893,9 +928,10 @@ otherwise noted.
release: called when the last reference to an open file is closed
- fsync: called by the fsync(2) system call. Errors that were previously
+ fsync: called by the fsync(2) system call. Errors that were previously
recorded using mapping_set_error will automatically be returned to
- the application and the file's error sequence advanced.
+ the application and the struct file's error sequence advanced.
+ See the section above on handling writeback errors.
fasync: called by the fcntl(2) system call when asynchronous
(non-blocking) mode is enabled for a file
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 26/27] mm: flesh out comments over mapping_set_error
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
include/linux/pagemap.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 9593eac41499..9b453eae0aa1 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -27,6 +27,20 @@ enum mapping_flags {
AS_NO_WRITEBACK_TAGS = 3,
};
+/**
+ * mapping_set_error - record a writeback error in the address_space
+ * @mapping - the mapping in which an error should be set
+ * @error - the error to set in the 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 will filesystems will want to call
+ * mapping_set_error to record the error in the mapping so that it will be
+ * automatically reported whenever fsync is called on the file.
+ */
static inline void mapping_set_error(struct address_space *mapping, int error)
{
return errseq_set(&mapping->wb_err, error);
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 27/27] mm: clean up comments in me_pagecache_dirty
From: Jeff Layton @ 2017-05-09 15:49 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509154930.29524-1-jlayton@redhat.com>
This no longer applies with the new writeback error tracking and
reporting infrastructure.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
mm/memory-failure.c | 35 +++++------------------------------
1 file changed, 5 insertions(+), 30 deletions(-)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 4b56e53e5378..be5f998a0772 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -642,37 +642,12 @@ static int me_pagecache_dirty(struct page *p, unsigned long pfn)
if (mapping) {
/*
* IO error will be reported by write(), fsync(), etc.
- * who check the mapping.
- * This way the application knows that something went
- * wrong with its dirty file data.
+ * who check the mapping. This way the application knows that
+ * something went wrong when writing back its dirty file data.
*
- * There's one open issue:
- *
- * The EIO will be only reported on the next IO
- * operation and then cleared through the IO map.
- * Normally Linux has two mechanisms to pass IO error
- * first through the AS_EIO flag in the address space
- * and then through the PageError flag in the page.
- * Since we drop pages on memory failure handling the
- * only mechanism open to use is through AS_AIO.
- *
- * This has the disadvantage that it gets cleared on
- * the first operation that returns an error, while
- * the PageError bit is more sticky and only cleared
- * when the page is reread or dropped. If an
- * application assumes it will always get error on
- * fsync, but does other operations on the fd before
- * and the page is dropped between then the error
- * will not be properly reported.
- *
- * This can already happen even without hwpoisoned
- * pages: first on metadata IO errors (which only
- * report through AS_EIO) or when the page is dropped
- * at the wrong time.
- *
- * So right now we assume that the application DTRT on
- * the first EIO, but we're not worse than other parts
- * of the kernel.
+ * Note that errors are reported only once per file
+ * description, but should be reported on all open file
+ * descriptions for this inode.
*/
mapping_set_error(mapping, -EIO);
}
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* Re: [PATCH] mm, vmalloc: fix vmalloc users tracking properly
From: kbuild test robot @ 2017-05-09 15:59 UTC (permalink / raw)
To: Michal Hocko
Cc: kbuild-all, Linus Torvalds, Andrew Morton, Tobias Klauser,
linux-mm, LKML, Michal Hocko
In-Reply-To: <20170509144108.31910-1-mhocko@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 5270 bytes --]
Hi Michal,
[auto build test ERROR on mmotm/master]
[also build test ERROR on next-20170509]
[cannot apply to v4.11]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Michal-Hocko/mm-vmalloc-fix-vmalloc-users-tracking-properly/20170509-224536
base: git://git.cmpxchg.org/linux-mmotm.git master
config: c6x-evmc6678_defconfig (attached as .config)
compiler: c6x-elf-gcc (GCC) 6.2.0
reproduce:
wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=c6x
All errors (new ones prefixed by >>):
mm/nommu.c:51:5: sparse: symbol 'sysctl_nr_trim_pages' was not declared. Should it be static?
mm/nommu.c:52:5: sparse: symbol 'heap_stack_gap' was not declared. Should it be static?
mm/nommu.c:63:35: sparse: symbol 'generic_file_vm_ops' was not declared. Should it be static?
mm/nommu.c:240:6: sparse: symbol '__vmalloc_node_flags' was not declared. Should it be static?
mm/nommu.c:1175:48: sparse: incorrect type in argument 2 (different address spaces)
mm/nommu.c:1175:48: expected char [noderef] <asn:1>*<noident>
mm/nommu.c:1175:48: got void *[assigned] base
mm/nommu.c:1790:15: sparse: symbol 'arch_get_unmapped_area' was not declared. Should it be static?
mm/nommu.c:638:9: sparse: context imbalance in '__put_nommu_region' - wrong count at exit
mm/nommu.c:659:13: sparse: context imbalance in 'put_nommu_region' - unexpected unlock
In file included from include/asm-generic/io.h:767:0,
from ./arch/c6x/include/generated/asm/io.h:1,
from include/linux/io.h:25,
from include/linux/irq.h:24,
from include/asm-generic/hardirq.h:12,
from arch/c6x/include/asm/hardirq.h:18,
from include/linux/hardirq.h:8,
from include/linux/memcontrol.h:24,
from include/linux/swap.h:8,
from mm/nommu.c:23:
include/linux/vmalloc.h:85:21: error: conflicting types for '__vmalloc_node_flags_caller'
static inline void *__vmalloc_node_flags_caller(unsigned long size, int node, gfp_t flags, void* caller)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/vmalloc.h:84:14: note: previous declaration of '__vmalloc_node_flags_caller' was here
extern void *__vmalloc_node_flags_caller(unsigned long size, int node, gfp_t flags);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/vmalloc.h: In function '__vmalloc_node_flags_caller':
include/linux/vmalloc.h:87:9: error: implicit declaration of function '__vmalloc_node_flags' [-Werror=implicit-function-declaration]
return __vmalloc_node_flags(size, node, flags);
^~~~~~~~~~~~~~~~~~~~
include/linux/vmalloc.h:87:9: warning: return makes pointer from integer without a cast [-Wint-conversion]
return __vmalloc_node_flags(size, node, flags);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mm/nommu.c: At top level:
>> mm/nommu.c:240:7: error: conflicting types for '__vmalloc_node_flags'
void *__vmalloc_node_flags(unsigned long size, int node, gfp_t flags)
^~~~~~~~~~~~~~~~~~~~
In file included from include/asm-generic/io.h:767:0,
from ./arch/c6x/include/generated/asm/io.h:1,
from include/linux/io.h:25,
from include/linux/irq.h:24,
from include/asm-generic/hardirq.h:12,
from arch/c6x/include/asm/hardirq.h:18,
from include/linux/hardirq.h:8,
from include/linux/memcontrol.h:24,
from include/linux/swap.h:8,
from mm/nommu.c:23:
include/linux/vmalloc.h:87:9: note: previous implicit declaration of '__vmalloc_node_flags' was here
return __vmalloc_node_flags(size, node, flags);
^~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/__vmalloc_node_flags +240 mm/nommu.c
8518609d Robert P. J. Day 2007-10-19 234 * returns only a logical address.
^1da177e Linus Torvalds 2005-04-16 235 */
84097518 Nick Piggin 2006-03-22 236 return kmalloc(size, (gfp_mask | __GFP_COMP) & ~__GFP_HIGHMEM);
^1da177e Linus Torvalds 2005-04-16 237 }
b5073173 Paul Mundt 2007-07-21 238 EXPORT_SYMBOL(__vmalloc);
^1da177e Linus Torvalds 2005-04-16 239
c7e6abdb Michal Hocko 2017-05-03 @240 void *__vmalloc_node_flags(unsigned long size, int node, gfp_t flags)
c7e6abdb Michal Hocko 2017-05-03 241 {
c7e6abdb Michal Hocko 2017-05-03 242 return __vmalloc(size, flags, PAGE_KERNEL);
c7e6abdb Michal Hocko 2017-05-03 243 }
:::::: The code at line 240 was first introduced by commit
:::::: c7e6abdbe12a86cfa1bdba2bd3e9f5fdb1cb175b mm: introduce kv[mz]alloc helpers
:::::: TO: Michal Hocko <mhocko@suse.com>
:::::: CC: Johannes Weiner <hannes@cmpxchg.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 5454 bytes --]
^ permalink raw reply
* [xfstests PATCH v2 0/3] xfstest for updated writeback error handling
From: Jeff Layton @ 2017-05-09 16:12 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block,
fstests
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
I've numbered the new test as 999 for the moment so as not to collide with
tests being added while I've been working on this. I can change that and
resend if this should go in.
I'm working on a set of kernel patches to change how writeback errors
are handled and reported in the kernel. Instead of reporting a
writeback error to only the first fsync caller on the file, I aim
to make the kernel report them once on every file description:
http://www.spinics.net/lists/kernel/msg2504453.html
This patch adds a test for the new behavior, on local filesystems that
can handle journalling to a separate device. Basically, open many fds to
the same file, turn on dm_error, write to each of the fds, and then
fsync them all to ensure that they all get an error back. Then, flip the
device back to working, reopen the files and ensure that no error is
reported.
With the kernel patch series in place, ext4 and xfs now pass. btrfs still
clears the error after the first fsync, so it seems like it still needs a
bit of work.
Jeff Layton (3):
generic: add a writeback error handling test
ext4: allow ext4 to use $SCRATCH_LOGDEV
btrfs: allow it to use $SCRATCH_LOGDEV
common/dmerror | 13 +++--
common/rc | 5 ++
src/Makefile | 2 +-
src/fsync-err.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++
tests/generic/999 | 75 +++++++++++++++++++++++++++
tests/generic/999.out | 3 ++
tests/generic/group | 1 +
tools/dmerror | 47 +++++++++++++++++
8 files changed, 278 insertions(+), 6 deletions(-)
create mode 100644 src/fsync-err.c
create mode 100755 tests/generic/999
create mode 100644 tests/generic/999.out
create mode 100755 tools/dmerror
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [xfstests PATCH v2 1/3] generic: add a writeback error handling test
From: Jeff Layton @ 2017-05-09 16:12 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block,
fstests
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509161245.29908-1-jlayton@redhat.com>
I'm working on a set of kernel patches to change how writeback errors
are handled and reported in the kernel. Instead of reporting a
writeback error to only the first fsync caller on the file, I aim
to make the kernel report them once on every file description.
This patch adds a test for the new behavior. Basically, open many fds
to the same file, turn on dm_error, write to each of the fds, and then
fsync them all to ensure that they all get an error back.
To do that, I'm adding a new tools/dmerror script that the C program
can use to load the error table. For now, that's all it can do, but
we can fill it out with other commands as necessary.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
common/dmerror | 13 +++--
src/Makefile | 2 +-
src/fsync-err.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++
tests/generic/999 | 75 +++++++++++++++++++++++++++
tests/generic/999.out | 3 ++
tests/generic/group | 1 +
tools/dmerror | 47 +++++++++++++++++
7 files changed, 273 insertions(+), 6 deletions(-)
create mode 100644 src/fsync-err.c
create mode 100755 tests/generic/999
create mode 100644 tests/generic/999.out
create mode 100755 tools/dmerror
diff --git a/common/dmerror b/common/dmerror
index d46c5d0b7266..238baa213b1f 100644
--- a/common/dmerror
+++ b/common/dmerror
@@ -23,22 +23,25 @@ if [ $? -eq 0 ]; then
_notrun "Cannot run tests with DAX on dmerror devices"
fi
-_dmerror_init()
+_dmerror_setup()
{
local dm_backing_dev=$SCRATCH_DEV
- $DMSETUP_PROG remove error-test > /dev/null 2>&1
-
local blk_dev_size=`blockdev --getsz $dm_backing_dev`
DMERROR_DEV='/dev/mapper/error-test'
DMLINEAR_TABLE="0 $blk_dev_size linear $dm_backing_dev 0"
+ DMERROR_TABLE="0 $blk_dev_size error $dm_backing_dev 0"
+}
+
+_dmerror_init()
+{
+ _dmerror_setup
+ $DMSETUP_PROG remove error-test > /dev/null 2>&1
$DMSETUP_PROG create error-test --table "$DMLINEAR_TABLE" || \
_fatal "failed to create dm linear device"
-
- DMERROR_TABLE="0 $blk_dev_size error $dm_backing_dev 0"
}
_dmerror_mount()
diff --git a/src/Makefile b/src/Makefile
index e5042c9b7d8e..eb8ff6c4a344 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -12,7 +12,7 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
godown resvtest writemod makeextents itrash rename \
multi_open_unlink dmiperf unwritten_sync genhashnames t_holes \
t_mmap_writev t_truncate_cmtime dirhash_collide t_rename_overwrite \
- holetest t_truncate_self t_mmap_dio af_unix t_mmap_stale_pmd
+ holetest t_truncate_self t_mmap_dio af_unix t_mmap_stale_pmd fsync-err
LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
diff --git a/src/fsync-err.c b/src/fsync-err.c
new file mode 100644
index 000000000000..8ad27b3da3e7
--- /dev/null
+++ b/src/fsync-err.c
@@ -0,0 +1,138 @@
+/*
+ * fsync-err.c: test whether writeback errors are reported to all open fds
+ * Copyright (c) 2017: Jeff Layton <jlayton@redhat.com>
+ *
+ * Open a file several times, write to it and then fsync. Flip dm_error over
+ * to make the backing device stop working. Overwrite the same section and
+ * call fsync on all fds and verify that we get errors on all of them. Then,
+ * fsync one more time on all of them and verify that they return 0.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NUM_FDS 10
+
+static void usage() {
+ fprintf(stderr, "Usage: fsync-err <filename>\n");
+}
+
+int main(int argc, char **argv)
+{
+ int fd[NUM_FDS], ret, i;
+ char *fname, *buf;
+
+ if (argc < 1) {
+ usage();
+ return 1;
+ }
+
+ /* First argument is filename */
+ fname = argv[1];
+
+ for (i = 0; i < NUM_FDS; ++i) {
+ fd[i] = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd[i] < 0) {
+ printf("open of fd[%d] failed: %m\n", i);
+ return 1;
+ }
+ }
+
+ buf = "foobar";
+ for (i = 0; i < NUM_FDS; ++i) {
+ ret = write(fd[i], buf, strlen(buf) + 1);
+ if (ret < 0) {
+ printf("First write on fd[%d] failed: %m\n", i);
+ return 1;
+ }
+ }
+
+ for (i = 0; i < NUM_FDS; ++i) {
+ ret = fsync(fd[i]);
+ if (ret < 0) {
+ printf("First fsync on fd[%d] failed: %m\n", i);
+ return 1;
+ }
+ }
+
+ /* flip the device to non-working mode */
+ ret = system("./tools/dmerror load_error_table");
+ if (ret) {
+ if (WIFEXITED(ret))
+ printf("system: program exited: %d\n",
+ WEXITSTATUS(ret));
+ else
+ printf("system: 0x%x\n", (int)ret);
+
+ return 1;
+ }
+
+ for (i = 0; i < NUM_FDS; ++i) {
+ ret = write(fd[i], buf, strlen(buf) + 1);
+ if (ret < 0) {
+ printf("Second write on fd[%d] failed: %m\n", i);
+ return 1;
+ }
+ }
+
+ for (i = 0; i < NUM_FDS; ++i) {
+ ret = fsync(fd[i]);
+ /* Now, we EXPECT the error! */
+ if (ret >= 0) {
+ printf("Success on second fsync on fd[%d]!\n", i);
+ return 1;
+ }
+ }
+
+ /* flip the device to working mode */
+ ret = system("./tools/dmerror load_working_table");
+ if (ret) {
+ if (WIFEXITED(ret))
+ printf("system: program exited: %d\n",
+ WEXITSTATUS(ret));
+ else
+ printf("system: 0x%x\n", (int)ret);
+
+ return 1;
+ }
+
+ for (i = 0; i < NUM_FDS; ++i) {
+ ret = fsync(fd[i]);
+ if (ret < 0) {
+ /* Now the error should be clear */
+ printf("Third fsync on fd[%d] failed: %m\n", i);
+ return 1;
+ }
+ }
+
+ /*
+ * reopen each file to guarantee the same one stays in core. fsync
+ * each one to make sure we see no errors.
+ */
+ for (i = 0; i < NUM_FDS; ++i) {
+ ret = close(fd[i]);
+ if (ret < 0) {
+ printf("Close of fd[%d] returned unexpected error: %m\n", i);
+ return 1;
+ }
+ fd[i] = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd[i] < 0) {
+ printf("Second open of fd[%d] failed: %m\n", i);
+ return 1;
+ }
+ ret = fsync(fd[i]);
+ if (ret < 0) {
+ /* New opens should not return an error */
+ printf("First fsync after reopen of fd[%d] failed: %m\n", i);
+ return 1;
+ }
+ }
+
+ printf("Test passed!\n");
+ return 0;
+}
diff --git a/tests/generic/999 b/tests/generic/999
new file mode 100755
index 000000000000..57e093b43416
--- /dev/null
+++ b/tests/generic/999
@@ -0,0 +1,75 @@
+#! /bin/bash
+# FS QA Test No. 999
+#
+# Open a file several times, write to it, fsync on all fds and make sure that
+# they all return 0. Change the device to start throwing errors. Write again
+# on all fds and fsync on all fds. Ensure that we get errors on all of them.
+# Then fsync on all one last time and verify that all return 0.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2017, Jeff Layton <jlayton@redhat.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#-----------------------------------------------------------------------
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1 # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+ cd /
+ rm -rf $tmp.* $testdir
+ _dmerror_cleanup
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/dmerror
+
+# real QA test starts here
+_supported_os Linux
+_require_scratch
+_require_logdev
+_require_dm_target error
+
+rm -f $seqres.full
+
+echo "Format and mount"
+$XFS_IO_PROG -d -c "pwrite -S 0x7c -b 1048576 0 $((64 * 1048576))" $SCRATCH_DEV >> $seqres.full
+_scratch_mkfs > $seqres.full 2>&1
+_dmerror_init
+_dmerror_mount >> $seqres.full 2>&1
+_dmerror_unmount
+_dmerror_mount
+
+_require_fs_space $SCRATCH_MNT 8192
+
+testfile=$SCRATCH_MNT/fsync-err-test
+
+$here/src/fsync-err $testfile
+
+# success, all done
+_dmerror_load_working_table
+_dmerror_unmount
+_dmerror_cleanup
+_repair_scratch_fs >> $seqres.full
+status=0
+exit
diff --git a/tests/generic/999.out b/tests/generic/999.out
new file mode 100644
index 000000000000..2e48492ff6d1
--- /dev/null
+++ b/tests/generic/999.out
@@ -0,0 +1,3 @@
+QA output created by 999
+Format and mount
+Test passed!
diff --git a/tests/generic/group b/tests/generic/group
index 9fc7f9d419a8..854c39277dd5 100644
--- a/tests/generic/group
+++ b/tests/generic/group
@@ -432,3 +432,4 @@
427 auto quick aio rw
428 auto quick
429 auto encrypt
+999 auto quick
diff --git a/tools/dmerror b/tools/dmerror
new file mode 100755
index 000000000000..fc0de295e778
--- /dev/null
+++ b/tools/dmerror
@@ -0,0 +1,47 @@
+#!/bin/bash
+#-----------------------------------------------------------------------
+# Copyright (c) 2017, Jeff Layton <jlayton@redhat.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#-----------------------------------------------------------------------
+
+. ./common/rc
+. ./common/dmerror
+
+_dmerror_setup
+
+case $1 in
+cleanup)
+ _dmerror_cleanup
+ ;;
+init)
+ _dmerror_init
+ ;;
+load_error_table)
+ _dmerror_load_error_table
+ ;;
+load_working_table)
+ _dmerror_load_working_table
+ ;;
+mount)
+ _dmerror_mount
+ ;;
+*)
+ echo "Usage: $0 {init|cleanup|load_error_table|load_working_table|mount}"
+ exit 1
+ ;;
+esac
+
+status=0
+exit
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [xfstests PATCH v2 2/3] ext4: allow ext4 to use $SCRATCH_LOGDEV
From: Jeff Layton @ 2017-05-09 16:12 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block,
fstests
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509161245.29908-1-jlayton@redhat.com>
The writeback error handling test requires that you put the journal on a
separate device. This allows us to use dmerror to simulate data
writeback failure, without affecting the journal.
xfs already has infrastructure for this (a'la $SCRATCH_LOGDEV), so wire
up the ext4 code so that it can do the same thing when _scratch_mkfs is
called.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
common/rc | 3 +++
1 file changed, 3 insertions(+)
diff --git a/common/rc b/common/rc
index 257b1903359d..8b815d9c8c33 100644
--- a/common/rc
+++ b/common/rc
@@ -675,6 +675,9 @@ _scratch_mkfs_ext4()
local tmp=`mktemp`
local mkfs_status
+ [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
+ $mkfs_cmd -O journal_dev $SCRATCH_LOGDEV && \
+ mkfs_cmd="$mkfs_cmd -J device=$SCRATCH_LOGDEV"
_scratch_do_mkfs "$mkfs_cmd" "$mkfs_filter" $* 2>$tmp.mkfserr 1>$tmp.mkfsstd
mkfs_status=$?
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [xfstests PATCH v2 3/3] btrfs: allow it to use $SCRATCH_LOGDEV
From: Jeff Layton @ 2017-05-09 16:12 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block,
fstests
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu
In-Reply-To: <20170509161245.29908-1-jlayton@redhat.com>
With btrfs, we can't really put the log on a separate device. What we
can do however is mirror the metadata across two devices and put the
data on a single device. When we turn on dmerror then the metadata can
fall back to using the other mirror while the data errors out.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
common/rc | 2 ++
1 file changed, 2 insertions(+)
diff --git a/common/rc b/common/rc
index 8b815d9c8c33..2084c1f24f30 100644
--- a/common/rc
+++ b/common/rc
@@ -829,6 +829,8 @@ _scratch_mkfs()
;;
btrfs)
mkfs_cmd="$MKFS_BTRFS_PROG"
+ [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
+ mkfs_cmd="$mkfs_cmd -d single -m raid1 $SCRATCH_LOGDEV"
mkfs_filter="cat"
;;
ext2|ext3)
--
2.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* Re: [PATCH v4 25/27] Documentation: flesh out the section in vfs.txt on storing and reporting writeback errors
From: Jeff Layton @ 2017-05-09 16:24 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, linux-btrfs, linux-ext4, linux-cifs,
linux-nfs, linux-mm, jfs-discussion, linux-xfs, cluster-devel,
linux-f2fs-devel, v9fs-developer, linux-nilfs, linux-block
Cc: dhowells, akpm, hch, ross.zwisler, mawilcox, jack, viro, corbet,
neilb, clm, tytso, axboe, josef, hubcap, rpeterso, bo.li.liu,
Michael Kerrisk
In-Reply-To: <20170509154930.29524-26-jlayton@redhat.com>
On Tue, 2017-05-09 at 11:49 -0400, Jeff Layton wrote:
> I waxed a little loquacious here, but I figured that more detail was
> better, and writeback error handling is so hard to get right.
>
> Cc: Jan Kara <jack@suse.cz>
> Signed-off-by: Jeff Layton <jlayton@redhat.com>
> ---
> Documentation/filesystems/vfs.txt | 54 ++++++++++++++++++++++++++++++++-------
> 1 file changed, 45 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
> index f201a77873f7..382190a872e5 100644
> --- a/Documentation/filesystems/vfs.txt
> +++ b/Documentation/filesystems/vfs.txt
> @@ -576,12 +576,46 @@ should clear PG_Dirty and set PG_Writeback. It can be actually
> written at any point after PG_Dirty is clear. Once it is known to be
> safe, PG_Writeback is cleared.
>
> -If there is an error during writeback, then the address_space should be
> -marked with an error (typically using mapping_set_error), in order to
> -ensure that the error can later be reported to the application when an
> -fsync is issued.
> -
> -Writeback makes use of a writeback_control structure...
> +Writeback makes use of a writeback_control structure to direct the
> +operations. This gives the the writepage and writepages operations some
> +information about the nature of and reason for the writeback request,
> +and the constraints under which it is being done. It is also used to
> +return information back to the caller about the result of a writepage or
> +writepages request.
> +
> +Handling errors during writeback
> +--------------------------------
> +Most applications that utilize the pagecache will periodically call
> +fsync to ensure that data written has made it to the backing store.
> +When there is an error during writeback, that error should be reported
> +when fsync is called. After an error has been reported to fsync,
> +subsequent fsync calls on the same file descriptor should return 0,
> +unless further writeback errors have occurred since the previous fsync.
> +
> +Ideally, the kernel would report it only on file descriptions on which
> +writes were done that subsequently failed to be written back. The
> +generic pagecache infrastructure does not track the file descriptions
> +that have dirtied each individual page however, so determining which
> +file descriptors should get back an error is not possible.
> +
> +Instead, the generic writeback error tracking infrastructure in the
> +kernel settles for reporting errors to fsync on all file descriptions
> +that were open at the time that the error occurred. In a situation with
> +multiple writers, all of them will get back an error on a subsequent fsync,
> +even if all of the writes done through that particular file descriptor
> +succeeded (or even if there were no writes on that file descriptor at all).
> +
(cc'ing Michael Kerrisk)
Once this is closer to merge, I think we'll also want to update the
fsync(2) manpage with something similar to the 3 paragraphs above, and
also with an explanation of the behavior that applications can expect
from earlier kernels.
> +Filesystems that wish to use this infrastructure should call
> +mapping_set_error to record the error in the address_space when it
> +occurs. The generic vfs code will then handle reporting the error when
> +fsync is called, even if the fsync file operation returned 0.
> +
> +Filesystems are free to track errors internally if they choose (i.e. if
> +they do keep track of how the pages were dirtied), but they should aim
> +to provide the same (or better) error reporting semantics for when there
> +are multiple writers. Those filesystems should avoid calling
> +mapping_set_error in order to ensure that errors stored in the mapping
> +aren't improperly reported by the generic filesystem code.
>
> struct address_space_operations
> -------------------------------
> @@ -810,7 +844,8 @@ struct address_space_operations {
> The File Object
> ===============
>
> -A file object represents a file opened by a process.
> +A file object represents a file opened by a process. This is also known
> +as an "open file description" in POSIX parlance.
>
>
> struct file_operations
> @@ -893,9 +928,10 @@ otherwise noted.
>
> release: called when the last reference to an open file is closed
>
> - fsync: called by the fsync(2) system call. Errors that were previously
> + fsync: called by the fsync(2) system call. Errors that were previously
> recorded using mapping_set_error will automatically be returned to
> - the application and the file's error sequence advanced.
> + the application and the struct file's error sequence advanced.
> + See the section above on handling writeback errors.
>
> fasync: called by the fcntl(2) system call when asynchronous
> (non-blocking) mode is enabled for a file
--
Jeff Layton <jlayton@redhat.com>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [RFC 03/10] x86/mm: Make the batched unmap TLB flush API more generic
From: Dave Hansen @ 2017-05-09 17:13 UTC (permalink / raw)
To: Andy Lutomirski
Cc: X86 ML, linux-kernel@vger.kernel.org, Borislav Petkov,
Linus Torvalds, Andrew Morton, Mel Gorman, linux-mm@kvack.org,
Rik van Riel, Nadav Amit, Michal Hocko, Sasha Levin
In-Reply-To: <CALCETrXO2etzB55ZYk9xy4=8bWQC1+mv877tJHg-tOUpWGk6qw@mail.gmail.com>
On 05/09/2017 06:02 AM, Andy Lutomirski wrote:
> On Mon, May 8, 2017 at 8:34 AM, Dave Hansen <dave.hansen@intel.com> wrote:
>> On 05/07/2017 05:38 AM, Andy Lutomirski wrote:
>>> diff --git a/mm/rmap.c b/mm/rmap.c
>>> index f6838015810f..2e568c82f477 100644
>>> --- a/mm/rmap.c
>>> +++ b/mm/rmap.c
>>> @@ -579,25 +579,12 @@ void page_unlock_anon_vma_read(struct anon_vma *anon_vma)
>>> void try_to_unmap_flush(void)
>>> {
>>> struct tlbflush_unmap_batch *tlb_ubc = ¤t->tlb_ubc;
>>> - int cpu;
>>>
>>> if (!tlb_ubc->flush_required)
>>> return;
>>>
>>> - cpu = get_cpu();
>>> -
>>> - if (cpumask_test_cpu(cpu, &tlb_ubc->cpumask)) {
>>> - count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
>>> - local_flush_tlb();
>>> - trace_tlb_flush(TLB_LOCAL_SHOOTDOWN, TLB_FLUSH_ALL);
>>> - }
>>> -
>>> - if (cpumask_any_but(&tlb_ubc->cpumask, cpu) < nr_cpu_ids)
>>> - flush_tlb_others(&tlb_ubc->cpumask, NULL, 0, TLB_FLUSH_ALL);
>>> - cpumask_clear(&tlb_ubc->cpumask);
>>> tlb_ubc->flush_required = false;
>>> tlb_ubc->writable = false;
>>> - put_cpu();
>>> }
>>>
>>> /* Flush iff there are potentially writable TLB entries that can race with IO */
>>> @@ -613,7 +600,7 @@ static void set_tlb_ubc_flush_pending(struct mm_struct *mm, bool writable)
>>> {
>>> struct tlbflush_unmap_batch *tlb_ubc = ¤t->tlb_ubc;
>>>
>>> - cpumask_or(&tlb_ubc->cpumask, &tlb_ubc->cpumask, mm_cpumask(mm));
>>> + arch_tlbbatch_add_mm(&tlb_ubc->arch, mm);
>>> tlb_ubc->flush_required = true;
>>>
>>> /*
>>
>> Looking at this patch in isolation, how can this be safe? It removes
>> TLB flushes from the generic code. Do other patches in the series fix
>> this up?
>
> Hmm? Unless I totally screwed this up, this patch just moves the
> flushes around -- it shouldn't remove any flushes.
This takes a flush out of try_to_unmap_flush(). It adds code for
arch_tlbbatch_flush(), but not *calls* to arch_tlbbatch_flush() that I
can see.
I actually don't see _any_ in the whole series in a quick grepping. Am
I just missing them?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [v3 0/9] parallelized "struct page" zeroing
From: Michal Hocko @ 2017-05-09 18:12 UTC (permalink / raw)
To: Pavel Tatashin
Cc: linux-kernel, sparclinux, linux-mm, linuxppc-dev, linux-s390,
borntraeger, heiko.carstens, davem
In-Reply-To: <1494003796-748672-1-git-send-email-pasha.tatashin@oracle.com>
On Fri 05-05-17 13:03:07, Pavel Tatashin wrote:
> Changelog:
> v2 - v3
> - Addressed David's comments about one change per patch:
> * Splited changes to platforms into 4 patches
> * Made "do not zero vmemmap_buf" as a separate patch
> v1 - v2
> - Per request, added s390 to deferred "struct page" zeroing
> - Collected performance data on x86 which proofs the importance to
> keep memset() as prefetch (see below).
>
> When deferred struct page initialization feature is enabled, we get a
> performance gain of initializing vmemmap in parallel after other CPUs are
> started. However, we still zero the memory for vmemmap using one boot CPU.
> This patch-set fixes the memset-zeroing limitation by deferring it as well.
I like the idea of postponing the zeroing from the allocation to the
init time. To be honest the improvement looks much larger than I would
expect (Btw. this should be a part of the changelog rather than a
outside link).
The implementation just looks too large to what I would expect. E.g. do
we really need to add zero argument to the large part of the memblock
API? Wouldn't it be easier to simply export memblock_virt_alloc_internal
(or its tiny wrapper memblock_virt_alloc_core) and move the zeroing
outside to its 2 callers? A completely untested scratched version at the
end of the email.
Also it seems that this is not 100% correct either as it only cares
about VMEMMAP while DEFERRED_STRUCT_PAGE_INIT might be enabled also for
SPARSEMEM. This would suggest that we would zero out pages twice,
right?
A similar concern would go to the memory hotplug patch which will
fall back to the slab/page allocator IIRC. On the other hand
__init_single_page is shared with the hotplug code so again we would
initialize 2 times.
So I suspect more changes are needed. I will have a closer look tomorrow.
> arch/powerpc/mm/init_64.c | 4 +-
> arch/s390/mm/vmem.c | 5 ++-
> arch/sparc/mm/init_64.c | 26 +++++++----------------
> arch/x86/mm/init_64.c | 3 +-
> include/linux/bootmem.h | 3 ++
> include/linux/mm.h | 15 +++++++++++--
> mm/memblock.c | 46 ++++++++++++++++++++++++++++++++++++------
> mm/page_alloc.c | 3 ++
> mm/sparse-vmemmap.c | 48 +++++++++++++++++++++++++++++---------------
> 9 files changed, 103 insertions(+), 50 deletions(-)
The bootmem API change mentioned above.
include/linux/bootmem.h | 3 +++
mm/memblock.c | 41 ++++++++++++++++++++++++++---------------
mm/sparse-vmemmap.c | 2 +-
3 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 962164d36506..c9a08463d9a8 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -160,6 +160,9 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
#define BOOTMEM_ALLOC_ANYWHERE (~(phys_addr_t)0)
/* FIXME: Move to memblock.h at a point where we remove nobootmem.c */
+void * memblock_virt_alloc_core(phys_addr_t size, phys_addr_t align,
+ phys_addr_t min_addr, phys_addr_t max_addr,
+ int nid);
void *memblock_virt_alloc_try_nid_nopanic(phys_addr_t size,
phys_addr_t align, phys_addr_t min_addr,
phys_addr_t max_addr, int nid);
diff --git a/mm/memblock.c b/mm/memblock.c
index b049c9b2dba8..eab7da94f873 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1271,8 +1271,7 @@ phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, i
*
* The memory block is aligned on SMP_CACHE_BYTES if @align == 0.
*
- * The phys address of allocated boot memory block is converted to virtual and
- * allocated memory is reset to 0.
+ * The function has to be zeroed out explicitly.
*
* In addition, function sets the min_count to 0 using kmemleak_alloc for
* allocated boot memory block, so that it is never reported as leaks.
@@ -1280,15 +1279,18 @@ phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, i
* RETURNS:
* Virtual address of allocated memory block on success, NULL on failure.
*/
-static void * __init memblock_virt_alloc_internal(
+static inline void * __init memblock_virt_alloc_internal(
phys_addr_t size, phys_addr_t align,
phys_addr_t min_addr, phys_addr_t max_addr,
- int nid)
+ int nid, void *caller)
{
phys_addr_t alloc;
void *ptr;
ulong flags = choose_memblock_flags();
+ memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx %pF\n",
+ __func__, (u64)size, (u64)align, nid, (u64)min_addr,
+ (u64)max_addr, caller);
if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
nid = NUMA_NO_NODE;
@@ -1334,7 +1336,6 @@ static void * __init memblock_virt_alloc_internal(
return NULL;
done:
ptr = phys_to_virt(alloc);
- memset(ptr, 0, size);
/*
* The min_count is set to 0 so that bootmem allocated blocks
@@ -1347,6 +1348,14 @@ static void * __init memblock_virt_alloc_internal(
return ptr;
}
+void * __init memblock_virt_alloc_core(phys_addr_t size, phys_addr_t align,
+ phys_addr_t min_addr, phys_addr_t max_addr,
+ int nid)
+{
+ return memblock_virt_alloc_internal(size, align, min_addr, max_addr, nid,
+ (void *)_RET_IP_);
+}
+
/**
* memblock_virt_alloc_try_nid_nopanic - allocate boot memory block
* @size: size of memory block to be allocated in bytes
@@ -1369,11 +1378,14 @@ void * __init memblock_virt_alloc_try_nid_nopanic(
phys_addr_t min_addr, phys_addr_t max_addr,
int nid)
{
- memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx %pF\n",
- __func__, (u64)size, (u64)align, nid, (u64)min_addr,
- (u64)max_addr, (void *)_RET_IP_);
- return memblock_virt_alloc_internal(size, align, min_addr,
- max_addr, nid);
+ void *ptr;
+
+ ptr = memblock_virt_alloc_internal(size, align, min_addr,
+ max_addr, nid, (void *)_RET_IP_);
+ if (ptr)
+ memset(ptr, 0, size);
+
+ return ptr;
}
/**
@@ -1401,13 +1413,12 @@ void * __init memblock_virt_alloc_try_nid(
{
void *ptr;
- memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx %pF\n",
- __func__, (u64)size, (u64)align, nid, (u64)min_addr,
- (u64)max_addr, (void *)_RET_IP_);
ptr = memblock_virt_alloc_internal(size, align,
- min_addr, max_addr, nid);
- if (ptr)
+ min_addr, max_addr, nid, (void *)_RET_IP_);
+ if (ptr) {
+ memset(ptr, 0, size);
return ptr;
+ }
panic("%s: Failed to allocate %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx\n",
__func__, (u64)size, (u64)align, nid, (u64)min_addr,
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index a56c3989f773..4e060f0f9fe5 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -41,7 +41,7 @@ static void * __ref __earlyonly_bootmem_alloc(int node,
unsigned long align,
unsigned long goal)
{
- return memblock_virt_alloc_try_nid(size, align, goal,
+ return memblock_virt_alloc_core(size, align, goal,
BOOTMEM_ALLOC_ACCESSIBLE, node);
}
--
Michal Hocko
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* Re: [v3 0/9] parallelized "struct page" zeroing
From: Pasha Tatashin @ 2017-05-09 18:54 UTC (permalink / raw)
To: Michal Hocko
Cc: linux-kernel, sparclinux, linux-mm, linuxppc-dev, linux-s390,
borntraeger, heiko.carstens, davem
In-Reply-To: <20170509181234.GA4397@dhcp22.suse.cz>
Hi Michal,
> I like the idea of postponing the zeroing from the allocation to the
> init time. To be honest the improvement looks much larger than I would
> expect (Btw. this should be a part of the changelog rather than a
> outside link).
The improvements are larger, because this time was never measured, as
Linux does not have early boot time stamps. I added them for x86 and
SPARC to emasure the performance. I am pushing those changes through
separate patchsets.
>
> The implementation just looks too large to what I would expect. E.g. do
> we really need to add zero argument to the large part of the memblock
> API? Wouldn't it be easier to simply export memblock_virt_alloc_internal
> (or its tiny wrapper memblock_virt_alloc_core) and move the zeroing
> outside to its 2 callers? A completely untested scratched version at the
> end of the email.
I am OK, with this change. But, I do not really see a difference between:
memblock_virt_alloc_raw()
and
memblock_virt_alloc_core()
In both cases we use memblock_virt_alloc_internal(), but the only
difference is that in my case we tell memblock_virt_alloc_internal() to
zero the pages if needed, and in your case the other two callers are
zeroing it. I like moving memblock_dbg() inside
memblock_virt_alloc_internal()
>
> Also it seems that this is not 100% correct either as it only cares
> about VMEMMAP while DEFERRED_STRUCT_PAGE_INIT might be enabled also for
> SPARSEMEM. This would suggest that we would zero out pages twice,
> right?
Thank you, I will check this combination before sending out the next patch.
>
> A similar concern would go to the memory hotplug patch which will
> fall back to the slab/page allocator IIRC. On the other hand
> __init_single_page is shared with the hotplug code so again we would
> initialize 2 times.
Correct, when memory it hotplugged, to gain the benefit of this fix, and
also not to regress by actually double zeroing "struct pages" we should
not zero it out. However, I do not really have means to test it.
>
> So I suspect more changes are needed. I will have a closer look tomorrow.
Thank you for reviewing this work. I will wait for your comments before
sending out updated patches.
Pasha
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH] mm, vmalloc: fix vmalloc users tracking properly
From: Geert Uytterhoeven @ 2017-05-09 19:01 UTC (permalink / raw)
To: Michal Hocko
Cc: Linus Torvalds, Andrew Morton, Tobias Klauser, Linux MM, LKML,
Michal Hocko
In-Reply-To: <20170509144108.31910-1-mhocko@kernel.org>
Hi Michal,
On Tue, May 9, 2017 at 4:41 PM, Michal Hocko <mhocko@kernel.org> wrote:
> From: Michal Hocko <mhocko@suse.com>
>
> 1f5307b1e094 ("mm, vmalloc: properly track vmalloc users") has pulled
> asm/pgtable.h include dependency to linux/vmalloc.h and that turned out
> to be a bad idea for some architectures. E.g. m68k fails with
> In file included from arch/m68k/include/asm/pgtable_mm.h:145:0,
> from arch/m68k/include/asm/pgtable.h:4,
> from include/linux/vmalloc.h:9,
> from arch/m68k/kernel/module.c:9:
> arch/m68k/include/asm/mcf_pgtable.h: In function 'nocache_page':
>>> arch/m68k/include/asm/mcf_pgtable.h:339:43: error: 'init_mm' undeclared (first use in this function)
> #define pgd_offset_k(address) pgd_offset(&init_mm, address)
>
> as spotted by kernel build bot. nios2 fails for other reason
> In file included from ./include/asm-generic/io.h:767:0,
> from ./arch/nios2/include/asm/io.h:61,
> from ./include/linux/io.h:25,
> from ./arch/nios2/include/asm/pgtable.h:18,
> from ./include/linux/mm.h:70,
> from ./include/linux/pid_namespace.h:6,
> from ./include/linux/ptrace.h:9,
> from ./arch/nios2/include/uapi/asm/elf.h:23,
> from ./arch/nios2/include/asm/elf.h:22,
> from ./include/linux/elf.h:4,
> from ./include/linux/module.h:15,
> from init/main.c:16:
> ./include/linux/vmalloc.h: In function '__vmalloc_node_flags':
> ./include/linux/vmalloc.h:99:40: error: 'PAGE_KERNEL' undeclared (first use in this function); did you mean 'GFP_KERNEL'?
>
> which is due to the newly added #include <asm/pgtable.h>, which on nios2
> includes <linux/io.h> and thus <asm/io.h> and <asm-generic/io.h> which
> again includes <linux/vmalloc.h>.
>
> Tweaking that around just turns out a bigger headache than
> necessary. This patch reverts 1f5307b1e094 and reimplements the original
> fix in a different way. __vmalloc_node_flags can stay static inline
> which will cover vmalloc* functions. We only have one external user
> (kvmalloc_node) and we can export __vmalloc_node_flags_caller and
> provide the caller directly. This is much simpler and it doesn't really
> need any games with header files.
>
> Fixes: 1f5307b1e094 ("mm, vmalloc: properly track vmalloc users")
> Signed-off-by: Michal Hocko <mhocko@suse.com>
FWIW, this did fix the following build failure on m68k in linus/master
(commit 2868b2513aa732a9 ("Merge tag 'linux-kselftest-4.12-rc1' of
git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest"):
In file included from arch/m68k/include/asm/pgtable_mm.h:148,
from arch/m68k/include/asm/pgtable.h:5,
from include/linux/vmalloc.h:10,
from arch/m68k/kernel/module.c:10:
arch/m68k/include/asm/motorola_pgtable.h: In function ‘pgd_offset’:
arch/m68k/include/asm/motorola_pgtable.h:198: error: dereferencing
pointer to incomplete type
scripts/Makefile.build:294: recipe for target
'arch/m68k/kernel/module.o' failed
but given the complaints from 0day on this and future versions, I think it's
better not to provide a Tested-by yet.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH] mm, vmalloc: fix vmalloc users tracking properly
From: Michal Hocko @ 2017-05-09 19:36 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Linus Torvalds, Andrew Morton, Tobias Klauser, Linux MM, LKML
In-Reply-To: <CAMuHMdV2=PUs64K8tnGw1oPDRjKbx0SRkN-59ToTpj57=CXYdA@mail.gmail.com>
On Tue 09-05-17 21:01:25, Geert Uytterhoeven wrote:
> Hi Michal,
>
> On Tue, May 9, 2017 at 4:41 PM, Michal Hocko <mhocko@kernel.org> wrote:
> > From: Michal Hocko <mhocko@suse.com>
> >
> > 1f5307b1e094 ("mm, vmalloc: properly track vmalloc users") has pulled
> > asm/pgtable.h include dependency to linux/vmalloc.h and that turned out
> > to be a bad idea for some architectures. E.g. m68k fails with
> > In file included from arch/m68k/include/asm/pgtable_mm.h:145:0,
> > from arch/m68k/include/asm/pgtable.h:4,
> > from include/linux/vmalloc.h:9,
> > from arch/m68k/kernel/module.c:9:
> > arch/m68k/include/asm/mcf_pgtable.h: In function 'nocache_page':
> >>> arch/m68k/include/asm/mcf_pgtable.h:339:43: error: 'init_mm' undeclared (first use in this function)
> > #define pgd_offset_k(address) pgd_offset(&init_mm, address)
> >
> > as spotted by kernel build bot. nios2 fails for other reason
> > In file included from ./include/asm-generic/io.h:767:0,
> > from ./arch/nios2/include/asm/io.h:61,
> > from ./include/linux/io.h:25,
> > from ./arch/nios2/include/asm/pgtable.h:18,
> > from ./include/linux/mm.h:70,
> > from ./include/linux/pid_namespace.h:6,
> > from ./include/linux/ptrace.h:9,
> > from ./arch/nios2/include/uapi/asm/elf.h:23,
> > from ./arch/nios2/include/asm/elf.h:22,
> > from ./include/linux/elf.h:4,
> > from ./include/linux/module.h:15,
> > from init/main.c:16:
> > ./include/linux/vmalloc.h: In function '__vmalloc_node_flags':
> > ./include/linux/vmalloc.h:99:40: error: 'PAGE_KERNEL' undeclared (first use in this function); did you mean 'GFP_KERNEL'?
> >
> > which is due to the newly added #include <asm/pgtable.h>, which on nios2
> > includes <linux/io.h> and thus <asm/io.h> and <asm-generic/io.h> which
> > again includes <linux/vmalloc.h>.
> >
> > Tweaking that around just turns out a bigger headache than
> > necessary. This patch reverts 1f5307b1e094 and reimplements the original
> > fix in a different way. __vmalloc_node_flags can stay static inline
> > which will cover vmalloc* functions. We only have one external user
> > (kvmalloc_node) and we can export __vmalloc_node_flags_caller and
> > provide the caller directly. This is much simpler and it doesn't really
> > need any games with header files.
> >
> > Fixes: 1f5307b1e094 ("mm, vmalloc: properly track vmalloc users")
> > Signed-off-by: Michal Hocko <mhocko@suse.com>
>
> FWIW, this did fix the following build failure on m68k in linus/master
> (commit 2868b2513aa732a9 ("Merge tag 'linux-kselftest-4.12-rc1' of
> git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest"):
>
> In file included from arch/m68k/include/asm/pgtable_mm.h:148,
> from arch/m68k/include/asm/pgtable.h:5,
> from include/linux/vmalloc.h:10,
> from arch/m68k/kernel/module.c:10:
> arch/m68k/include/asm/motorola_pgtable.h: In function a??pgd_offseta??:
> arch/m68k/include/asm/motorola_pgtable.h:198: error: dereferencing
> pointer to incomplete type
> scripts/Makefile.build:294: recipe for target
> 'arch/m68k/kernel/module.o' failed
>
> but given the complaints from 0day on this and future versions, I think it's
> better not to provide a Tested-by yet.
FWIW I have already sent a follow up fix
http://lkml.kernel.org/r/20170509153702.GR6481@dhcp22.suse.cz
--
Michal Hocko
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox