xfs: improve local fork verification
authorChristoph Hellwig <hch@lst.de>
Thu, 14 May 2020 21:01:31 +0000 (14:01 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Tue, 19 May 2020 16:40:58 +0000 (09:40 -0700)
Call the data/attr local fork verifiers as soon as we are ready for them.
This keeps them close to the code setting up the forks, and avoids a
few branches later on.  Also open code xfs_inode_verify_forks in the
only remaining caller.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/libxfs/xfs_inode_fork.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode_item_recover.c

index 2d424ab9d734340478f49b2d2de0cf24de391c12..6c24c27f5f44bca1798dc825bea79f795889952c 100644 (file)
@@ -227,6 +227,7 @@ xfs_iformat_data_fork(
        struct xfs_dinode       *dip)
 {
        struct inode            *inode = VFS_I(ip);
+       int                     error;
 
        switch (inode->i_mode & S_IFMT) {
        case S_IFIFO:
@@ -241,8 +242,11 @@ xfs_iformat_data_fork(
        case S_IFDIR:
                switch (dip->di_format) {
                case XFS_DINODE_FMT_LOCAL:
-                       return xfs_iformat_local(ip, dip, XFS_DATA_FORK,
+                       error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
                                        be64_to_cpu(dip->di_size));
+                       if (!error)
+                               error = xfs_ifork_verify_local_data(ip);
+                       return error;
                case XFS_DINODE_FMT_EXTENTS:
                        return xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
                case XFS_DINODE_FMT_BTREE:
@@ -282,6 +286,8 @@ xfs_iformat_attr_fork(
        case XFS_DINODE_FMT_LOCAL:
                error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
                                xfs_dfork_attr_shortform_size(dip));
+               if (!error)
+                       error = xfs_ifork_verify_local_attr(ip);
                break;
        case XFS_DINODE_FMT_EXTENTS:
                error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
index af5748f5d927111c538541d1bd5c6c5957367c79..5a3a520b952887dd610cdbf6bf38e53ac641e23c 100644 (file)
@@ -543,14 +543,8 @@ xfs_iget_cache_miss(
                        goto out_destroy;
        }
 
-       if (!xfs_inode_verify_forks(ip)) {
-               error = -EFSCORRUPTED;
-               goto out_destroy;
-       }
-
        trace_xfs_iget_miss(ip);
 
-
        /*
         * Check the inode free state is valid. This also detects lookup
         * racing with unlinks.
index c8abdefe003771df5b3ce3286b3caf6a50261cbd..549ff468b7b60648909292840fdd9374e55ba84e 100644 (file)
@@ -3707,23 +3707,6 @@ shutdown:
        return error;
 }
 
-/*
- * If there are inline format data / attr forks attached to this inode,
- * make sure they're not corrupt.
- */
-bool
-xfs_inode_verify_forks(
-       struct xfs_inode        *ip)
-{
-       if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL &&
-           xfs_ifork_verify_local_data(ip))
-               return false;
-       if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL &&
-           xfs_ifork_verify_local_attr(ip))
-               return false;
-       return true;
-}
-
 STATIC int
 xfs_iflush_int(
        struct xfs_inode        *ip,
@@ -3808,8 +3791,15 @@ xfs_iflush_int(
        if (!xfs_sb_version_has_v3inode(&mp->m_sb))
                ip->i_d.di_flushiter++;
 
-       /* Check the inline fork data before we write out. */
-       if (!xfs_inode_verify_forks(ip))
+       /*
+        * If there are inline format data / attr forks attached to this inode,
+        * make sure they are not corrupt.
+        */
+       if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL &&
+           xfs_ifork_verify_local_data(ip))
+               goto flush_out;
+       if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL &&
+           xfs_ifork_verify_local_attr(ip))
                goto flush_out;
 
        /*
index 83073c883fbf95ced9414df91b49b781fe2adba5..ff846197941e43e68b8f22f3cde3372e2ef68222 100644 (file)
@@ -498,8 +498,6 @@ extern struct kmem_zone     *xfs_inode_zone;
 /* The default CoW extent size hint. */
 #define XFS_DEFAULT_COWEXTSZ_HINT 32
 
-bool xfs_inode_verify_forks(struct xfs_inode *ip);
-
 int xfs_iunlink_init(struct xfs_perag *pag);
 void xfs_iunlink_destroy(struct xfs_perag *pag);
 
index 82ca5ce312c52c2190c24fc348112c32e6605be1..dc3e26ff16c906004c7d3e50de01bcfc3b2bc8e9 100644 (file)
@@ -94,11 +94,6 @@ xfs_recover_inode_owner_change(
        if (error)
                goto out_free_ip;
 
-       if (!xfs_inode_verify_forks(ip)) {
-               error = -EFSCORRUPTED;
-               goto out_free_ip;
-       }
-
        if (in_f->ilf_fields & XFS_ILOG_DOWNER) {
                ASSERT(in_f->ilf_fields & XFS_ILOG_DBROOT);
                error = xfs_bmbt_change_owner(NULL, ip, XFS_DATA_FORK,