Message ID | 156944765991.303060.7541074919992777157.stgit@magnolia (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | xfs_db: fixes to the btheight command | expand |
On Wed, Sep 25, 2019 at 02:40:59PM -0700, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@oracle.com> > > (Ab)use the btheight command to calculate the geometry of the incore > extent tree. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- > db/btheight.c | 87 +++++++++++++++++++++++++++++++++++++++------------------ > 1 file changed, 60 insertions(+), 27 deletions(-) > > > diff --git a/db/btheight.c b/db/btheight.c > index e2c9759f..be604ebc 100644 > --- a/db/btheight.c > +++ b/db/btheight.c > @@ -22,18 +22,37 @@ static int rmap_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > return libxfs_rmapbt_maxrecs(blocklen, leaf); > } > > +static int iext_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > +{ > + blocklen -= 2 * sizeof(void *); > + > + return blocklen / sizeof(struct xfs_bmbt_rec); > +} > + > +static int disk_blocksize(struct xfs_mount *mp) This naming looks confusing to me, disk_blocksize sounds to me like 'sector size', maybe fs_blocksize() or get_fs_blocksize()? > +{ > + return mp->m_sb.sb_blocksize; > +} > + Otherwise looks good. > +static int iext_blocksize(struct xfs_mount *mp) > +{ > + return 256; > +} > + > struct btmap { > const char *tag; > int (*maxrecs)(struct xfs_mount *mp, int blocklen, > int leaf); > + int (*default_blocksize)(struct xfs_mount *mp); > } maps[] = { > - {"bnobt", libxfs_allocbt_maxrecs}, > - {"cntbt", libxfs_allocbt_maxrecs}, > - {"inobt", libxfs_inobt_maxrecs}, > - {"finobt", libxfs_inobt_maxrecs}, > - {"bmapbt", libxfs_bmbt_maxrecs}, > - {"refcountbt", refc_maxrecs}, > - {"rmapbt", rmap_maxrecs}, > + {"bnobt", libxfs_allocbt_maxrecs, disk_blocksize}, > + {"cntbt", libxfs_allocbt_maxrecs, disk_blocksize}, > + {"inobt", libxfs_inobt_maxrecs, disk_blocksize}, > + {"finobt", libxfs_inobt_maxrecs, disk_blocksize}, > + {"bmapbt", libxfs_bmbt_maxrecs, disk_blocksize}, > + {"refcountbt", refc_maxrecs, disk_blocksize}, > + {"rmapbt", rmap_maxrecs, disk_blocksize}, > + {"iext", iext_maxrecs, iext_blocksize}, > }; > > static void > @@ -108,7 +127,7 @@ calc_height( > static int > construct_records_per_block( > char *tag, > - int blocksize, > + int *blocksize, > unsigned int *records_per_block) > { > char *toktag; > @@ -119,8 +138,10 @@ construct_records_per_block( > > for (i = 0, m = maps; i < ARRAY_SIZE(maps); i++, m++) { > if (!strcmp(m->tag, tag)) { > - records_per_block[0] = m->maxrecs(mp, blocksize, 1); > - records_per_block[1] = m->maxrecs(mp, blocksize, 0); > + if (*blocksize < 0) > + *blocksize = m->default_blocksize(mp); > + records_per_block[0] = m->maxrecs(mp, *blocksize, 1); > + records_per_block[1] = m->maxrecs(mp, *blocksize, 0); > return 0; > } > } > @@ -178,38 +199,50 @@ construct_records_per_block( > fprintf(stderr, _("%s: header type not found.\n"), tag); > goto out; > } > - if (!strcmp(p, "short")) > + if (!strcmp(p, "short")) { > + if (*blocksize < 0) > + *blocksize = mp->m_sb.sb_blocksize; > blocksize -= XFS_BTREE_SBLOCK_LEN; > - else if (!strcmp(p, "shortcrc")) > + } else if (!strcmp(p, "shortcrc")) { > + if (*blocksize < 0) > + *blocksize = mp->m_sb.sb_blocksize; > blocksize -= XFS_BTREE_SBLOCK_CRC_LEN; > - else if (!strcmp(p, "long")) > + } else if (!strcmp(p, "long")) { > + if (*blocksize < 0) > + *blocksize = mp->m_sb.sb_blocksize; > blocksize -= XFS_BTREE_LBLOCK_LEN; > - else if (!strcmp(p, "longcrc")) > + } else if (!strcmp(p, "longcrc")) { > + if (*blocksize < 0) > + *blocksize = mp->m_sb.sb_blocksize; > blocksize -= XFS_BTREE_LBLOCK_CRC_LEN; > - else { > + } else if (!strcmp(p, "iext")) { > + if (*blocksize < 0) > + *blocksize = 256; > + blocksize -= 2 * sizeof(void *); > + } else { > fprintf(stderr, _("%s: unrecognized btree header type."), > p); > goto out; > } > > - if (record_size > blocksize) { > + if (record_size > *blocksize) { > fprintf(stderr, > _("%s: record size must be less than %u bytes.\n"), > - tag, blocksize); > + tag, *blocksize); > goto out; > } > > - if (key_size > blocksize) { > + if (key_size > *blocksize) { > fprintf(stderr, > _("%s: key size must be less than %u bytes.\n"), > - tag, blocksize); > + tag, *blocksize); > goto out; > } > > - if (ptr_size > blocksize) { > + if (ptr_size > *blocksize) { > fprintf(stderr, > _("%s: pointer size must be less than %u bytes.\n"), > - tag, blocksize); > + tag, *blocksize); > goto out; > } > > @@ -221,8 +254,8 @@ construct_records_per_block( > goto out; > } > > - records_per_block[0] = blocksize / record_size; > - records_per_block[1] = blocksize / (key_size + ptr_size); > + records_per_block[0] = *blocksize / record_size; > + records_per_block[1] = *blocksize / (key_size + ptr_size); > ret = 0; > out: > free(toktag); > @@ -238,12 +271,12 @@ report( > char *tag, > unsigned int report_what, > unsigned long long nr_records, > - unsigned int blocksize) > + int blocksize) > { > unsigned int records_per_block[2]; > int ret; > > - ret = construct_records_per_block(tag, blocksize, records_per_block); > + ret = construct_records_per_block(tag, &blocksize, records_per_block); > if (ret) > return; > > @@ -302,7 +335,7 @@ btheight_f( > int argc, > char **argv) > { > - long long blocksize = mp->m_sb.sb_blocksize; > + long long blocksize = -1; > uint64_t nr_records = 0; > int report_what = REPORT_DEFAULT; > int i, c; > @@ -355,7 +388,7 @@ _("The largest block size this command will consider is %u bytes.\n"), > return 0; > } > > - if (blocksize < 128) { > + if (blocksize >= 0 && blocksize < 128) { > fprintf(stderr, > _("The smallest block size this command will consider is 128 bytes.\n")); > return 0; >
On Thu, Sep 26, 2019 at 11:20:42AM +0200, Carlos Maiolino wrote: > On Wed, Sep 25, 2019 at 02:40:59PM -0700, Darrick J. Wong wrote: > > From: Darrick J. Wong <darrick.wong@oracle.com> > > > > (Ab)use the btheight command to calculate the geometry of the incore > > extent tree. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > --- > > db/btheight.c | 87 +++++++++++++++++++++++++++++++++++++++------------------ > > 1 file changed, 60 insertions(+), 27 deletions(-) > > > > > > diff --git a/db/btheight.c b/db/btheight.c > > index e2c9759f..be604ebc 100644 > > --- a/db/btheight.c > > +++ b/db/btheight.c > > @@ -22,18 +22,37 @@ static int rmap_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > > return libxfs_rmapbt_maxrecs(blocklen, leaf); > > } > > > > +static int iext_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > > +{ > > + blocklen -= 2 * sizeof(void *); > > + > > + return blocklen / sizeof(struct xfs_bmbt_rec); > > +} > > + > > +static int disk_blocksize(struct xfs_mount *mp) > > This naming looks confusing to me, disk_blocksize sounds to me like > 'sector size', maybe fs_blocksize() or get_fs_blocksize()? Fixed. --D > > +{ > > + return mp->m_sb.sb_blocksize; > > +} > > + > > Otherwise looks good. > > > > +static int iext_blocksize(struct xfs_mount *mp) > > +{ > > + return 256; > > +} > > + > > struct btmap { > > const char *tag; > > int (*maxrecs)(struct xfs_mount *mp, int blocklen, > > int leaf); > > + int (*default_blocksize)(struct xfs_mount *mp); > > } maps[] = { > > - {"bnobt", libxfs_allocbt_maxrecs}, > > - {"cntbt", libxfs_allocbt_maxrecs}, > > - {"inobt", libxfs_inobt_maxrecs}, > > - {"finobt", libxfs_inobt_maxrecs}, > > - {"bmapbt", libxfs_bmbt_maxrecs}, > > - {"refcountbt", refc_maxrecs}, > > - {"rmapbt", rmap_maxrecs}, > > + {"bnobt", libxfs_allocbt_maxrecs, disk_blocksize}, > > + {"cntbt", libxfs_allocbt_maxrecs, disk_blocksize}, > > + {"inobt", libxfs_inobt_maxrecs, disk_blocksize}, > > + {"finobt", libxfs_inobt_maxrecs, disk_blocksize}, > > + {"bmapbt", libxfs_bmbt_maxrecs, disk_blocksize}, > > + {"refcountbt", refc_maxrecs, disk_blocksize}, > > + {"rmapbt", rmap_maxrecs, disk_blocksize}, > > + {"iext", iext_maxrecs, iext_blocksize}, > > }; > > > > static void > > @@ -108,7 +127,7 @@ calc_height( > > static int > > construct_records_per_block( > > char *tag, > > - int blocksize, > > + int *blocksize, > > unsigned int *records_per_block) > > { > > char *toktag; > > @@ -119,8 +138,10 @@ construct_records_per_block( > > > > for (i = 0, m = maps; i < ARRAY_SIZE(maps); i++, m++) { > > if (!strcmp(m->tag, tag)) { > > - records_per_block[0] = m->maxrecs(mp, blocksize, 1); > > - records_per_block[1] = m->maxrecs(mp, blocksize, 0); > > + if (*blocksize < 0) > > + *blocksize = m->default_blocksize(mp); > > + records_per_block[0] = m->maxrecs(mp, *blocksize, 1); > > + records_per_block[1] = m->maxrecs(mp, *blocksize, 0); > > return 0; > > } > > } > > @@ -178,38 +199,50 @@ construct_records_per_block( > > fprintf(stderr, _("%s: header type not found.\n"), tag); > > goto out; > > } > > - if (!strcmp(p, "short")) > > + if (!strcmp(p, "short")) { > > + if (*blocksize < 0) > > + *blocksize = mp->m_sb.sb_blocksize; > > blocksize -= XFS_BTREE_SBLOCK_LEN; > > - else if (!strcmp(p, "shortcrc")) > > + } else if (!strcmp(p, "shortcrc")) { > > + if (*blocksize < 0) > > + *blocksize = mp->m_sb.sb_blocksize; > > blocksize -= XFS_BTREE_SBLOCK_CRC_LEN; > > - else if (!strcmp(p, "long")) > > + } else if (!strcmp(p, "long")) { > > + if (*blocksize < 0) > > + *blocksize = mp->m_sb.sb_blocksize; > > blocksize -= XFS_BTREE_LBLOCK_LEN; > > - else if (!strcmp(p, "longcrc")) > > + } else if (!strcmp(p, "longcrc")) { > > + if (*blocksize < 0) > > + *blocksize = mp->m_sb.sb_blocksize; > > blocksize -= XFS_BTREE_LBLOCK_CRC_LEN; > > - else { > > + } else if (!strcmp(p, "iext")) { > > + if (*blocksize < 0) > > + *blocksize = 256; > > + blocksize -= 2 * sizeof(void *); > > + } else { > > fprintf(stderr, _("%s: unrecognized btree header type."), > > p); > > goto out; > > } > > > > - if (record_size > blocksize) { > > + if (record_size > *blocksize) { > > fprintf(stderr, > > _("%s: record size must be less than %u bytes.\n"), > > - tag, blocksize); > > + tag, *blocksize); > > goto out; > > } > > > > - if (key_size > blocksize) { > > + if (key_size > *blocksize) { > > fprintf(stderr, > > _("%s: key size must be less than %u bytes.\n"), > > - tag, blocksize); > > + tag, *blocksize); > > goto out; > > } > > > > - if (ptr_size > blocksize) { > > + if (ptr_size > *blocksize) { > > fprintf(stderr, > > _("%s: pointer size must be less than %u bytes.\n"), > > - tag, blocksize); > > + tag, *blocksize); > > goto out; > > } > > > > @@ -221,8 +254,8 @@ construct_records_per_block( > > goto out; > > } > > > > - records_per_block[0] = blocksize / record_size; > > - records_per_block[1] = blocksize / (key_size + ptr_size); > > + records_per_block[0] = *blocksize / record_size; > > + records_per_block[1] = *blocksize / (key_size + ptr_size); > > ret = 0; > > out: > > free(toktag); > > @@ -238,12 +271,12 @@ report( > > char *tag, > > unsigned int report_what, > > unsigned long long nr_records, > > - unsigned int blocksize) > > + int blocksize) > > { > > unsigned int records_per_block[2]; > > int ret; > > > > - ret = construct_records_per_block(tag, blocksize, records_per_block); > > + ret = construct_records_per_block(tag, &blocksize, records_per_block); > > if (ret) > > return; > > > > @@ -302,7 +335,7 @@ btheight_f( > > int argc, > > char **argv) > > { > > - long long blocksize = mp->m_sb.sb_blocksize; > > + long long blocksize = -1; > > uint64_t nr_records = 0; > > int report_what = REPORT_DEFAULT; > > int i, c; > > @@ -355,7 +388,7 @@ _("The largest block size this command will consider is %u bytes.\n"), > > return 0; > > } > > > > - if (blocksize < 128) { > > + if (blocksize >= 0 && blocksize < 128) { > > fprintf(stderr, > > _("The smallest block size this command will consider is 128 bytes.\n")); > > return 0; > > > > -- > Carlos >
On Wed, Sep 25, 2019 at 02:40:59PM -0700, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@oracle.com> > > (Ab)use the btheight command to calculate the geometry of the incore > extent tree. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- > db/btheight.c | 87 +++++++++++++++++++++++++++++++++++++++------------------ > 1 file changed, 60 insertions(+), 27 deletions(-) > > > diff --git a/db/btheight.c b/db/btheight.c > index e2c9759f..be604ebc 100644 > --- a/db/btheight.c > +++ b/db/btheight.c > @@ -22,18 +22,37 @@ static int rmap_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > return libxfs_rmapbt_maxrecs(blocklen, leaf); > } > > +static int iext_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > +{ > + blocklen -= 2 * sizeof(void *); > + > + return blocklen / sizeof(struct xfs_bmbt_rec); > +} This isn't correct for the iext nodes. They hold 16 key/ptr pairs, not 15. I suspect you should be lifting the iext btree format definitions like this one: enum { NODE_SIZE = 256, KEYS_PER_NODE = NODE_SIZE / (sizeof(uint64_t) + sizeof(void *)), RECS_PER_LEAF = (NODE_SIZE - (2 * sizeof(struct xfs_iext_leaf *))) / sizeof(struct xfs_iext_rec), }; from libxfs/xfs_iext_tree.c to a libxfs header file and then using KEYS_PER_NODE and RECS_PER_LEAF here. See the patch below, lifted from a varaint of my range locking prototypes... However, these are not on-disk values and so are subject to change, hence it may be that a warning might be needed when xfs_db is used to calculate the height of this tree. > +static int disk_blocksize(struct xfs_mount *mp) > +{ > + return mp->m_sb.sb_blocksize; > +} > + > +static int iext_blocksize(struct xfs_mount *mp) > +{ > + return 256; > +} NODE_SIZE.... Cheers, Dave.
On Fri, Sep 27, 2019 at 07:41:02AM +1000, Dave Chinner wrote: > On Wed, Sep 25, 2019 at 02:40:59PM -0700, Darrick J. Wong wrote: > > From: Darrick J. Wong <darrick.wong@oracle.com> > > > > (Ab)use the btheight command to calculate the geometry of the incore > > extent tree. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > --- > > db/btheight.c | 87 +++++++++++++++++++++++++++++++++++++++------------------ > > 1 file changed, 60 insertions(+), 27 deletions(-) > > > > > > diff --git a/db/btheight.c b/db/btheight.c > > index e2c9759f..be604ebc 100644 > > --- a/db/btheight.c > > +++ b/db/btheight.c > > @@ -22,18 +22,37 @@ static int rmap_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > > return libxfs_rmapbt_maxrecs(blocklen, leaf); > > } > > > > +static int iext_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > > +{ > > + blocklen -= 2 * sizeof(void *); > > + > > + return blocklen / sizeof(struct xfs_bmbt_rec); > > +} > > This isn't correct for the iext nodes. They hold 16 key/ptr pairs, > not 15. > > I suspect you should be lifting the iext btree format definitions > like this one: > > enum { > NODE_SIZE = 256, > KEYS_PER_NODE = NODE_SIZE / (sizeof(uint64_t) + sizeof(void *)), > RECS_PER_LEAF = (NODE_SIZE - (2 * sizeof(struct xfs_iext_leaf *))) / > sizeof(struct xfs_iext_rec), > }; > > from libxfs/xfs_iext_tree.c to a libxfs header file and then using > KEYS_PER_NODE and RECS_PER_LEAF here. See the patch below, lifted > from a varaint of my range locking prototypes... > > However, these are not on-disk values and so are subject to change, > hence it may be that a warning might be needed when xfs_db is used > to calculate the height of this tree. Er... I don't mind lifting the iext values, but I don't see a patch? --D > > +static int disk_blocksize(struct xfs_mount *mp) > > +{ > > + return mp->m_sb.sb_blocksize; > > +} > > + > > +static int iext_blocksize(struct xfs_mount *mp) > > +{ > > + return 256; > > +} > > NODE_SIZE.... > > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com
On Thu, Sep 26, 2019 at 07:58:57PM -0700, Darrick J. Wong wrote: > On Fri, Sep 27, 2019 at 07:41:02AM +1000, Dave Chinner wrote: > > On Wed, Sep 25, 2019 at 02:40:59PM -0700, Darrick J. Wong wrote: > > > From: Darrick J. Wong <darrick.wong@oracle.com> > > > > > > (Ab)use the btheight command to calculate the geometry of the incore > > > extent tree. > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > --- > > > db/btheight.c | 87 +++++++++++++++++++++++++++++++++++++++------------------ > > > 1 file changed, 60 insertions(+), 27 deletions(-) > > > > > > > > > diff --git a/db/btheight.c b/db/btheight.c > > > index e2c9759f..be604ebc 100644 > > > --- a/db/btheight.c > > > +++ b/db/btheight.c > > > @@ -22,18 +22,37 @@ static int rmap_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > > > return libxfs_rmapbt_maxrecs(blocklen, leaf); > > > } > > > > > > +static int iext_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > > > +{ > > > + blocklen -= 2 * sizeof(void *); > > > + > > > + return blocklen / sizeof(struct xfs_bmbt_rec); > > > +} > > > > This isn't correct for the iext nodes. They hold 16 key/ptr pairs, > > not 15. > > > > I suspect you should be lifting the iext btree format definitions > > like this one: > > > > enum { > > NODE_SIZE = 256, > > KEYS_PER_NODE = NODE_SIZE / (sizeof(uint64_t) + sizeof(void *)), > > RECS_PER_LEAF = (NODE_SIZE - (2 * sizeof(struct xfs_iext_leaf *))) / > > sizeof(struct xfs_iext_rec), > > }; > > > > from libxfs/xfs_iext_tree.c to a libxfs header file and then using > > KEYS_PER_NODE and RECS_PER_LEAF here. See the patch below, lifted > > from a varaint of my range locking prototypes... > > > > However, these are not on-disk values and so are subject to change, > > hence it may be that a warning might be needed when xfs_db is used > > to calculate the height of this tree. > > Er... I don't mind lifting the iext values, but I don't see a patch? Ah, sorry, I realised it wouldn't apply at all - there's several precursor patches that move stuff about (reworking the xfs_ifork structure) and it didn't lift the enum (but could have) and so I didn't attach it. Of course, I then forgot to edit email... I'll attach it anyway... Cheers, Dave.
On Fri, Sep 27, 2019 at 07:41:02AM +1000, Dave Chinner wrote: > > +static int iext_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > > +{ > > + blocklen -= 2 * sizeof(void *); > > + > > + return blocklen / sizeof(struct xfs_bmbt_rec); > > +} > > This isn't correct for the iext nodes. They hold 16 key/ptr pairs, > not 15. > > I suspect you should be lifting the iext btree format definitions > like this one: Is the command supposed to deal with the on-disk or in-memory nodes? The ones your quote are the in-memory btrees, but the file seems (the way I read it, the documentation seems to be lacking) with the on-disk btrees.
On Mon, Sep 30, 2019 at 12:58:54AM -0700, Christoph Hellwig wrote: > On Fri, Sep 27, 2019 at 07:41:02AM +1000, Dave Chinner wrote: > > > +static int iext_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) > > > +{ > > > + blocklen -= 2 * sizeof(void *); > > > + > > > + return blocklen / sizeof(struct xfs_bmbt_rec); > > > +} > > > > This isn't correct for the iext nodes. They hold 16 key/ptr pairs, > > not 15. > > > > I suspect you should be lifting the iext btree format definitions > > like this one: > > Is the command supposed to deal with the on-disk or in-memory nodes? > The ones your quote are the in-memory btrees, but the file seems > (the way I read it, the documentation seems to be lacking) with the > on-disk btrees. It started as a command for calculating ondisk btree geometry but then we were discussing the iext tree geometry on irc so I extended it to handle that too. (Ugh, where /did/ the documentation go...) --D
On Mon, Sep 30, 2019 at 09:11:52AM -0700, Darrick J. Wong wrote: > > Is the command supposed to deal with the on-disk or in-memory nodes? > > The ones your quote are the in-memory btrees, but the file seems > > (the way I read it, the documentation seems to be lacking) with the > > on-disk btrees. > > It started as a command for calculating ondisk btree geometry but then > we were discussing the iext tree geometry on irc so I extended it to > handle that too. I think mixing the on-disk trees an an in-memory structure in the same command is a really bad idea. In fact I'm not sure what use the calculation for the iext tree is. It is an implementation detail that can (and did) change from release to release, unlike the other trees that not going to change without an on-disk format change.
diff --git a/db/btheight.c b/db/btheight.c index e2c9759f..be604ebc 100644 --- a/db/btheight.c +++ b/db/btheight.c @@ -22,18 +22,37 @@ static int rmap_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) return libxfs_rmapbt_maxrecs(blocklen, leaf); } +static int iext_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) +{ + blocklen -= 2 * sizeof(void *); + + return blocklen / sizeof(struct xfs_bmbt_rec); +} + +static int disk_blocksize(struct xfs_mount *mp) +{ + return mp->m_sb.sb_blocksize; +} + +static int iext_blocksize(struct xfs_mount *mp) +{ + return 256; +} + struct btmap { const char *tag; int (*maxrecs)(struct xfs_mount *mp, int blocklen, int leaf); + int (*default_blocksize)(struct xfs_mount *mp); } maps[] = { - {"bnobt", libxfs_allocbt_maxrecs}, - {"cntbt", libxfs_allocbt_maxrecs}, - {"inobt", libxfs_inobt_maxrecs}, - {"finobt", libxfs_inobt_maxrecs}, - {"bmapbt", libxfs_bmbt_maxrecs}, - {"refcountbt", refc_maxrecs}, - {"rmapbt", rmap_maxrecs}, + {"bnobt", libxfs_allocbt_maxrecs, disk_blocksize}, + {"cntbt", libxfs_allocbt_maxrecs, disk_blocksize}, + {"inobt", libxfs_inobt_maxrecs, disk_blocksize}, + {"finobt", libxfs_inobt_maxrecs, disk_blocksize}, + {"bmapbt", libxfs_bmbt_maxrecs, disk_blocksize}, + {"refcountbt", refc_maxrecs, disk_blocksize}, + {"rmapbt", rmap_maxrecs, disk_blocksize}, + {"iext", iext_maxrecs, iext_blocksize}, }; static void @@ -108,7 +127,7 @@ calc_height( static int construct_records_per_block( char *tag, - int blocksize, + int *blocksize, unsigned int *records_per_block) { char *toktag; @@ -119,8 +138,10 @@ construct_records_per_block( for (i = 0, m = maps; i < ARRAY_SIZE(maps); i++, m++) { if (!strcmp(m->tag, tag)) { - records_per_block[0] = m->maxrecs(mp, blocksize, 1); - records_per_block[1] = m->maxrecs(mp, blocksize, 0); + if (*blocksize < 0) + *blocksize = m->default_blocksize(mp); + records_per_block[0] = m->maxrecs(mp, *blocksize, 1); + records_per_block[1] = m->maxrecs(mp, *blocksize, 0); return 0; } } @@ -178,38 +199,50 @@ construct_records_per_block( fprintf(stderr, _("%s: header type not found.\n"), tag); goto out; } - if (!strcmp(p, "short")) + if (!strcmp(p, "short")) { + if (*blocksize < 0) + *blocksize = mp->m_sb.sb_blocksize; blocksize -= XFS_BTREE_SBLOCK_LEN; - else if (!strcmp(p, "shortcrc")) + } else if (!strcmp(p, "shortcrc")) { + if (*blocksize < 0) + *blocksize = mp->m_sb.sb_blocksize; blocksize -= XFS_BTREE_SBLOCK_CRC_LEN; - else if (!strcmp(p, "long")) + } else if (!strcmp(p, "long")) { + if (*blocksize < 0) + *blocksize = mp->m_sb.sb_blocksize; blocksize -= XFS_BTREE_LBLOCK_LEN; - else if (!strcmp(p, "longcrc")) + } else if (!strcmp(p, "longcrc")) { + if (*blocksize < 0) + *blocksize = mp->m_sb.sb_blocksize; blocksize -= XFS_BTREE_LBLOCK_CRC_LEN; - else { + } else if (!strcmp(p, "iext")) { + if (*blocksize < 0) + *blocksize = 256; + blocksize -= 2 * sizeof(void *); + } else { fprintf(stderr, _("%s: unrecognized btree header type."), p); goto out; } - if (record_size > blocksize) { + if (record_size > *blocksize) { fprintf(stderr, _("%s: record size must be less than %u bytes.\n"), - tag, blocksize); + tag, *blocksize); goto out; } - if (key_size > blocksize) { + if (key_size > *blocksize) { fprintf(stderr, _("%s: key size must be less than %u bytes.\n"), - tag, blocksize); + tag, *blocksize); goto out; } - if (ptr_size > blocksize) { + if (ptr_size > *blocksize) { fprintf(stderr, _("%s: pointer size must be less than %u bytes.\n"), - tag, blocksize); + tag, *blocksize); goto out; } @@ -221,8 +254,8 @@ construct_records_per_block( goto out; } - records_per_block[0] = blocksize / record_size; - records_per_block[1] = blocksize / (key_size + ptr_size); + records_per_block[0] = *blocksize / record_size; + records_per_block[1] = *blocksize / (key_size + ptr_size); ret = 0; out: free(toktag); @@ -238,12 +271,12 @@ report( char *tag, unsigned int report_what, unsigned long long nr_records, - unsigned int blocksize) + int blocksize) { unsigned int records_per_block[2]; int ret; - ret = construct_records_per_block(tag, blocksize, records_per_block); + ret = construct_records_per_block(tag, &blocksize, records_per_block); if (ret) return; @@ -302,7 +335,7 @@ btheight_f( int argc, char **argv) { - long long blocksize = mp->m_sb.sb_blocksize; + long long blocksize = -1; uint64_t nr_records = 0; int report_what = REPORT_DEFAULT; int i, c; @@ -355,7 +388,7 @@ _("The largest block size this command will consider is %u bytes.\n"), return 0; } - if (blocksize < 128) { + if (blocksize >= 0 && blocksize < 128) { fprintf(stderr, _("The smallest block size this command will consider is 128 bytes.\n")); return 0;