]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: support deferred bmap updates on the attr fork
authorDarrick J. Wong <djwong@kernel.org>
Thu, 22 Feb 2024 20:44:32 +0000 (12:44 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 22 Feb 2024 20:44:32 +0000 (12:44 -0800)
The deferred bmap update log item has always supported the attr fork, so
plumb this in so that higher layers can access this.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_reflink.c

index 939947d00bc905819e2229cf93689a20ffb06dfc..8d62fd626be5178ec5ce845c501467be806c5d9d 100644 (file)
@@ -6172,17 +6172,8 @@ del_cursor:
        return error;
 }
 
-/* Deferred mapping is only for real extents in the data fork. */
-static bool
-xfs_bmap_is_update_needed(
-       struct xfs_bmbt_irec    *bmap)
-{
-       return  bmap->br_startblock != HOLESTARTBLOCK &&
-               bmap->br_startblock != DELAYSTARTBLOCK;
-}
-
 /* Record a bmap intent. */
-static int
+static inline void
 __xfs_bmap_add(
        struct xfs_trans                *tp,
        enum xfs_bmap_intent_type       type,
@@ -6192,6 +6183,11 @@ __xfs_bmap_add(
 {
        struct xfs_bmap_intent          *bi;
 
+       if ((whichfork != XFS_DATA_FORK && whichfork != XFS_ATTR_FORK) ||
+           bmap->br_startblock == HOLESTARTBLOCK ||
+           bmap->br_startblock == DELAYSTARTBLOCK)
+               return;
+
        bi = kmem_cache_alloc(xfs_bmap_intent_cache, GFP_KERNEL | __GFP_NOFAIL);
        INIT_LIST_HEAD(&bi->bi_list);
        bi->bi_type = type;
@@ -6200,7 +6196,6 @@ __xfs_bmap_add(
        bi->bi_bmap = *bmap;
 
        xfs_bmap_defer_add(tp, bi);
-       return 0;
 }
 
 /* Map an extent into a file. */
@@ -6208,12 +6203,10 @@ void
 xfs_bmap_map_extent(
        struct xfs_trans        *tp,
        struct xfs_inode        *ip,
+       int                     whichfork,
        struct xfs_bmbt_irec    *PREV)
 {
-       if (!xfs_bmap_is_update_needed(PREV))
-               return;
-
-       __xfs_bmap_add(tp, XFS_BMAP_MAP, ip, XFS_DATA_FORK, PREV);
+       __xfs_bmap_add(tp, XFS_BMAP_MAP, ip, whichfork, PREV);
 }
 
 /* Unmap an extent out of a file. */
@@ -6221,12 +6214,10 @@ void
 xfs_bmap_unmap_extent(
        struct xfs_trans        *tp,
        struct xfs_inode        *ip,
+       int                     whichfork,
        struct xfs_bmbt_irec    *PREV)
 {
-       if (!xfs_bmap_is_update_needed(PREV))
-               return;
-
-       __xfs_bmap_add(tp, XFS_BMAP_UNMAP, ip, XFS_DATA_FORK, PREV);
+       __xfs_bmap_add(tp, XFS_BMAP_UNMAP, ip, whichfork, PREV);
 }
 
 /*
@@ -6240,29 +6231,29 @@ xfs_bmap_finish_one(
 {
        struct xfs_bmbt_irec            *bmap = &bi->bi_bmap;
        int                             error = 0;
+       int                             flags = 0;
+
+       if (bi->bi_whichfork == XFS_ATTR_FORK)
+               flags |= XFS_BMAPI_ATTRFORK;
 
        ASSERT(tp->t_highest_agno == NULLAGNUMBER);
 
        trace_xfs_bmap_deferred(bi);
 
-       if (WARN_ON_ONCE(bi->bi_whichfork != XFS_DATA_FORK)) {
-               xfs_bmap_mark_sick(bi->bi_owner, bi->bi_whichfork);
-               return -EFSCORRUPTED;
-       }
-
-       if (XFS_TEST_ERROR(false, tp->t_mountp,
-                       XFS_ERRTAG_BMAP_FINISH_ONE))
+       if (XFS_TEST_ERROR(false, tp->t_mountp, XFS_ERRTAG_BMAP_FINISH_ONE))
                return -EIO;
 
        switch (bi->bi_type) {
        case XFS_BMAP_MAP:
                error = xfs_bmapi_remap(tp, bi->bi_owner, bmap->br_startoff,
-                               bmap->br_blockcount, bmap->br_startblock, 0);
+                               bmap->br_blockcount, bmap->br_startblock,
+                               flags);
                bmap->br_blockcount = 0;
                break;
        case XFS_BMAP_UNMAP:
                error = __xfs_bunmapi(tp, bi->bi_owner, bmap->br_startoff,
-                               &bmap->br_blockcount, XFS_BMAPI_REMAP, 1);
+                               &bmap->br_blockcount, flags | XFS_BMAPI_REMAP,
+                               1);
                break;
        default:
                ASSERT(0);
index 325cc232a4153df49d8a83e6df0f0cad5529be92..f7662595309d8611ec5de1a731fb7bdaf5097d87 100644 (file)
@@ -247,9 +247,9 @@ struct xfs_bmap_intent {
 
 int    xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_bmap_intent *bi);
 void   xfs_bmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
-               struct xfs_bmbt_irec *imap);
+               int whichfork, struct xfs_bmbt_irec *imap);
 void   xfs_bmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip,
-               struct xfs_bmbt_irec *imap);
+               int whichfork, struct xfs_bmbt_irec *imap);
 
 static inline uint32_t xfs_bmap_fork_to_state(int whichfork)
 {
index 2fe306fd71fcb46f2b61b05dadcf7b60d97a18ad..19e11d1da66074a61f464a8300fc56bb4b186277 100644 (file)
@@ -1305,16 +1305,16 @@ xfs_swap_extent_rmap(
                        }
 
                        /* Remove the mapping from the donor file. */
-                       xfs_bmap_unmap_extent(tp, tip, &uirec);
+                       xfs_bmap_unmap_extent(tp, tip, XFS_DATA_FORK, &uirec);
 
                        /* Remove the mapping from the source file. */
-                       xfs_bmap_unmap_extent(tp, ip, &irec);
+                       xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &irec);
 
                        /* Map the donor file's blocks into the source file. */
-                       xfs_bmap_map_extent(tp, ip, &uirec);
+                       xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, &uirec);
 
                        /* Map the source file's blocks into the donor file. */
-                       xfs_bmap_map_extent(tp, tip, &irec);
+                       xfs_bmap_map_extent(tp, tip, XFS_DATA_FORK, &irec);
 
                        error = xfs_defer_finish(tpp);
                        tp = *tpp;
index cd9a00fd16e7c367acb23b0b9b2ce88b789664e4..7da0e8f961d351183eefa996e13affda1d0a635a 100644 (file)
@@ -806,7 +806,7 @@ xfs_reflink_end_cow_extent(
                 * If the extent we're remapping is backed by storage (written
                 * or not), unmap the extent and drop its refcount.
                 */
-               xfs_bmap_unmap_extent(tp, ip, &data);
+               xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &data);
                xfs_refcount_decrease_extent(tp, &data);
                xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT,
                                -data.br_blockcount);
@@ -830,7 +830,7 @@ xfs_reflink_end_cow_extent(
        xfs_refcount_free_cow_extent(tp, del.br_startblock, del.br_blockcount);
 
        /* Map the new blocks into the data fork. */
-       xfs_bmap_map_extent(tp, ip, &del);
+       xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, &del);
 
        /* Charge this new data fork mapping to the on-disk quota. */
        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT,
@@ -1294,7 +1294,7 @@ xfs_reflink_remap_extent(
                 * If the extent we're unmapping is backed by storage (written
                 * or not), unmap the extent and drop its refcount.
                 */
-               xfs_bmap_unmap_extent(tp, ip, &smap);
+               xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &smap);
                xfs_refcount_decrease_extent(tp, &smap);
                qdelta -= smap.br_blockcount;
        } else if (smap.br_startblock == DELAYSTARTBLOCK) {
@@ -1319,7 +1319,7 @@ xfs_reflink_remap_extent(
         */
        if (dmap_written) {
                xfs_refcount_increase_extent(tp, dmap);
-               xfs_bmap_map_extent(tp, ip, dmap);
+               xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, dmap);
                qdelta += dmap->br_blockcount;
        }