xref: /csrg-svn/sys/ufs/lfs/lfs_balloc.c (revision 51183)
123396Smckusick /*
237736Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
337736Smckusick  * All rights reserved.
423396Smckusick  *
544537Sbostic  * %sccs.include.redist.c%
637736Smckusick  *
7*51183Sbostic  *	@(#)lfs_balloc.c	7.15 (Berkeley) 09/25/91
823396Smckusick  */
97443Sroot 
1017099Sbloom #include "param.h"
1117099Sbloom #include "systm.h"
1217099Sbloom #include "buf.h"
13*51183Sbostic #include "time.h"
14*51183Sbostic #include "resource.h"
15*51183Sbostic #include "resourcevar.h"
1617099Sbloom #include "proc.h"
1737736Smckusick #include "file.h"
1837736Smckusick #include "vnode.h"
19*51183Sbostic #include "mount.h"
20*51183Sbostic #include "specdev.h"
217443Sroot 
2251155Sbostic #include "../ufs/quota.h"
2351155Sbostic #include "../ufs/inode.h"
24*51183Sbostic #include "../ufs/ufsmount.h"
25*51183Sbostic #include "trace.h"
2651155Sbostic #include "lfs.h"
2751155Sbostic #include "lfs_extern.h"
2847571Skarels 
297443Sroot /*
3049450Smckusick  * Bmap converts a the logical block number of a file
3149450Smckusick  * to its physical block number on the disk. The conversion
3249450Smckusick  * is done by using the logical block number to index into
3349450Smckusick  * the array of block pointers described by the dinode.
347443Sroot  */
3551155Sbostic lfs_bmap(ip, bn, bnp)
367443Sroot 	register struct inode *ip;
3737736Smckusick 	register daddr_t bn;
3837736Smckusick 	daddr_t	*bnp;
397443Sroot {
4051155Sbostic 	register LFS *fs;					/* LFS */
4137736Smckusick 	register daddr_t nb;
42*51183Sbostic 	struct vnode *devvp, *vp;
4337736Smckusick 	struct buf *bp;
44*51183Sbostic 	daddr_t *bap, daddr;
45*51183Sbostic 	daddr_t lbn_ind;
46*51183Sbostic 	int i, j, off, sh;
4737736Smckusick 	int error;
4837736Smckusick 
4951155Sbostic printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number);
5051155Sbostic 	fs = ip->i_lfs;						/* LFS */
5137736Smckusick 
5237736Smckusick 	/*
53*51183Sbostic 	 * We access all blocks in the cache, even indirect blocks by means of
54*51183Sbostic 	 * a logical address. Indirect blocks (single, double, triple) all have
55*51183Sbostic 	 * negative block numbers. The first NDADDR blocks are direct blocks,
56*51183Sbostic 	 * the first NIADDR negative blocks are the indirect block pointers.
57*51183Sbostic 	 * The single, double and triple indirect blocks in the inode
58*51183Sbostic 	 * are addressed: -1, -2 and -3 respectively.
59*51183Sbostic 	 * XXX we don't handle triple indirect at all.
60*51183Sbostic 	 */
61*51183Sbostic 	if (bn < 0) {
62*51183Sbostic 		/* Shouldn't be here -- we don't think */
63*51183Sbostic 		printf("lfs_bmap: NEGATIVE indirect block number %d\n", bn);
64*51183Sbostic 		panic("negative indirect block number");
65*51183Sbostic 	}
66*51183Sbostic 
67*51183Sbostic 	/*
6837736Smckusick 	 * The first NDADDR blocks are direct blocks
6937736Smckusick 	 */
7037736Smckusick 	if (bn < NDADDR) {
7137736Smckusick 		nb = ip->i_db[bn];
7237736Smckusick 		if (nb == 0) {
7337736Smckusick 			*bnp = (daddr_t)-1;
7437736Smckusick 			return (0);
7537736Smckusick 		}
7651155Sbostic 		*bnp = nb;
7737736Smckusick 		return (0);
7837736Smckusick 	}
7937736Smckusick 	/*
8039679Smckusick 	 * Determine the number of levels of indirection.
8137736Smckusick 	 */
8237736Smckusick 	sh = 1;
8337736Smckusick 	bn -= NDADDR;
84*51183Sbostic 	lbn_ind = 0;
8537736Smckusick 	for (j = NIADDR; j > 0; j--) {
86*51183Sbostic 		lbn_ind--;
8737736Smckusick 		sh *= NINDIR(fs);
8837736Smckusick 		if (bn < sh)
8937736Smckusick 			break;
9037736Smckusick 		bn -= sh;
9137736Smckusick 	}
9237736Smckusick 	if (j == 0)
9337736Smckusick 		return (EFBIG);
9437736Smckusick 	/*
9539679Smckusick 	 * Fetch through the indirect blocks.
9637736Smckusick 	 */
97*51183Sbostic 
98*51183Sbostic 	vp = ITOV(ip);
99*51183Sbostic 	devvp = VFSTOUFS(vp->v_mount)->um_devvp;
100*51183Sbostic 	for (off = NIADDR - j, bap = ip->i_ib; j <= NIADDR; j++) {
101*51183Sbostic 		if((daddr = bap[off]) == 0) {
102*51183Sbostic 			daddr = (daddr_t)-1;
103*51183Sbostic 			break;
104*51183Sbostic 		}
105*51183Sbostic 		if (bp)
10637736Smckusick 			brelse(bp);
107*51183Sbostic 		bp = getblk(vp, lbn_ind, fs->lfs_bsize);
108*51183Sbostic 		if (bp->b_flags & (B_DONE | B_DELWRI)) {
109*51183Sbostic 			trace(TR_BREADHIT, pack(vp, size), lbn_ind);
110*51183Sbostic 		} else {
111*51183Sbostic 			trace(TR_BREADMISS, pack(vp, size), lbn_ind);
112*51183Sbostic 			bp->b_blkno = daddr;
113*51183Sbostic 			bp->b_flags |= B_READ;
114*51183Sbostic 			bp->b_dev = devvp->v_rdev;
115*51183Sbostic 			(*(devvp->v_op->vop_strategy))(bp);
116*51183Sbostic 			curproc->p_stats->p_ru.ru_inblock++;	/* XXX */
117*51183Sbostic 			if (error = biowait(bp)) {
118*51183Sbostic 				brelse(bp);
119*51183Sbostic 				return (error);
120*51183Sbostic 			}
12137736Smckusick 		}
12237736Smckusick 		bap = bp->b_un.b_daddr;
12337736Smckusick 		sh /= NINDIR(fs);
124*51183Sbostic 		off = (bn / sh) % NINDIR(fs);
125*51183Sbostic 		lbn_ind  = -(NIADDR + 1 + off);
126*51183Sbostic 	}
127*51183Sbostic 	if (bp)
12839679Smckusick 		brelse(bp);
129*51183Sbostic 
130*51183Sbostic 	*bnp = daddr;
13137736Smckusick 	return (0);
13237736Smckusick }
133