From e87475b595d2b790fd0736e992b7bb876c1b0cd4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 16 Jul 2024 14:35:56 +0200 Subject: [PATCH] metadump: refactor inode processing The code to dump inodes in metadump is rather convoluted because it tries to determine the inode "type" early and pass it down, which also leads to dumping the metadata inodes twice as we only determine their actual type in the second pass and not as part of the AGI scan. Switch to passing down the mount and dinode as far as possible, and then use a helper to determine the type only when it actually is needed. With that we can simply add the data for dump for the metadata inodes to the normal AGI scan and remove the second pass. Signed-off-by: Christoph Hellwig --- db/metadump.c | 421 +++++++++++++++++++------------------------------- 1 file changed, 163 insertions(+), 258 deletions(-) diff --git a/db/metadump.c b/db/metadump.c index 212bcad6f..f16383c7f 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -1155,6 +1155,15 @@ add_remap: free(orig_name); } +static inline bool +is_metadir_ino( + struct xfs_dinode *dip) +{ + if (!xfs_has_metadir(mp) || dip->di_version < 3) + return false; + return dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADIR); +} + static inline bool want_obfuscate_dirents(bool is_meta) { @@ -1163,9 +1172,9 @@ want_obfuscate_dirents(bool is_meta) static void process_sf_dir( - struct xfs_dinode *dip, - bool is_meta) + struct xfs_dinode *dip) { + bool is_meta = is_metadir_ino(dip); struct xfs_dir2_sf_hdr *sfp; xfs_dir2_sf_entry_t *sfep; uint64_t ino_dir_size; @@ -1397,16 +1406,15 @@ want_obfuscate_attr( return true; } +/* + * Obfuscate the attr names and fill the actual values with 'v' (to see a valid + * string length, as opposed to NULLs). + */ static void process_sf_attr( - struct xfs_dinode *dip, - bool is_meta) + struct xfs_dinode *dip) { - /* - * with extended attributes, obfuscate the names and fill the actual - * values with 'v' (to see a valid string length, as opposed to NULLs) - */ - + bool is_meta = is_metadir_ino(dip); struct xfs_attr_sf_hdr *hdr = XFS_DFORK_APTR(dip); struct xfs_attr_sf_entry *asfep = libxfs_attr_sf_firstentry(hdr); int ino_attr_size; @@ -2079,6 +2087,38 @@ out_pop: return rval; } +static typnm_t +ifork_data_type( + struct xfs_dinode *dip, + int whichfork) +{ + xfs_ino_t ino = be64_to_cpu(dip->di_ino); + + if (whichfork == XFS_ATTR_FORK) + return TYP_ATTR; + + switch (be16_to_cpu(dip->di_mode) & S_IFMT) { + case S_IFDIR: + return TYP_DIR2; + case S_IFLNK: + return TYP_SYMLINK; + case S_IFREG: + if (ino == mp->m_sb.sb_rbmino) + return TYP_RTBITMAP; + if (ino == mp->m_sb.sb_rsumino) + return TYP_RTSUMMARY; + if (ino == mp->m_sb.sb_uquotino) + return TYP_DQBLK; + if (ino == mp->m_sb.sb_gquotino) + return TYP_DQBLK; + if (ino == mp->m_sb.sb_pquotino) + return TYP_DQBLK; + return TYP_DATA; + default: + return TYP_NONE; + } +} + static bool is_multi_fsb_object( struct xfs_mount *mp, @@ -2114,11 +2154,13 @@ process_multi_fsb_objects( /* inode copy routines */ static int process_bmbt_reclist( - xfs_bmbt_rec_t *rp, - int numrecs, - typnm_t btype, - bool is_meta) + struct xfs_dinode *dip, + int whichfork, + struct xfs_bmbt_rec *rp, + int numrecs) { + bool is_meta = is_metadir_ino(dip); + typnm_t btype = ifork_data_type(dip, whichfork); int i; xfs_fileoff_t o, op = NULLFILEOFF; xfs_fsblock_t s; @@ -2127,7 +2169,6 @@ process_bmbt_reclist( xfs_fileoff_t last; xfs_agnumber_t agno; xfs_agblock_t agbno; - bool is_multi_fsb = is_multi_fsb_object(mp, btype); int rval = 1; if (btype == TYP_DATA) @@ -2195,7 +2236,7 @@ process_bmbt_reclist( } /* multi-extent blocks require special handling */ - if (is_multi_fsb) + if (is_multi_fsb_object(mp, btype)) rval = process_multi_fsb_objects(o, s, c, btype, last, is_meta); else @@ -2209,8 +2250,8 @@ process_bmbt_reclist( } struct scan_bmap { - enum typnm typ; - bool is_meta; + struct xfs_dinode *dip; + int whichfork; }; static int @@ -2220,7 +2261,7 @@ scanfunc_bmap( xfs_agblock_t agbno, int level, typnm_t btype, - void *arg) /* ptr to itype */ + void *arg) { struct scan_bmap *sbm = arg; int i; @@ -2237,8 +2278,8 @@ scanfunc_bmap( typtab[btype].name, agno, agbno); return 1; } - return process_bmbt_reclist(xfs_bmbt_rec_addr(mp, block, 1), - nrecs, sbm->typ, sbm->is_meta); + return process_bmbt_reclist(sbm->dip, sbm->whichfork, + xfs_bmbt_rec_addr(mp, block, 1), nrecs); } if (nrecs > mp->m_bmap_dmxr[1]) { @@ -2270,36 +2311,20 @@ scanfunc_bmap( return 1; } -static inline bool -is_metadata_ino( - struct xfs_dinode *dip) -{ - return xfs_has_metadir(mp) && - dip->di_version >= 3 && - (dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADIR)); -} - static int process_btinode( struct xfs_dinode *dip, - typnm_t itype) + int whichfork) { - xfs_bmdr_block_t *dib; - int i; - xfs_bmbt_ptr_t *pp; - int level; - int nrecs; + struct xfs_bmdr_block *dib = + (struct xfs_bmdr_block *)XFS_DFORK_PTR(dip, whichfork); + int level = be16_to_cpu(dib->bb_level); + int nrecs = be16_to_cpu(dib->bb_numrecs); int maxrecs; - int whichfork; - typnm_t btype; - bool is_meta = is_metadata_ino(dip); - - whichfork = (itype == TYP_ATTR) ? XFS_ATTR_FORK : XFS_DATA_FORK; - btype = (itype == TYP_ATTR) ? TYP_BMAPBTA : TYP_BMAPBTD; - - dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); - level = be16_to_cpu(dib->bb_level); - nrecs = be16_to_cpu(dib->bb_numrecs); + typnm_t btype = (whichfork == XFS_ATTR_FORK) ? + TYP_BMAPBTA : TYP_BMAPBTD; + xfs_bmbt_ptr_t *pp; + int i; if (level > XFS_BM_MAXLEVELS(mp, whichfork)) { if (metadump.show_warnings) @@ -2310,8 +2335,9 @@ process_btinode( } if (level == 0) { - return process_bmbt_reclist(xfs_bmdr_rec_addr(dib, 1), - nrecs, itype, is_meta); + return process_bmbt_reclist(dip, whichfork, + xfs_bmdr_rec_addr(dib, 1), + nrecs); } maxrecs = libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0); @@ -2339,8 +2365,8 @@ process_btinode( for (i = 0; i < nrecs; i++) { struct scan_bmap sbm = { - .typ = itype, - .is_meta = is_meta, + .dip = dip, + .whichfork = whichfork, }; xfs_agnumber_t ag; xfs_agblock_t bno; @@ -2367,20 +2393,13 @@ process_btinode( static int process_exinode( struct xfs_dinode *dip, - typnm_t itype) + int whichfork) { - int whichfork; - int used; - xfs_extnum_t nex, max_nex; - bool is_meta = is_metadata_ino(dip); - - whichfork = (itype == TYP_ATTR) ? XFS_ATTR_FORK : XFS_DATA_FORK; + xfs_extnum_t max_nex = xfs_iext_max_nextents( + xfs_dinode_has_large_extent_counts(dip), whichfork); + xfs_extnum_t nex = xfs_dfork_nextents(dip, whichfork); + int used = nex * sizeof(struct xfs_bmbt_rec); - nex = xfs_dfork_nextents(dip, whichfork); - max_nex = xfs_iext_max_nextents( - xfs_dinode_has_large_extent_counts(dip), - whichfork); - used = nex * sizeof(xfs_bmbt_rec_t); if (nex > max_nex || used > XFS_DFORK_SIZE(dip, mp, whichfork)) { if (metadump.show_warnings) print_warning("bad number of extents %llu in inode %lld", @@ -2396,36 +2415,24 @@ process_exinode( XFS_DFORK_SIZE(dip, mp, whichfork) - used); - return process_bmbt_reclist((xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, - whichfork), nex, itype, is_meta); + return process_bmbt_reclist(dip, whichfork, + (struct xfs_bmbt_rec *)XFS_DFORK_PTR(dip, whichfork), + nex); } static int process_rtrmap( - struct xfs_dinode *dip, - typnm_t itype) + struct xfs_dinode *dip) { - struct xfs_rtrmap_root *dib; - int i; - xfs_rtrmap_ptr_t *pp; - int level; - int nrecs; + int whichfork = XFS_DATA_FORK; + struct xfs_rtrmap_root *dib = + (struct xfs_rtrmap_root *)XFS_DFORK_PTR(dip, whichfork); + int level = be16_to_cpu(dib->bb_level); + int nrecs = be16_to_cpu(dib->bb_numrecs); + typnm_t btype = TYP_RTRMAPBT; int maxrecs; - int whichfork; - typnm_t btype; - - if (itype == TYP_ATTR && metadump.show_warnings) { - print_warning("ignoring rtrmapbt root in inode %llu attr fork", - (unsigned long long)metadump.cur_ino); - return 1; - } - - whichfork = XFS_DATA_FORK; - btype = TYP_RTRMAPBT; - - dib = (struct xfs_rtrmap_root *)XFS_DFORK_PTR(dip, whichfork); - level = be16_to_cpu(dib->bb_level); - nrecs = be16_to_cpu(dib->bb_numrecs); + xfs_rtrmap_ptr_t *pp; + int i; if (level > mp->m_rtrmap_maxlevels) { if (metadump.show_warnings) @@ -2470,8 +2477,7 @@ process_rtrmap( continue; } - if (!scan_btree(ag, bno, level, btype, &itype, - scanfunc_rtrmapbt)) + if (!scan_btree(ag, bno, level, btype, NULL, scanfunc_rtrmapbt)) return 0; } return 1; @@ -2479,30 +2485,17 @@ process_rtrmap( static int process_rtrefc( - struct xfs_dinode *dip, - typnm_t itype) + struct xfs_dinode *dip) { - struct xfs_rtrefcount_root *dib; - int i; - xfs_rtrefcount_ptr_t *pp; - int level; - int nrecs; + int whichfork = XFS_DATA_FORK; + struct xfs_rtrefcount_root *dib = + (struct xfs_rtrefcount_root *)XFS_DFORK_PTR(dip, whichfork); + int level = be16_to_cpu(dib->bb_level); + int nrecs = be16_to_cpu(dib->bb_numrecs); + typnm_t btype = TYP_RTREFCBT; int maxrecs; - int whichfork; - typnm_t btype; - - if (itype == TYP_ATTR && metadump.show_warnings) { - print_warning("ignoring rtrefcbt root in inode %llu attr fork", - (unsigned long long)metadump.cur_ino); - return 1; - } - - whichfork = XFS_DATA_FORK; - btype = TYP_RTREFCBT; - - dib = (struct xfs_rtrefcount_root *)XFS_DFORK_PTR(dip, whichfork); - level = be16_to_cpu(dib->bb_level); - nrecs = be16_to_cpu(dib->bb_numrecs); + xfs_rtrefcount_ptr_t *pp; + int i; if (level > mp->m_rtrefc_maxlevels) { if (metadump.show_warnings) @@ -2547,8 +2540,7 @@ process_rtrefc( continue; } - if (!scan_btree(ag, bno, level, btype, &itype, - scanfunc_rtrefcbt)) + if (!scan_btree(ag, bno, level, btype, NULL, scanfunc_rtrefcbt)) return 0; } return 1; @@ -2556,54 +2548,45 @@ process_rtrefc( static int process_inode_data( - struct xfs_dinode *dip, - typnm_t itype) + struct xfs_dinode *dip) { - bool is_meta = is_metadata_ino(dip); - switch (dip->di_format) { - case XFS_DINODE_FMT_LOCAL: - if (!(metadump.obfuscate || metadump.zero_stale_data)) - break; + case XFS_DINODE_FMT_LOCAL: + if (!(metadump.obfuscate || metadump.zero_stale_data)) + break; - /* - * If the fork size is invalid, we can't safely do - * anything with this fork. Leave it alone to preserve - * the information for diagnostic purposes. - */ - if (XFS_DFORK_DSIZE(dip, mp) > XFS_LITINO(mp)) { - print_warning( + /* + * If the fork size is invalid, we can't safely do + * anything with this fork. Leave it alone to preserve + * the information for diagnostic purposes. + */ + if (XFS_DFORK_DSIZE(dip, mp) > XFS_LITINO(mp)) { + print_warning( "Invalid data fork size (%d) in inode %llu, preserving contents!", - XFS_DFORK_DSIZE(dip, mp), - (long long)metadump.cur_ino); - break; - } - - switch (itype) { - case TYP_DIR2: - process_sf_dir(dip, is_meta); - break; - - case TYP_SYMLINK: - process_sf_symlink(dip); - break; - - default: - break; - } + XFS_DFORK_DSIZE(dip, mp), + (long long)metadump.cur_ino); break; + } - case XFS_DINODE_FMT_EXTENTS: - return process_exinode(dip, itype); - - case XFS_DINODE_FMT_BTREE: - return process_btinode(dip, itype); - - case XFS_DINODE_FMT_RMAP: - return process_rtrmap(dip, itype); - - case XFS_DINODE_FMT_REFCOUNT: - return process_rtrefc(dip, itype); + switch (be16_to_cpu(dip->di_mode) & S_IFMT) { + case S_IFDIR: + process_sf_dir(dip); + break; + case S_IFLNK: + process_sf_symlink(dip); + break; + default: + break; + } + break; + case XFS_DINODE_FMT_EXTENTS: + return process_exinode(dip, XFS_DATA_FORK); + case XFS_DINODE_FMT_BTREE: + return process_btinode(dip, XFS_DATA_FORK); + case XFS_DINODE_FMT_RMAP: + return process_rtrmap(dip); + case XFS_DINODE_FMT_REFCOUNT: + return process_rtrefc(dip); } return 1; } @@ -2676,28 +2659,22 @@ process_inode( /* copy appropriate data fork metadata */ switch (be16_to_cpu(dip->di_mode) & S_IFMT) { - case S_IFDIR: - rval = process_inode_data(dip, TYP_DIR2); - if (dip->di_format == XFS_DINODE_FMT_LOCAL) - need_new_crc = true; - break; - case S_IFLNK: - rval = process_inode_data(dip, TYP_SYMLINK); - if (dip->di_format == XFS_DINODE_FMT_LOCAL) - need_new_crc = true; - break; - case S_IFREG: - rval = process_inode_data(dip, TYP_DATA); - break; - case S_IFIFO: - case S_IFCHR: - case S_IFBLK: - case S_IFSOCK: - process_dev_inode(dip); + case S_IFDIR: + case S_IFLNK: + case S_IFREG: + rval = process_inode_data(dip); + if (dip->di_format == XFS_DINODE_FMT_LOCAL) need_new_crc = true; - break; - default: - break; + break; + case S_IFIFO: + case S_IFCHR: + case S_IFBLK: + case S_IFSOCK: + process_dev_inode(dip); + need_new_crc = true; + break; + default: + break; } nametable_clear(); if (!rval) @@ -2705,24 +2682,20 @@ process_inode( /* copy extended attributes if they exist and forkoff is valid */ if (XFS_DFORK_DSIZE(dip, mp) < XFS_LITINO(mp)) { - bool is_meta = is_metadata_ino(dip); - attr_data.remote_val_count = 0; switch (dip->di_aformat) { - case XFS_DINODE_FMT_LOCAL: - need_new_crc = true; - if (metadump.obfuscate || - metadump.zero_stale_data) - process_sf_attr(dip, is_meta); - break; - - case XFS_DINODE_FMT_EXTENTS: - rval = process_exinode(dip, TYP_ATTR); - break; - - case XFS_DINODE_FMT_BTREE: - rval = process_btinode(dip, TYP_ATTR); - break; + case XFS_DINODE_FMT_LOCAL: + need_new_crc = true; + if (metadump.obfuscate || + metadump.zero_stale_data) + process_sf_attr(dip); + break; + case XFS_DINODE_FMT_EXTENTS: + rval = process_exinode(dip, XFS_ATTR_FORK); + break; + case XFS_DINODE_FMT_BTREE: + rval = process_btinode(dip, XFS_ATTR_FORK); + break; } nametable_clear(); } @@ -3099,70 +3072,6 @@ pop_out: return rval; } -static int -copy_ino( - xfs_ino_t ino, - typnm_t itype) -{ - xfs_agnumber_t agno; - xfs_agblock_t agbno; - xfs_agino_t agino; - int offset; - int rval = 1; - - if (ino == 0 || ino == NULLFSINO) - return 1; - - agno = XFS_INO_TO_AGNO(mp, ino); - agino = XFS_INO_TO_AGINO(mp, ino); - agbno = XFS_AGINO_TO_AGBNO(mp, agino); - offset = XFS_AGINO_TO_OFFSET(mp, agino); - - if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || - offset >= mp->m_sb.sb_inopblock) { - if (metadump.show_warnings) - print_warning("invalid %s inode number (%lld)", - typtab[itype].name, (long long)ino); - return 1; - } - - push_cur(); - set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, agbno), - blkbb, DB_RING_IGN, NULL); - if (iocur_top->data == NULL) { - print_warning("cannot read %s inode %lld", - typtab[itype].name, (long long)ino); - rval = !metadump.stop_on_read_error; - goto pop_out; - } - off_cur(offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize); - - metadump.cur_ino = ino; - rval = process_inode_data(iocur_top->data, itype); -pop_out: - pop_cur(); - return rval; -} - - -static int -copy_sb_inodes(void) -{ - if (!copy_ino(mp->m_sb.sb_rbmino, TYP_RTBITMAP)) - return 0; - - if (!copy_ino(mp->m_sb.sb_rsumino, TYP_RTSUMMARY)) - return 0; - - if (!copy_ino(mp->m_sb.sb_uquotino, TYP_DQBLK)) - return 0; - - if (!copy_ino(mp->m_sb.sb_gquotino, TYP_DQBLK)) - return 0; - - return copy_ino(mp->m_sb.sb_pquotino, TYP_DQBLK); -} - static int copy_log(void) { @@ -3644,10 +3553,6 @@ metadump_f( } } - /* copy realtime and quota inode contents */ - if (!exitcode) - exitcode = !copy_sb_inodes(); - /* copy log */ if (!exitcode && !(metadump.version == 1 && metadump.external_log)) exitcode = !copy_log(); -- 2.50.1