LCOV - code coverage report
Current view: top level - ufs/ffs - ffs_balloc.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 463 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.13