On 8/22/19 2:13 PM, Eric Sandeen wrote: > On 8/22/19 9:48 AM, Eric Sandeen wrote: >> On 8/22/19 1:01 AM, Dave Chinner wrote: > > ... > >>> Hence scanning all the inodes in the first indoe chunk won't find >>> the root indoe if any of these situations has occurred, and we may >>> have to scan 1500 or more inodes in to find the root chunk (6 btree >>> roots - BNOBT,CNTBT,INOBT,FINOBT,RMAPBT,REFCBT - and 64k blocks). >> >> Hm. So, the one report I had of this had a root inode of 128, and >> bulkstat returned a first inode of 64, triggering the assert above. >> (but even then you're right, scanning 64 isn't enough) >> >> If it really can be that far off then maybe this is a bad way to go, >> although the long scan is going to be exceedingly rare I think. Most >> people will get the root inode on the first bulkstat call. >> >>> So I think the best thing to do here is try to calculate the root >>> inode number as per xfs_repair, and then bulkstat that. i.e. see >>> the calculation of "first_prealloc_ino" in repair/xfs_repair.c >>> (about line 450). Probably requires a XFS_IOC_FSGEOMETRY_V1 call to >>> get the necessary info to calculate it... >> >> I had started to go down that path and it seemed like a real mess. >> We need m_ag_maxlevels, m_rmap_maxlevels, sb_logstart, features, >> etc etc etc. I guess I can revisit it. I had thought about a common >> function to calculate this so we aren't coding it twice but I'm not >> sure we have the same sets of inputs for the various cases ... > > I'm not sure it's possible without a ton of setup (or at all). > (repair has already done a full libxfs_mount setup, so it has what it needs.) > > For example we need inode alignment; calculating that depends on whether > we have sparse inodes, and sparse inodes is an incompat feature not > reported by GEOM. :( > > if (fp->inode_align) { > int cluster_size = XFS_INODE_BIG_CLUSTER_SIZE; > > sbp->sb_versionnum |= XFS_SB_VERSION_ALIGNBIT; > if (cfg->sb_feat.crcs_enabled) > cluster_size *= cfg->inodesize / XFS_DINODE_MIN_SIZE; > sbp->sb_inoalignmt = cluster_size >> cfg->blocklog; > } else > sbp->sb_inoalignmt = 0; > ... > /* > * Sparse inode chunk support has two main inode alignment requirements. > * First, sparse chunk alignment must match the cluster size. Second, > * full chunk alignment must match the inode chunk size. > * > * Copy the already calculated/scaled inoalignmt to spino_align and > * update the former to the full inode chunk size. > */ > if (fp->spinodes) { > sbp->sb_spino_align = sbp->sb_inoalignmt; > sbp->sb_inoalignmt = XFS_INODES_PER_CHUNK * > cfg->inodesize >> cfg->blocklog; > sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES; > } > > -Eric Should the root inode number always be a multiple of XFS_INODES_PER_CHUNK? if so I could speed up a longer search that way ... but this sucks. :/ Maybe I should just disallow dumping via a bind-mounted dir. Stat the target dir, get the inode, bulkstat it, check the gen, and if it's not zero, bail out with an error. ... that's probably better and less surprising anyway. -Eric