The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ufs/ext2fs/ext2fs_inode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ext2fs_inode.c,v 1.40 2004/03/22 19:23:08 bouyer Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1982, 1986, 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)ffs_inode.c 8.8 (Berkeley) 10/19/94
   32  * Modified for ext2fs by Manuel Bouyer.
   33  */
   34 
   35 /*
   36  * Copyright (c) 1997 Manuel Bouyer.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. All advertising materials mentioning features or use of this software
   47  *    must display the following acknowledgement:
   48  *      This product includes software developed by Manuel Bouyer.
   49  * 4. The name of the author may not be used to endorse or promote products
   50  *    derived from this software without specific prior written permission.
   51  *
   52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   53  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   54  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   55  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   56  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   57  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   58  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   59  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   60  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   61  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   62  *
   63  *      @(#)ffs_inode.c 8.8 (Berkeley) 10/19/94
   64  * Modified for ext2fs by Manuel Bouyer.
   65  */
   66 
   67 #include <sys/cdefs.h>
   68 __KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.40 2004/03/22 19:23:08 bouyer Exp $");
   69 
   70 #include <sys/param.h>
   71 #include <sys/systm.h>
   72 #include <sys/mount.h>
   73 #include <sys/proc.h>
   74 #include <sys/file.h>
   75 #include <sys/buf.h>
   76 #include <sys/vnode.h>
   77 #include <sys/kernel.h>
   78 #include <sys/malloc.h>
   79 #include <sys/trace.h>
   80 #include <sys/resourcevar.h>
   81 
   82 #include <ufs/ufs/inode.h>
   83 #include <ufs/ufs/ufsmount.h>
   84 #include <ufs/ufs/ufs_extern.h>
   85 
   86 #include <ufs/ext2fs/ext2fs.h>
   87 #include <ufs/ext2fs/ext2fs_extern.h>
   88 
   89 extern int prtactive;
   90 
   91 static int ext2fs_indirtrunc __P((struct inode *, daddr_t, daddr_t,
   92                                   daddr_t, int, long *));
   93 
   94 /*
   95  * Last reference to an inode.  If necessary, write or delete it.
   96  */
   97 int
   98 ext2fs_inactive(v)
   99         void *v;
  100 {   
  101         struct vop_inactive_args /* {
  102                 struct vnode *a_vp;
  103                 struct proc *a_p;
  104         } */ *ap = v;
  105         struct vnode *vp = ap->a_vp;
  106         struct inode *ip = VTOI(vp);
  107         struct mount *mp;
  108         struct proc *p = ap->a_p;
  109         struct timespec ts;
  110         int error = 0;
  111         
  112         if (prtactive && vp->v_usecount != 0)
  113                 vprint("ext2fs_inactive: pushing active", vp);
  114         /* Get rid of inodes related to stale file handles. */
  115         if (ip->i_e2fs_mode == 0 || ip->i_e2fs_dtime != 0)
  116                 goto out;
  117 
  118         error = 0;
  119         if (ip->i_e2fs_nlink == 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
  120                 vn_start_write(vp, &mp, V_WAIT | V_LOWER);
  121                 if (ip->i_e2fs_size != 0) {
  122                         error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL);
  123                 }
  124                 TIMEVAL_TO_TIMESPEC(&time, &ts);
  125                 ip->i_e2fs_dtime = ts.tv_sec;
  126                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
  127                 VOP_VFREE(vp, ip->i_number, ip->i_e2fs_mode);
  128                 vn_finished_write(mp, V_LOWER);
  129         }
  130         if (ip->i_flag &
  131             (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFIED | IN_ACCESSED)) {
  132                 vn_start_write(vp, &mp, V_WAIT | V_LOWER);
  133                 VOP_UPDATE(vp, NULL, NULL, 0);
  134                 vn_finished_write(mp, V_LOWER);
  135         }
  136 out:
  137         VOP_UNLOCK(vp, 0);
  138         /*
  139          * If we are done with the inode, reclaim it
  140          * so that it can be reused immediately.
  141          */
  142         if (ip->i_e2fs_dtime != 0)
  143                 vrecycle(vp, NULL, p);
  144         return (error);
  145 }   
  146 
  147 
  148 /*
  149  * Update the access, modified, and inode change times as specified by the
  150  * IACCESS, IUPDATE, and ICHANGE flags respectively. The IMODIFIED flag is
  151  * used to specify that the inode needs to be updated but that the times have
  152  * already been set. The access and modified times are taken from the second
  153  * and third parameters; the inode change time is always taken from the current
  154  * time. If UPDATE_WAIT or UPDATE_DIROP is set, then wait for the disk
  155  * write of the inode to complete.
  156  */
  157 int
  158 ext2fs_update(v)
  159         void *v;
  160 {
  161         struct vop_update_args /* {
  162                 struct vnode *a_vp;
  163                 struct timespec *a_access;
  164                 struct timespec *a_modify;
  165                 int a_flags;
  166         } */ *ap = v;
  167         struct m_ext2fs *fs;
  168         struct buf *bp;
  169         struct inode *ip;
  170         int error;
  171         struct timespec ts;
  172         caddr_t cp;
  173         int flags;
  174 
  175         if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
  176                 return (0);
  177         ip = VTOI(ap->a_vp);
  178         TIMEVAL_TO_TIMESPEC(&time, &ts);
  179         EXT2FS_ITIMES(ip,
  180             ap->a_access ? ap->a_access : &ts,
  181             ap->a_modify ? ap->a_modify : &ts, &ts);
  182         flags = ip->i_flag & (IN_MODIFIED | IN_ACCESSED);
  183         if (flags == 0)
  184                 return (0);
  185         fs = ip->i_e2fs;
  186 
  187         error = bread(ip->i_devvp,
  188                           fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
  189                           (int)fs->e2fs_bsize, NOCRED, &bp);
  190         if (error) {
  191                 brelse(bp);
  192                 return (error);
  193         }
  194         ip->i_flag &= ~(IN_MODIFIED | IN_ACCESSED);
  195         cp = (caddr_t)bp->b_data +
  196             (ino_to_fsbo(fs, ip->i_number) * EXT2_DINODE_SIZE);
  197         e2fs_isave(ip->i_din.e2fs_din, (struct ext2fs_dinode *)cp);
  198         if ((ap->a_flags & (UPDATE_WAIT|UPDATE_DIROP)) != 0 &&
  199             (flags & IN_MODIFIED) != 0 &&
  200             (ap->a_vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
  201                 return (bwrite(bp));
  202         else {
  203                 bdwrite(bp);
  204                 return (0);
  205         }
  206 }
  207 
  208 #define SINGLE  0       /* index of single indirect block */
  209 #define DOUBLE  1       /* index of double indirect block */
  210 #define TRIPLE  2       /* index of triple indirect block */
  211 /*
  212  * Truncate the inode oip to at most length size, freeing the
  213  * disk blocks.
  214  */
  215 int
  216 ext2fs_truncate(v)
  217         void *v;
  218 {
  219         struct vop_truncate_args /* {
  220                 struct vnode *a_vp;
  221                 off_t a_length;
  222                 int a_flags;
  223                 struct ucred *a_cred;
  224                 struct proc *a_p;
  225         } */ *ap = v;
  226         struct vnode *ovp = ap->a_vp;
  227         daddr_t lastblock;
  228         struct inode *oip;
  229         daddr_t bn, lastiblock[NIADDR], indir_lbn[NIADDR];
  230         /* XXX ondisk32 */
  231         int32_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
  232         off_t length = ap->a_length;
  233         struct m_ext2fs *fs;
  234         int offset, size, level;
  235         long count, nblocks, blocksreleased = 0;
  236         int i;
  237         int error, allerror = 0;
  238         off_t osize;
  239 
  240         if (length < 0)
  241                 return (EINVAL);
  242 
  243         oip = VTOI(ovp);
  244         if (ovp->v_type == VLNK &&
  245                 (oip->i_e2fs_size < ovp->v_mount->mnt_maxsymlinklen ||
  246                  (ovp->v_mount->mnt_maxsymlinklen == 0 &&
  247                   oip->i_e2fs_nblock == 0))) {
  248 #ifdef DIAGNOSTIC
  249                 if (length != 0)
  250                         panic("ext2fs_truncate: partial truncate of symlink");
  251 #endif
  252                 memset((char *)&oip->i_din.e2fs_din->e2di_shortlink, 0,
  253                         (u_int)oip->i_e2fs_size);
  254                 oip->i_e2fs_size = 0;
  255                 oip->i_flag |= IN_CHANGE | IN_UPDATE;
  256                 return (VOP_UPDATE(ovp, NULL, NULL, UPDATE_WAIT));
  257         }
  258         if (oip->i_e2fs_size == length) {
  259                 oip->i_flag |= IN_CHANGE | IN_UPDATE;
  260                 return (VOP_UPDATE(ovp, NULL, NULL, 0));
  261         }
  262         fs = oip->i_e2fs;
  263         osize = oip->i_e2fs_size;
  264         /*
  265          * Lengthen the size of the file. We must ensure that the
  266          * last byte of the file is allocated. Since the smallest
  267          * value of osize is 0, length will be at least 1.
  268          */
  269         if (osize < length) {
  270 #if 0 /* XXX */
  271                 if (length > fs->fs_maxfilesize)
  272                         return (EFBIG);
  273 #endif
  274                 ufs_balloc_range(ovp, length - 1, 1, ap->a_cred,
  275                     ap->a_flags & IO_SYNC ? B_SYNC : 0);
  276                 oip->i_flag |= IN_CHANGE | IN_UPDATE;
  277                 return (VOP_UPDATE(ovp, NULL, NULL, 1));
  278         }
  279         /*
  280          * Shorten the size of the file. If the file is not being
  281          * truncated to a block boundry, the contents of the
  282          * partial block following the end of the file must be
  283          * zero'ed in case it ever become accessible again because
  284          * of subsequent file growth.
  285          */
  286         offset = blkoff(fs, length);
  287         if (offset != 0) {
  288                 size = fs->e2fs_bsize;
  289 
  290                 /* XXXUBC we should handle more than just VREG */
  291                 uvm_vnp_zerorange(ovp, length, size - offset);
  292         }
  293         oip->i_e2fs_size = length;
  294         uvm_vnp_setsize(ovp, length);
  295 
  296         /*
  297          * Calculate index into inode's block list of
  298          * last direct and indirect blocks (if any)
  299          * which we want to keep.  Lastblock is -1 when
  300          * the file is truncated to 0.
  301          */
  302         lastblock = lblkno(fs, length + fs->e2fs_bsize - 1) - 1;
  303         lastiblock[SINGLE] = lastblock - NDADDR;
  304         lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
  305         lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
  306         nblocks = btodb(fs->e2fs_bsize);
  307         /*
  308          * Update file and block pointers on disk before we start freeing
  309          * blocks.  If we crash before free'ing blocks below, the blocks
  310          * will be returned to the free list.  lastiblock values are also
  311          * normalized to -1 for calls to ext2fs_indirtrunc below.
  312          */
  313         memcpy((caddr_t)oldblks, (caddr_t)&oip->i_e2fs_blocks[0], sizeof oldblks);
  314         for (level = TRIPLE; level >= SINGLE; level--)
  315                 if (lastiblock[level] < 0) {
  316                         oip->i_e2fs_blocks[NDADDR + level] = 0;
  317                         lastiblock[level] = -1;
  318                 }
  319         for (i = NDADDR - 1; i > lastblock; i--)
  320                 oip->i_e2fs_blocks[i] = 0;
  321         oip->i_flag |= IN_CHANGE | IN_UPDATE;
  322         error = VOP_UPDATE(ovp, NULL, NULL, UPDATE_WAIT);
  323         if (error && !allerror)
  324                 allerror = error;
  325 
  326         /*
  327          * Having written the new inode to disk, save its new configuration
  328          * and put back the old block pointers long enough to process them.
  329          * Note that we save the new block configuration so we can check it
  330          * when we are done.
  331          */
  332 
  333         memcpy((caddr_t)newblks, (caddr_t)&oip->i_e2fs_blocks[0], sizeof newblks);
  334         memcpy((caddr_t)&oip->i_e2fs_blocks[0], (caddr_t)oldblks, sizeof oldblks);
  335         oip->i_e2fs_size = osize;
  336         error = vtruncbuf(ovp, lastblock + 1, 0, 0);
  337         if (error && !allerror)
  338                 allerror = error;
  339 
  340         /*
  341          * Indirect blocks first.
  342          */
  343         indir_lbn[SINGLE] = -NDADDR;
  344         indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) -1;
  345         indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1;
  346         for (level = TRIPLE; level >= SINGLE; level--) {
  347                 /* XXX ondisk32 */
  348                 bn = fs2h32(oip->i_e2fs_blocks[NDADDR + level]);
  349                 if (bn != 0) {
  350                         error = ext2fs_indirtrunc(oip, indir_lbn[level],
  351                             fsbtodb(fs, bn), lastiblock[level], level, &count);
  352                         if (error)
  353                                 allerror = error;
  354                         blocksreleased += count;
  355                         if (lastiblock[level] < 0) {
  356                                 oip->i_e2fs_blocks[NDADDR + level] = 0;
  357                                 ext2fs_blkfree(oip, bn);
  358                                 blocksreleased += nblocks;
  359                         }
  360                 }
  361                 if (lastiblock[level] >= 0)
  362                         goto done;
  363         }
  364 
  365         /*
  366          * All whole direct blocks or frags.
  367          */
  368         for (i = NDADDR - 1; i > lastblock; i--) {
  369                 /* XXX ondisk32 */
  370                 bn = fs2h32(oip->i_e2fs_blocks[i]);
  371                 if (bn == 0)
  372                         continue;
  373                 oip->i_e2fs_blocks[i] = 0;
  374                 ext2fs_blkfree(oip, bn);
  375                 blocksreleased += btodb(fs->e2fs_bsize);
  376         }
  377 
  378 done:
  379 #ifdef DIAGNOSTIC
  380         for (level = SINGLE; level <= TRIPLE; level++)
  381                 if (newblks[NDADDR + level] !=
  382                     oip->i_e2fs_blocks[NDADDR + level])
  383                         panic("ext2fs_truncate1");
  384         for (i = 0; i < NDADDR; i++)
  385                 if (newblks[i] != oip->i_e2fs_blocks[i])
  386                         panic("ext2fs_truncate2");
  387         if (length == 0 &&
  388             (!LIST_EMPTY(&ovp->v_cleanblkhd) ||
  389              !LIST_EMPTY(&ovp->v_dirtyblkhd)))
  390                 panic("ext2fs_truncate3");
  391 #endif /* DIAGNOSTIC */
  392         /*
  393          * Put back the real size.
  394          */
  395         oip->i_e2fs_size = length;
  396         oip->i_e2fs_nblock -= blocksreleased;
  397         oip->i_flag |= IN_CHANGE;
  398         return (allerror);
  399 }
  400 
  401 /*
  402  * Release blocks associated with the inode ip and stored in the indirect
  403  * block bn.  Blocks are free'd in LIFO order up to (but not including)
  404  * lastbn.  If level is greater than SINGLE, the block is an indirect block
  405  * and recursive calls to indirtrunc must be used to cleanse other indirect
  406  * blocks.
  407  *
  408  * NB: triple indirect blocks are untested.
  409  */
  410 static int
  411 ext2fs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
  412         struct inode *ip;
  413         daddr_t lbn, lastbn;
  414         daddr_t dbn;
  415         int level;
  416         long *countp;
  417 {
  418         int i;
  419         struct buf *bp;
  420         struct m_ext2fs *fs = ip->i_e2fs;
  421         int32_t *bap;   /* XXX ondisk32 */
  422         struct vnode *vp;
  423         daddr_t nb, nlbn, last;
  424         int32_t *copy = NULL;   /* XXX ondisk32 */
  425         long blkcount, factor;
  426         int nblocks, blocksreleased = 0;
  427         int error = 0, allerror = 0;
  428 
  429         /*
  430          * Calculate index in current block of last
  431          * block to be kept.  -1 indicates the entire
  432          * block so we need not calculate the index.
  433          */
  434         factor = 1;
  435         for (i = SINGLE; i < level; i++)
  436                 factor *= NINDIR(fs);
  437         last = lastbn;
  438         if (lastbn > 0)
  439                 last /= factor;
  440         nblocks = btodb(fs->e2fs_bsize);
  441         /*
  442          * Get buffer of block pointers, zero those entries corresponding
  443          * to blocks to be free'd, and update on disk copy first.  Since
  444          * double(triple) indirect before single(double) indirect, calls
  445          * to bmap on these blocks will fail.  However, we already have
  446          * the on disk address, so we have to set the b_blkno field
  447          * explicitly instead of letting bread do everything for us.
  448          */
  449         vp = ITOV(ip);
  450         bp = getblk(vp, lbn, (int)fs->e2fs_bsize, 0, 0);
  451         if (bp->b_flags & (B_DONE | B_DELWRI)) {
  452                 /* Braces must be here in case trace evaluates to nothing. */
  453                 trace(TR_BREADHIT, pack(vp, fs->e2fs_bsize), lbn);
  454         } else {
  455                 trace(TR_BREADMISS, pack(vp, fs->e2fs_bsize), lbn);
  456                 curproc->p_stats->p_ru.ru_inblock++;    /* pay for read */
  457                 bp->b_flags |= B_READ;
  458                 if (bp->b_bcount > bp->b_bufsize)
  459                         panic("ext2fs_indirtrunc: bad buffer size");
  460                 bp->b_blkno = dbn;
  461                 VOP_STRATEGY(vp, bp);
  462                 error = biowait(bp);
  463         }
  464         if (error) {
  465                 brelse(bp);
  466                 *countp = 0;
  467                 return (error);
  468         }
  469 
  470         bap = (int32_t *)bp->b_data;    /* XXX ondisk32 */
  471         if (lastbn >= 0) {
  472                 /* XXX ondisk32 */
  473                 MALLOC(copy, int32_t *, fs->e2fs_bsize, M_TEMP, M_WAITOK);
  474                 memcpy((caddr_t)copy, (caddr_t)bap, (u_int)fs->e2fs_bsize);
  475                 memset((caddr_t)&bap[last + 1], 0,
  476                         (u_int)(NINDIR(fs) - (last + 1)) * sizeof (u_int32_t));
  477                 error = bwrite(bp);
  478                 if (error)
  479                         allerror = error;
  480                 bap = copy;
  481         }
  482 
  483         /*
  484          * Recursively free totally unused blocks.
  485          */
  486         for (i = NINDIR(fs) - 1,
  487                 nlbn = lbn + 1 - i * factor; i > last;
  488                 i--, nlbn += factor) {
  489                 /* XXX ondisk32 */
  490                 nb = fs2h32(bap[i]);
  491                 if (nb == 0)
  492                         continue;
  493                 if (level > SINGLE) {
  494                         error = ext2fs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
  495                                                    (daddr_t)-1, level - 1,
  496                                                    &blkcount);
  497                         if (error)
  498                                 allerror = error;
  499                         blocksreleased += blkcount;
  500                 }
  501                 ext2fs_blkfree(ip, nb);
  502                 blocksreleased += nblocks;
  503         }
  504 
  505         /*
  506          * Recursively free last partial block.
  507          */
  508         if (level > SINGLE && lastbn >= 0) {
  509                 last = lastbn % factor;
  510                 /* XXX ondisk32 */
  511                 nb = fs2h32(bap[i]);
  512                 if (nb != 0) {
  513                         error = ext2fs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
  514                                                    last, level - 1, &blkcount);
  515                         if (error)
  516                                 allerror = error;
  517                         blocksreleased += blkcount;
  518                 }
  519         }
  520 
  521         if (copy != NULL) {
  522                 FREE(copy, M_TEMP);
  523         } else {
  524                 bp->b_flags |= B_INVAL;
  525                 brelse(bp);
  526         }
  527 
  528         *countp = blocksreleased;
  529         return (allerror);
  530 }

Cache object: 7cec09d2d26bd694a29e42563783c4ed


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.