free(orig_name);
}
+static inline bool
+is_metadata_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_METADATA);
+}
+
+static inline bool
+want_obfuscate_dirents(bool is_meta)
+{
+ return metadump.obfuscate && !is_meta;
+}
+
static void
process_sf_dir(
struct xfs_dinode *dip)
{
+ bool is_meta = is_metadata_ino(dip);
struct xfs_dir2_sf_hdr *sfp;
xfs_dir2_sf_entry_t *sfep;
uint64_t ino_dir_size;
(char *)sfp);
}
- if (metadump.obfuscate)
+ if (want_obfuscate_dirents(is_meta))
generate_obfuscated_name(
libxfs_dir2_sf_get_ino(mp, sfp, sfep),
namelen, &sfep->name[0]);
uint8_t *name,
int namelen,
const void *value,
- int valuelen)
+ int valuelen,
+ bool is_meta)
{
unsigned char old_name[MAXNAMELEN];
struct remap_ent *remap;
xfs_ino_t parent_ino;
int error;
- if (!metadump.obfuscate)
+ if (!metadump.obfuscate || is_meta)
return;
if (!(attr_flags & XFS_ATTR_PARENT))
const void *name,
unsigned int namelen,
const void *value,
- unsigned int valuelen)
+ unsigned int valuelen,
+ bool is_meta)
{
- if (!metadump.obfuscate)
+ if (!metadump.obfuscate || is_meta)
return false;
/*
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)
{
- /*
- * 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_metadata_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;
if (asfep->flags & XFS_ATTR_PARENT) {
maybe_obfuscate_pptr(asfep->flags, name, namelen,
- value, asfep->valuelen);
+ value, asfep->valuelen, is_meta);
} else if (want_obfuscate_attr(asfep->flags, name, namelen,
- value, asfep->valuelen)) {
+ value, asfep->valuelen, is_meta)) {
generate_obfuscated_name(0, asfep->namelen, name);
memset(value, 'v', asfep->valuelen);
}
process_dir_data_block(
char *block,
xfs_fileoff_t offset,
- int is_block_format)
+ int is_block_format,
+ bool is_meta)
{
/*
* we have to rely on the fileoffset and signature of the block to
dir_offset)
return;
- if (metadump.obfuscate)
+ if (want_obfuscate_dirents(is_meta))
generate_obfuscated_name(be64_to_cpu(dep->inumber),
dep->namelen, &dep->name[0]);
dir_offset += length;
xfs_fsblock_t s,
xfs_filblks_t c,
typnm_t btype,
- xfs_fileoff_t last)
+ xfs_fileoff_t last,
+ bool is_meta)
{
struct bbmap map;
char *link;
if (xfs_has_crc((mp)))
link += sizeof(struct xfs_dsymlink_hdr);
- if (metadump.obfuscate)
+ if (want_obfuscate_dirents(is_meta))
obfuscate_path_components(link, XFS_SYMLINK_BUF_SPACE(mp,
mp->m_sb.sb_blocksize));
if (metadump.zero_stale_data) {
static void
process_attr_block(
char *block,
- xfs_fileoff_t offset)
+ xfs_fileoff_t offset,
+ bool is_meta)
{
struct xfs_attr_leafblock *leaf;
struct xfs_attr3_icleaf_hdr hdr;
if (entry->flags & XFS_ATTR_PARENT) {
maybe_obfuscate_pptr(entry->flags, name,
local->namelen, value,
- valuelen);
+ valuelen, is_meta);
} else if (want_obfuscate_attr(entry->flags, name,
local->namelen, value,
- valuelen)) {
+ valuelen, is_meta)) {
generate_obfuscated_name(0, local->namelen,
name);
memset(value, 'v', valuelen);
/* do not obfuscate obviously busted pptr */
add_remote_vals(be32_to_cpu(remote->valueblk),
be32_to_cpu(remote->valuelen));
- } else if (metadump.obfuscate) {
+ } else if (want_obfuscate_dirents(is_meta)) {
generate_obfuscated_name(0, remote->namelen,
&remote->name[0]);
add_remote_vals(be32_to_cpu(remote->valueblk),
xfs_fsblock_t s,
xfs_filblks_t c,
typnm_t btype,
- xfs_fileoff_t last)
+ xfs_fileoff_t last,
+ bool is_meta)
{
int rval = 1;
char *dp;
process_dir_leaf_block(dp);
} else {
process_dir_data_block(dp, o,
- last == mp->m_dir_geo->fsbcount);
+ last == mp->m_dir_geo->fsbcount,
+ is_meta);
}
iocur_top->need_crc = 1;
break;
case TYP_ATTR:
- process_attr_block(dp, o);
+ process_attr_block(dp, o, is_meta);
iocur_top->need_crc = 1;
break;
default:
xfs_fsblock_t s,
xfs_filblks_t c,
typnm_t btype,
- xfs_fileoff_t last)
+ xfs_fileoff_t last,
+ bool is_meta)
{
char *dp;
int rval = 1;
process_dir_leaf_block(dp);
} else {
process_dir_data_block(dp, o,
- last == mp->m_dir_geo->fsbcount);
+ last == mp->m_dir_geo->fsbcount,
+ is_meta);
}
iocur_top->need_crc = 1;
write:
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,
xfs_fsblock_t s,
xfs_filblks_t c,
typnm_t btype,
- xfs_fileoff_t last)
+ xfs_fileoff_t last,
+ bool is_meta)
{
switch (btype) {
case TYP_DIR2:
- return process_multi_fsb_dir(o, s, c, btype, last);
+ return process_multi_fsb_dir(o, s, c, btype, last, is_meta);
case TYP_SYMLINK:
- return process_symlink_block(o, s, c, btype, last);
+ return process_symlink_block(o, s, c, btype, last, is_meta);
default:
print_warning("bad type for multi-fsb object %d", btype);
return 1;
/* inode copy routines */
static int
process_bmbt_reclist(
- xfs_bmbt_rec_t *rp,
- int numrecs,
- typnm_t btype)
+ struct xfs_dinode *dip,
+ int whichfork,
+ struct xfs_bmbt_rec *rp,
+ int numrecs)
{
+ bool is_meta = is_metadata_ino(dip);
+ typnm_t btype = ifork_data_type(dip, whichfork);
int i;
xfs_fileoff_t o, op = NULLFILEOFF;
xfs_fsblock_t s;
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)
}
/* 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);
+ last, is_meta);
else
rval = process_single_fsb_objects(o, s, c, btype,
- last);
+ last, is_meta);
if (!rval)
break;
}
return rval;
}
+struct scan_bmap {
+ struct xfs_dinode *dip;
+ int whichfork;
+};
+
static int
scanfunc_bmap(
struct xfs_btree_block *block,
xfs_agblock_t agbno,
int level,
typnm_t btype,
- void *arg) /* ptr to itype */
+ void *arg)
{
+ struct scan_bmap *sbm = arg;
int i;
xfs_bmbt_ptr_t *pp;
int nrecs;
typtab[btype].name, agno, agbno);
return 1;
}
- return process_bmbt_reclist(xfs_bmbt_rec_addr(mp, block, 1),
- nrecs, *(typnm_t*)arg);
+ return process_bmbt_reclist(sbm->dip, sbm->whichfork,
+ xfs_bmbt_rec_addr(mp, block, 1), nrecs);
}
if (nrecs > mp->m_bmap_dmxr[1]) {
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;
-
- 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)
}
if (level == 0) {
- return process_bmbt_reclist(xfs_bmdr_rec_addr(dib, 1),
- nrecs, itype);
+ return process_bmbt_reclist(dip, whichfork,
+ xfs_bmdr_rec_addr(dib, 1), nrecs);
}
maxrecs = libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0);
}
for (i = 0; i < nrecs; i++) {
+ struct scan_bmap sbm = {
+ .dip = dip,
+ .whichfork = whichfork,
+ };
xfs_agnumber_t ag;
xfs_agblock_t bno;
continue;
}
- if (!scan_btree(ag, bno, level, btype, &itype, scanfunc_bmap))
+ if (!scan_btree(ag, bno, level, btype, &sbm, scanfunc_bmap))
return 0;
}
return 1;
static int
process_exinode(
struct xfs_dinode *dip,
- typnm_t itype)
+ int whichfork)
{
- int whichfork;
- int used;
- xfs_extnum_t nex, max_nex;
-
- 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",
XFS_DFORK_SIZE(dip, mp, whichfork) - used);
- return process_bmbt_reclist((xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip,
- whichfork), nex, itype);
+ return process_bmbt_reclist(dip, whichfork,
+ (struct xfs_bmbt_rec *)XFS_DFORK_PTR(dip, whichfork),
+ nex);
}
static int
process_inode_data(
- struct xfs_dinode *dip,
- typnm_t itype)
+ struct xfs_dinode *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;
- }
+ XFS_DFORK_DSIZE(dip, mp),
+ (long long)metadump.cur_ino);
+ break;
+ }
- switch (itype) {
- case TYP_DIR2:
- process_sf_dir(dip);
- break;
+ switch (be16_to_cpu(dip->di_mode) & S_IFMT) {
+ case S_IFDIR:
+ process_sf_dir(dip);
+ break;
- case TYP_SYMLINK:
- process_sf_symlink(dip);
- break;
+ case S_IFLNK:
+ process_sf_symlink(dip);
+ break;
- default:
- break;
- }
+ default:
break;
+ }
+ break;
- case XFS_DINODE_FMT_EXTENTS:
- return process_exinode(dip, itype);
+ case XFS_DINODE_FMT_EXTENTS:
+ return process_exinode(dip, XFS_DATA_FORK);
- case XFS_DINODE_FMT_BTREE:
- return process_btinode(dip, itype);
+ case XFS_DINODE_FMT_BTREE:
+ return process_btinode(dip, XFS_DATA_FORK);
}
return 1;
}
/* 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)
if (XFS_DFORK_DSIZE(dip, mp) < XFS_LITINO(mp)) {
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);
- 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();
}
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)
{
}
}
- /* 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();