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