FreeBSD/sys/fs/ext2fs/ext2_bmap.c
/*
 * Create an array of logical block number/offset pairs which represent the
 * path of indirect blocks required to access a data block.  The first "pair"
 * contains the logical block number of the appropriate single, double or
 * triple indirect block and the offset into the inode indirect block array.
 * Note, the logical block number of the inode single/double/triple indirect
 * block appears twice in the array, once with the offset into the i_ib and
 * once with the offset into the page itself.
 */
Create an array of logical block number/offset pairs which represent the
path of indirect blocks required to access a data block.  The first "pair"
contains the logical block number of the appropriate single, double or
triple indirect block and the offset into the inode indirect block array.
Note, the logical block number of the inode single/double/triple indirect
block appears twice in the array, once with the offset into the i_ib and
once with the offset into the page itself.
Create an array of logical block number / offset pairs which represent the path of indirect blocks required to access a data block . The first " pair " contains the logical block number of the appropriate single double or triple indirect block and the offset into the inode indirect block array . Note the logical block number of the inode single / double / triple indirect block appears twice in the array once with the offset into the i_ib and once with the offset into the page itself .
int
ext2_getlbns(struct vnode *vp, daddr_t bn, struct indir *ap, int *nump)
{
	long blockcnt;
	e2fs_lbn_t metalbn, realbn;
	struct ext2mount *ump;
	int i, numlevels, off;
	int64_t qblockcnt;
	ump = VFSTOEXT2(vp->v_mount);
	if (nump)
		*nump = 0;
	numlevels = 0;
	realbn = bn;
	if ((long)bn < 0)
		bn = -(long)bn;
	if (bn < NDADDR)
		return (0);
	for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) {
		if (i == 0)
			return (EFBIG);
		qblockcnt = (int64_t)blockcnt * MNINDIR(ump);
		if (bn < qblockcnt)
			break;
		blockcnt = qblockcnt;
	}
	if (realbn >= 0)
		metalbn = -(realbn - bn + NIADDR - i);
	else
		metalbn = -(-realbn - bn + NIADDR - i);
	ap->in_lbn = metalbn;
	ap->in_off = off = NIADDR - i;
	ap++;
	for (++numlevels; i <= NIADDR; i++) {
		if (metalbn == realbn)
			break;
		off = (bn / blockcnt) % MNINDIR(ump);
		++numlevels;
		ap->in_lbn = metalbn;
		ap->in_off = off;
		++ap;
		metalbn -= -1 + off * blockcnt;
		blockcnt /= MNINDIR(ump);
	}
	if (nump)
		*nump = numlevels;
	return (0);
}
int ext2_getlbns ( struct vnode * vp , daddr_t bn , struct indir * ap , int * nump ) { long blockcnt ; e2fs_lbn_t metalbn , realbn ; struct ext2mount * ump ; int i , numlevels , off ; int64_t qblockcnt ; ump = VFSTOEXT2 ( vp -> v_mount ) ; if ( nump ) * nump = 0 ; numlevels = 0 ; realbn = bn ; if ( ( long ) bn < 0 ) bn = - ( long ) bn ; if ( bn < NDADDR ) return ( 0 ) ; for ( blockcnt = 1 , i = NIADDR , bn -= NDADDR ; ; i -- , bn -= blockcnt ) { if ( i == 0 ) return ( EFBIG ) ; qblockcnt = ( int64_t ) blockcnt * MNINDIR ( ump ) ; if ( bn < qblockcnt ) break ; blockcnt = qblockcnt ; } if ( realbn >= 0 ) metalbn = - ( realbn - bn + NIADDR - i ) ; else metalbn = - ( - realbn - bn + NIADDR - i ) ; ap -> in_lbn = metalbn ; ap -> in_off = off = NIADDR - i ; ap ++ ; for ( ++ numlevels ; i <= NIADDR ; i ++ ) { if ( metalbn == realbn ) break ; off = ( bn / blockcnt ) % MNINDIR ( ump ) ; ++ numlevels ; ap -> in_lbn = metalbn ; ap -> in_off = off ; ++ ap ; metalbn -= -1 + off * blockcnt ; blockcnt /= MNINDIR ( ump ) ; } if ( nump ) * nump = numlevels ; return ( 0 ) ; }
Create an array of logical block number/offset pairs which represent the
 path of indirect blocks required to access a data block.
Create an array of logical block number / offset pairs which represent the path of indirect blocks required to access a data block .
/* The first NDADDR blocks are direct blocks. */ /*
	 * Determine the number of levels of indirection.  After this loop
	 * is done, blockcnt indicates the number of data blocks possible
	 * at the previous level of indirection, and NIADDR - i is the number
	 * of levels of indirection needed to locate the requested block.
	 */ /*
		 * Use int64_t's here to avoid overflow for triple indirect
		 * blocks when longs have 32 bits and the block size is more
		 * than 4K.
		 */ /* Calculate the address of the first meta-block. */ /*
	 * At each iteration, off is the offset into the bap array which is
	 * an array of disk addresses at the current level of indirection.
	 * The logical block number and the offset in that block are stored
	 * into the argument array.
	 */ /* If searching for a meta-data block, quit when found. */