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