]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: skip bmbt block ino validation during owner change
authorBrian Foster <bfoster@redhat.com>
Wed, 18 Oct 2017 18:39:01 +0000 (13:39 -0500)
committerEric Sandeen <sandeen@redhat.com>
Wed, 18 Oct 2017 18:39:01 +0000 (13:39 -0500)
Source kernel commit: 99c794c639a65cc7b74f30a674048fd100fe9ac8

Extent swap uses xfs_btree_visit_blocks() to fix up bmbt block
owners on v5 (!rmapbt) filesystems. The bmbt scan uses
xfs_btree_lookup_get_block() to read bmbt blocks which verifies the
current owner of the block against the parent inode of the bmbt.
This works during extent swap because the bmbt owners are updated to
the opposite inode number before the inode extent forks are swapped.

The modified bmbt blocks are marked as ordered buffers which allows
everything to commit in a single transaction. If the transaction
extent swap is required, log recovery restarts the bmbt scan to fix
up any bmbt blocks that may have not been written back before the
crash. The log recovery bmbt scan occurs after the inode forks have
been swapped, however. This causes the bmbt block owner verification
to fail, leads to log recovery failure and requires xfs_repair to
zap the log to recover.

Define a new invalid inode owner flag to inform the btree block
lookup mechanism that the current inode may be invalid with respect
to the current owner of the bmbt block. Set this flag on the cursor
used for change owner scans to allow this operation to work at
runtime and during log recovery.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Fixes: bb3be7e7c ("xfs: check for bogus values in btree block headers")
Cc: stable@vger.kernel.org
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/xfs_bmap_btree.c
libxfs/xfs_btree.c
libxfs/xfs_btree.h

index c9c9572d8d45423028a6780fdb04d4aaed57dc5b..f7e3aded2bf5cbf9f144e3a99e24666035802e12 100644 (file)
@@ -855,6 +855,7 @@ xfs_bmbt_change_owner(
        cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
        if (!cur)
                return -ENOMEM;
+       cur->bc_private.b.flags |= XFS_BTCUR_BPRV_INVALID_OWNER;
 
        error = xfs_btree_change_owner(cur, new_owner, buffer_list);
        xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
index 4f7474d250945d33f5cb493790d0e927ce2ee65d..5244bf1c07b8018b0702b87eb7651c55251be43d 100644 (file)
@@ -1787,6 +1787,7 @@ xfs_btree_lookup_get_block(
 
        /* Check the inode owner since the verifiers don't. */
        if (xfs_sb_version_hascrc(&cur->bc_mp->m_sb) &&
+           !(cur->bc_private.b.flags & XFS_BTCUR_BPRV_INVALID_OWNER) &&
            (cur->bc_flags & XFS_BTREE_LONG_PTRS) &&
            be64_to_cpu((*blkp)->bb_u.l.bb_owner) !=
                        cur->bc_private.b.ip->i_ino)
index f9ce370626c2c2154622ea2497edf1206651e3c3..bc01edbb99db80a44fd7bd448c01bcacb53f5bae 100644 (file)
@@ -233,7 +233,8 @@ typedef struct xfs_btree_cur
                        short           forksize;       /* fork's inode space */
                        char            whichfork;      /* data or attr fork */
                        char            flags;          /* flags */
-#define        XFS_BTCUR_BPRV_WASDEL   1                       /* was delayed */
+#define        XFS_BTCUR_BPRV_WASDEL           (1<<0)          /* was delayed */
+#define        XFS_BTCUR_BPRV_INVALID_OWNER    (1<<1)          /* for ext swap */
                } b;
        }               bc_private;     /* per-btree type data */
 } xfs_btree_cur_t;