make comments more precise
[unix-history] / usr / src / sys / ufs / lfs / lfs_balloc.c
CommitLineData
da7c5cc6 1/*
7188ac27
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
a3257f3c 7 * @(#)lfs_balloc.c 7.13 (Berkeley) %G%
da7c5cc6 8 */
52212483 9
94368568
JB
10#include "param.h"
11#include "systm.h"
94368568
JB
12#include "buf.h"
13#include "proc.h"
7188ac27
KM
14#include "file.h"
15#include "vnode.h"
c6f5111d
MK
16
17#include "quota.h"
18#include "inode.h"
19#include "fs.h"
52212483
BJ
20
21/*
a3257f3c
KM
22 * Bmap converts a the logical block number of a file
23 * to its physical block number on the disk. The conversion
24 * is done by using the logical block number to index into
25 * the array of block pointers described by the dinode.
52212483 26 */
9b392e39 27bmap(ip, bn, bnp)
52212483 28 register struct inode *ip;
7188ac27
KM
29 register daddr_t bn;
30 daddr_t *bnp;
52212483 31{
7188ac27
KM
32 register struct fs *fs;
33 register daddr_t nb;
34 struct buf *bp;
35 daddr_t *bap;
36 int i, j, sh;
37 int error;
38
39 if (bn < 0)
40 return (EFBIG);
41 fs = ip->i_fs;
42
43 /*
44 * The first NDADDR blocks are direct blocks
45 */
46 if (bn < NDADDR) {
47 nb = ip->i_db[bn];
48 if (nb == 0) {
49 *bnp = (daddr_t)-1;
50 return (0);
51 }
7188ac27
KM
52 *bnp = fsbtodb(fs, nb);
53 return (0);
54 }
7188ac27 55 /*
9b392e39 56 * Determine the number of levels of indirection.
7188ac27
KM
57 */
58 sh = 1;
59 bn -= NDADDR;
60 for (j = NIADDR; j > 0; j--) {
61 sh *= NINDIR(fs);
62 if (bn < sh)
63 break;
64 bn -= sh;
65 }
66 if (j == 0)
67 return (EFBIG);
7188ac27 68 /*
9b392e39 69 * Fetch through the indirect blocks.
7188ac27
KM
70 */
71 nb = ip->i_ib[NIADDR - j];
72 if (nb == 0) {
73 *bnp = (daddr_t)-1;
74 return (0);
52212483 75 }
7188ac27
KM
76 for (; j <= NIADDR; j++) {
77 if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
a937f856 78 (int)fs->fs_bsize, NOCRED, &bp)) {
7188ac27
KM
79 brelse(bp);
80 return (error);
81 }
82 bap = bp->b_un.b_daddr;
83 sh /= NINDIR(fs);
84 i = (bn / sh) % NINDIR(fs);
85 nb = bap[i];
86 if (nb == 0) {
87 *bnp = (daddr_t)-1;
88 brelse(bp);
89 return (0);
90 }
9b392e39 91 brelse(bp);
7188ac27
KM
92 }
93 *bnp = fsbtodb(fs, nb);
7188ac27
KM
94 return (0);
95}
96
97/*
98 * Balloc defines the structure of file system storage
9b392e39
KM
99 * by allocating the physical blocks on a device given
100 * the inode and the logical block number in a file.
7188ac27 101 */
9b392e39 102balloc(ip, bn, size, bpp, flags)
7188ac27
KM
103 register struct inode *ip;
104 register daddr_t bn;
105 int size;
9b392e39 106 struct buf **bpp;
7188ac27
KM
107 int flags;
108{
109 register struct fs *fs;
110 register daddr_t nb;
111 struct buf *bp, *nbp;
9b392e39 112 struct vnode *vp = ITOV(ip);
7188ac27 113 int osize, nsize, i, j, sh, error;
9b392e39 114 daddr_t newb, lbn, *bap, pref, blkpref();
7188ac27 115
9b392e39 116 *bpp = (struct buf *)0;
7188ac27
KM
117 if (bn < 0)
118 return (EFBIG);
52212483 119 fs = ip->i_fs;
52212483
BJ
120
121 /*
122 * If the next write will extend the file into a new block,
123 * and the file is currently composed of a fragment
124 * this fragment has to be extended to be a full block.
125 */
126 nb = lblkno(fs, ip->i_size);
7188ac27 127 if (nb < NDADDR && nb < bn) {
52212483
BJ
128 osize = blksize(fs, ip, nb);
129 if (osize < fs->fs_bsize && osize > 0) {
9b392e39 130 error = realloccg(ip, nb,
4f083fd7 131 blkpref(ip, nb, (int)nb, &ip->i_db[0]),
7188ac27 132 osize, (int)fs->fs_bsize, &bp);
9b392e39 133 if (error)
7188ac27 134 return (error);
52212483 135 ip->i_size = (nb + 1) * fs->fs_bsize;
8986c97c 136 vnode_pager_setsize(ITOV(ip), (u_long)ip->i_size);
52212483
BJ
137 ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
138 ip->i_flag |= IUPD|ICHG;
9b392e39
KM
139 if (flags & B_SYNC)
140 bwrite(bp);
141 else
142 bawrite(bp);
52212483
BJ
143 }
144 }
145 /*
146 * The first NDADDR blocks are direct blocks
147 */
148 if (bn < NDADDR) {
a6e7e3c6 149 nb = ip->i_db[bn];
9b392e39
KM
150 if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) {
151 error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp);
7188ac27 152 if (error) {
9b392e39 153 brelse(bp);
7188ac27 154 return (error);
52212483 155 }
9b392e39
KM
156 *bpp = bp;
157 return (0);
158 }
159 if (nb != 0) {
160 /*
161 * Consider need to reallocate a fragment.
162 */
163 osize = fragroundup(fs, blkoff(fs, ip->i_size));
164 nsize = fragroundup(fs, size);
165 if (nsize <= osize) {
166 error = bread(vp, bn, osize, NOCRED, &bp);
167 if (error) {
168 brelse(bp);
169 return (error);
170 }
171 } else {
172 error = realloccg(ip, bn,
173 blkpref(ip, bn, (int)bn, &ip->i_db[0]),
174 osize, nsize, &bp);
175 if (error)
176 return (error);
177 }
178 } else {
179 if (ip->i_size < (bn + 1) * fs->fs_bsize)
180 nsize = fragroundup(fs, size);
52212483 181 else
9b392e39
KM
182 nsize = fs->fs_bsize;
183 error = alloc(ip, bn,
184 blkpref(ip, bn, (int)bn, &ip->i_db[0]),
185 nsize, &newb);
186 if (error)
187 return (error);
188 bp = getblk(vp, bn, nsize);
189 bp->b_blkno = fsbtodb(fs, newb);
190 if (flags & B_CLRBUF)
191 clrbuf(bp);
52212483 192 }
9b392e39
KM
193 ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
194 ip->i_flag |= IUPD|ICHG;
195 *bpp = bp;
7188ac27 196 return (0);
52212483 197 }
52212483 198 /*
9b392e39 199 * Determine the number of levels of indirection.
52212483 200 */
a6e7e3c6 201 pref = 0;
52212483 202 sh = 1;
a6e7e3c6 203 lbn = bn;
52212483 204 bn -= NDADDR;
7188ac27 205 for (j = NIADDR; j > 0; j--) {
52212483
BJ
206 sh *= NINDIR(fs);
207 if (bn < sh)
208 break;
209 bn -= sh;
210 }
7188ac27
KM
211 if (j == 0)
212 return (EFBIG);
52212483 213 /*
9b392e39 214 * Fetch the first indirect block allocating if necessary.
52212483
BJ
215 */
216 nb = ip->i_ib[NIADDR - j];
217 if (nb == 0) {
4f083fd7 218 pref = blkpref(ip, lbn, 0, (daddr_t *)0);
9b392e39 219 if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb))
7188ac27 220 return (error);
9b392e39
KM
221 nb = newb;
222 bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
223 clrbuf(bp);
52212483
BJ
224 /*
225 * Write synchronously so that indirect blocks
226 * never point at garbage.
227 */
9b392e39
KM
228 if (error = bwrite(bp)) {
229 blkfree(ip, nb, fs->fs_bsize);
230 return (error);
231 }
52212483
BJ
232 ip->i_ib[NIADDR - j] = nb;
233 ip->i_flag |= IUPD|ICHG;
234 }
52212483 235 /*
9b392e39 236 * Fetch through the indirect blocks, allocating as necessary.
52212483 237 */
9b392e39
KM
238 for (; ; j++) {
239 error = bread(ip->i_devvp, fsbtodb(fs, nb),
240 (int)fs->fs_bsize, NOCRED, &bp);
241 if (error) {
52212483 242 brelse(bp);
7188ac27 243 return (error);
52212483
BJ
244 }
245 bap = bp->b_un.b_daddr;
246 sh /= NINDIR(fs);
247 i = (bn / sh) % NINDIR(fs);
248 nb = bap[i];
9b392e39
KM
249 if (j == NIADDR)
250 break;
251 if (nb != 0) {
252 brelse(bp);
253 continue;
254 }
255 if (pref == 0)
256 pref = blkpref(ip, lbn, 0, (daddr_t *)0);
257 if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
258 brelse(bp);
259 return (error);
260 }
261 nb = newb;
262 nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
263 clrbuf(nbp);
9b392e39
KM
264 /*
265 * Write synchronously so that indirect blocks
266 * never point at garbage.
267 */
268 if (error = bwrite(nbp)) {
269 blkfree(ip, nb, fs->fs_bsize);
270 brelse(bp);
271 return (error);
272 }
273 bap[i] = nb;
3cf3d516
KM
274 /*
275 * If required, write synchronously, otherwise use
276 * delayed write. If this is the first instance of
277 * the delayed write, reassociate the buffer with the
278 * file so it will be written if the file is sync'ed.
279 */
280 if (flags & B_SYNC) {
9b392e39 281 bwrite(bp);
3cf3d516 282 } else if (bp->b_flags & B_DELWRI) {
52212483 283 bdwrite(bp);
3cf3d516
KM
284 } else {
285 bdwrite(bp);
286 reassignbuf(bp, vp);
287 }
9b392e39
KM
288 }
289 /*
290 * Get the data block, allocating if necessary.
291 */
292 if (nb == 0) {
293 pref = blkpref(ip, lbn, i, &bap[0]);
294 if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
52212483 295 brelse(bp);
9b392e39
KM
296 return (error);
297 }
298 nb = newb;
299 nbp = getblk(vp, lbn, fs->fs_bsize);
300 nbp->b_blkno = fsbtodb(fs, nb);
301 if (flags & B_CLRBUF)
302 clrbuf(nbp);
303 bap[i] = nb;
3cf3d516
KM
304 /*
305 * If required, write synchronously, otherwise use
306 * delayed write. If this is the first instance of
307 * the delayed write, reassociate the buffer with the
308 * file so it will be written if the file is sync'ed.
309 */
310 if (flags & B_SYNC) {
9b392e39 311 bwrite(bp);
3cf3d516 312 } else if (bp->b_flags & B_DELWRI) {
9b392e39 313 bdwrite(bp);
3cf3d516
KM
314 } else {
315 bdwrite(bp);
316 reassignbuf(bp, vp);
317 }
9b392e39
KM
318 *bpp = nbp;
319 return (0);
52212483 320 }
9b392e39 321 brelse(bp);
0b4c7ad8 322 if (flags & B_CLRBUF) {
9b392e39
KM
323 error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
324 if (error) {
325 brelse(nbp);
326 return (error);
327 }
0b4c7ad8
KM
328 } else {
329 nbp = getblk(vp, lbn, fs->fs_bsize);
330 nbp->b_blkno = fsbtodb(fs, nb);
9b392e39
KM
331 }
332 *bpp = nbp;
7188ac27 333 return (0);
52212483 334}