]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: apply rt extent alignment constraints to CoW extsize hint
authorDarrick J. Wong <djwong@kernel.org>
Mon, 24 Feb 2025 18:21:54 +0000 (10:21 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 25 Feb 2025 17:15:59 +0000 (09:15 -0800)
Source kernel commit: 4de1a7ba4171db681691bd80506d0cf43c5cb46a

The copy-on-write extent size hint is subject to the same alignment
constraints as the regular extent size hint.  Since we're in the process
of adding reflink (and therefore CoW) to the realtime device, we must
apply the same scattered rextsize alignment validation strategies to
both hints to deal with the possibility of rextsize changing.

Therefore, fix the inode validator to perform rextsize alignment checks
on regular realtime files, and to remove misaligned directory hints.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/xfs_inode_buf.c

index a7774fc32e2755d350f976e06336f31ee638626f..5ca857ca2dc10ee6d9800b829b2beee5bb7d2b00 100644 (file)
@@ -907,11 +907,29 @@ xfs_inode_validate_cowextsize(
        bool                            rt_flag;
        bool                            hint_flag;
        uint32_t                        cowextsize_bytes;
+       uint32_t                        blocksize_bytes;
 
        rt_flag = (flags & XFS_DIFLAG_REALTIME);
        hint_flag = (flags2 & XFS_DIFLAG2_COWEXTSIZE);
        cowextsize_bytes = XFS_FSB_TO_B(mp, cowextsize);
 
+       /*
+        * Similar to extent size hints, a directory can be configured to
+        * propagate realtime status and a CoW extent size hint to newly
+        * created files even if there is no realtime device, and the hints on
+        * disk can become misaligned if the sysadmin changes the rt extent
+        * size while adding the realtime device.
+        *
+        * Therefore, we can only enforce the rextsize alignment check against
+        * regular realtime files, and rely on callers to decide when alignment
+        * checks are appropriate, and fix things up as needed.
+        */
+
+       if (rt_flag)
+               blocksize_bytes = XFS_FSB_TO_B(mp, mp->m_sb.sb_rextsize);
+       else
+               blocksize_bytes = mp->m_sb.sb_blocksize;
+
        if (hint_flag && !xfs_has_reflink(mp))
                return __this_address;
 
@@ -925,16 +943,13 @@ xfs_inode_validate_cowextsize(
        if (mode && !hint_flag && cowextsize != 0)
                return __this_address;
 
-       if (hint_flag && rt_flag)
-               return __this_address;
-
-       if (cowextsize_bytes % mp->m_sb.sb_blocksize)
+       if (cowextsize_bytes % blocksize_bytes)
                return __this_address;
 
        if (cowextsize > XFS_MAX_BMBT_EXTLEN)
                return __this_address;
 
-       if (cowextsize > mp->m_sb.sb_agblocks / 2)
+       if (!rt_flag && cowextsize > mp->m_sb.sb_agblocks / 2)
                return __this_address;
 
        return NULL;