]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libxfs: retain ifork_ops when flushing inode
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 26 Apr 2019 20:41:59 +0000 (15:41 -0500)
committerEric Sandeen <sandeen@redhat.com>
Fri, 26 Apr 2019 20:41:59 +0000 (15:41 -0500)
Retain the ifork ops used to validate the inode so that we can use the
same one to iflush it.  xfs_repair phase 6 can use multiple transactions
to fix various inode problems, which means that the inode might not be
fully fixed when each transaction commits.

This can be a particular problem if there's a shortform directory with
both invalid directory entries and incorrect i8count.  Phase 3 will set
the parent inode to "0" to signal to phase 6 that it needs to reset the
parent and i8count, but phase 6 starts a transaction to junk the bad
entries which fail to commit because the parent is invalid:

fixing i8count in inode 69022994673
Invalid inode number 0x0
xfs_dir_ino_validate: XFS_ERROR_REPORT
Metadata corruption detected at 0x464eb0, inode 0x10121750f1 data fork
xfs_repair: warning - iflush_int failed (-117)

And thus the inode fixes never get written out.

Reported-by: Arkadiusz Miskiewicz <arekm@maven.pl>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Bill O'Donnell <billodo@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
include/xfs_inode.h
libxfs/rdwr.c
libxfs/util.c

index 79ec3a2d46e99165f116ceeafde86af2fac0bb34..e1e8b43085144c000464fb98476469158282ceb7 100644 (file)
@@ -51,6 +51,7 @@ typedef struct xfs_inode {
 
        xfs_fsize_t             i_size;         /* in-memory size */
        const struct xfs_dir_ops *d_ops;        /* directory ops vector */
+       struct xfs_ifork_ops    *i_fork_ops;    /* fork verifiers */
        struct inode            i_vnode;
 } xfs_inode_t;
 
index a00360e703a6a6e15816c5f08e134cfca4780694..69d5abb2cbca3b3881a7a8af0b2ea8c7e08c5934 100644 (file)
@@ -1391,6 +1391,7 @@ libxfs_iget(
                return error;
        }
 
+       ip->i_fork_ops = ifork_ops;
        if (!libxfs_inode_verify_forks(ip, ifork_ops)) {
                libxfs_irele(ip);
                return -EFSCORRUPTED;
index 4ac151e6b47e90fc837d51a1e4534eb5113c1996..2e3b9d511211519468ff45123be0eb39bbcaff92 100644 (file)
@@ -422,7 +422,7 @@ libxfs_iflush_int(xfs_inode_t *ip, xfs_buf_t *bp)
                VFS_I(ip)->i_version++;
 
        /* Check the inline fork data before we write out. */
-       if (!libxfs_inode_verify_forks(ip, &xfs_default_ifork_ops))
+       if (!libxfs_inode_verify_forks(ip, ip->i_fork_ops))
                return -EFSCORRUPTED;
 
        /*