ffs_balloc.c revision 1.24 1 /* $NetBSD: ffs_balloc.c,v 1.24 2001/05/30 11:57:18 mrg Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
36 */
37
38 #if defined(_KERNEL_OPT)
39 #include "opt_quota.h"
40 #endif
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/buf.h>
45 #include <sys/proc.h>
46 #include <sys/file.h>
47 #include <sys/mount.h>
48 #include <sys/vnode.h>
49 #include <sys/mount.h>
50
51 #include <ufs/ufs/quota.h>
52 #include <ufs/ufs/ufsmount.h>
53 #include <ufs/ufs/inode.h>
54 #include <ufs/ufs/ufs_extern.h>
55 #include <ufs/ufs/ufs_bswap.h>
56
57 #include <ufs/ffs/fs.h>
58 #include <ufs/ffs/ffs_extern.h>
59
60 #include <uvm/uvm.h>
61
62 /*
63 * Balloc defines the structure of file system storage
64 * by allocating the physical blocks on a device given
65 * the inode and the logical block number in a file.
66 */
67 int
68 ffs_balloc(v)
69 void *v;
70 {
71 struct vop_balloc_args /* {
72 struct vnode *a_vp;
73 off_t a_startpoint;
74 int a_size;
75 struct ucred *a_cred;
76 int a_flags;
77 struct buf **a_bpp;
78 } */ *ap = v;
79 ufs_daddr_t lbn;
80 int size;
81 struct ucred *cred;
82 int flags;
83 ufs_daddr_t nb;
84 struct buf *bp, *nbp;
85 struct vnode *vp = ap->a_vp;
86 struct inode *ip = VTOI(vp);
87 struct fs *fs = ip->i_fs;
88 struct indir indirs[NIADDR + 2];
89 ufs_daddr_t newb, *bap, pref;
90 int deallocated, osize, nsize, num, i, error;
91 ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
92 int unwindidx = -1;
93 struct buf **bpp = ap->a_bpp;
94 #ifdef FFS_EI
95 const int needswap = UFS_FSNEEDSWAP(fs);
96 #endif
97 UVMHIST_FUNC("ffs_balloc"); UVMHIST_CALLED(ubchist);
98
99 lbn = lblkno(fs, ap->a_startoffset);
100 size = blkoff(fs, ap->a_startoffset) + ap->a_size;
101 if (size > fs->fs_bsize)
102 panic("ffs_balloc: blk too big");
103 if (bpp != NULL) {
104 *bpp = NULL;
105 }
106 UVMHIST_LOG(ubchist, "vp %p lbn 0x%x size 0x%x", vp, lbn, size,0);
107
108 KASSERT(size <= fs->fs_bsize);
109 if (lbn < 0)
110 return (EFBIG);
111 cred = ap->a_cred;
112 flags = ap->a_flags;
113
114 /*
115 * If the next write will extend the file into a new block,
116 * and the file is currently composed of a fragment
117 * this fragment has to be extended to be a full block.
118 */
119
120 nb = lblkno(fs, ip->i_ffs_size);
121 if (nb < NDADDR && nb < lbn) {
122 osize = blksize(fs, ip, nb);
123 if (osize < fs->fs_bsize && osize > 0) {
124 error = ffs_realloccg(ip, nb,
125 ffs_blkpref(ip, nb, (int)nb, &ip->i_ffs_db[0]),
126 osize, (int)fs->fs_bsize, cred, bpp, &newb);
127 if (error)
128 return (error);
129 if (DOINGSOFTDEP(vp))
130 softdep_setup_allocdirect(ip, nb, newb,
131 ufs_rw32(ip->i_ffs_db[nb], needswap),
132 fs->fs_bsize, osize, bpp ? *bpp : NULL);
133 ip->i_ffs_size = lblktosize(fs, nb + 1);
134 uvm_vnp_setsize(vp, ip->i_ffs_size);
135 ip->i_ffs_db[nb] = ufs_rw32(newb, needswap);
136 ip->i_flag |= IN_CHANGE | IN_UPDATE;
137 if (bpp) {
138 if (flags & B_SYNC)
139 bwrite(*bpp);
140 else
141 bawrite(*bpp);
142 }
143 }
144 }
145
146 /*
147 * The first NDADDR blocks are direct blocks
148 */
149
150 if (lbn < NDADDR) {
151 nb = ufs_rw32(ip->i_ffs_db[lbn], needswap);
152 if (nb != 0 && ip->i_ffs_size >= lblktosize(fs, lbn + 1)) {
153
154 /*
155 * The block is an already-allocated direct block
156 * and the file already extends past this block,
157 * thus this must be a whole block.
158 * Just read the block (if requested).
159 */
160
161 if (bpp != NULL) {
162 error = bread(vp, lbn, fs->fs_bsize, NOCRED,
163 bpp);
164 if (error) {
165 brelse(*bpp);
166 return (error);
167 }
168 }
169 return (0);
170 }
171 if (nb != 0) {
172
173 /*
174 * Consider need to reallocate a fragment.
175 */
176
177 osize = fragroundup(fs, blkoff(fs, ip->i_ffs_size));
178 nsize = fragroundup(fs, size);
179 if (nsize <= osize) {
180
181 /*
182 * The existing block is already
183 * at least as big as we want.
184 * Just read the block (if requested).
185 */
186
187 if (bpp != NULL) {
188 error = bread(vp, lbn, osize, NOCRED,
189 bpp);
190 if (error) {
191 brelse(*bpp);
192 return (error);
193 }
194 }
195 return 0;
196 } else {
197
198 /*
199 * The existing block is smaller than we want,
200 * grow it.
201 */
202
203 error = ffs_realloccg(ip, lbn,
204 ffs_blkpref(ip, lbn, (int)lbn,
205 &ip->i_ffs_db[0]), osize, nsize, cred,
206 bpp, &newb);
207 if (error)
208 return (error);
209 if (DOINGSOFTDEP(vp))
210 softdep_setup_allocdirect(ip, lbn,
211 newb, nb, nsize, osize,
212 bpp ? *bpp : NULL);
213 }
214 } else {
215
216 /*
217 * the block was not previously allocated,
218 * allocate a new block or fragment.
219 */
220
221 if (ip->i_ffs_size < lblktosize(fs, lbn + 1))
222 nsize = fragroundup(fs, size);
223 else
224 nsize = fs->fs_bsize;
225 error = ffs_alloc(ip, lbn,
226 ffs_blkpref(ip, lbn, (int)lbn, &ip->i_ffs_db[0]),
227 nsize, cred, &newb);
228 if (error)
229 return (error);
230 if (bpp != NULL) {
231 bp = getblk(vp, lbn, nsize, 0, 0);
232 bp->b_blkno = fsbtodb(fs, newb);
233 if (flags & B_CLRBUF)
234 clrbuf(bp);
235 *bpp = bp;
236 }
237 if (DOINGSOFTDEP(vp)) {
238 softdep_setup_allocdirect(ip, lbn, newb, 0,
239 nsize, 0, bpp ? *bpp : NULL);
240 }
241 }
242 ip->i_ffs_db[lbn] = ufs_rw32(newb, needswap);
243 ip->i_flag |= IN_CHANGE | IN_UPDATE;
244 return (0);
245 }
246 /*
247 * Determine the number of levels of indirection.
248 */
249 pref = 0;
250 if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
251 return(error);
252
253 #ifdef DIAGNOSTIC
254 if (num < 1)
255 panic ("ffs_balloc: ufs_bmaparray returned indirect block\n");
256 #endif
257 /*
258 * Fetch the first indirect block allocating if necessary.
259 */
260 --num;
261 nb = ufs_rw32(ip->i_ffs_ib[indirs[0].in_off], needswap);
262 allocib = NULL;
263 allocblk = allociblk;
264 if (nb == 0) {
265 pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
266 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
267 &newb);
268 if (error)
269 return (error);
270 nb = newb;
271 *allocblk++ = nb;
272 bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
273 bp->b_blkno = fsbtodb(fs, nb);
274 clrbuf(bp);
275 if (DOINGSOFTDEP(vp)) {
276 softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off,
277 newb, 0, fs->fs_bsize, 0, bp);
278 bdwrite(bp);
279 } else {
280 /*
281 * Write synchronously so that indirect blocks
282 * never point at garbage.
283 */
284 if ((error = bwrite(bp)) != 0)
285 goto fail;
286 }
287 unwindidx = 0;
288 allocib = &ip->i_ffs_ib[indirs[0].in_off];
289 *allocib = ufs_rw32(nb, needswap);
290 ip->i_flag |= IN_CHANGE | IN_UPDATE;
291 }
292 /*
293 * Fetch through the indirect blocks, allocating as necessary.
294 */
295 for (i = 1;;) {
296 error = bread(vp,
297 indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
298 if (error) {
299 brelse(bp);
300 goto fail;
301 }
302 bap = (ufs_daddr_t *)bp->b_data;
303 nb = ufs_rw32(bap[indirs[i].in_off], needswap);
304 if (i == num)
305 break;
306 i++;
307 if (nb != 0) {
308 brelse(bp);
309 continue;
310 }
311 if (pref == 0)
312 pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
313 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
314 &newb);
315 if (error) {
316 brelse(bp);
317 goto fail;
318 }
319 nb = newb;
320 *allocblk++ = nb;
321 nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
322 nbp->b_blkno = fsbtodb(fs, nb);
323 clrbuf(nbp);
324 if (DOINGSOFTDEP(vp)) {
325 softdep_setup_allocindir_meta(nbp, ip, bp,
326 indirs[i - 1].in_off, nb);
327 bdwrite(nbp);
328 } else {
329 /*
330 * Write synchronously so that indirect blocks
331 * never point at garbage.
332 */
333 if ((error = bwrite(nbp)) != 0) {
334 brelse(bp);
335 goto fail;
336 }
337 }
338 if (unwindidx < 0)
339 unwindidx = i - 1;
340 bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap);
341 /*
342 * If required, write synchronously, otherwise use
343 * delayed write.
344 */
345 if (flags & B_SYNC) {
346 bwrite(bp);
347 } else {
348 bdwrite(bp);
349 }
350 }
351 /*
352 * Get the data block, allocating if necessary.
353 */
354 if (nb == 0) {
355 pref = ffs_blkpref(ip, lbn, indirs[num].in_off, &bap[0]);
356 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
357 &newb);
358 if (error) {
359 brelse(bp);
360 goto fail;
361 }
362 nb = newb;
363 *allocblk++ = nb;
364 if (bpp != NULL) {
365 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
366 nbp->b_blkno = fsbtodb(fs, nb);
367 if (flags & B_CLRBUF)
368 clrbuf(nbp);
369 *bpp = nbp;
370 }
371 if (DOINGSOFTDEP(vp))
372 softdep_setup_allocindir_page(ip, lbn, bp,
373 indirs[num].in_off, nb, 0, bpp ? *bpp : NULL);
374 bap[indirs[num].in_off] = ufs_rw32(nb, needswap);
375 if (allocib == NULL && unwindidx < 0) {
376 unwindidx = i - 1;
377 }
378 /*
379 * If required, write synchronously, otherwise use
380 * delayed write.
381 */
382 if (flags & B_SYNC) {
383 bwrite(bp);
384 } else {
385 bdwrite(bp);
386 }
387 return (0);
388 }
389 brelse(bp);
390 if (bpp != NULL) {
391 if (flags & B_CLRBUF) {
392 error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
393 if (error) {
394 brelse(nbp);
395 goto fail;
396 }
397 } else {
398 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
399 nbp->b_blkno = fsbtodb(fs, nb);
400 clrbuf(nbp);
401 }
402 *bpp = nbp;
403 }
404 return (0);
405 fail:
406 /*
407 * If we have failed part way through block allocation, we
408 * have to deallocate any indirect blocks that we have allocated.
409 * We have to fsync the file before we start to get rid of all
410 * of its dependencies so that we do not leave them dangling.
411 * We have to sync it at the end so that the soft updates code
412 * does not find any untracked changes. Although this is really
413 * slow, running out of disk space is not expected to be a common
414 * occurence. The error return from fsync is ignored as we already
415 * have an error to return to the user.
416 */
417 (void) VOP_FSYNC(vp, cred, FSYNC_WAIT, 0, 0, curproc);
418 for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
419 ffs_blkfree(ip, *blkp, fs->fs_bsize);
420 deallocated += fs->fs_bsize;
421 }
422 if (unwindidx >= 0) {
423 if (unwindidx == 0) {
424 *allocib = 0;
425 } else {
426 int r;
427
428 r = bread(vp, indirs[unwindidx].in_lbn,
429 (int)fs->fs_bsize, NOCRED, &bp);
430 if (r) {
431 panic("Could not unwind indirect block, error %d", r);
432 brelse(bp);
433 } else {
434 bap = (ufs_daddr_t *)bp->b_data;
435 bap[indirs[unwindidx].in_off] = 0;
436 if (flags & B_SYNC)
437 bwrite(bp);
438 else
439 bdwrite(bp);
440 }
441 }
442 for (i = unwindidx + 1; i <= num; i++) {
443 bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
444 0);
445 bp->b_flags |= B_INVAL;
446 brelse(bp);
447 }
448 }
449 if (deallocated) {
450 #ifdef QUOTA
451 /*
452 * Restore user's disk quota because allocation failed.
453 */
454 (void)chkdq(ip, (long)-btodb(deallocated), cred, FORCE);
455 #endif
456 ip->i_ffs_blocks -= btodb(deallocated);
457 ip->i_flag |= IN_CHANGE | IN_UPDATE;
458 }
459 (void) VOP_FSYNC(vp, cred, FSYNC_WAIT, 0, 0, curproc);
460 return (error);
461 }
462
463
464 int
465 ffs_ballocn(v)
466 void *v;
467 {
468 struct vop_ballocn_args /* {
469 struct vnode *a_vp;
470 off_t a_offset;
471 off_t a_length;
472 struct ucred *a_cred;
473 int a_flags;
474 } */ *ap = v;
475
476 off_t off, len;
477 struct vnode *vp = ap->a_vp;
478 struct inode *ip = VTOI(vp);
479 struct fs *fs = ip->i_fs;
480 int error, delta, bshift, bsize;
481
482 error = 0;
483 bshift = fs->fs_bshift;
484 bsize = 1 << bshift;
485
486 off = ap->a_offset;
487 len = ap->a_length;
488
489 delta = off & (bsize - 1);
490 off -= delta;
491 len += delta;
492
493 while (len > 0) {
494 bsize = min(bsize, len);
495
496 error = VOP_BALLOC(vp, off, bsize, ap->a_cred, ap->a_flags,
497 NULL);
498 if (error) {
499 goto out;
500 }
501
502 /*
503 * increase file size now, VOP_BALLOC() requires that
504 * EOF be up-to-date before each call.
505 */
506
507 if (ip->i_ffs_size < off + bsize) {
508 ip->i_ffs_size = off + bsize;
509 if (vp->v_uvm.u_size < ip->i_ffs_size) {
510 uvm_vnp_setsize(vp, ip->i_ffs_size);
511 }
512 }
513
514 off += bsize;
515 len -= bsize;
516 }
517
518 out:
519 return error;
520 }
521