ffs_balloc.c revision 1.40.8.1 1 /* $NetBSD: ffs_balloc.c,v 1.40.8.1 2006/04/01 12:07:51 yamt 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.40.8.1 2006/04/01 12:07:51 yamt 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(struct vnode *, off_t, int, struct ucred *, int,
70 struct buf **);
71 static int ffs_balloc_ufs2(struct vnode *, off_t, int, struct ucred *, 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, struct ucred *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, struct ucred *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) {
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 if (DOINGSOFTDEP(vp) && unwindidx == 0) {
476 ip->i_flag |= IN_CHANGE | IN_UPDATE;
477 ffs_update(vp, NULL, NULL, UPDATE_WAIT);
478 }
479
480 /*
481 * Now that any dependencies that we created have been
482 * resolved, we can undo the partial allocation.
483 */
484
485 if (unwindidx == 0) {
486 *allocib = 0;
487 ip->i_flag |= IN_CHANGE | IN_UPDATE;
488 if (DOINGSOFTDEP(vp))
489 ffs_update(vp, NULL, NULL, UPDATE_WAIT);
490 } else {
491 int r;
492
493 r = bread(vp, indirs[unwindidx].in_lbn,
494 (int)fs->fs_bsize, NOCRED, &bp);
495 if (r) {
496 panic("Could not unwind indirect block, error %d", r);
497 brelse(bp);
498 } else {
499 bap = (int32_t *)bp->b_data; /* XXX ondisk32 */
500 bap[indirs[unwindidx].in_off] = 0;
501 bwrite(bp);
502 }
503 }
504 for (i = unwindidx + 1; i <= num; i++) {
505 bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
506 0);
507 bp->b_flags |= B_INVAL;
508 brelse(bp);
509 }
510 }
511 for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
512 ffs_blkfree(fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number);
513 deallocated += fs->fs_bsize;
514 }
515 if (deallocated) {
516 #ifdef QUOTA
517 /*
518 * Restore user's disk quota because allocation failed.
519 */
520 (void)chkdq(ip, -btodb(deallocated), cred, FORCE);
521 #endif
522 ip->i_ffs1_blocks -= btodb(deallocated);
523 ip->i_flag |= IN_CHANGE | IN_UPDATE;
524 }
525 return (error);
526 }
527
528 static int
529 ffs_balloc_ufs2(struct vnode *vp, off_t off, int size, struct ucred *cred,
530 int flags, struct buf **bpp)
531 {
532 daddr_t lbn, lastlbn;
533 struct buf *bp, *nbp;
534 struct inode *ip = VTOI(vp);
535 struct fs *fs = ip->i_fs;
536 struct indir indirs[NIADDR + 2];
537 daddr_t newb, pref, nb;
538 int64_t *bap;
539 int deallocated, osize, nsize, num, i, error;
540 daddr_t *blkp, *allocblk, allociblk[NIADDR + 1];
541 int64_t *allocib;
542 int unwindidx = -1;
543 #ifdef FFS_EI
544 const int needswap = UFS_FSNEEDSWAP(fs);
545 #endif
546 UVMHIST_FUNC("ffs_balloc"); UVMHIST_CALLED(ubchist);
547
548 lbn = lblkno(fs, off);
549 size = blkoff(fs, off) + size;
550 if (size > fs->fs_bsize)
551 panic("ffs_balloc: blk too big");
552 if (bpp != NULL) {
553 *bpp = NULL;
554 }
555 UVMHIST_LOG(ubchist, "vp %p lbn 0x%x size 0x%x", vp, lbn, size,0);
556
557 KASSERT(size <= fs->fs_bsize);
558 if (lbn < 0)
559 return (EFBIG);
560
561 #ifdef notyet
562 /*
563 * Check for allocating external data.
564 */
565 if (flags & IO_EXT) {
566 if (lbn >= NXADDR)
567 return (EFBIG);
568 /*
569 * If the next write will extend the data into a new block,
570 * and the data is currently composed of a fragment
571 * this fragment has to be extended to be a full block.
572 */
573 lastlbn = lblkno(fs, dp->di_extsize);
574 if (lastlbn < lbn) {
575 nb = lastlbn;
576 osize = sblksize(fs, dp->di_extsize, nb);
577 if (osize < fs->fs_bsize && osize > 0) {
578 error = ffs_realloccg(ip, -1 - nb,
579 dp->di_extb[nb],
580 ffs_blkpref_ufs2(ip, lastlbn, (int)nb,
581 &dp->di_extb[0]), osize,
582 (int)fs->fs_bsize, cred, &bp);
583 if (error)
584 return (error);
585 if (DOINGSOFTDEP(vp))
586 softdep_setup_allocext(ip, nb,
587 dbtofsb(fs, bp->b_blkno),
588 dp->di_extb[nb],
589 fs->fs_bsize, osize, bp);
590 dp->di_extsize = smalllblktosize(fs, nb + 1);
591 dp->di_extb[nb] = dbtofsb(fs, bp->b_blkno);
592 bp->b_xflags |= BX_ALTDATA;
593 ip->i_flag |= IN_CHANGE | IN_UPDATE;
594 if (flags & IO_SYNC)
595 bwrite(bp);
596 else
597 bawrite(bp);
598 }
599 }
600 /*
601 * All blocks are direct blocks
602 */
603 if (flags & BA_METAONLY)
604 panic("ffs_balloc_ufs2: BA_METAONLY for ext block");
605 nb = dp->di_extb[lbn];
606 if (nb != 0 && dp->di_extsize >= smalllblktosize(fs, lbn + 1)) {
607 error = bread(vp, -1 - lbn, fs->fs_bsize, NOCRED, &bp);
608 if (error) {
609 brelse(bp);
610 return (error);
611 }
612 bp->b_blkno = fsbtodb(fs, nb);
613 bp->b_xflags |= BX_ALTDATA;
614 *bpp = bp;
615 return (0);
616 }
617 if (nb != 0) {
618 /*
619 * Consider need to reallocate a fragment.
620 */
621 osize = fragroundup(fs, blkoff(fs, dp->di_extsize));
622 nsize = fragroundup(fs, size);
623 if (nsize <= osize) {
624 error = bread(vp, -1 - lbn, osize, NOCRED, &bp);
625 if (error) {
626 brelse(bp);
627 return (error);
628 }
629 bp->b_blkno = fsbtodb(fs, nb);
630 bp->b_xflags |= BX_ALTDATA;
631 } else {
632 error = ffs_realloccg(ip, -1 - lbn,
633 dp->di_extb[lbn],
634 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
635 &dp->di_extb[0]), osize, nsize, cred, &bp);
636 if (error)
637 return (error);
638 bp->b_xflags |= BX_ALTDATA;
639 if (DOINGSOFTDEP(vp))
640 softdep_setup_allocext(ip, lbn,
641 dbtofsb(fs, bp->b_blkno), nb,
642 nsize, osize, bp);
643 }
644 } else {
645 if (dp->di_extsize < smalllblktosize(fs, lbn + 1))
646 nsize = fragroundup(fs, size);
647 else
648 nsize = fs->fs_bsize;
649 error = ffs_alloc(ip, lbn,
650 ffs_blkpref_ufs2(ip, lbn, (int)lbn, &dp->di_extb[0]),
651 nsize, cred, &newb);
652 if (error)
653 return (error);
654 bp = getblk(vp, -1 - lbn, nsize, 0, 0);
655 bp->b_blkno = fsbtodb(fs, newb);
656 bp->b_xflags |= BX_ALTDATA;
657 if (flags & BA_CLRBUF)
658 vfs_bio_clrbuf(bp);
659 if (DOINGSOFTDEP(vp))
660 softdep_setup_allocext(ip, lbn, newb, 0,
661 nsize, 0, bp);
662 }
663 dp->di_extb[lbn] = dbtofsb(fs, bp->b_blkno);
664 ip->i_flag |= IN_CHANGE | IN_UPDATE;
665 *bpp = bp;
666 return (0);
667 }
668 #endif
669 /*
670 * If the next write will extend the file into a new block,
671 * and the file is currently composed of a fragment
672 * this fragment has to be extended to be a full block.
673 */
674
675 lastlbn = lblkno(fs, ip->i_size);
676 if (lastlbn < NDADDR && lastlbn < lbn) {
677 nb = lastlbn;
678 osize = blksize(fs, ip, nb);
679 if (osize < fs->fs_bsize && osize > 0) {
680 error = ffs_realloccg(ip, nb,
681 ffs_blkpref_ufs2(ip, lastlbn, nb,
682 &ip->i_ffs2_db[0]),
683 osize, (int)fs->fs_bsize, cred, bpp, &newb);
684 if (error)
685 return (error);
686 if (DOINGSOFTDEP(vp))
687 softdep_setup_allocdirect(ip, nb, newb,
688 ufs_rw64(ip->i_ffs2_db[nb], needswap),
689 fs->fs_bsize, osize, bpp ? *bpp : NULL);
690 ip->i_size = lblktosize(fs, nb + 1);
691 ip->i_ffs2_size = ip->i_size;
692 uvm_vnp_setsize(vp, ip->i_size);
693 ip->i_ffs2_db[nb] = ufs_rw64(newb, needswap);
694 ip->i_flag |= IN_CHANGE | IN_UPDATE;
695 if (bpp) {
696 if (flags & B_SYNC)
697 bwrite(*bpp);
698 else
699 bawrite(*bpp);
700 }
701 }
702 }
703
704 /*
705 * The first NDADDR blocks are direct blocks
706 */
707
708 if (lbn < NDADDR) {
709 nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap);
710 if (nb != 0 && ip->i_size >= lblktosize(fs, lbn + 1)) {
711
712 /*
713 * The block is an already-allocated direct block
714 * and the file already extends past this block,
715 * thus this must be a whole block.
716 * Just read the block (if requested).
717 */
718
719 if (bpp != NULL) {
720 error = bread(vp, lbn, fs->fs_bsize, NOCRED,
721 bpp);
722 if (error) {
723 brelse(*bpp);
724 return (error);
725 }
726 }
727 return (0);
728 }
729 if (nb != 0) {
730
731 /*
732 * Consider need to reallocate a fragment.
733 */
734
735 osize = fragroundup(fs, blkoff(fs, ip->i_size));
736 nsize = fragroundup(fs, size);
737 if (nsize <= osize) {
738
739 /*
740 * The existing block is already
741 * at least as big as we want.
742 * Just read the block (if requested).
743 */
744
745 if (bpp != NULL) {
746 error = bread(vp, lbn, osize, NOCRED,
747 bpp);
748 if (error) {
749 brelse(*bpp);
750 return (error);
751 }
752 }
753 return 0;
754 } else {
755
756 /*
757 * The existing block is smaller than we want,
758 * grow it.
759 */
760
761 error = ffs_realloccg(ip, lbn,
762 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
763 &ip->i_ffs2_db[0]), osize, nsize, cred,
764 bpp, &newb);
765 if (error)
766 return (error);
767 if (DOINGSOFTDEP(vp))
768 softdep_setup_allocdirect(ip, lbn,
769 newb, nb, nsize, osize,
770 bpp ? *bpp : NULL);
771 }
772 } else {
773
774 /*
775 * the block was not previously allocated,
776 * allocate a new block or fragment.
777 */
778
779 if (ip->i_size < lblktosize(fs, lbn + 1))
780 nsize = fragroundup(fs, size);
781 else
782 nsize = fs->fs_bsize;
783 error = ffs_alloc(ip, lbn,
784 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
785 &ip->i_ffs2_db[0]), nsize, cred, &newb);
786 if (error)
787 return (error);
788 if (bpp != NULL) {
789 bp = getblk(vp, lbn, nsize, 0, 0);
790 bp->b_blkno = fsbtodb(fs, newb);
791 if (flags & B_CLRBUF)
792 clrbuf(bp);
793 *bpp = bp;
794 }
795 if (DOINGSOFTDEP(vp)) {
796 softdep_setup_allocdirect(ip, lbn, newb, 0,
797 nsize, 0, bpp ? *bpp : NULL);
798 }
799 }
800 ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap);
801 ip->i_flag |= IN_CHANGE | IN_UPDATE;
802 return (0);
803 }
804
805 /*
806 * Determine the number of levels of indirection.
807 */
808
809 pref = 0;
810 if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
811 return (error);
812
813 /*
814 * Fetch the first indirect block allocating if necessary.
815 */
816
817 --num;
818 nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap);
819 allocib = NULL;
820 allocblk = allociblk;
821 if (nb == 0) {
822 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
823 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
824 &newb);
825 if (error)
826 goto fail;
827 nb = newb;
828 *allocblk++ = nb;
829 bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
830 bp->b_blkno = fsbtodb(fs, nb);
831 clrbuf(bp);
832 if (DOINGSOFTDEP(vp)) {
833 softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off,
834 newb, 0, fs->fs_bsize, 0, bp);
835 bdwrite(bp);
836 } else {
837
838 /*
839 * Write synchronously so that indirect blocks
840 * never point at garbage.
841 */
842
843 if ((error = bwrite(bp)) != 0)
844 goto fail;
845 }
846 unwindidx = 0;
847 allocib = &ip->i_ffs2_ib[indirs[0].in_off];
848 *allocib = ufs_rw64(nb, needswap);
849 ip->i_flag |= IN_CHANGE | IN_UPDATE;
850 }
851
852 /*
853 * Fetch through the indirect blocks, allocating as necessary.
854 */
855
856 for (i = 1;;) {
857 error = bread(vp,
858 indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
859 if (error) {
860 brelse(bp);
861 goto fail;
862 }
863 bap = (int64_t *)bp->b_data;
864 nb = ufs_rw64(bap[indirs[i].in_off], needswap);
865 if (i == num)
866 break;
867 i++;
868 if (nb != 0) {
869 brelse(bp);
870 continue;
871 }
872 if (pref == 0)
873 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
874 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
875 &newb);
876 if (error) {
877 brelse(bp);
878 goto fail;
879 }
880 nb = newb;
881 *allocblk++ = nb;
882 nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
883 nbp->b_blkno = fsbtodb(fs, nb);
884 clrbuf(nbp);
885 if (DOINGSOFTDEP(vp)) {
886 softdep_setup_allocindir_meta(nbp, ip, bp,
887 indirs[i - 1].in_off, nb);
888 bdwrite(nbp);
889 } else {
890
891 /*
892 * Write synchronously so that indirect blocks
893 * never point at garbage.
894 */
895
896 if ((error = bwrite(nbp)) != 0) {
897 brelse(bp);
898 goto fail;
899 }
900 }
901 if (unwindidx < 0)
902 unwindidx = i - 1;
903 bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap);
904
905 /*
906 * If required, write synchronously, otherwise use
907 * delayed write.
908 */
909
910 if (flags & B_SYNC) {
911 bwrite(bp);
912 } else {
913 bdwrite(bp);
914 }
915 }
916
917 if (flags & B_METAONLY) {
918 KASSERT(bpp != NULL);
919 *bpp = bp;
920 return (0);
921 }
922
923 /*
924 * Get the data block, allocating if necessary.
925 */
926
927 if (nb == 0) {
928 pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]);
929 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
930 &newb);
931 if (error) {
932 brelse(bp);
933 goto fail;
934 }
935 nb = newb;
936 *allocblk++ = nb;
937 if (bpp != NULL) {
938 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
939 nbp->b_blkno = fsbtodb(fs, nb);
940 if (flags & B_CLRBUF)
941 clrbuf(nbp);
942 *bpp = nbp;
943 }
944 if (DOINGSOFTDEP(vp))
945 softdep_setup_allocindir_page(ip, lbn, bp,
946 indirs[num].in_off, nb, 0, bpp ? *bpp : NULL);
947 bap[indirs[num].in_off] = ufs_rw64(nb, needswap);
948 if (allocib == NULL && unwindidx < 0) {
949 unwindidx = i - 1;
950 }
951
952 /*
953 * If required, write synchronously, otherwise use
954 * delayed write.
955 */
956
957 if (flags & B_SYNC) {
958 bwrite(bp);
959 } else {
960 bdwrite(bp);
961 }
962 return (0);
963 }
964 brelse(bp);
965 if (bpp != NULL) {
966 if (flags & B_CLRBUF) {
967 error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
968 if (error) {
969 brelse(nbp);
970 goto fail;
971 }
972 } else {
973 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
974 nbp->b_blkno = fsbtodb(fs, nb);
975 clrbuf(nbp);
976 }
977 *bpp = nbp;
978 }
979 return (0);
980
981 fail:
982 /*
983 * If we have failed part way through block allocation, we
984 * have to deallocate any indirect blocks that we have allocated.
985 */
986
987 if (unwindidx >= 0) {
988
989 /*
990 * First write out any buffers we've created to resolve their
991 * softdeps. This must be done in reverse order of creation
992 * so that we resolve the dependencies in one pass.
993 * Write the cylinder group buffers for these buffers too.
994 */
995
996 for (i = num; i >= unwindidx; i--) {
997 if (i == 0) {
998 break;
999 }
1000 bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
1001 0);
1002 if (bp->b_flags & B_DELWRI) {
1003 nb = fsbtodb(fs, cgtod(fs, dtog(fs,
1004 dbtofsb(fs, bp->b_blkno))));
1005 bwrite(bp);
1006 bp = getblk(ip->i_devvp, nb, (int)fs->fs_cgsize,
1007 0, 0);
1008 if (bp->b_flags & B_DELWRI) {
1009 bwrite(bp);
1010 } else {
1011 bp->b_flags |= B_INVAL;
1012 brelse(bp);
1013 }
1014 } else {
1015 bp->b_flags |= B_INVAL;
1016 brelse(bp);
1017 }
1018 }
1019 if (DOINGSOFTDEP(vp) && unwindidx == 0) {
1020 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1021 ffs_update(vp, NULL, NULL, UPDATE_WAIT);
1022 }
1023
1024 /*
1025 * Now that any dependencies that we created have been
1026 * resolved, we can undo the partial allocation.
1027 */
1028
1029 if (unwindidx == 0) {
1030 *allocib = 0;
1031 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1032 if (DOINGSOFTDEP(vp))
1033 ffs_update(vp, NULL, NULL, UPDATE_WAIT);
1034 } else {
1035 int r;
1036
1037 r = bread(vp, indirs[unwindidx].in_lbn,
1038 (int)fs->fs_bsize, NOCRED, &bp);
1039 if (r) {
1040 panic("Could not unwind indirect block, error %d", r);
1041 brelse(bp);
1042 } else {
1043 bap = (int64_t *)bp->b_data;
1044 bap[indirs[unwindidx].in_off] = 0;
1045 bwrite(bp);
1046 }
1047 }
1048 for (i = unwindidx + 1; i <= num; i++) {
1049 bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0,
1050 0);
1051 bp->b_flags |= B_INVAL;
1052 brelse(bp);
1053 }
1054 }
1055 for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
1056 ffs_blkfree(fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number);
1057 deallocated += fs->fs_bsize;
1058 }
1059 if (deallocated) {
1060 #ifdef QUOTA
1061 /*
1062 * Restore user's disk quota because allocation failed.
1063 */
1064 (void)chkdq(ip, -btodb(deallocated), cred, FORCE);
1065 #endif
1066 ip->i_ffs2_blocks -= btodb(deallocated);
1067 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1068 }
1069 return (error);
1070 }
1071