From 0e81250e5125dc664e1938288e47ff52b1cacbe4 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Apr 2019 15:40:28 -0500 Subject: [PATCH] xfs_db: metadump should handle symlinks properly Remote symlink target blocks are multi-fsb objects on XFS v5 filesystems because we only write one rmt header per data fork extent. For fs blocksize >= 2048 we never have more than one block and therefore nobody noticed, but for blocksize == 1024 this is definitely not true and leads to metadump spraying error messages about symlink block crc errors. Therefore, reformulate the symlink metadump into a multi-fsb dump function. Signed-off-by: Darrick J. Wong Reviewed-by: Eric Sandeen [sandeen: shrink the map declaration] Signed-off-by: Eric Sandeen --- db/metadump.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) Index: xfsprogs-4.5.0/db/metadump.c =================================================================== --- xfsprogs-4.5.0.orig/db/metadump.c +++ xfsprogs-4.5.0/db/metadump.c @@ -1425,11 +1425,34 @@ process_dir_data_block( } } -static void +static int process_symlink_block( - char *block) + xfs_fileoff_t o, + xfs_fsblock_t s, + xfs_filblks_t c, + typnm_t btype, + xfs_fileoff_t last) { - char *link = block; + struct bbmap map; + char *link; + int ret = 0; + + push_cur(); + map.nmaps = 1; + map.b[0].bm_bn = XFS_FSB_TO_DADDR(mp, s); + map.b[0].bm_len = XFS_FSB_TO_BB(mp, c); + set_cur(&typtab[btype], 0, 0, DB_RING_IGN, &map); + if (!iocur_top->data) { + xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, s); + xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, s); + + print_warning("cannot read %s block %u/%u (%llu)", + typtab[btype].name, agno, agbno, s); + if (stop_on_read_error) + ret = -1; + goto out_pop; + } + link = iocur_top->data; if (xfs_sb_version_hascrc(&(mp)->m_sb)) link += sizeof(struct xfs_dsymlink_hdr); @@ -1447,6 +1470,12 @@ process_symlink_block( if (zlen < mp->m_sb.sb_blocksize) memset(link + linklen, 0, zlen); } + + iocur_top->need_crc = 1; + ret = write_buf(iocur_top); +out_pop: + pop_cur(); + return ret; } #define MAX_REMOTE_VALS 4095 @@ -1663,10 +1692,6 @@ process_single_fsb_objects( last == mp->m_dir_geo->fsbcount); iocur_top->need_crc = 1; break; - case TYP_SYMLINK: - process_symlink_block(dp); - iocur_top->need_crc = 1; - break; case TYP_ATTR: process_attr_block(dp, o); iocur_top->need_crc = 1; @@ -1764,6 +1789,8 @@ is_multi_fsb_object( { if (btype == TYP_DIR2 && mp->m_dir_geo->fsbcount > 1) return true; + if (btype == TYP_SYMLINK) + return true; return false; } @@ -1778,6 +1805,8 @@ process_multi_fsb_objects( switch (btype) { case TYP_DIR2: return process_multi_fsb_dir(o, s, c, btype, last); + case TYP_SYMLINK: + return process_symlink_block(o, s, c, btype, last); default: print_warning("bad type for multi-fsb object %d", btype); return -EINVAL;