On Fri, Sep 20, 2024 at 08:26:21PM +0800, Julian Sun wrote: > Attempting to unshare extents beyond EOF will trigger > the need zeroing case, which in turn triggers a warning. > Therefore, let's skip the unshare process if extents are > beyond EOF. > > Reported-and-tested-by: syzbot+296b1c84b9cbf306e5a0@xxxxxxxxxxxxxxxxxxxxxxxxx > Closes: https://syzkaller.appspot.com/bug?extid=296b1c84b9cbf306e5a0 > Fixes: 32a38a499104 ("iomap: use write_begin to read pages to unshare") > Inspired-by: Dave Chinner <david@xxxxxxxxxxxxx> > Signed-off-by: Julian Sun <sunjunchao2870@xxxxxxxxx> > --- > fs/xfs/xfs_reflink.c | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c > index 6fde6ec8092f..65509ff6aba0 100644 > --- a/fs/xfs/xfs_reflink.c > +++ b/fs/xfs/xfs_reflink.c > @@ -3,6 +3,7 @@ > * Copyright (C) 2016 Oracle. All Rights Reserved. > * Author: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > */ > +#include "linux/fs.h" This really should not be needed (and is the wrong way to include non-local headers anyway). > #include "xfs.h" > #include "xfs_fs.h" > #include "xfs_shared.h" > @@ -1669,6 +1670,9 @@ xfs_reflink_unshare( > > if (!xfs_is_reflink_inode(ip)) > return 0; > + /* don't try to unshare any ranges beyond EOF. */ > + if (offset + len > i_size_read(inode)) > + len = i_size_read(inode) - offset; So i_size is a byte granularity value, but later on iomap_file_unshare operates on blocks. If you reduce the value like this here this means we can't ever unshare the last block of a file if the file size is not block aligned, which feels odd.