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