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