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