]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_repair: use library functions to reset root/rbm/rsum inodes
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:21:37 +0000 (14:21 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 31 Jul 2024 01:46:43 +0000 (18:46 -0700)
Use the iroot reset function to reset root inodes instead of open-coding
the reset routine.  While we're at it, fix a longstanding memory leak if
the inode being reset actually had an xattr fork full of mappings.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/libxfs_api_defs.h
repair/phase6.c

index b6a95e57cca0283eec9a962ae62d7972cf830692..1a5fdaa59edd0b0c60ed96028167da58bb3d060b 100644 (file)
 #define xfs_inode_from_disk            libxfs_inode_from_disk
 #define xfs_inode_from_disk_ts         libxfs_inode_from_disk_ts
 #define xfs_inode_hasattr              libxfs_inode_hasattr
+#define xfs_inode_init                 libxfs_inode_init
 #define xfs_inode_to_disk              libxfs_inode_to_disk
 #define xfs_inode_validate_cowextsize  libxfs_inode_validate_cowextsize
 #define xfs_inode_validate_extsize     libxfs_inode_validate_extsize
index 85f122ec79ae5f9e74a1a9ae919c44cb545f8787..2c4f230105c0f26db5baf3750458b232c2ce0fe4 100644 (file)
@@ -447,20 +447,31 @@ res_failed(
                do_error(_("xfs_trans_reserve returned %d\n"), err);
 }
 
-static inline void
-reset_inode_fields(struct xfs_inode *ip)
+/*
+ * Forcibly reinitialize a file that is a child of the superblock and has a
+ * statically defined inumber.  These files are the root of a directory tree or
+ * the realtime free space inodes.  The inode must not otherwise be in use; the
+ * data fork must be empty, and the attr fork will be reset.
+ */
+static void
+reset_sbroot_ino(
+       struct xfs_trans        *tp,
+       umode_t                 mode,
+       struct xfs_inode        *ip)
 {
-       ip->i_projid = 0;
-       ip->i_disk_size = 0;
-       ip->i_nblocks = 0;
-       ip->i_extsize = 0;
-       ip->i_cowextsize = 0;
-       ip->i_flushiter = 0;
+       struct xfs_icreate_args args = {
+               .idmap          = libxfs_nop_idmap,
+               .mode           = mode,
+               /* Root directories cannot be linked to a parent. */
+               .flags          = XFS_ICREATE_UNLINKABLE,
+       };
+
+       /* Erase the attr fork since libxfs_inode_init won't do it for us. */
        ip->i_forkoff = 0;
-       ip->i_diflags = 0;
-       ip->i_diflags2 = 0;
-       ip->i_crtime.tv_sec = 0;
-       ip->i_crtime.tv_nsec = 0;
+       libxfs_ifork_zap_attr(ip);
+
+       libxfs_trans_ijoin(tp, ip, 0);
+       libxfs_inode_init(tp, &args, ip);
 }
 
 static void
@@ -474,7 +485,6 @@ mk_rbmino(xfs_mount_t *mp)
        int             error;
        xfs_fileoff_t   bno;
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
-       int             times;
        uint            blocks;
 
        /*
@@ -491,34 +501,9 @@ mk_rbmino(xfs_mount_t *mp)
                        error);
        }
 
-       reset_inode_fields(ip);
-
-       VFS_I(ip)->i_mode = S_IFREG;
-       ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
-       libxfs_ifork_zap_attr(ip);
-
-       set_nlink(VFS_I(ip), 1);        /* account for sb ptr */
-
-       times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
-       if (xfs_has_v3inodes(mp)) {
-               VFS_I(ip)->i_version = 1;
-               ip->i_diflags2 = 0;
-               times |= XFS_ICHGTIME_CREATE;
-       }
-       libxfs_trans_ichgtime(tp, ip, times);
-
-       /*
-        * now the ifork
-        */
-       ip->i_df.if_bytes = 0;
-       ip->i_df.if_data = NULL;
-
+       /* Reset the realtime bitmap inode. */
+       reset_sbroot_ino(tp, S_IFREG, ip);
        ip->i_disk_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
-
-       /*
-        * commit changes
-        */
-       libxfs_trans_ijoin(tp, ip, 0);
        libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        error = -libxfs_trans_commit(tp);
        if (error)
@@ -729,7 +714,6 @@ mk_rsumino(xfs_mount_t *mp)
        int             nsumblocks;
        xfs_fileoff_t   bno;
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
-       int             times;
        uint            blocks;
 
        /*
@@ -746,34 +730,9 @@ mk_rsumino(xfs_mount_t *mp)
                        error);
        }
 
-       reset_inode_fields(ip);
-
-       VFS_I(ip)->i_mode = S_IFREG;
-       ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
-       libxfs_ifork_zap_attr(ip);
-
-       set_nlink(VFS_I(ip), 1);        /* account for sb ptr */
-
-       times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
-       if (xfs_has_v3inodes(mp)) {
-               VFS_I(ip)->i_version = 1;
-               ip->i_diflags2 = 0;
-               times |= XFS_ICHGTIME_CREATE;
-       }
-       libxfs_trans_ichgtime(tp, ip, times);
-
-       /*
-        * now the ifork
-        */
-       ip->i_df.if_bytes = 0;
-       ip->i_df.if_data = NULL;
-
+       /* Reset the rt summary inode. */
+       reset_sbroot_ino(tp, S_IFREG, ip);
        ip->i_disk_size = mp->m_rsumsize;
-
-       /*
-        * commit changes
-        */
-       libxfs_trans_ijoin(tp, ip, 0);
        libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        error = -libxfs_trans_commit(tp);
        if (error)
@@ -829,7 +788,6 @@ mk_root_dir(xfs_mount_t *mp)
        int             error;
        const mode_t    mode = 0755;
        ino_tree_node_t *irec;
-       int             times;
 
        ip = NULL;
        i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 10, 0, 0, &tp);
@@ -841,37 +799,8 @@ mk_root_dir(xfs_mount_t *mp)
                do_error(_("could not iget root inode -- error - %d\n"), error);
        }
 
-       /*
-        * take care of the core since we didn't call the libxfs ialloc function
-        * (comment changed to avoid tangling xfs/437)
-        */
-       reset_inode_fields(ip);
-
-       VFS_I(ip)->i_mode = mode|S_IFDIR;
-       ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
-       libxfs_ifork_zap_attr(ip);
-
-       set_nlink(VFS_I(ip), 2);        /* account for . and .. */
-
-       times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
-       if (xfs_has_v3inodes(mp)) {
-               VFS_I(ip)->i_version = 1;
-               ip->i_diflags2 = 0;
-               times |= XFS_ICHGTIME_CREATE;
-       }
-       libxfs_trans_ichgtime(tp, ip, times);
-       libxfs_trans_ijoin(tp, ip, 0);
-       libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
-       /*
-        * now the ifork
-        */
-       ip->i_df.if_bytes = 0;
-       ip->i_df.if_data = NULL;
-
-       /*
-        * initialize the directory
-        */
+       /* Reset the root directory. */
+       reset_sbroot_ino(tp, mode | S_IFDIR, ip);
        libxfs_dir_init(tp, ip, ip);
 
        error = -libxfs_trans_commit(tp);