xref: /csrg-svn/sys/ufs/lfs/lfs_balloc.c (revision 55942)
123396Smckusick /*
251494Sbostic  * Copyright (c) 1989, 1991 Regents of the University of California.
337736Smckusick  * All rights reserved.
423396Smckusick  *
544537Sbostic  * %sccs.include.redist.c%
637736Smckusick  *
7*55942Sbostic  *	@(#)lfs_balloc.c	7.36 (Berkeley) 08/21/92
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/trace.h>
177443Sroot 
1855048Smckusick #include <miscfs/specfs/specdev.h>
1955048Smckusick 
2051494Sbostic #include <ufs/ufs/quota.h>
2151494Sbostic #include <ufs/ufs/inode.h>
2251494Sbostic #include <ufs/ufs/ufsmount.h>
2347571Skarels 
2451494Sbostic #include <ufs/lfs/lfs.h>
2551494Sbostic #include <ufs/lfs/lfs_extern.h>
2651486Sbostic 
2751962Sbostic int lfs_getlbns __P((struct vnode *, daddr_t, INDIR *, int *));
2851855Sbostic 
297443Sroot /*
3051486Sbostic  * Bmap converts a the logical block number of a file to its physical block
3151486Sbostic  * number on the disk. The conversion is done by using the logical block
3251486Sbostic  * number to index into the array of block pointers described by the dinode.
3351855Sbostic  */
3451855Sbostic int
3554687Sbostic lfs_bmap(ap)
3654687Sbostic 	struct vop_bmap_args /* {
3754687Sbostic 		struct vnode *a_vp;
3854687Sbostic 		daddr_t  a_bn;
3954687Sbostic 		struct vnode **a_vpp;
4054687Sbostic 		daddr_t *a_bnp;
4154687Sbostic 	} */ *ap;
4251855Sbostic {
4351855Sbostic 	/*
4451855Sbostic 	 * Check for underlying vnode requests and ensure that logical
4551855Sbostic 	 * to physical mapping is requested.
4651855Sbostic 	 */
4753591Sheideman 	if (ap->a_vpp != NULL)
4853591Sheideman 		*ap->a_vpp = VTOI(ap->a_vp)->i_devvp;
4953591Sheideman 	if (ap->a_bnp == NULL)
5051855Sbostic 		return (0);
5151855Sbostic 
5253591Sheideman 	return (lfs_bmaparray(ap->a_vp, ap->a_bn, ap->a_bnp, NULL, NULL));
5351855Sbostic }
5451855Sbostic 
5551855Sbostic /*
5651846Sbostic  * LFS has a different version of bmap from FFS because of a naming conflict.
5751846Sbostic  * In FFS, meta blocks are given real disk addresses at allocation time, and
5851846Sbostic  * are linked into the device vnode, using a logical block number which is
5951846Sbostic  * the same as the physical block number.  This can't be done by LFS because
6051846Sbostic  * blocks aren't given disk addresses until they're written, so there's no
6151846Sbostic  * way to distinguish the meta-data blocks for one file from any other file.
6251846Sbostic  * This means that meta-data blocks have to be on the vnode for the file so
6351846Sbostic  * they can be found, and have to have "names" different from the standard
6451846Sbostic  * data blocks.  To do this, we divide the name space into positive and
6551846Sbostic  * negative block numbers, and give the meta-data blocks negative logical
6651847Sbostic  * numbers.  Indirect blocks are addressed by the negative address of the
6751847Sbostic  * first data block to which they point.  Double indirect blocks are addressed
6851847Sbostic  * by one less than the address of the first indirect block to which they
6951847Sbostic  * point.  Triple indirect blocks are addressed by one less than the address
7051847Sbostic  * of the first double indirect block to which they point.
717443Sroot  */
7251348Sroot int
7351855Sbostic lfs_bmaparray(vp, bn, bnp, ap, nump)
7451561Smckusick 	struct vnode *vp;
7537736Smckusick 	register daddr_t bn;
7651561Smckusick 	daddr_t *bnp;
7751855Sbostic 	INDIR *ap;
7851855Sbostic 	int *nump;
797443Sroot {
8051561Smckusick 	register struct inode *ip;
8151846Sbostic 	struct buf *bp;
8251855Sbostic 	struct lfs *fs;
8351561Smckusick 	struct vnode *devvp;
8451855Sbostic 	INDIR a[NIADDR], *xap;
8551855Sbostic 	daddr_t *bap, daddr;
8651855Sbostic 	long metalbn;
8751855Sbostic 	int error, num, off;
8854687Sbostic 	struct vop_strategy_args vop_strategy_a;
8937736Smckusick 
9051561Smckusick 	ip = VTOI(vp);
9151855Sbostic #ifdef DIAGNOSTIC
9251855Sbostic 	if (ap != NULL && nump == NULL || ap == NULL && nump != NULL)
9351855Sbostic 		panic("lfs_bmaparray: invalid arguments");
9451855Sbostic #endif
9551847Sbostic 
9651855Sbostic 	xap = ap == NULL ? a : ap;
9755457Sbostic 	if (!nump)
9855457Sbostic 		nump = &num;
9951855Sbostic 	if (error = lfs_getlbns(vp, bn, xap, nump))
10051855Sbostic 		return (error);
10151855Sbostic 
10251855Sbostic 	num = *nump;
10351855Sbostic 	if (num == 0) {
10451855Sbostic 		*bnp = ip->i_db[bn];
10551855Sbostic 		if (*bnp == 0)
10651348Sroot 			*bnp = UNASSIGNED;
10737736Smckusick 		return (0);
10837736Smckusick 	}
10951486Sbostic 
11052994Sbostic 
11152994Sbostic 	/* Get disk address out of indirect block array */
11252994Sbostic 	daddr = ip->i_ib[xap->in_off];
11352994Sbostic 
11451855Sbostic 	/* Fetch through the indirect blocks. */
11552994Sbostic 	fs = ip->i_lfs;
11651183Sbostic 	devvp = VFSTOUFS(vp->v_mount)->um_devvp;
11752994Sbostic 
118*55942Sbostic 	for (bp = NULL, ++xap; --num; ++xap) {
119*55942Sbostic 		/*
120*55942Sbostic 		 * If we were called explicitly then we don't want to create
121*55942Sbostic 		 * indirect blocks.  Since BMAP calls pass NULL for the ap,
122*55942Sbostic 		 * we can use that to detect if we are called from BMAP or not.
123*55942Sbostic 		 */
124*55942Sbostic 		if (daddr == 0 && ap != NULL)
125*55942Sbostic 			break;
126*55942Sbostic 
12752994Sbostic 		/* If looking for a meta-block, break out when we find it. */
12851855Sbostic 		metalbn = xap->in_lbn;
12951855Sbostic 		if (metalbn == bn)
13051847Sbostic 			break;
13151847Sbostic 
13251846Sbostic 		/*
13351846Sbostic 		 * Read in the appropriate indirect block.  LFS can't do a
13451846Sbostic 		 * bread because bread knows that FFS will hand it the device
13551846Sbostic 		 * vnode, not the file vnode, so the b_dev and b_blkno would
13651846Sbostic 		 * be wrong.
13751846Sbostic 		 *
13851846Sbostic 		 * XXX
13951846Sbostic 		 * This REALLY needs to be fixed, at the very least it needs
14051855Sbostic 		 * to be rethought when the buffer cache goes away.  When it's
14151855Sbostic 		 * fixed, change lfs_bmaparray and lfs_getlbns to take an ip,
14251855Sbostic 		 * not a vp.
14351846Sbostic 		 */
14451183Sbostic 		if (bp)
14537736Smckusick 			brelse(bp);
14651847Sbostic 		bp = getblk(vp, metalbn, fs->lfs_bsize);
14751183Sbostic 		if (bp->b_flags & (B_DONE | B_DELWRI)) {
14851847Sbostic 			trace(TR_BREADHIT, pack(vp, size), metalbn);
149*55942Sbostic 		} else if (!daddr) {
150*55942Sbostic 			/* Need to create an indirect block */
151*55942Sbostic 			trace(TR_BREADMISS, pack(vp, size), metalbn);
152*55942Sbostic 			bzero(bp->b_un.b_addr, fs->lfs_bsize);
153*55942Sbostic 			*bnp = UNASSIGNED;
154*55942Sbostic 			ip->i_blocks += fsbtodb(fs, 1);
155*55942Sbostic 			fs->lfs_bfree -= fsbtodb(fs, 1);
156*55942Sbostic 			daddr = bp->b_un.b_daddr[xap->in_off];
157*55942Sbostic 			if (error = VOP_BWRITE(bp))
158*55942Sbostic 				return (error);
159*55942Sbostic 			bp = NULL;
160*55942Sbostic 			continue;
16151183Sbostic 		} else {
16251847Sbostic 			trace(TR_BREADMISS, pack(vp, size), metalbn);
16351847Sbostic 			bp->b_blkno = daddr;
16451846Sbostic 			bp->b_flags |= B_READ;
16551183Sbostic 			bp->b_dev = devvp->v_rdev;
16653574Sheideman 			/*
16753574Sheideman 			 * Call a strategy VOP by hand.
16853574Sheideman 			 */
16953574Sheideman 			vop_strategy_a.a_desc = VDESC(vop_strategy);
17053574Sheideman 			vop_strategy_a.a_bp=bp;
17153574Sheideman 			VOCALL(devvp->v_op, VOFFSET(vop_strategy), \
17253574Sheideman 			       &vop_strategy_a);
17351183Sbostic 			curproc->p_stats->p_ru.ru_inblock++;	/* XXX */
17451183Sbostic 			if (error = biowait(bp)) {
17551183Sbostic 				brelse(bp);
17651183Sbostic 				return (error);
17751183Sbostic 			}
17837736Smckusick 		}
17952994Sbostic 		daddr = bp->b_un.b_daddr[xap->in_off];
18051183Sbostic 	}
18151183Sbostic 	if (bp)
18239679Smckusick 		brelse(bp);
18351183Sbostic 
18452994Sbostic 	*bnp = daddr == 0 ? UNASSIGNED : daddr;
18537736Smckusick 	return (0);
18637736Smckusick }
18751855Sbostic 
18851855Sbostic /*
18951855Sbostic  * Create an array of logical block number/offset pairs which represent the
19051855Sbostic  * path of indirect blocks required to access a data block.  The first "pair"
19151855Sbostic  * contains the logical block number of the appropriate single, double or
19251855Sbostic  * triple indirect block and the offset into the inode indirect block array.
19351855Sbostic  * Note, the logical block number of the inode single/double/triple indirect
19451855Sbostic  * block appears twice in the array, once with the offset into the i_ib and
19551855Sbostic  * once with the offset into the page itself.
19651855Sbostic  */
19751855Sbostic int
19851855Sbostic lfs_getlbns(vp, bn, ap, nump)
19951855Sbostic 	struct vnode *vp;
20051855Sbostic 	register daddr_t bn;
20151855Sbostic 	INDIR *ap;
20251855Sbostic 	int *nump;
20351855Sbostic {
20451855Sbostic 	struct lfs *fs;
20551855Sbostic 	long metalbn, realbn;
20654687Sbostic 	int j, numlevels, off, sh;
20751855Sbostic 
20854687Sbostic 	if (nump)
20954687Sbostic 		*nump = 0;
21054687Sbostic 	numlevels = 0;
21151855Sbostic 	realbn = bn;
21251855Sbostic 	if ((long)bn < 0)
21351855Sbostic 		bn = -(long)bn;
21451855Sbostic 
21551855Sbostic 	/* The first NDADDR blocks are direct blocks. */
21651855Sbostic 	if (bn < NDADDR)
21752994Sbostic 		return (0);
21851855Sbostic 
21951855Sbostic 	/*
22051855Sbostic 	 * Determine the number of levels of indirection.  After this loop
22151855Sbostic 	 * is done, sh indicates the number of data blocks possible at the
22251855Sbostic 	 * given level of indirection, and NIADDR - j is the number of levels
22351855Sbostic 	 * of indirection needed to locate the requested block.
22451855Sbostic 	 */
22551855Sbostic 	bn -= NDADDR;
22651855Sbostic 	fs = VTOI(vp)->i_lfs;
22751855Sbostic 	sh = 1;
22851855Sbostic 	for (j = NIADDR; j > 0; j--) {
22951855Sbostic 		sh *= NINDIR(fs);
23051855Sbostic 		if (bn < sh)
23151855Sbostic 			break;
23251855Sbostic 		bn -= sh;
23351855Sbostic 	}
23451855Sbostic 	if (j == 0)
23551855Sbostic 		return (EFBIG);
23651855Sbostic 
23751855Sbostic 	/* Calculate the address of the first meta-block. */
23851855Sbostic 	if (realbn >= 0)
23951855Sbostic 		metalbn = -(realbn - bn + NIADDR - j);
24051855Sbostic 	else
24151855Sbostic 		metalbn = -(-realbn - bn + NIADDR - j);
24251855Sbostic 
24351855Sbostic 	/*
24451855Sbostic 	 * At each iteration, off is the offset into the bap array which is
24551855Sbostic 	 * an array of disk addresses at the current level of indirection.
24651855Sbostic 	 * The logical block number and the offset in that block are stored
24751855Sbostic 	 * into the argument array.
24851855Sbostic 	 */
24954687Sbostic 	++numlevels;
25051855Sbostic 	ap->in_lbn = metalbn;
25151855Sbostic 	ap->in_off = off = NIADDR - j;
25251855Sbostic 	ap++;
25351855Sbostic 	for (; j <= NIADDR; j++) {
25451855Sbostic 		/* If searching for a meta-data block, quit when found. */
25551855Sbostic 		if (metalbn == realbn)
25651855Sbostic 			break;
25751855Sbostic 
25851855Sbostic 		sh /= NINDIR(fs);
25951855Sbostic 		off = (bn / sh) % NINDIR(fs);
26051855Sbostic 
26154687Sbostic 		++numlevels;
26251855Sbostic 		ap->in_lbn = metalbn;
26351855Sbostic 		ap->in_off = off;
26451855Sbostic 		++ap;
26551855Sbostic 
26651855Sbostic 		metalbn -= -1 + off * sh;
26751855Sbostic 	}
26854687Sbostic 	if (nump)
26954687Sbostic 		*nump = numlevels;
27051855Sbostic 	return (0);
27151855Sbostic }
27252082Sbostic 
27352082Sbostic int
27452082Sbostic lfs_balloc(vp, iosize, lbn, bpp)
27552082Sbostic 	struct vnode *vp;
27652082Sbostic 	u_long iosize;
27752082Sbostic 	daddr_t lbn;
27852082Sbostic 	struct buf **bpp;
27952082Sbostic {
28052082Sbostic 	struct buf *bp;
28152082Sbostic 	struct inode *ip;
28252082Sbostic 	struct lfs *fs;
28352082Sbostic 	daddr_t daddr;
284*55942Sbostic 	int error;
28552082Sbostic 
28652082Sbostic 	ip = VTOI(vp);
28752082Sbostic 	fs = ip->i_lfs;
28852082Sbostic 
28952082Sbostic 	/*
29052082Sbostic 	 * Three cases: it's a block beyond the end of file, it's a block in
29152082Sbostic 	 * the file that may or may not have been assigned a disk address or
29252082Sbostic 	 * we're writing an entire block.  Note, if the daddr is unassigned,
29352082Sbostic 	 * the block might still have existed in the cache.  If it did, make
29452082Sbostic 	 * sure we don't count it as a new block or zero out its contents.
295*55942Sbostic 	 * Note that we always call bmap, even if it's a new block beyond
296*55942Sbostic 	 * the end of file. The reason is so that we can allocate any new
297*55942Sbostic 	 * indirect blocks that are necessary.
29852082Sbostic 	 */
299*55942Sbostic 
300*55942Sbostic 	*bpp = NULL;
301*55942Sbostic 	if (error = VOP_BMAP(vp, lbn, NULL, &daddr))
30252994Sbostic 		return (error);
30352082Sbostic 
304*55942Sbostic 	if (daddr == UNASSIGNED || iosize == fs->lfs_bsize) {
30552082Sbostic 		*bpp = bp = getblk(vp, lbn, fs->lfs_bsize);
306*55942Sbostic 		if (daddr == UNASSIGNED && !(bp->b_flags & B_CACHE)) {
30755457Sbostic 			ip->i_blocks += btodb(fs->lfs_bsize);
30855594Sbostic 			fs->lfs_bfree -= btodb(fs->lfs_bsize);
30952082Sbostic 			if (iosize != fs->lfs_bsize)
31052082Sbostic 				clrbuf(bp);
31152082Sbostic 		}
31252994Sbostic 		return (0);
31352082Sbostic 	}
31452994Sbostic 	return (bread(vp, lbn, fs->lfs_bsize, NOCRED, bpp));
31552082Sbostic 
31652082Sbostic }
317