more lint
[unix-history] / usr / src / sys / ufs / ffs / ffs_balloc.c
CommitLineData
a6e7e3c6 1/* ffs_balloc.c 5.2 82/09/25 */
52212483
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/conf.h"
6#include "../h/inode.h"
7#include "../h/dir.h"
8#include "../h/user.h"
9#include "../h/buf.h"
10#include "../h/proc.h"
11#include "../h/fs.h"
12
13/*
14 * Bmap defines the structure of file system storage
15 * by returning the physical block number on a device given the
16 * inode and the logical block number in a file.
17 * When convenient, it also leaves the physical
18 * block number of the next block of the file in rablock
19 * for use in read-ahead.
20 */
21/*VARARGS3*/
22daddr_t
23bmap(ip, bn, rwflg, size)
24 register struct inode *ip;
25 daddr_t bn;
26 int rwflg;
27 int size; /* supplied only when rwflg == B_WRITE */
28{
29 register int i;
30 int osize, nsize;
31 struct buf *bp, *nbp;
32 struct fs *fs;
33 int j, sh;
a6e7e3c6 34 daddr_t nb, lbn, *bap, pref, blkpref();
52212483
BJ
35
36 if (bn < 0) {
37 u.u_error = EFBIG;
38 return ((daddr_t)0);
39 }
40 fs = ip->i_fs;
41 rablock = 0;
42 rasize = 0; /* conservative */
43
44 /*
45 * If the next write will extend the file into a new block,
46 * and the file is currently composed of a fragment
47 * this fragment has to be extended to be a full block.
48 */
49 nb = lblkno(fs, ip->i_size);
50 if (rwflg == B_WRITE && nb < NDADDR && nb < bn) {
51 osize = blksize(fs, ip, nb);
52 if (osize < fs->fs_bsize && osize > 0) {
53 bp = realloccg(ip, ip->i_db[nb],
a6e7e3c6 54 blkpref(ip, nb, nb, &ip->i_db[0]),
52212483
BJ
55 osize, fs->fs_bsize);
56 ip->i_size = (nb + 1) * fs->fs_bsize;
57 ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
58 ip->i_flag |= IUPD|ICHG;
59 bdwrite(bp);
60 }
61 }
62 /*
63 * The first NDADDR blocks are direct blocks
64 */
65 if (bn < NDADDR) {
a6e7e3c6 66 nb = ip->i_db[bn];
52212483
BJ
67 if (rwflg == B_READ) {
68 if (nb == 0)
69 return ((daddr_t)-1);
70 goto gotit;
71 }
a6e7e3c6 72 if (nb == 0 || ip->i_size < (bn + 1) * fs->fs_bsize) {
52212483
BJ
73 if (nb != 0) {
74 /* consider need to reallocate a frag */
75 osize = fragroundup(fs, blkoff(fs, ip->i_size));
76 nsize = fragroundup(fs, size);
77 if (nsize <= osize)
78 goto gotit;
a6e7e3c6
KM
79 bp = realloccg(ip, nb,
80 blkpref(ip, bn, bn, &ip->i_db[0]),
52212483
BJ
81 osize, nsize);
82 } else {
a6e7e3c6 83 if (ip->i_size < (bn + 1) * fs->fs_bsize)
52212483
BJ
84 nsize = fragroundup(fs, size);
85 else
86 nsize = fs->fs_bsize;
a6e7e3c6
KM
87 bp = alloc(ip,
88 blkpref(ip, bn, bn, &ip->i_db[0]),
52212483
BJ
89 nsize);
90 }
91 if (bp == NULL)
92 return ((daddr_t)-1);
93 nb = dbtofsb(fs, bp->b_blkno);
94 if ((ip->i_mode&IFMT) == IFDIR)
95 /*
96 * Write directory blocks synchronously
97 * so they never appear with garbage in
98 * them on the disk.
99 */
100 bwrite(bp);
101 else
102 bdwrite(bp);
a6e7e3c6 103 ip->i_db[bn] = nb;
52212483
BJ
104 ip->i_flag |= IUPD|ICHG;
105 }
106gotit:
a6e7e3c6
KM
107 if (bn < NDADDR - 1) {
108 rablock = fsbtodb(fs, ip->i_db[bn + 1]);
109 rasize = blksize(fs, ip, bn + 1);
52212483
BJ
110 }
111 return (nb);
112 }
113
114 /*
115 * Determine how many levels of indirection.
116 */
a6e7e3c6 117 pref = 0;
52212483 118 sh = 1;
a6e7e3c6 119 lbn = bn;
52212483
BJ
120 bn -= NDADDR;
121 for (j = NIADDR; j>0; j--) {
122 sh *= NINDIR(fs);
123 if (bn < sh)
124 break;
125 bn -= sh;
126 }
127 if (j == 0) {
128 u.u_error = EFBIG;
129 return ((daddr_t)0);
130 }
131
132 /*
133 * fetch the first indirect block
134 */
135 nb = ip->i_ib[NIADDR - j];
136 if (nb == 0) {
a6e7e3c6
KM
137 if (rwflg == B_READ)
138 return ((daddr_t)-1);
139 pref = blkpref(ip, lbn, 0, 0);
140 bp = alloc(ip, pref, fs->fs_bsize);
141 if (bp == NULL)
52212483
BJ
142 return ((daddr_t)-1);
143 nb = dbtofsb(fs, bp->b_blkno);
144 /*
145 * Write synchronously so that indirect blocks
146 * never point at garbage.
147 */
148 bwrite(bp);
149 ip->i_ib[NIADDR - j] = nb;
150 ip->i_flag |= IUPD|ICHG;
151 }
152
153 /*
154 * fetch through the indirect blocks
155 */
156 for (; j <= NIADDR; j++) {
157 bp = bread(ip->i_dev, fsbtodb(fs, nb), fs->fs_bsize);
158 if (bp->b_flags & B_ERROR) {
159 brelse(bp);
160 return ((daddr_t)0);
161 }
162 bap = bp->b_un.b_daddr;
163 sh /= NINDIR(fs);
164 i = (bn / sh) % NINDIR(fs);
165 nb = bap[i];
166 if (nb == 0) {
167 if (rwflg==B_READ) {
168 brelse(bp);
169 return ((daddr_t)-1);
170 }
a6e7e3c6
KM
171 if (pref == 0)
172 if (j < NIADDR)
173 pref = blkpref(ip, lbn, 0, 0);
174 else
175 pref = blkpref(ip, lbn, i, &bap[0]);
52212483
BJ
176 nbp = alloc(ip, pref, fs->fs_bsize);
177 if (nbp == NULL) {
178 brelse(bp);
179 return ((daddr_t)-1);
180 }
181 nb = dbtofsb(fs, nbp->b_blkno);
182 if (j < NIADDR || (ip->i_mode&IFMT) == IFDIR)
183 /*
184 * Write synchronously so indirect blocks
185 * never point at garbage and blocks
186 * in directories never contain garbage.
187 */
188 bwrite(nbp);
189 else
190 bdwrite(nbp);
191 bap[i] = nb;
192 bdwrite(bp);
193 } else
194 brelse(bp);
195 }
196
197 /*
198 * calculate read-ahead.
199 */
200 if (i < NINDIR(fs) - 1) {
201 rablock = fsbtodb(fs, bap[i+1]);
202 rasize = fs->fs_bsize;
203 }
204 return (nb);
205}