1 /* $NetBSD: ffs_balloc.c,v 1.34 2003/08/07 16:34:29 agc Exp $ */
2
3 /*
4 * Copyright (c) 2002 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed for the FreeBSD Project by Marshall
8 * Kirk McKusick and Network Associates Laboratories, the Security
9 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
10 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
11 * research program
12 *
13 * Copyright (c) 1982, 1986, 1989, 1993
14 * The Regents of the University of California. All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
41 */
42
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c,v 1.34 2003/08/07 16:34:29 agc Exp $");
45
46 #if defined(_KERNEL_OPT)
47 #include "opt_quota.h"
48 #endif
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/buf.h>
53 #include <sys/file.h>
54 #include <sys/mount.h>
55 #include <sys/vnode.h>
56 #include <sys/mount.h>
57
58 #include <ufs/ufs/quota.h>
59 #include <ufs/ufs/ufsmount.h>
60 #include <ufs/ufs/inode.h>
61 #include <ufs/ufs/ufs_extern.h>
62 #include <ufs/ufs/ufs_bswap.h>
63
64 #include <ufs/ffs/fs.h>
65 #include <ufs/ffs/ffs_extern.h>
66
67 #include <uvm/uvm.h>
68
69 static int ffs_balloc_ufs1(void *);
70 static int ffs_balloc_ufs2(void *);
71
72 /*
73 * Balloc defines the structure of file system storage
74 * by allocating the physical blocks on a device given
75 * the inode and the logical block number in a file.
76 */
77
78 int
79 ffs_balloc(v)
80 void *v;
81 {
82 struct vop_balloc_args *ap = v;
83
84 if (VTOI(ap->a_vp)->i_fs->fs_magic == FS_UFS2_MAGIC)
85 return ffs_balloc_ufs2(v);
86 else
87 return ffs_balloc_ufs1(v);
88 }
89
90 static int
91 ffs_balloc_ufs1(v)
92 void *v;
93 {
94 struct vop_balloc_args /* {
95 struct vnode *a_vp;
96 off_t a_startoffset;
97 int a_size;
98 struct ucred *a_cred;
99 int a_flags;
100 struct buf **a_bpp;
101 } */ *ap = v;
102 daddr_t lbn, lastlbn;
103 int size;
104 struct ucred *cred;
105 int flags;
106 int32_t nb;
107 struct buf *bp, *nbp;
108 struct vnode *vp = ap->a_vp;
109 struct inode *ip = VTOI(vp);
110 struct fs *fs = ip->i_fs;
111 struct indir indirs[NIADDR + 2];
112 daddr_t newb, pref;
113 int32_t *bap; /* XXX ondisk32 */
114 int deallocated, osize, nsize, num, i, error;
115 int32_t *blkp, *allocblk, allociblk[NIADDR + 1];
116 int32_t *allocib;
117 int unwindidx = -1;
118 struct buf **bpp = ap->a_bpp;
119 #ifdef FFS_EI
120 const int needswap = UFS_FSNEEDSWAP(fs);
121 #endif
122 UVMHIST_FUNC("ffs_balloc"); UVMHIST_CALLED(ubchist);
123
124 lbn = lblkno(fs, ap->a_startoffset);
125 size = blkoff(fs, ap->a_startoffset) + ap->a_size;
126 if (size > fs->fs_bsize)
127 panic("ffs_balloc: blk too big");
128 if (bpp != NULL) {
129 *bpp = NULL;
130 }
131 UVMHIST_LOG(ubchist, "vp %p lbn 0x%x size 0x%x", vp, lbn, size,0);
132
133 KASSERT(size <= fs->fs_bsize);
134 if (lbn < 0)
135 return (EFBIG);
136 cred = ap->a_cred;
137 flags = ap->a_flags;
138
139 /*
140 * If the next write will extend the file into a new block,
141 * and the file is currently composed of a fragment
142 * this fragment has to be extended to be a full block.
143 */
144
145 lastlbn = lblkno(fs, ip->i_size);
146 if (lastlbn < NDADDR && lastlbn < lbn) {
147 nb = lastlbn;
148 osize = blksize(fs, ip, nb);
149 if (osize < fs->fs_bsize && osize > 0) {
150 error = ffs_realloccg(ip, nb,
151 ffs_blkpref_ufs1(ip, lastlbn, nb,
152 &ip->i_ffs1_db[0]),
153 osize, (int)fs->fs_bsize, cred, bpp, &newb);
154 if (error)
155 return (error);
156 if (DOINGSOFTDEP(vp))
157 softdep_setup_allocdirect(ip, nb, newb,
158 ufs_rw32(ip->i_ffs1_db[nb], needswap),
159 fs->fs_bsize, osize, bpp ? *bpp : NULL);
160 ip->i_size = lblktosize(fs, nb + 1);
161 ip->i_ffs1_size = ip->i_size;
162 uvm_vnp_setsize(vp, ip->i_ffs1_size);
163 ip->i_ffs1_db[nb] = ufs_rw32((int32_t)newb, needswap);
164 ip->i_flag |= IN_CHANGE | IN_UPDATE;
165 if (bpp) {
166 if (flags & B_SYNC)
167 bwrite(*bpp);
168 else
169 bawrite(*bpp);
170 }
171 }
172 }
173
174 /*
175 * The first NDADDR blocks are direct blocks
176 */
177
178 if (lbn < NDADDR) {
179 nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap);
180 if (nb != 0 && ip->i_size >= lblktosize(fs, lbn + 1)) {
181
182 /*
183 * The block is an already-allocated direct block
184 * and the file already extends past this block,
185 * thus this must be a whole block.
186 * Just read the block (if requested).
187 */
188
189 if (bpp != NULL) {
190 error = bread(vp, lbn, fs->fs_bsize, NOCRED,
191 bpp);
192 if (error) {
193 brelse(*bpp);
194 return (error);
195 }
196 }
197 return (0);
198 }
199 if (nb != 0) {
200
201 /*
202 * Consider need to reallocate a fragment.
203 */
204
205 osize = fragroundup(fs, blkoff(fs, ip->i_size));
206 nsize = fragroundup(fs, size);
207 if (nsize <= osize) {
208
209 /*
210 * The existing block is already
211 * at least as big as we want.
212 * Just read the block (if requested).
213 */
214
215 if (bpp != NULL) {
216 error = bread(vp, lbn, osize, NOCRED,
217 bpp);
218 if (error) {
219 brelse(*bpp);
220 return (error);
221 }
222 }
223 return 0;
224 } else {
225
226 /*
227 * The existing block is smaller than we want,
228 * grow it.
229 */
230
231 error = ffs_realloccg(ip, lbn,
232 ffs_blkpref_ufs1(ip, lbn, (int)lbn,
233 &ip->i_ffs1_db[0]), osize, nsize, cred,
234 bpp, &newb);
235 if (error)
236 return (error);
237 if (DOINGSOFTDEP(vp))
238 softdep_setup_allocdirect(ip, lbn,
239 newb, nb, nsize, osize,
240 bpp ? *bpp : NULL);
241 }
242 } else {
243
244 /*
245 * the block was not previously allocated,
246 * allocate a new block or fragment.
247 */
248
249 if (ip->i_size < lblktosize(fs, lbn + 1))
250 nsize = fragroundup(fs, size);
251 else
252 nsize = fs->fs_bsize;
253 error = ffs_alloc(ip, lbn,
254 ffs_blkpref_ufs1(ip, lbn, (int)lbn,
255 &ip->i_ffs1_db[0]),
256 nsize, cred, &newb);
257 if (error)
258 return (error);
259 if (bpp != NULL) {
260 bp = getblk(vp, lbn, nsize, 0, 0);
261 bp->b_blkno = fsbtodb(fs, newb);
262 if (flags & B_CLRBUF)
263 clrbuf(bp);
264 *bpp = bp;
265 }
266 if (DOINGSOFTDEP(vp)) {
267 softdep_setup_allocdirect(ip, lbn, newb, 0,
268 nsize, 0, bpp ? *bpp : NULL);
269 }
270 }
271 ip->i_ffs1_db[lbn] = ufs_rw32((int32_t)newb, needswap);
272 ip->i_flag |= IN_CHANGE | IN_UPDATE;
273 return (0);
274 }
275
276 /*
277 * Determine the number of levels of indirection.
278 */
279
280 pref = 0;
281 if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
282 return (error);
283
284 /*
285 * Fetch the first indirect block allocating if necessary.
286 */
287
288 --num;
289 nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap);
290 allocib = NULL;
291 allocblk = allociblk;
292 if (nb == 0) {
293 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
294 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
295 &newb);
296 if (error)
297 goto fail;
298 nb = newb;
299 *allocblk++ = nb;
300 bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
301 bp->b_blkno = fsbtodb(fs, nb);
302 clrbuf(bp);
303 if (DOINGSOFTDEP(vp)) {
304 softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off,
305 newb, 0, fs->fs_bsize, 0, bp);
306 bdwrite(bp);
307 } else {
308
309 /*
310 * Write synchronously so that indirect blocks
311 * never point at garbage.
312 */
313
314 if ((error = bwrite(bp)) != 0)
315 goto fail;
316 }
317 unwindidx = 0;
318 allocib = &ip->i_ffs1_ib[indirs[0].in_off];
319 *allocib = ufs_rw32(nb, needswap);
320 ip->i_flag |= IN_CHANGE | IN_UPDATE;
321 }
322
323 /*
324 * Fetch through the indirect blocks, allocating as necessary.
325 */
326
327 for (i = 1;;) {
328 error = bread(vp,
329 indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
330 if (error) {
331 brelse(bp);
332 goto fail;
333 }
334 bap = (int32_t *)bp->b_data; /* XXX ondisk32 */
335 nb = ufs_rw32(bap[indirs[i].in_off], needswap);
336 if (i == num)
337 break;
338 i++;
339 if (nb != 0) {
340 brelse(bp);
341 continue;
342 }
343 if (pref == 0)
344 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
345 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
346 &newb);
347 if (error) {
348 brelse(bp);
349 goto fail;
350 }
351 nb = newb;
352 *allocblk++ = nb;
353 nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
354 nbp->b_blkno = fsbtodb(fs, nb);
355 clrbuf(nbp);
356 if (DOINGSOFTDEP(vp)) {
357 softdep_setup_allocindir_meta(nbp, ip, bp,
358 indirs[i - 1].in_off, nb);
359 bdwrite(nbp);
360 } else {
361
362 /*
363 * Write synchronously so that indirect blocks
364 * never point at garbage.
365 */
366
367 if ((error = bwrite(nbp)) != 0) {
368 brelse(bp);
369 goto fail;
370 }
371 }
372 if (unwindidx < 0)
373 unwindidx = i - 1;
374 bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap);
375
376 /*
377 * If required, write synchronously, otherwise use
378 * delayed write.
379 */
380
381 if (flags & B_SYNC) {
382 bwrite(bp);
383 } else {
384 bdwrite(bp);
385 }
386 }
387
388 /*
389 * Get the data block, allocating if necessary.
390 */
391
392 if (nb == 0) {
393 pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]);
394 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
395 &newb);
396 if (error) {
397 brelse(bp);
398 goto fail;
399 }
400 nb = newb;
401 *allocblk++ = nb;
402 if (bpp != NULL) {
403 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
404 nbp->b_blkno = fsbtodb(fs, nb);
405 if (flags & B_CLRBUF)
406 clrbuf(nbp);
407 *bpp = nbp;
408 }
409 if (DOINGSOFTDEP(vp))
410 softdep_setup_allocindir_page(ip, lbn, bp,
411 indirs[num].in_off, nb, 0, bpp ? *bpp : NULL);
412 bap[indirs[num].in_off] = ufs_rw32(nb, needswap);
413 if (allocib == NULL && unwindidx < 0) {
414 unwindidx = i - 1;
415 }
416
417 /*
418 * If required, write synchronously, otherwise use
419 * delayed write.
420 */
421
422 if (flags & B_SYNC) {
423 bwrite(bp);
424 } else {
425 bdwrite(bp);
426 }
427 return (0);
428 }
429 brelse(bp);
430 if (bpp != NULL) {
431 if (flags & B_CLRBUF) {
432 error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
433 if (error) {
434 brelse(nbp);
435 goto fail;
436 }
437 } else {
438 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
439 nbp->b_blkno = fsbtodb(fs, nb);
440 clrbuf(nbp);
441 }
442 *bpp = nbp;
443 }
444 return (0);
445
446 fail:
447 /*
448 * If we have failed part way through block allocation, we
449 * have to deallocate any indirect blocks that we have allocated.
450 */
451
452 if (unwindidx >= 0) {
453
454 /*
455 * First write out any buffers we've created to resolve their
456 * softdeps. This must be done in reverse order of creation
457 * so that we resolve the dependencies in one pass.
458 * Write the cylinder group buffers for these buffers too.
459 */
460
461 for (i = num; i >= unwindidx; i--) {
462 if (i == 0) {
463 break;
464 }
465 bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
466 0);
467 if (bp->b_flags & B_DELWRI) {
468 nb = fsbtodb(fs, cgtod(fs, dtog(fs,
469 dbtofsb(fs, bp->b_blkno))));
470 bwrite(bp);
471 bp = getblk(ip->i_devvp, nb, (int)fs->fs_cgsize,
472 0, 0);
473 if (bp->b_flags & B_DELWRI) {
474 bwrite(bp);
475 } else {
476 bp->b_flags |= B_INVAL;
477 brelse(bp);
478 }
479 } else {
480 bp->b_flags |= B_INVAL;
481 brelse(bp);
482 }
483 }
484 if (unwindidx == 0) {
485 ip->i_flag |= IN_MODIFIED | IN_CHANGE | IN_UPDATE;
486 VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
487 }
488
489 /*
490 * Now that any dependencies that we created have been
491 * resolved, we can undo the partial allocation.
492 */
493
494 if (unwindidx == 0) {
495 *allocib = 0;
496 ip->i_flag |= IN_MODIFIED | IN_CHANGE | IN_UPDATE;
497 VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
498 } else {
499 int r;
500
501 r = bread(vp, indirs[unwindidx].in_lbn,
502 (int)fs->fs_bsize, NOCRED, &bp);
503 if (r) {
504 panic("Could not unwind indirect block, error %d", r);
505 brelse(bp);
506 } else {
507 bap = (int32_t *)bp->b_data; /* XXX ondisk32 */
508 bap[indirs[unwindidx].in_off] = 0;
509 bwrite(bp);
510 }
511 }
512 for (i = unwindidx + 1; i <= num; i++) {
513 bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
514 0);
515 bp->b_flags |= B_INVAL;
516 brelse(bp);
517 }
518 }
519 for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
520 ffs_blkfree(ip, *blkp, fs->fs_bsize);
521 deallocated += fs->fs_bsize;
522 }
523 if (deallocated) {
524 #ifdef QUOTA
525 /*
526 * Restore user's disk quota because allocation failed.
527 */
528 (void)chkdq(ip, -btodb(deallocated), cred, FORCE);
529 #endif
530 ip->i_ffs1_blocks -= btodb(deallocated);
531 ip->i_flag |= IN_CHANGE | IN_UPDATE;
532 }
533 return (error);
534 }
535
536 static int
537 ffs_balloc_ufs2(v)
538 void *v;
539 {
540 struct vop_balloc_args /* {
541 struct vnode *a_vp;
542 off_t a_startoffset;
543 int a_size;
544 struct ucred *a_cred;
545 int a_flags;
546 struct buf **a_bpp;
547 } */ *ap = v;
548 daddr_t lbn, lastlbn;
549 int size;
550 struct ucred *cred;
551 int flags;
552 struct buf *bp, *nbp;
553 struct vnode *vp = ap->a_vp;
554 struct inode *ip = VTOI(vp);
555 struct fs *fs = ip->i_fs;
556 struct indir indirs[NIADDR + 2];
557 daddr_t newb, pref, nb;
558 int64_t *bap;
559 int deallocated, osize, nsize, num, i, error;
560 daddr_t *blkp, *allocblk, allociblk[NIADDR + 1];
561 int64_t *allocib;
562 int unwindidx = -1;
563 struct buf **bpp = ap->a_bpp;
564 #ifdef FFS_EI
565 const int needswap = UFS_FSNEEDSWAP(fs);
566 #endif
567 UVMHIST_FUNC("ffs_balloc"); UVMHIST_CALLED(ubchist);
568
569 lbn = lblkno(fs, ap->a_startoffset);
570 size = blkoff(fs, ap->a_startoffset) + ap->a_size;
571 if (size > fs->fs_bsize)
572 panic("ffs_balloc: blk too big");
573 if (bpp != NULL) {
574 *bpp = NULL;
575 }
576 UVMHIST_LOG(ubchist, "vp %p lbn 0x%x size 0x%x", vp, lbn, size,0);
577
578 KASSERT(size <= fs->fs_bsize);
579 if (lbn < 0)
580 return (EFBIG);
581 cred = ap->a_cred;
582 flags = ap->a_flags;
583
584 #ifdef notyet
585 /*
586 * Check for allocating external data.
587 */
588 if (flags & IO_EXT) {
589 if (lbn >= NXADDR)
590 return (EFBIG);
591 /*
592 * If the next write will extend the data into a new block,
593 * and the data is currently composed of a fragment
594 * this fragment has to be extended to be a full block.
595 */
596 lastlbn = lblkno(fs, dp->di_extsize);
597 if (lastlbn < lbn) {
598 nb = lastlbn;
599 osize = sblksize(fs, dp->di_extsize, nb);
600 if (osize < fs->fs_bsize && osize > 0) {
601 error = ffs_realloccg(ip, -1 - nb,
602 dp->di_extb[nb],
603 ffs_blkpref_ufs2(ip, lastlbn, (int)nb,
604 &dp->di_extb[0]), osize,
605 (int)fs->fs_bsize, cred, &bp);
606 if (error)
607 return (error);
608 if (DOINGSOFTDEP(vp))
609 softdep_setup_allocext(ip, nb,
610 dbtofsb(fs, bp->b_blkno),
611 dp->di_extb[nb],
612 fs->fs_bsize, osize, bp);
613 dp->di_extsize = smalllblktosize(fs, nb + 1);
614 dp->di_extb[nb] = dbtofsb(fs, bp->b_blkno);
615 bp->b_xflags |= BX_ALTDATA;
616 ip->i_flag |= IN_CHANGE | IN_UPDATE;
617 if (flags & IO_SYNC)
618 bwrite(bp);
619 else
620 bawrite(bp);
621 }
622 }
623 /*
624 * All blocks are direct blocks
625 */
626 if (flags & BA_METAONLY)
627 panic("ffs_balloc_ufs2: BA_METAONLY for ext block");
628 nb = dp->di_extb[lbn];
629 if (nb != 0 && dp->di_extsize >= smalllblktosize(fs, lbn + 1)) {
630 error = bread(vp, -1 - lbn, fs->fs_bsize, NOCRED, &bp);
631 if (error) {
632 brelse(bp);
633 return (error);
634 }
635 bp->b_blkno = fsbtodb(fs, nb);
636 bp->b_xflags |= BX_ALTDATA;
637 *bpp = bp;
638 return (0);
639 }
640 if (nb != 0) {
641 /*
642 * Consider need to reallocate a fragment.
643 */
644 osize = fragroundup(fs, blkoff(fs, dp->di_extsize));
645 nsize = fragroundup(fs, size);
646 if (nsize <= osize) {
647 error = bread(vp, -1 - lbn, osize, NOCRED, &bp);
648 if (error) {
649 brelse(bp);
650 return (error);
651 }
652 bp->b_blkno = fsbtodb(fs, nb);
653 bp->b_xflags |= BX_ALTDATA;
654 } else {
655 error = ffs_realloccg(ip, -1 - lbn,
656 dp->di_extb[lbn],
657 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
658 &dp->di_extb[0]), osize, nsize, cred, &bp);
659 if (error)
660 return (error);
661 bp->b_xflags |= BX_ALTDATA;
662 if (DOINGSOFTDEP(vp))
663 softdep_setup_allocext(ip, lbn,
664 dbtofsb(fs, bp->b_blkno), nb,
665 nsize, osize, bp);
666 }
667 } else {
668 if (dp->di_extsize < smalllblktosize(fs, lbn + 1))
669 nsize = fragroundup(fs, size);
670 else
671 nsize = fs->fs_bsize;
672 error = ffs_alloc(ip, lbn,
673 ffs_blkpref_ufs2(ip, lbn, (int)lbn, &dp->di_extb[0]),
674 nsize, cred, &newb);
675 if (error)
676 return (error);
677 bp = getblk(vp, -1 - lbn, nsize, 0, 0);
678 bp->b_blkno = fsbtodb(fs, newb);
679 bp->b_xflags |= BX_ALTDATA;
680 if (flags & BA_CLRBUF)
681 vfs_bio_clrbuf(bp);
682 if (DOINGSOFTDEP(vp))
683 softdep_setup_allocext(ip, lbn, newb, 0,
684 nsize, 0, bp);
685 }
686 dp->di_extb[lbn] = dbtofsb(fs, bp->b_blkno);
687 ip->i_flag |= IN_CHANGE | IN_UPDATE;
688 *bpp = bp;
689 return (0);
690 }
691 #endif
692 /*
693 * If the next write will extend the file into a new block,
694 * and the file is currently composed of a fragment
695 * this fragment has to be extended to be a full block.
696 */
697
698 lastlbn = lblkno(fs, ip->i_size);
699 if (lastlbn < NDADDR && lastlbn < lbn) {
700 nb = lastlbn;
701 osize = blksize(fs, ip, nb);
702 if (osize < fs->fs_bsize && osize > 0) {
703 error = ffs_realloccg(ip, nb,
704 ffs_blkpref_ufs2(ip, lastlbn, nb,
705 &ip->i_ffs2_db[0]),
706 osize, (int)fs->fs_bsize, cred, bpp, &newb);
707 if (error)
708 return (error);
709 if (DOINGSOFTDEP(vp))
710 softdep_setup_allocdirect(ip, nb, newb,
711 ufs_rw64(ip->i_ffs2_db[nb], needswap),
712 fs->fs_bsize, osize, bpp ? *bpp : NULL);
713 ip->i_size = lblktosize(fs, nb + 1);
714 ip->i_ffs2_size = ip->i_size;
715 uvm_vnp_setsize(vp, ip->i_size);
716 ip->i_ffs2_db[nb] = ufs_rw64(newb, needswap);
717 ip->i_flag |= IN_CHANGE | IN_UPDATE;
718 if (bpp) {
719 if (flags & B_SYNC)
720 bwrite(*bpp);
721 else
722 bawrite(*bpp);
723 }
724 }
725 }
726
727 /*
728 * The first NDADDR blocks are direct blocks
729 */
730
731 if (lbn < NDADDR) {
732 nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap);
733 if (nb != 0 && ip->i_size >= lblktosize(fs, lbn + 1)) {
734
735 /*
736 * The block is an already-allocated direct block
737 * and the file already extends past this block,
738 * thus this must be a whole block.
739 * Just read the block (if requested).
740 */
741
742 if (bpp != NULL) {
743 error = bread(vp, lbn, fs->fs_bsize, NOCRED,
744 bpp);
745 if (error) {
746 brelse(*bpp);
747 return (error);
748 }
749 }
750 return (0);
751 }
752 if (nb != 0) {
753
754 /*
755 * Consider need to reallocate a fragment.
756 */
757
758 osize = fragroundup(fs, blkoff(fs, ip->i_size));
759 nsize = fragroundup(fs, size);
760 if (nsize <= osize) {
761
762 /*
763 * The existing block is already
764 * at least as big as we want.
765 * Just read the block (if requested).
766 */
767
768 if (bpp != NULL) {
769 error = bread(vp, lbn, osize, NOCRED,
770 bpp);
771 if (error) {
772 brelse(*bpp);
773 return (error);
774 }
775 }
776 return 0;
777 } else {
778
779 /*
780 * The existing block is smaller than we want,
781 * grow it.
782 */
783
784 error = ffs_realloccg(ip, lbn,
785 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
786 &ip->i_ffs2_db[0]), osize, nsize, cred,
787 bpp, &newb);
788 if (error)
789 return (error);
790 if (DOINGSOFTDEP(vp))
791 softdep_setup_allocdirect(ip, lbn,
792 newb, nb, nsize, osize,
793 bpp ? *bpp : NULL);
794 }
795 } else {
796
797 /*
798 * the block was not previously allocated,
799 * allocate a new block or fragment.
800 */
801
802 if (ip->i_size < lblktosize(fs, lbn + 1))
803 nsize = fragroundup(fs, size);
804 else
805 nsize = fs->fs_bsize;
806 error = ffs_alloc(ip, lbn,
807 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
808 &ip->i_ffs2_db[0]), nsize, cred, &newb);
809 if (error)
810 return (error);
811 if (bpp != NULL) {
812 bp = getblk(vp, lbn, nsize, 0, 0);
813 bp->b_blkno = fsbtodb(fs, newb);
814 if (flags & B_CLRBUF)
815 clrbuf(bp);
816 *bpp = bp;
817 }
818 if (DOINGSOFTDEP(vp)) {
819 softdep_setup_allocdirect(ip, lbn, newb, 0,
820 nsize, 0, bpp ? *bpp : NULL);
821 }
822 }
823 ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap);
824 ip->i_flag |= IN_CHANGE | IN_UPDATE;
825 return (0);
826 }
827
828 /*
829 * Determine the number of levels of indirection.
830 */
831
832 pref = 0;
833 if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
834 return (error);
835
836 /*
837 * Fetch the first indirect block allocating if necessary.
838 */
839
840 --num;
841 nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap);
842 allocib = NULL;
843 allocblk = allociblk;
844 if (nb == 0) {
845 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
846 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
847 &newb);
848 if (error)
849 goto fail;
850 nb = newb;
851 *allocblk++ = nb;
852 bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
853 bp->b_blkno = fsbtodb(fs, nb);
854 clrbuf(bp);
855 if (DOINGSOFTDEP(vp)) {
856 softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off,
857 newb, 0, fs->fs_bsize, 0, bp);
858 bdwrite(bp);
859 } else {
860
861 /*
862 * Write synchronously so that indirect blocks
863 * never point at garbage.
864 */
865
866 if ((error = bwrite(bp)) != 0)
867 goto fail;
868 }
869 unwindidx = 0;
870 allocib = &ip->i_ffs2_ib[indirs[0].in_off];
871 *allocib = ufs_rw64(nb, needswap);
872 ip->i_flag |= IN_CHANGE | IN_UPDATE;
873 }
874
875 /*
876 * Fetch through the indirect blocks, allocating as necessary.
877 */
878
879 for (i = 1;;) {
880 error = bread(vp,
881 indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
882 if (error) {
883 brelse(bp);
884 goto fail;
885 }
886 bap = (int64_t *)bp->b_data;
887 nb = ufs_rw64(bap[indirs[i].in_off], needswap);
888 if (i == num)
889 break;
890 i++;
891 if (nb != 0) {
892 brelse(bp);
893 continue;
894 }
895 if (pref == 0)
896 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
897 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
898 &newb);
899 if (error) {
900 brelse(bp);
901 goto fail;
902 }
903 nb = newb;
904 *allocblk++ = nb;
905 nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
906 nbp->b_blkno = fsbtodb(fs, nb);
907 clrbuf(nbp);
908 if (DOINGSOFTDEP(vp)) {
909 softdep_setup_allocindir_meta(nbp, ip, bp,
910 indirs[i - 1].in_off, nb);
911 bdwrite(nbp);
912 } else {
913
914 /*
915 * Write synchronously so that indirect blocks
916 * never point at garbage.
917 */
918
919 if ((error = bwrite(nbp)) != 0) {
920 brelse(bp);
921 goto fail;
922 }
923 }
924 if (unwindidx < 0)
925 unwindidx = i - 1;
926 bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap);
927
928 /*
929 * If required, write synchronously, otherwise use
930 * delayed write.
931 */
932
933 if (flags & B_SYNC) {
934 bwrite(bp);
935 } else {
936 bdwrite(bp);
937 }
938 }
939
940 /*
941 * Get the data block, allocating if necessary.
942 */
943
944 if (nb == 0) {
945 pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]);
946 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
947 &newb);
948 if (error) {
949 brelse(bp);
950 goto fail;
951 }
952 nb = newb;
953 *allocblk++ = nb;
954 if (bpp != NULL) {
955 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
956 nbp->b_blkno = fsbtodb(fs, nb);
957 if (flags & B_CLRBUF)
958 clrbuf(nbp);
959 *bpp = nbp;
960 }
961 if (DOINGSOFTDEP(vp))
962 softdep_setup_allocindir_page(ip, lbn, bp,
963 indirs[num].in_off, nb, 0, bpp ? *bpp : NULL);
964 bap[indirs[num].in_off] = ufs_rw64(nb, needswap);
965 if (allocib == NULL && unwindidx < 0) {
966 unwindidx = i - 1;
967 }
968
969 /*
970 * If required, write synchronously, otherwise use
971 * delayed write.
972 */
973
974 if (flags & B_SYNC) {
975 bwrite(bp);
976 } else {
977 bdwrite(bp);
978 }
979 return (0);
980 }
981 brelse(bp);
982 if (bpp != NULL) {
983 if (flags & B_CLRBUF) {
984 error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
985 if (error) {
986 brelse(nbp);
987 goto fail;
988 }
989 } else {
990 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
991 nbp->b_blkno = fsbtodb(fs, nb);
992 clrbuf(nbp);
993 }
994 *bpp = nbp;
995 }
996 return (0);
997
998 fail:
999 /*
1000 * If we have failed part way through block allocation, we
1001 * have to deallocate any indirect blocks that we have allocated.
1002 */
1003
1004 if (unwindidx >= 0) {
1005
1006 /*
1007 * First write out any buffers we've created to resolve their
1008 * softdeps. This must be done in reverse order of creation
1009 * so that we resolve the dependencies in one pass.
1010 * Write the cylinder group buffers for these buffers too.
1011 */
1012
1013 for (i = num; i >= unwindidx; i--) {
1014 if (i == 0) {
1015 break;
1016 }
1017 bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
1018 0);
1019 if (bp->b_flags & B_DELWRI) {
1020 nb = fsbtodb(fs, cgtod(fs, dtog(fs,
1021 dbtofsb(fs, bp->b_blkno))));
1022 bwrite(bp);
1023 bp = getblk(ip->i_devvp, nb, (int)fs->fs_cgsize,
1024 0, 0);
1025 if (bp->b_flags & B_DELWRI) {
1026 bwrite(bp);
1027 } else {
1028 bp->b_flags |= B_INVAL;
1029 brelse(bp);
1030 }
1031 } else {
1032 bp->b_flags |= B_INVAL;
1033 brelse(bp);
1034 }
1035 }
1036 if (unwindidx == 0) {
1037 ip->i_flag |= IN_MODIFIED | IN_CHANGE | IN_UPDATE;
1038 VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
1039 }
1040
1041 /*
1042 * Now that any dependencies that we created have been
1043 * resolved, we can undo the partial allocation.
1044 */
1045
1046 if (unwindidx == 0) {
1047 *allocib = 0;
1048 ip->i_flag |= IN_MODIFIED | IN_CHANGE | IN_UPDATE;
1049 VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
1050 } else {
1051 int r;
1052
1053 r = bread(vp, indirs[unwindidx].in_lbn,
1054 (int)fs->fs_bsize, NOCRED, &bp);
1055 if (r) {
1056 panic("Could not unwind indirect block, error %d", r);
1057 brelse(bp);
1058 } else {
1059 bap = (int64_t *)bp->b_data;
1060 bap[indirs[unwindidx].in_off] = 0;
1061 bwrite(bp);
1062 }
1063 }
1064 for (i = unwindidx + 1; i <= num; i++) {
1065 bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
1066 0);
1067 bp->b_flags |= B_INVAL;
1068 brelse(bp);
1069 }
1070 }
1071 for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
1072 ffs_blkfree(ip, *blkp, fs->fs_bsize);
1073 deallocated += fs->fs_bsize;
1074 }
1075 if (deallocated) {
1076 #ifdef QUOTA
1077 /*
1078 * Restore user's disk quota because allocation failed.
1079 */
1080 (void)chkdq(ip, -btodb(deallocated), cred, FORCE);
1081 #endif
1082 ip->i_ffs2_blocks -= btodb(deallocated);
1083 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1084 }
1085 return (error);
1086 }
Cache object: 414d944b37dd283a1cb54865a95d3105
|