Ext2 vs UFS getlbns

Bruce Evans bde at zeta.org.au
Fri Jun 11 18:14:49 GMT 2004


On Fri, 11 Jun 2004, Brian Bergstrand wrote:

> I just noticed something in ext2_getlbns() (ext2_bmap.c, v1.57) vs.
> ufs_getlbns() (ufs_bmap.c, v1.60)
>
> In the last loop to setup the indir array,
>
> UFS does:
>
> {
> ...
> blockcnt /= MNINDIR(ump);
> off = (bn / blockcnt) % MNINDIR(ump);
>
> ++numlevels;
> ap->in_lbn = metalbn;
> ap->in_off = off;
> ap->in_exists = 0;
> ++ap;
>
> metalbn -= -1 + off * blockcnt;
> }
>
> While Ext2 does:
>
> {
> ...
> off = (bn / blockcnt) % MNINDIR(ump);
>
> ++numlevels;
> ap->in_lbn = metalbn;
> ap->in_off = off;
> ap->in_exists = 0;
> ++ap;
>
> metalbn -= -1 + off * blockcnt;
> blockcnt /= MNINDIR(ump);
> }
>
> Notice that blockcnt is changed AFTER offset/metalbn in Ext2 and BEFORE
> those in UFS.
>
> Was this change in Ext2 done on purpose for some reason? It makes a
> difference in calculating in_off and metalbn for some block #'s.

This is to fix overflow in the calculation of block numbers for triple
indirect blocks.  ffs used to do this, and ext2_getlbns() was a copy
ufs_getlbns(), but ffs was changed back to use simpler code when its
daddr type (ufs2_daddr_t) was changed to 64 bits and the longs in
ufs_getlbns() were fixed to use ufs_daddr_t.  Overflow is probably
theoretically possible again, but it would take a 128-bit calculation
to avoid it and 64 bit block numbers should be enough for anyone.

This difference shouldn't affect in_off or metalbn for any reachable
block number (32 bit ones in ext2fs).  There is another variable
"int64_t qblockcnt" that is used instead of "long blockcnt" in
some places in ext2_getlbns().  The logic for using blockcnt in the
above is a little different because earlier calculations set
qblockcnt instead of qblockcnt.

Bruce


More information about the freebsd-fs mailing list