]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xfs: Check for delayed allocations before setting extsize
authorOjaswin Mujoo <ojaswin@linux.ibm.com>
Wed, 5 Feb 2025 21:40:25 +0000 (13:40 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Feb 2025 12:10:44 +0000 (04:10 -0800)
commit 2a492ff66673c38a77d0815d67b9a8cce2ef57f8 upstream.

Extsize should only be allowed to be set on files with no data in it.
For this, we check if the files have extents but miss to check if
delayed extents are present. This patch adds that check.

While we are at it, also refactor this check into a helper since
it's used in some other places as well like xfs_inactive() or
xfs_ioctl_setattr_xflags()

**Without the patch (SUCCEEDS)**

$ xfs_io -c 'open -f testfile' -c 'pwrite 0 1024' -c 'extsize 65536'

wrote 1024/1024 bytes at offset 0
1 KiB, 1 ops; 0.0002 sec (4.628 MiB/sec and 4739.3365 ops/sec)

**With the patch (FAILS as expected)**

$ xfs_io -c 'open -f testfile' -c 'pwrite 0 1024' -c 'extsize 65536'

wrote 1024/1024 bytes at offset 0
1 KiB, 1 ops; 0.0002 sec (4.628 MiB/sec and 4739.3365 ops/sec)
xfs_io: FS_IOC_FSSETXATTR testfile: Invalid argument

Fixes: e94af02a9cd7 ("[XFS] fix old xfs_setattr mis-merge from irix; mostly harmless esp if not using xfs rt")
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Catherine Hoang <catherine.hoang@oracle.com>
Acked-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_ioctl.c

index b9784348ebc5c49cd7887e7298c96e48c03b8a81..e1adad91dba6660c5e879aaf45e3f1ac0cbd871b 100644 (file)
@@ -1758,7 +1758,7 @@ xfs_inactive(
 
        if (S_ISREG(VFS_I(ip)->i_mode) &&
            (ip->i_disk_size != 0 || XFS_ISIZE(ip) != 0 ||
-            ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
+            xfs_inode_has_filedata(ip)))
                truncate = 1;
 
        if (xfs_iflags_test(ip, XFS_IQUOTAUNCHECKED)) {
index 0f2999b84e7d96d45f08b14255679424ee9bcc3f..4820c4699f7d0f322b5ecd3a161ef1d96e9f8b44 100644 (file)
@@ -286,6 +286,11 @@ static inline bool xfs_is_metadata_inode(struct xfs_inode *ip)
                xfs_is_quota_inode(&mp->m_sb, ip->i_ino);
 }
 
+static inline bool xfs_inode_has_filedata(const struct xfs_inode *ip)
+{
+       return ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0;
+}
+
 /*
  * Check if an inode has any data in the COW fork.  This might be often false
  * even for inodes with the reflink flag when there is no pending COW operation.
index 32e718043e0e2ee9e28ba13e918b3d3727d4059b..d22285a745394047bef3581747435784593f80ca 100644 (file)
@@ -1126,7 +1126,7 @@ xfs_ioctl_setattr_xflags(
 
        if (rtflag != XFS_IS_REALTIME_INODE(ip)) {
                /* Can't change realtime flag if any extents are allocated. */
-               if (ip->i_df.if_nextents || ip->i_delayed_blks)
+               if (xfs_inode_has_filedata(ip))
                        return -EINVAL;
 
                /*
@@ -1247,7 +1247,7 @@ xfs_ioctl_setattr_check_extsize(
        if (!fa->fsx_valid)
                return 0;
 
-       if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
+       if (S_ISREG(VFS_I(ip)->i_mode) && xfs_inode_has_filedata(ip) &&
            XFS_FSB_TO_B(mp, ip->i_extsize) != fa->fsx_extsize)
                return -EINVAL;