]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: handle unallocated inodes in xfs_inode_from_disk
authorChristoph Hellwig <hch@lst.de>
Mon, 10 Aug 2020 20:32:06 +0000 (16:32 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Mon, 10 Aug 2020 20:32:06 +0000 (16:32 -0400)
Source kernel commit: 0bce8173fdcf203c92a4d57dc7d3bb642ed478a1

Handle inodes with a 0 di_mode in xfs_inode_from_disk, instead of partially
duplicating inode reading in xfs_iread.

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>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/xfs_inode_buf.c

index 4679819bf0223bbe6a6ceff3f682b6d12def7c11..f90217af9cac6e05cb57b9de81bf2a4db167898d 100644 (file)
@@ -189,6 +189,17 @@ xfs_inode_from_disk(
        ASSERT(ip->i_cowfp == NULL);
        ASSERT(ip->i_afp == NULL);
 
+       /*
+        * First get the permanent information that is needed to allocate an
+        * inode. If the inode is unused, mode is zero and we shouldn't mess
+        * with the unitialized part of it.
+        */
+       to->di_flushiter = be16_to_cpu(from->di_flushiter);
+       inode->i_generation = be32_to_cpu(from->di_gen);
+       inode->i_mode = be16_to_cpu(from->di_mode);
+       if (!inode->i_mode)
+               return 0;
+
        /*
         * Convert v1 inodes immediately to v2 inode format as this is the
         * minimum inode version format we support in the rest of the code.
@@ -206,7 +217,6 @@ xfs_inode_from_disk(
        to->di_format = from->di_format;
        i_uid_write(inode, be32_to_cpu(from->di_uid));
        i_gid_write(inode, be32_to_cpu(from->di_gid));
-       to->di_flushiter = be16_to_cpu(from->di_flushiter);
 
        /*
         * Time is signed, so need to convert to signed 32 bit before
@@ -220,8 +230,6 @@ xfs_inode_from_disk(
        inode->i_mtime.tv_nsec = (int)be32_to_cpu(from->di_mtime.t_nsec);
        inode->i_ctime.tv_sec = (int)be32_to_cpu(from->di_ctime.t_sec);
        inode->i_ctime.tv_nsec = (int)be32_to_cpu(from->di_ctime.t_nsec);
-       inode->i_generation = be32_to_cpu(from->di_gen);
-       inode->i_mode = be16_to_cpu(from->di_mode);
 
        to->di_size = be64_to_cpu(from->di_size);
        to->di_nblocks = be64_to_cpu(from->di_nblocks);
@@ -650,39 +658,9 @@ xfs_iread(
                goto out_brelse;
        }
 
-       /*
-        * If the on-disk inode is already linked to a directory
-        * entry, copy all of the inode into the in-core inode.
-        * xfs_iformat_fork() handles copying in the inode format
-        * specific information.
-        * Otherwise, just get the truly permanent information.
-        */
-       if (dip->di_mode) {
-               error = xfs_inode_from_disk(ip, dip);
-               if (error)  {
-#ifdef DEBUG
-                       xfs_alert(mp, "%s: xfs_iformat() returned error %d",
-                               __func__, error);
-#endif /* DEBUG */
-                       goto out_brelse;
-               }
-       } else {
-               /*
-                * Partial initialisation of the in-core inode. Just the bits
-                * that xfs_ialloc won't overwrite or relies on being correct.
-                */
-               VFS_I(ip)->i_generation = be32_to_cpu(dip->di_gen);
-               ip->i_d.di_flushiter = be16_to_cpu(dip->di_flushiter);
-
-               /*
-                * Make sure to pull in the mode here as well in
-                * case the inode is released without being used.
-                * This ensures that xfs_inactive() will see that
-                * the inode is already free and not try to mess
-                * with the uninitialized part of it.
-                */
-               VFS_I(ip)->i_mode = 0;
-       }
+       error = xfs_inode_from_disk(ip, dip);
+       if (error)
+               goto out_brelse;
 
        ip->i_delayed_blks = 0;