xref: /csrg-svn/sys/ufs/lfs/lfs_balloc.c (revision 51561)
123396Smckusick /*
251494Sbostic  * Copyright (c) 1989, 1991 Regents of the University of California.
337736Smckusick  * All rights reserved.
423396Smckusick  *
544537Sbostic  * %sccs.include.redist.c%
637736Smckusick  *
7*51561Smckusick  *	@(#)lfs_balloc.c	7.20 (Berkeley) 11/05/91
823396Smckusick  */
97443Sroot 
1051486Sbostic #include <sys/param.h>
1151486Sbostic #include <sys/buf.h>
1251486Sbostic #include <sys/proc.h>
1351486Sbostic #include <sys/vnode.h>
1451486Sbostic #include <sys/mount.h>
1551486Sbostic #include <sys/resourcevar.h>
1651486Sbostic #include <sys/specdev.h>
1751486Sbostic #include <sys/trace.h>
187443Sroot 
1951494Sbostic #include <ufs/ufs/quota.h>
2051494Sbostic #include <ufs/ufs/inode.h>
2151494Sbostic #include <ufs/ufs/ufsmount.h>
2247571Skarels 
2351494Sbostic #include <ufs/lfs/lfs.h>
2451494Sbostic #include <ufs/lfs/lfs_extern.h>
2551486Sbostic 
267443Sroot /*
2751486Sbostic  * Bmap converts a the logical block number of a file to its physical block
2851486Sbostic  * number on the disk. The conversion is done by using the logical block
2951486Sbostic  * number to index into the array of block pointers described by the dinode.
307443Sroot  */
3151348Sroot int
32*51561Smckusick lfs_bmap(vp, bn, vpp, bnp)
33*51561Smckusick 	struct vnode *vp;
3437736Smckusick 	register daddr_t bn;
35*51561Smckusick 	struct vnode **vpp;
36*51561Smckusick 	daddr_t *bnp;
377443Sroot {
38*51561Smckusick 	register struct inode *ip;
3951494Sbostic 	register struct lfs *fs;
4037736Smckusick 	register daddr_t nb;
41*51561Smckusick 	struct vnode *devvp;
4237736Smckusick 	struct buf *bp;
4351183Sbostic 	daddr_t *bap, daddr;
4451183Sbostic 	daddr_t lbn_ind;
4551348Sroot 	int j, off, sh;
4637736Smckusick 	int error;
4737736Smckusick 
48*51561Smckusick 	/*
49*51561Smckusick 	 * Check for underlying vnode requests and ensure that logical
50*51561Smckusick 	 * to physical mapping is requested.
51*51561Smckusick 	 */
52*51561Smckusick 	ip = VTOI(vp);
53*51561Smckusick 	if (vpp != NULL)
54*51561Smckusick 		*vpp = ip->i_devvp;
55*51561Smckusick 	if (bnp == NULL)
56*51561Smckusick 		return (0);
5751155Sbostic printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number);
5851486Sbostic 	fs = ip->i_lfs;
5937736Smckusick 
6037736Smckusick 	/*
6151486Sbostic 	 * We access all blocks in the cache, even indirect blocks by means
6251486Sbostic 	 * of a logical address. Indirect blocks (single, double, triple) all
6351486Sbostic 	 * have negative block numbers. The first NDADDR blocks are direct
6451486Sbostic 	 * blocks, the first NIADDR negative blocks are the indirect block
6551486Sbostic 	 * pointers.  The single, double and triple indirect blocks in the
6651486Sbostic 	 * inode * are addressed: -1, -2 and -3 respectively.
6751486Sbostic 	 *
6851486Sbostic 	 * XXX
6951486Sbostic 	 * We don't handle triple indirect at all.
7051486Sbostic 	 *
7151486Sbostic 	 * XXX
7251486Sbostic 	 * This panic shouldn't be here???
7351183Sbostic 	 */
7451486Sbostic 	if (bn < 0)
7551486Sbostic 		panic("lfs_bmap: negative indirect block number %d", bn);
7651183Sbostic 
7751486Sbostic 	/* The first NDADDR blocks are direct blocks. */
7837736Smckusick 	if (bn < NDADDR) {
7937736Smckusick 		nb = ip->i_db[bn];
8037736Smckusick 		if (nb == 0) {
8151348Sroot 			*bnp = UNASSIGNED;
8237736Smckusick 			return (0);
8337736Smckusick 		}
8451155Sbostic 		*bnp = nb;
8537736Smckusick 		return (0);
8637736Smckusick 	}
8751486Sbostic 
8851486Sbostic 	/* Determine the number of levels of indirection. */
8937736Smckusick 	sh = 1;
9037736Smckusick 	bn -= NDADDR;
9151183Sbostic 	lbn_ind = 0;
9237736Smckusick 	for (j = NIADDR; j > 0; j--) {
9351183Sbostic 		lbn_ind--;
9437736Smckusick 		sh *= NINDIR(fs);
9537736Smckusick 		if (bn < sh)
9637736Smckusick 			break;
9737736Smckusick 		bn -= sh;
9837736Smckusick 	}
9937736Smckusick 	if (j == 0)
10037736Smckusick 		return (EFBIG);
10151183Sbostic 
10251486Sbostic 	/* Fetch through the indirect blocks. */
10351183Sbostic 	vp = ITOV(ip);
10451183Sbostic 	devvp = VFSTOUFS(vp->v_mount)->um_devvp;
10551183Sbostic 	for (off = NIADDR - j, bap = ip->i_ib; j <= NIADDR; j++) {
10651183Sbostic 		if((daddr = bap[off]) == 0) {
10751348Sroot 			daddr = UNASSIGNED;
10851183Sbostic 			break;
10951183Sbostic 		}
11051183Sbostic 		if (bp)
11137736Smckusick 			brelse(bp);
11251183Sbostic 		bp = getblk(vp, lbn_ind, fs->lfs_bsize);
11351183Sbostic 		if (bp->b_flags & (B_DONE | B_DELWRI)) {
11451183Sbostic 			trace(TR_BREADHIT, pack(vp, size), lbn_ind);
11551183Sbostic 		} else {
11651183Sbostic 			trace(TR_BREADMISS, pack(vp, size), lbn_ind);
11751183Sbostic 			bp->b_blkno = daddr;
11851183Sbostic 			bp->b_flags |= B_READ;
11951183Sbostic 			bp->b_dev = devvp->v_rdev;
12051215Sbostic 			(devvp->v_op->vop_strategy)(bp);
12151183Sbostic 			curproc->p_stats->p_ru.ru_inblock++;	/* XXX */
12251183Sbostic 			if (error = biowait(bp)) {
12351183Sbostic 				brelse(bp);
12451183Sbostic 				return (error);
12551183Sbostic 			}
12637736Smckusick 		}
12737736Smckusick 		bap = bp->b_un.b_daddr;
12837736Smckusick 		sh /= NINDIR(fs);
12951183Sbostic 		off = (bn / sh) % NINDIR(fs);
13051183Sbostic 		lbn_ind  = -(NIADDR + 1 + off);
13151183Sbostic 	}
13251183Sbostic 	if (bp)
13339679Smckusick 		brelse(bp);
13451183Sbostic 
13551183Sbostic 	*bnp = daddr;
13637736Smckusick 	return (0);
13737736Smckusick }
138