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