[BACK]Return to ffs_balloc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / ufs / ffs

Annotation of src/sys/ufs/ffs/ffs_balloc.c, Revision 1.45.6.2

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

CVSweb <webmaster@jp.NetBSD.org>