-/*
- * Bmap converts a the logical block number of a file
- * to its physical block number on the disk. The conversion
- * is done by using the logical block number to index into
- * the array of block pointers described by the dinode.
- */
-int
-ffs_bmap(vp, bn, vpp, bnp)
- struct vnode *vp;
- register daddr_t bn;
- struct vnode **vpp;
- daddr_t *bnp;
-{
- register struct inode *ip;
- register struct fs *fs;
- register daddr_t nb;
- struct buf *bp;
- daddr_t *bap;
- int i, j, sh;
- int error;
-
- /*
- * Check for underlying vnode requests and ensure that logical
- * to physical mapping is requested.
- */
- ip = VTOI(vp);
- if (vpp != NULL)
- *vpp = ip->i_devvp;
- if (bnp == NULL)
- return (0);
- if (bn < 0)
- return (EFBIG);
- fs = ip->i_fs;
-
- /*
- * The first NDADDR blocks are direct blocks
- */
- if (bn < NDADDR) {
- nb = ip->i_db[bn];
- if (nb == 0) {
- *bnp = (daddr_t)-1;
- return (0);
- }
- *bnp = fsbtodb(fs, nb);
- return (0);
- }
- /*
- * Determine the number of levels of indirection.
- */
- sh = 1;
- bn -= NDADDR;
- for (j = NIADDR; j > 0; j--) {
- sh *= NINDIR(fs);
- if (bn < sh)
- break;
- bn -= sh;
- }
- if (j == 0)
- return (EFBIG);
- /*
- * Fetch through the indirect blocks.
- */
- nb = ip->i_ib[NIADDR - j];
- if (nb == 0) {
- *bnp = (daddr_t)-1;
- return (0);
- }
- for (; j <= NIADDR; j++) {
- if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
- (int)fs->fs_bsize, NOCRED, &bp)) {
- brelse(bp);
- return (error);
- }
- bap = bp->b_un.b_daddr;
- sh /= NINDIR(fs);
- i = (bn / sh) % NINDIR(fs);
- nb = bap[i];
- if (nb == 0) {
- *bnp = (daddr_t)-1;
- brelse(bp);
- return (0);
- }
- brelse(bp);
- }
- *bnp = fsbtodb(fs, nb);
- return (0);
-}
-