linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH AUTOSEL 5.9 45/55] iomap: clean up writeback state logic on writepage error
       [not found] <20201110035318.423757-1-sashal@kernel.org>
@ 2020-11-10  3:53 ` Sasha Levin
  2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 46/55] selftests: proc: fix warning: _GNU_SOURCE redefined Sasha Levin
  2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 53/55] seq_file: add seq_read_iter Sasha Levin
  2 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2020-11-10  3:53 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Brian Foster, Darrick J . Wong, Sasha Levin, linux-xfs, linux-fsdevel

From: Brian Foster <bfoster@redhat.com>

[ Upstream commit 50e7d6c7a5210063b9a6f0d8799d9d1440907fcf ]

The iomap writepage error handling logic is a mash of old and
slightly broken XFS writepage logic. When keepwrite writeback state
tracking was introduced in XFS in commit 0d085a529b42 ("xfs: ensure
WB_SYNC_ALL writeback handles partial pages correctly"), XFS had an
additional cluster writeback context that scanned ahead of
->writepage() to process dirty pages over the current ->writepage()
extent mapping. This context expected a dirty page and required
retention of the TOWRITE tag on partial page processing so the
higher level writeback context would revisit the page (in contrast
to ->writepage(), which passes a page with the dirty bit already
cleared).

The cluster writeback mechanism was eventually removed and some of
the error handling logic folded into the primary writeback path in
commit 150d5be09ce4 ("xfs: remove xfs_cancel_ioend"). This patch
accidentally conflated the two contexts by using the keepwrite logic
in ->writepage() without accounting for the fact that the page is
not dirty. Further, the keepwrite logic has no practical effect on
the core ->writepage() caller (write_cache_pages()) because it never
revisits a page in the current function invocation.

Technically, the page should be redirtied for the keepwrite logic to
have any effect. Otherwise, write_cache_pages() may find the tagged
page but will skip it since it is clean. Even if the page was
redirtied, however, there is still no practical effect to keepwrite
since write_cache_pages() does not wrap around within a single
invocation of the function. Therefore, the dirty page would simply
end up retagged on the next writeback sequence over the associated
range.

All that being said, none of this really matters because redirtying
a partially processed page introduces a potential infinite redirty
-> writeback failure loop that deviates from the current design
principle of clearing the dirty state on writepage failure to avoid
building up too much dirty, unreclaimable memory on the system.
Therefore, drop the spurious keepwrite usage and dirty state
clearing logic from iomap_writepage_map(), treat the partially
processed page the same as a fully processed page, and let the
imminent ioend failure clean up the writeback state.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/iomap/buffered-io.c | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index b115e7d47fcec..238613443bec2 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -1395,6 +1395,7 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
 	WARN_ON_ONCE(!wpc->ioend && !list_empty(&submit_list));
 	WARN_ON_ONCE(!PageLocked(page));
 	WARN_ON_ONCE(PageWriteback(page));
+	WARN_ON_ONCE(PageDirty(page));
 
 	/*
 	 * We cannot cancel the ioend directly here on error.  We may have
@@ -1415,21 +1416,9 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
 			unlock_page(page);
 			goto done;
 		}
-
-		/*
-		 * If the page was not fully cleaned, we need to ensure that the
-		 * higher layers come back to it correctly.  That means we need
-		 * to keep the page dirty, and for WB_SYNC_ALL writeback we need
-		 * to ensure the PAGECACHE_TAG_TOWRITE index mark is not removed
-		 * so another attempt to write this page in this writeback sweep
-		 * will be made.
-		 */
-		set_page_writeback_keepwrite(page);
-	} else {
-		clear_page_dirty_for_io(page);
-		set_page_writeback(page);
 	}
 
+	set_page_writeback(page);
 	unlock_page(page);
 
 	/*
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH AUTOSEL 5.9 46/55] selftests: proc: fix warning: _GNU_SOURCE redefined
       [not found] <20201110035318.423757-1-sashal@kernel.org>
  2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 45/55] iomap: clean up writeback state logic on writepage error Sasha Levin
@ 2020-11-10  3:53 ` Sasha Levin
  2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 53/55] seq_file: add seq_read_iter Sasha Levin
  2 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2020-11-10  3:53 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Tommi Rantala, Shuah Khan, Sasha Levin, linux-fsdevel, linux-kselftest

From: Tommi Rantala <tommi.t.rantala@nokia.com>

[ Upstream commit f3ae6c6e8a3ea49076d826c64e63ea78fbf9db43 ]

Makefile already contains -D_GNU_SOURCE, so we can remove it from the
*.c files.

Signed-off-by: Tommi Rantala <tommi.t.rantala@nokia.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 tools/testing/selftests/proc/proc-loadavg-001.c  | 1 -
 tools/testing/selftests/proc/proc-self-syscall.c | 1 -
 tools/testing/selftests/proc/proc-uptime-002.c   | 1 -
 3 files changed, 3 deletions(-)

diff --git a/tools/testing/selftests/proc/proc-loadavg-001.c b/tools/testing/selftests/proc/proc-loadavg-001.c
index 471e2aa280776..fb4fe9188806e 100644
--- a/tools/testing/selftests/proc/proc-loadavg-001.c
+++ b/tools/testing/selftests/proc/proc-loadavg-001.c
@@ -14,7 +14,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 /* Test that /proc/loadavg correctly reports last pid in pid namespace. */
-#define _GNU_SOURCE
 #include <errno.h>
 #include <sched.h>
 #include <sys/types.h>
diff --git a/tools/testing/selftests/proc/proc-self-syscall.c b/tools/testing/selftests/proc/proc-self-syscall.c
index 9f6d000c02455..8511dcfe67c75 100644
--- a/tools/testing/selftests/proc/proc-self-syscall.c
+++ b/tools/testing/selftests/proc/proc-self-syscall.c
@@ -13,7 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-#define _GNU_SOURCE
 #include <unistd.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
diff --git a/tools/testing/selftests/proc/proc-uptime-002.c b/tools/testing/selftests/proc/proc-uptime-002.c
index 30e2b78490898..e7ceabed7f51f 100644
--- a/tools/testing/selftests/proc/proc-uptime-002.c
+++ b/tools/testing/selftests/proc/proc-uptime-002.c
@@ -15,7 +15,6 @@
  */
 // Test that values in /proc/uptime increment monotonically
 // while shifting across CPUs.
-#define _GNU_SOURCE
 #undef NDEBUG
 #include <assert.h>
 #include <unistd.h>
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH AUTOSEL 5.9 53/55] seq_file: add seq_read_iter
       [not found] <20201110035318.423757-1-sashal@kernel.org>
  2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 45/55] iomap: clean up writeback state logic on writepage error Sasha Levin
  2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 46/55] selftests: proc: fix warning: _GNU_SOURCE redefined Sasha Levin
@ 2020-11-10  3:53 ` Sasha Levin
  2020-11-10  6:30   ` Greg Kroah-Hartman
  2020-11-10  9:05   ` Christoph Hellwig
  2 siblings, 2 replies; 6+ messages in thread
From: Sasha Levin @ 2020-11-10  3:53 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Christoph Hellwig, Greg Kroah-Hartman, Linus Torvalds,
	Sasha Levin, linux-fsdevel

From: Christoph Hellwig <hch@lst.de>

[ Upstream commit d4d50710a8b46082224376ef119a4dbb75b25c56 ]

iov_iter based variant for reading a seq_file.  seq_read is
reimplemented on top of the iter variant.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Tested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/seq_file.c            | 45 ++++++++++++++++++++++++++++------------
 include/linux/seq_file.h |  1 +
 2 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/fs/seq_file.c b/fs/seq_file.c
index 31219c1db17de..3b20e21604e74 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -18,6 +18,7 @@
 #include <linux/mm.h>
 #include <linux/printk.h>
 #include <linux/string_helpers.h>
+#include <linux/uio.h>
 
 #include <linux/uaccess.h>
 #include <asm/page.h>
@@ -146,7 +147,28 @@ static int traverse(struct seq_file *m, loff_t offset)
  */
 ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 {
-	struct seq_file *m = file->private_data;
+	struct iovec iov = { .iov_base = buf, .iov_len = size};
+	struct kiocb kiocb;
+	struct iov_iter iter;
+	ssize_t ret;
+
+	init_sync_kiocb(&kiocb, file);
+	iov_iter_init(&iter, READ, &iov, 1, size);
+
+	kiocb.ki_pos = *ppos;
+	ret = seq_read_iter(&kiocb, &iter);
+	*ppos = kiocb.ki_pos;
+	return ret;
+}
+EXPORT_SYMBOL(seq_read);
+
+/*
+ * Ready-made ->f_op->read_iter()
+ */
+ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+	struct seq_file *m = iocb->ki_filp->private_data;
+	size_t size = iov_iter_count(iter);
 	size_t copied = 0;
 	size_t n;
 	void *p;
@@ -158,14 +180,14 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 	 * if request is to read from zero offset, reset iterator to first
 	 * record as it might have been already advanced by previous requests
 	 */
-	if (*ppos == 0) {
+	if (iocb->ki_pos == 0) {
 		m->index = 0;
 		m->count = 0;
 	}
 
-	/* Don't assume *ppos is where we left it */
-	if (unlikely(*ppos != m->read_pos)) {
-		while ((err = traverse(m, *ppos)) == -EAGAIN)
+	/* Don't assume ki_pos is where we left it */
+	if (unlikely(iocb->ki_pos != m->read_pos)) {
+		while ((err = traverse(m, iocb->ki_pos)) == -EAGAIN)
 			;
 		if (err) {
 			/* With prejudice... */
@@ -174,7 +196,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 			m->count = 0;
 			goto Done;
 		} else {
-			m->read_pos = *ppos;
+			m->read_pos = iocb->ki_pos;
 		}
 	}
 
@@ -187,13 +209,11 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 	/* if not empty - flush it first */
 	if (m->count) {
 		n = min(m->count, size);
-		err = copy_to_user(buf, m->buf + m->from, n);
-		if (err)
+		if (copy_to_iter(m->buf + m->from, n, iter) != n)
 			goto Efault;
 		m->count -= n;
 		m->from += n;
 		size -= n;
-		buf += n;
 		copied += n;
 		if (!size)
 			goto Done;
@@ -254,8 +274,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 	}
 	m->op->stop(m, p);
 	n = min(m->count, size);
-	err = copy_to_user(buf, m->buf, n);
-	if (err)
+	if (copy_to_iter(m->buf, n, iter) != n)
 		goto Efault;
 	copied += n;
 	m->count -= n;
@@ -264,7 +283,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 	if (!copied)
 		copied = err;
 	else {
-		*ppos += copied;
+		iocb->ki_pos += copied;
 		m->read_pos += copied;
 	}
 	mutex_unlock(&m->lock);
@@ -276,7 +295,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 	err = -EFAULT;
 	goto Done;
 }
-EXPORT_SYMBOL(seq_read);
+EXPORT_SYMBOL(seq_read_iter);
 
 /**
  *	seq_lseek -	->llseek() method for sequential files.
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 813614d4b71fb..b83b3ae3c877f 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -107,6 +107,7 @@ void seq_pad(struct seq_file *m, char c);
 char *mangle_path(char *s, const char *p, const char *esc);
 int seq_open(struct file *, const struct seq_operations *);
 ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);
+ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter);
 loff_t seq_lseek(struct file *, loff_t, int);
 int seq_release(struct inode *, struct file *);
 int seq_write(struct seq_file *seq, const void *data, size_t len);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH AUTOSEL 5.9 53/55] seq_file: add seq_read_iter
  2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 53/55] seq_file: add seq_read_iter Sasha Levin
@ 2020-11-10  6:30   ` Greg Kroah-Hartman
  2020-11-10  9:05   ` Christoph Hellwig
  1 sibling, 0 replies; 6+ messages in thread
From: Greg Kroah-Hartman @ 2020-11-10  6:30 UTC (permalink / raw)
  To: Sasha Levin
  Cc: linux-kernel, stable, Christoph Hellwig, Linus Torvalds, linux-fsdevel

On Mon, Nov 09, 2020 at 10:53:16PM -0500, Sasha Levin wrote:
> From: Christoph Hellwig <hch@lst.de>
> 
> [ Upstream commit d4d50710a8b46082224376ef119a4dbb75b25c56 ]
> 
> iov_iter based variant for reading a seq_file.  seq_read is
> reimplemented on top of the iter variant.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Tested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
>  fs/seq_file.c            | 45 ++++++++++++++++++++++++++++------------
>  include/linux/seq_file.h |  1 +
>  2 files changed, 33 insertions(+), 13 deletions(-)

This is not needed for anything older than 5.10, please drop.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH AUTOSEL 5.9 53/55] seq_file: add seq_read_iter
  2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 53/55] seq_file: add seq_read_iter Sasha Levin
  2020-11-10  6:30   ` Greg Kroah-Hartman
@ 2020-11-10  9:05   ` Christoph Hellwig
  2020-11-10 17:35     ` Sasha Levin
  1 sibling, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2020-11-10  9:05 UTC (permalink / raw)
  To: Sasha Levin
  Cc: linux-kernel, stable, Christoph Hellwig, Greg Kroah-Hartman,
	Linus Torvalds, linux-fsdevel

Should not be needed in stable in any form.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH AUTOSEL 5.9 53/55] seq_file: add seq_read_iter
  2020-11-10  9:05   ` Christoph Hellwig
@ 2020-11-10 17:35     ` Sasha Levin
  0 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2020-11-10 17:35 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: linux-kernel, stable, Greg Kroah-Hartman, Linus Torvalds, linux-fsdevel

On Tue, Nov 10, 2020 at 10:05:28AM +0100, Christoph Hellwig wrote:
>Should not be needed in stable in any form.

I'll drop it, thanks!

-- 
Thanks,
Sasha

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-11-10 17:36 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20201110035318.423757-1-sashal@kernel.org>
2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 45/55] iomap: clean up writeback state logic on writepage error Sasha Levin
2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 46/55] selftests: proc: fix warning: _GNU_SOURCE redefined Sasha Levin
2020-11-10  3:53 ` [PATCH AUTOSEL 5.9 53/55] seq_file: add seq_read_iter Sasha Levin
2020-11-10  6:30   ` Greg Kroah-Hartman
2020-11-10  9:05   ` Christoph Hellwig
2020-11-10 17:35     ` Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).