xref: /csrg-svn/sys/ufs/lfs/lfs_balloc.c (revision 51215)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)lfs_balloc.c	7.16 (Berkeley) 10/02/91
8  */
9 
10 #ifdef LOGFS
11 #include "param.h"
12 #include "systm.h"
13 #include "buf.h"
14 #include "time.h"
15 #include "resource.h"
16 #include "resourcevar.h"
17 #include "proc.h"
18 #include "file.h"
19 #include "vnode.h"
20 #include "mount.h"
21 #include "specdev.h"
22 
23 #include "../ufs/quota.h"
24 #include "../ufs/inode.h"
25 #include "../ufs/ufsmount.h"
26 #include "trace.h"
27 #include "lfs.h"
28 #include "lfs_extern.h"
29 
30 /*
31  * Bmap converts a the logical block number of a file
32  * to its physical block number on the disk. The conversion
33  * is done by using the logical block number to index into
34  * the array of block pointers described by the dinode.
35  */
36 lfs_bmap(ip, bn, bnp)
37 	register struct inode *ip;
38 	register daddr_t bn;
39 	daddr_t	*bnp;
40 {
41 	register LFS *fs;					/* LFS */
42 	register daddr_t nb;
43 	struct vnode *devvp, *vp;
44 	struct buf *bp;
45 	daddr_t *bap, daddr;
46 	daddr_t lbn_ind;
47 	int i, j, off, sh;
48 	int error;
49 
50 printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number);
51 	fs = ip->i_lfs;						/* LFS */
52 
53 	/*
54 	 * We access all blocks in the cache, even indirect blocks by means of
55 	 * a logical address. Indirect blocks (single, double, triple) all have
56 	 * negative block numbers. The first NDADDR blocks are direct blocks,
57 	 * the first NIADDR negative blocks are the indirect block pointers.
58 	 * The single, double and triple indirect blocks in the inode
59 	 * are addressed: -1, -2 and -3 respectively.
60 	 * XXX we don't handle triple indirect at all.
61 	 */
62 	if (bn < 0) {
63 		/* Shouldn't be here -- we don't think */
64 		printf("lfs_bmap: NEGATIVE indirect block number %d\n", bn);
65 		panic("negative indirect block number");
66 	}
67 
68 	/*
69 	 * The first NDADDR blocks are direct blocks
70 	 */
71 	if (bn < NDADDR) {
72 		nb = ip->i_db[bn];
73 		if (nb == 0) {
74 			*bnp = (daddr_t)-1;
75 			return (0);
76 		}
77 		*bnp = nb;
78 		return (0);
79 	}
80 	/*
81 	 * Determine the number of levels of indirection.
82 	 */
83 	sh = 1;
84 	bn -= NDADDR;
85 	lbn_ind = 0;
86 	for (j = NIADDR; j > 0; j--) {
87 		lbn_ind--;
88 		sh *= NINDIR(fs);
89 		if (bn < sh)
90 			break;
91 		bn -= sh;
92 	}
93 	if (j == 0)
94 		return (EFBIG);
95 	/*
96 	 * Fetch through the indirect blocks.
97 	 */
98 
99 	vp = ITOV(ip);
100 	devvp = VFSTOUFS(vp->v_mount)->um_devvp;
101 	for (off = NIADDR - j, bap = ip->i_ib; j <= NIADDR; j++) {
102 		if((daddr = bap[off]) == 0) {
103 			daddr = (daddr_t)-1;
104 			break;
105 		}
106 		if (bp)
107 			brelse(bp);
108 		bp = getblk(vp, lbn_ind, fs->lfs_bsize);
109 		if (bp->b_flags & (B_DONE | B_DELWRI)) {
110 			trace(TR_BREADHIT, pack(vp, size), lbn_ind);
111 		} else {
112 			trace(TR_BREADMISS, pack(vp, size), lbn_ind);
113 			bp->b_blkno = daddr;
114 			bp->b_flags |= B_READ;
115 			bp->b_dev = devvp->v_rdev;
116 			(devvp->v_op->vop_strategy)(bp);
117 			curproc->p_stats->p_ru.ru_inblock++;	/* XXX */
118 			if (error = biowait(bp)) {
119 				brelse(bp);
120 				return (error);
121 			}
122 		}
123 		bap = bp->b_un.b_daddr;
124 		sh /= NINDIR(fs);
125 		off = (bn / sh) % NINDIR(fs);
126 		lbn_ind  = -(NIADDR + 1 + off);
127 	}
128 	if (bp)
129 		brelse(bp);
130 
131 	*bnp = daddr;
132 	return (0);
133 }
134 #endif /* LOGFS */
135