From: Jaegeuk Kim via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
To: Chao Yu <chao@kernel.org>
Cc: stable@kernel.org, linux-kernel@vger.kernel.org,
linux-f2fs-devel@lists.sourceforge.net
Subject: Re: [f2fs-dev] [PATCH] f2fs: fix to zero post-eof page
Date: Wed, 28 May 2025 16:12:36 +0000 [thread overview]
Message-ID: <aDc19Lwwm3JkCi3Z@google.com> (raw)
In-Reply-To: <20250521062403.742048-1-chao@kernel.org>
Chao,
Can we add the similar path that other filesystems have?
On 05/21, Chao Yu wrote:
> fstest reports a f2fs bug:
>
> generic/363 42s ... [failed, exit status 1]- output mismatch (see /share/git/fstests/results//generic/363.out.bad)
> --- tests/generic/363.out 2025-01-12 21:57:40.271440542 +0800
> +++ /share/git/fstests/results//generic/363.out.bad 2025-05-19 19:55:58.000000000 +0800
> @@ -1,2 +1,78 @@
> QA output created by 363
> fsx -q -S 0 -e 1 -N 100000
> +READ BAD DATA: offset = 0xd6fb, size = 0xf044, fname = /mnt/f2fs/junk
> +OFFSET GOOD BAD RANGE
> +0x1540d 0x0000 0x2a25 0x0
> +operation# (mod 256) for the bad data may be 37
> +0x1540e 0x0000 0x2527 0x1
> ...
> (Run 'diff -u /share/git/fstests/tests/generic/363.out /share/git/fstests/results//generic/363.out.bad' to see the entire diff)
> Ran: generic/363
> Failures: generic/363
> Failed 1 of 1 tests
>
> The root cause is user can update post-eof page via mmap, however, f2fs missed
> to zero post-eof page in below operations, so, once it expands i_size, then it
> will include dummy data locates previous post-eof page, so during below
> operations, we need to zero post-eof page.
>
> Operations which can include dummy data after previous i_size after expanding
> i_size:
> - write
> - mapwrite
> - truncate
> - fallocate
> * preallocate
> * zero_range
> * insert_range
> * collapse_range
> - clone_range (doesn’t support in f2fs)
> - copy_range (doesn’t support in f2fs)
>
> Cc: stable@kernel.org
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
> fs/f2fs/file.c | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 6bd3de64f2a8..c7c66e591ebc 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -35,6 +35,17 @@
> #include <trace/events/f2fs.h>
> #include <uapi/linux/f2fs.h>
>
> +static void f2fs_zero_post_eof_page(struct inode *inode, loff_t new_size)
> +{
> + loff_t old_size = i_size_read(inode);
> +
> + if (old_size > new_size)
> + return;
> +
> + /* zero or drop pages only in range of [old_size, new_size] */
> + truncate_pagecache(inode, old_size);
> +}
> +
> static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
> {
> struct inode *inode = file_inode(vmf->vma->vm_file);
> @@ -105,6 +116,9 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
>
> file_update_time(vmf->vma->vm_file);
> filemap_invalidate_lock_shared(inode->i_mapping);
> +
> + f2fs_zero_post_eof_page(inode, (folio->index + 1) << PAGE_SHIFT);
> +
> folio_lock(folio);
> if (unlikely(folio->mapping != inode->i_mapping ||
> folio_pos(folio) > i_size_read(inode) ||
> @@ -1109,6 +1123,8 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> f2fs_down_write(&fi->i_gc_rwsem[WRITE]);
> filemap_invalidate_lock(inode->i_mapping);
>
> + if (attr->ia_size > old_size)
> + f2fs_zero_post_eof_page(inode, old_size);
> truncate_setsize(inode, attr->ia_size);
>
> if (attr->ia_size <= old_size)
> @@ -1227,6 +1243,8 @@ static int f2fs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
> if (ret)
> return ret;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> pg_start = ((unsigned long long) offset) >> PAGE_SHIFT;
> pg_end = ((unsigned long long) offset + len) >> PAGE_SHIFT;
>
> @@ -1542,6 +1560,8 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
> if (ret)
> return ret;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> ret = f2fs_do_collapse(inode, offset, len);
> if (ret)
> return ret;
> @@ -1631,6 +1651,8 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
> if (ret)
> return ret;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> pg_start = ((unsigned long long) offset) >> PAGE_SHIFT;
> pg_end = ((unsigned long long) offset + len) >> PAGE_SHIFT;
>
> @@ -1754,6 +1776,8 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
> if (ret)
> return ret;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> pg_start = offset >> PAGE_SHIFT;
> pg_end = (offset + len) >> PAGE_SHIFT;
> delta = pg_end - pg_start;
> @@ -1819,6 +1843,8 @@ static int f2fs_expand_inode_data(struct inode *inode, loff_t offset,
> if (err)
> return err;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> f2fs_balance_fs(sbi, true);
>
> pg_start = ((unsigned long long)offset) >> PAGE_SHIFT;
> @@ -4860,6 +4886,8 @@ static ssize_t f2fs_write_checks(struct kiocb *iocb, struct iov_iter *from)
> err = file_modified(file);
> if (err)
> return err;
> +
> + f2fs_zero_post_eof_page(inode, iocb->ki_pos + iov_iter_count(from));
> return count;
> }
>
> --
> 2.49.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
WARNING: multiple messages have this Message-ID (diff)
From: Jaegeuk Kim <jaegeuk@kernel.org>
To: Chao Yu <chao@kernel.org>
Cc: linux-f2fs-devel@lists.sourceforge.net,
linux-kernel@vger.kernel.org, stable@kernel.org
Subject: Re: [PATCH] f2fs: fix to zero post-eof page
Date: Wed, 28 May 2025 16:12:36 +0000 [thread overview]
Message-ID: <aDc19Lwwm3JkCi3Z@google.com> (raw)
In-Reply-To: <20250521062403.742048-1-chao@kernel.org>
Chao,
Can we add the similar path that other filesystems have?
On 05/21, Chao Yu wrote:
> fstest reports a f2fs bug:
>
> generic/363 42s ... [failed, exit status 1]- output mismatch (see /share/git/fstests/results//generic/363.out.bad)
> --- tests/generic/363.out 2025-01-12 21:57:40.271440542 +0800
> +++ /share/git/fstests/results//generic/363.out.bad 2025-05-19 19:55:58.000000000 +0800
> @@ -1,2 +1,78 @@
> QA output created by 363
> fsx -q -S 0 -e 1 -N 100000
> +READ BAD DATA: offset = 0xd6fb, size = 0xf044, fname = /mnt/f2fs/junk
> +OFFSET GOOD BAD RANGE
> +0x1540d 0x0000 0x2a25 0x0
> +operation# (mod 256) for the bad data may be 37
> +0x1540e 0x0000 0x2527 0x1
> ...
> (Run 'diff -u /share/git/fstests/tests/generic/363.out /share/git/fstests/results//generic/363.out.bad' to see the entire diff)
> Ran: generic/363
> Failures: generic/363
> Failed 1 of 1 tests
>
> The root cause is user can update post-eof page via mmap, however, f2fs missed
> to zero post-eof page in below operations, so, once it expands i_size, then it
> will include dummy data locates previous post-eof page, so during below
> operations, we need to zero post-eof page.
>
> Operations which can include dummy data after previous i_size after expanding
> i_size:
> - write
> - mapwrite
> - truncate
> - fallocate
> * preallocate
> * zero_range
> * insert_range
> * collapse_range
> - clone_range (doesn’t support in f2fs)
> - copy_range (doesn’t support in f2fs)
>
> Cc: stable@kernel.org
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
> fs/f2fs/file.c | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 6bd3de64f2a8..c7c66e591ebc 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -35,6 +35,17 @@
> #include <trace/events/f2fs.h>
> #include <uapi/linux/f2fs.h>
>
> +static void f2fs_zero_post_eof_page(struct inode *inode, loff_t new_size)
> +{
> + loff_t old_size = i_size_read(inode);
> +
> + if (old_size > new_size)
> + return;
> +
> + /* zero or drop pages only in range of [old_size, new_size] */
> + truncate_pagecache(inode, old_size);
> +}
> +
> static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
> {
> struct inode *inode = file_inode(vmf->vma->vm_file);
> @@ -105,6 +116,9 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
>
> file_update_time(vmf->vma->vm_file);
> filemap_invalidate_lock_shared(inode->i_mapping);
> +
> + f2fs_zero_post_eof_page(inode, (folio->index + 1) << PAGE_SHIFT);
> +
> folio_lock(folio);
> if (unlikely(folio->mapping != inode->i_mapping ||
> folio_pos(folio) > i_size_read(inode) ||
> @@ -1109,6 +1123,8 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> f2fs_down_write(&fi->i_gc_rwsem[WRITE]);
> filemap_invalidate_lock(inode->i_mapping);
>
> + if (attr->ia_size > old_size)
> + f2fs_zero_post_eof_page(inode, old_size);
> truncate_setsize(inode, attr->ia_size);
>
> if (attr->ia_size <= old_size)
> @@ -1227,6 +1243,8 @@ static int f2fs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
> if (ret)
> return ret;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> pg_start = ((unsigned long long) offset) >> PAGE_SHIFT;
> pg_end = ((unsigned long long) offset + len) >> PAGE_SHIFT;
>
> @@ -1542,6 +1560,8 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
> if (ret)
> return ret;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> ret = f2fs_do_collapse(inode, offset, len);
> if (ret)
> return ret;
> @@ -1631,6 +1651,8 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
> if (ret)
> return ret;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> pg_start = ((unsigned long long) offset) >> PAGE_SHIFT;
> pg_end = ((unsigned long long) offset + len) >> PAGE_SHIFT;
>
> @@ -1754,6 +1776,8 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
> if (ret)
> return ret;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> pg_start = offset >> PAGE_SHIFT;
> pg_end = (offset + len) >> PAGE_SHIFT;
> delta = pg_end - pg_start;
> @@ -1819,6 +1843,8 @@ static int f2fs_expand_inode_data(struct inode *inode, loff_t offset,
> if (err)
> return err;
>
> + f2fs_zero_post_eof_page(inode, offset + len);
> +
> f2fs_balance_fs(sbi, true);
>
> pg_start = ((unsigned long long)offset) >> PAGE_SHIFT;
> @@ -4860,6 +4886,8 @@ static ssize_t f2fs_write_checks(struct kiocb *iocb, struct iov_iter *from)
> err = file_modified(file);
> if (err)
> return err;
> +
> + f2fs_zero_post_eof_page(inode, iocb->ki_pos + iov_iter_count(from));
> return count;
> }
>
> --
> 2.49.0
next prev parent reply other threads:[~2025-05-28 16:12 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-21 6:24 [f2fs-dev] [PATCH] f2fs: fix to zero post-eof page Chao Yu via Linux-f2fs-devel
2025-05-21 6:24 ` Chao Yu
2025-05-28 16:12 ` Jaegeuk Kim via Linux-f2fs-devel [this message]
2025-05-28 16:12 ` Jaegeuk Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aDc19Lwwm3JkCi3Z@google.com \
--to=linux-f2fs-devel@lists.sourceforge.net \
--cc=chao@kernel.org \
--cc=jaegeuk@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.