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/ffs/ffs_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 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    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.13 (Berkeley) 4/21/95
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include "opt_ufs.h"
   38 #include "opt_quota.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/bio.h>
   43 #include <sys/buf.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mount.h>
   46 #include <sys/proc.h>
   47 #include <sys/racct.h>
   48 #include <sys/random.h>
   49 #include <sys/resourcevar.h>
   50 #include <sys/rwlock.h>
   51 #include <sys/stat.h>
   52 #include <sys/vmmeter.h>
   53 #include <sys/vnode.h>
   54 
   55 #include <vm/vm.h>
   56 #include <vm/vm_extern.h>
   57 #include <vm/vm_object.h>
   58 
   59 #include <ufs/ufs/extattr.h>
   60 #include <ufs/ufs/quota.h>
   61 #include <ufs/ufs/ufsmount.h>
   62 #include <ufs/ufs/inode.h>
   63 #include <ufs/ufs/dir.h>
   64 #ifdef UFS_DIRHASH
   65 #include <ufs/ufs/dirhash.h>
   66 #endif
   67 #include <ufs/ufs/ufs_extern.h>
   68 
   69 #include <ufs/ffs/fs.h>
   70 #include <ufs/ffs/ffs_extern.h>
   71 
   72 static int ffs_indirtrunc(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
   73             ufs2_daddr_t, int, ufs2_daddr_t *);
   74 
   75 static void
   76 ffs_inode_bwrite(struct vnode *vp, struct buf *bp, int flags)
   77 {
   78         if ((flags & IO_SYNC) != 0)
   79                 bwrite(bp);
   80         else if (DOINGASYNC(vp))
   81                 bdwrite(bp);
   82         else
   83                 bawrite(bp);
   84 }
   85 
   86 /*
   87  * Update the access, modified, and inode change times as specified by the
   88  * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively.  Write the inode
   89  * to disk if the IN_MODIFIED flag is set (it may be set initially, or by
   90  * the timestamp update).  The IN_LAZYMOD flag is set to force a write
   91  * later if not now.  The IN_LAZYACCESS is set instead of IN_MODIFIED if the fs
   92  * is currently being suspended (or is suspended) and vnode has been accessed.
   93  * If we write now, then clear IN_MODIFIED, IN_LAZYACCESS and IN_LAZYMOD to
   94  * reflect the presumably successful write, and if waitfor is set, then wait
   95  * for the write to complete.
   96  */
   97 int
   98 ffs_update(struct vnode *vp, int waitfor)
   99 {
  100         struct fs *fs;
  101         struct buf *bp;
  102         struct inode *ip;
  103         daddr_t bn;
  104         int flags, error;
  105 
  106         ASSERT_VOP_ELOCKED(vp, "ffs_update");
  107         ufs_itimes(vp);
  108         ip = VTOI(vp);
  109         if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0)
  110                 return (0);
  111         ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED);
  112         /*
  113          * The IN_SIZEMOD and IN_IBLKDATA flags indicate changes to the
  114          * file size and block pointer fields in the inode. When these
  115          * fields have been changed, the fsync() and fsyncdata() system 
  116          * calls must write the inode to ensure their semantics that the 
  117          * file is on stable store.
  118          *
  119          * The IN_SIZEMOD and IN_IBLKDATA flags cannot be cleared until
  120          * a synchronous write of the inode is done. If they are cleared
  121          * on an asynchronous write, then the inode may not yet have been
  122          * written to the disk when an fsync() or fsyncdata() call is done.
  123          * Absent these flags, these calls would not know that they needed
  124          * to write the inode. Thus, these flags only can be cleared on
  125          * synchronous writes of the inode. Since the inode will be locked
  126          * for the duration of the I/O that writes it to disk, no fsync()
  127          * or fsyncdata() will be able to run before the on-disk inode
  128          * is complete.
  129          */
  130         if (waitfor)
  131                 ip->i_flag &= ~(IN_SIZEMOD | IN_IBLKDATA);
  132         fs = ITOFS(ip);
  133         if (fs->fs_ronly)
  134                 return (0);
  135         /*
  136          * If we are updating a snapshot and another process is currently
  137          * writing the buffer containing the inode for this snapshot then
  138          * a deadlock can occur when it tries to check the snapshot to see
  139          * if that block needs to be copied. Thus when updating a snapshot
  140          * we check to see if the buffer is already locked, and if it is
  141          * we drop the snapshot lock until the buffer has been written
  142          * and is available to us. We have to grab a reference to the
  143          * snapshot vnode to prevent it from being removed while we are
  144          * waiting for the buffer.
  145          */
  146 loop:
  147         flags = 0;
  148         if (IS_SNAPSHOT(ip))
  149                 flags = GB_LOCK_NOWAIT;
  150         bn = fsbtodb(fs, ino_to_fsba(fs, ip->i_number));
  151         error = ffs_breadz(VFSTOUFS(vp->v_mount), ITODEVVP(ip), bn, bn,
  152              (int) fs->fs_bsize, NULL, NULL, 0, NOCRED, flags, NULL, &bp);
  153         if (error != 0) {
  154                 /*
  155                  * If EBUSY was returned without GB_LOCK_NOWAIT (which
  156                  * requests trylock for buffer lock), it is for some
  157                  * other reason and we should not handle it specially.
  158                  */
  159                 if (error != EBUSY || (flags & GB_LOCK_NOWAIT) == 0)
  160                         return (error);
  161 
  162                 /*
  163                  * Wait for our inode block to become available.
  164                  *
  165                  * Hold a reference to the vnode to protect against
  166                  * ffs_snapgone(). Since we hold a reference, it can only
  167                  * get reclaimed (VIRF_DOOMED flag) in a forcible downgrade
  168                  * or unmount. For an unmount, the entire filesystem will be
  169                  * gone, so we cannot attempt to touch anything associated
  170                  * with it while the vnode is unlocked; all we can do is 
  171                  * pause briefly and try again. If when we relock the vnode
  172                  * we discover that it has been reclaimed, updating it is no
  173                  * longer necessary and we can just return an error.
  174                  */
  175                 vref(vp);
  176                 VOP_UNLOCK(vp);
  177                 pause("ffsupd", 1);
  178                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  179                 vrele(vp);
  180                 if (!IS_UFS(vp))
  181                         return (ENOENT);
  182 
  183                 /*
  184                  * Recalculate flags, because the vnode was relocked and
  185                  * could no longer be a snapshot.
  186                  */
  187                 goto loop;
  188         }
  189         if (DOINGSOFTDEP(vp))
  190                 softdep_update_inodeblock(ip, bp, waitfor);
  191         else if (ip->i_effnlink != ip->i_nlink)
  192                 panic("ffs_update: bad link cnt");
  193         if (I_IS_UFS1(ip)) {
  194                 *((struct ufs1_dinode *)bp->b_data +
  195                     ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
  196                 /*
  197                  * XXX: FIX? The entropy here is desirable,
  198                  * but the harvesting may be expensive
  199                  */
  200                 random_harvest_queue(&(ip->i_din1), sizeof(ip->i_din1), RANDOM_FS_ATIME);
  201         } else {
  202                 ffs_update_dinode_ckhash(fs, ip->i_din2);
  203                 *((struct ufs2_dinode *)bp->b_data +
  204                     ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
  205                 /*
  206                  * XXX: FIX? The entropy here is desirable,
  207                  * but the harvesting may be expensive
  208                  */
  209                 random_harvest_queue(&(ip->i_din2), sizeof(ip->i_din2), RANDOM_FS_ATIME);
  210         }
  211         if (waitfor) {
  212                 error = bwrite(bp);
  213                 if (ffs_fsfail_cleanup(VFSTOUFS(vp->v_mount), error))
  214                         error = 0;
  215         } else if (vm_page_count_severe() || buf_dirty_count_severe()) {
  216                 bawrite(bp);
  217                 error = 0;
  218         } else {
  219                 if (bp->b_bufsize == fs->fs_bsize)
  220                         bp->b_flags |= B_CLUSTEROK;
  221                 bdwrite(bp);
  222                 error = 0;
  223         }
  224         return (error);
  225 }
  226 
  227 #define SINGLE  0       /* index of single indirect block */
  228 #define DOUBLE  1       /* index of double indirect block */
  229 #define TRIPLE  2       /* index of triple indirect block */
  230 /*
  231  * Truncate the inode ip to at most length size, freeing the
  232  * disk blocks.
  233  */
  234 int
  235 ffs_truncate(struct vnode *vp,
  236         off_t length,
  237         int flags,
  238         struct ucred *cred)
  239 {
  240         struct inode *ip;
  241         ufs2_daddr_t bn, lbn, lastblock, lastiblock[UFS_NIADDR];
  242         ufs2_daddr_t indir_lbn[UFS_NIADDR], oldblks[UFS_NDADDR + UFS_NIADDR];
  243         ufs2_daddr_t newblks[UFS_NDADDR + UFS_NIADDR];
  244         ufs2_daddr_t count, blocksreleased = 0, blkno;
  245         struct bufobj *bo __diagused;
  246         struct fs *fs;
  247         struct buf *bp;
  248         struct ufsmount *ump;
  249         int softdeptrunc, journaltrunc;
  250         int needextclean, extblocks;
  251         int offset, size, level, nblocks;
  252         int i, error, allerror, indiroff, waitforupdate;
  253         u_long key;
  254         off_t osize;
  255 
  256         ip = VTOI(vp);
  257         ump = VFSTOUFS(vp->v_mount);
  258         fs = ump->um_fs;
  259         bo = &vp->v_bufobj;
  260 
  261         ASSERT_VOP_LOCKED(vp, "ffs_truncate");
  262 
  263         if (length < 0)
  264                 return (EINVAL);
  265         if (length > fs->fs_maxfilesize)
  266                 return (EFBIG);
  267 #ifdef QUOTA
  268         error = getinoquota(ip);
  269         if (error)
  270                 return (error);
  271 #endif
  272         /*
  273          * Historically clients did not have to specify which data
  274          * they were truncating. So, if not specified, we assume
  275          * traditional behavior, e.g., just the normal data.
  276          */
  277         if ((flags & (IO_EXT | IO_NORMAL)) == 0)
  278                 flags |= IO_NORMAL;
  279         if (!DOINGSOFTDEP(vp) && !DOINGASYNC(vp))
  280                 flags |= IO_SYNC;
  281         waitforupdate = (flags & IO_SYNC) != 0 || !DOINGASYNC(vp);
  282         /*
  283          * If we are truncating the extended-attributes, and cannot
  284          * do it with soft updates, then do it slowly here. If we are
  285          * truncating both the extended attributes and the file contents
  286          * (e.g., the file is being unlinked), then pick it off with
  287          * soft updates below.
  288          */
  289         allerror = 0;
  290         needextclean = 0;
  291         softdeptrunc = 0;
  292         journaltrunc = DOINGSUJ(vp);
  293         journaltrunc = 0;       /* XXX temp patch until bug found */
  294         if (journaltrunc == 0 && DOINGSOFTDEP(vp) && length == 0)
  295                 softdeptrunc = !softdep_slowdown(vp);
  296         extblocks = 0;
  297         if (fs->fs_magic == FS_UFS2_MAGIC && ip->i_din2->di_extsize > 0) {
  298                 extblocks = btodb(fragroundup(fs, ip->i_din2->di_extsize));
  299         }
  300         if ((flags & IO_EXT) && extblocks > 0) {
  301                 if (length != 0)
  302                         panic("ffs_truncate: partial trunc of extdata");
  303                 if (softdeptrunc || journaltrunc) {
  304                         if ((flags & IO_NORMAL) == 0)
  305                                 goto extclean;
  306                         needextclean = 1;
  307                 } else {
  308                         if ((error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0)
  309                                 return (error);
  310 #ifdef QUOTA
  311                         (void) chkdq(ip, -extblocks, NOCRED, FORCE);
  312 #endif
  313                         vinvalbuf(vp, V_ALT, 0, 0);
  314                         vn_pages_remove(vp,
  315                             OFF_TO_IDX(lblktosize(fs, -extblocks)), 0);
  316                         osize = ip->i_din2->di_extsize;
  317                         ip->i_din2->di_blocks -= extblocks;
  318                         ip->i_din2->di_extsize = 0;
  319                         for (i = 0; i < UFS_NXADDR; i++) {
  320                                 oldblks[i] = ip->i_din2->di_extb[i];
  321                                 ip->i_din2->di_extb[i] = 0;
  322                         }
  323                         UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
  324                         if ((error = ffs_update(vp, waitforupdate)))
  325                                 return (error);
  326                         for (i = 0; i < UFS_NXADDR; i++) {
  327                                 if (oldblks[i] == 0)
  328                                         continue;
  329                                 ffs_blkfree(ump, fs, ITODEVVP(ip), oldblks[i],
  330                                     sblksize(fs, osize, i), ip->i_number,
  331                                     vp->v_type, NULL, SINGLETON_KEY);
  332                         }
  333                 }
  334         }
  335         if ((flags & IO_NORMAL) == 0)
  336                 return (0);
  337         if (vp->v_type == VLNK && ip->i_size < ump->um_maxsymlinklen) {
  338 #ifdef INVARIANTS
  339                 if (length != 0)
  340                         panic("ffs_truncate: partial truncate of symlink");
  341 #endif
  342                 bzero(DIP(ip, i_shortlink), (u_int)ip->i_size);
  343                 ip->i_size = 0;
  344                 DIP_SET(ip, i_size, 0);
  345                 UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
  346                 if (needextclean)
  347                         goto extclean;
  348                 return (ffs_update(vp, waitforupdate));
  349         }
  350         if (ip->i_size == length) {
  351                 UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
  352                 if (needextclean)
  353                         goto extclean;
  354                 return (ffs_update(vp, 0));
  355         }
  356         if (fs->fs_ronly)
  357                 panic("ffs_truncate: read-only filesystem");
  358         if (IS_SNAPSHOT(ip))
  359                 ffs_snapremove(vp);
  360         cluster_init_vn(&ip->i_clusterw);
  361         osize = ip->i_size;
  362         /*
  363          * Lengthen the size of the file. We must ensure that the
  364          * last byte of the file is allocated. Since the smallest
  365          * value of osize is 0, length will be at least 1.
  366          */
  367         if (osize < length) {
  368                 vnode_pager_setsize(vp, length);
  369                 flags |= BA_CLRBUF;
  370                 error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp);
  371                 if (error) {
  372                         vnode_pager_setsize(vp, osize);
  373                         return (error);
  374                 }
  375                 ip->i_size = length;
  376                 DIP_SET(ip, i_size, length);
  377                 if (bp->b_bufsize == fs->fs_bsize)
  378                         bp->b_flags |= B_CLUSTEROK;
  379                 ffs_inode_bwrite(vp, bp, flags);
  380                 UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
  381                 return (ffs_update(vp, waitforupdate));
  382         }
  383         /*
  384          * Lookup block number for a given offset. Zero length files
  385          * have no blocks, so return a blkno of -1.
  386          */
  387         lbn = lblkno(fs, length - 1);
  388         if (length == 0) {
  389                 blkno = -1;
  390         } else if (lbn < UFS_NDADDR) {
  391                 blkno = DIP(ip, i_db[lbn]);
  392         } else {
  393                 error = UFS_BALLOC(vp, lblktosize(fs, (off_t)lbn), fs->fs_bsize,
  394                     cred, BA_METAONLY, &bp);
  395                 if (error)
  396                         return (error);
  397                 indiroff = (lbn - UFS_NDADDR) % NINDIR(fs);
  398                 if (I_IS_UFS1(ip))
  399                         blkno = ((ufs1_daddr_t *)(bp->b_data))[indiroff];
  400                 else
  401                         blkno = ((ufs2_daddr_t *)(bp->b_data))[indiroff];
  402                 /*
  403                  * If the block number is non-zero, then the indirect block
  404                  * must have been previously allocated and need not be written.
  405                  * If the block number is zero, then we may have allocated
  406                  * the indirect block and hence need to write it out.
  407                  */
  408                 if (blkno != 0)
  409                         brelse(bp);
  410                 else if (flags & IO_SYNC)
  411                         bwrite(bp);
  412                 else
  413                         bdwrite(bp);
  414         }
  415         /*
  416          * If the block number at the new end of the file is zero,
  417          * then we must allocate it to ensure that the last block of 
  418          * the file is allocated. Soft updates does not handle this
  419          * case, so here we have to clean up the soft updates data
  420          * structures describing the allocation past the truncation
  421          * point. Finding and deallocating those structures is a lot of
  422          * work. Since partial truncation with a hole at the end occurs
  423          * rarely, we solve the problem by syncing the file so that it
  424          * will have no soft updates data structures left.
  425          */
  426         if (blkno == 0 && (error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0)
  427                 return (error);
  428         if (blkno != 0 && DOINGSOFTDEP(vp)) {
  429                 if (softdeptrunc == 0 && journaltrunc == 0) {
  430                         /*
  431                          * If soft updates cannot handle this truncation,
  432                          * clean up soft dependency data structures and
  433                          * fall through to the synchronous truncation.
  434                          */
  435                         if ((error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0)
  436                                 return (error);
  437                 } else {
  438                         flags = IO_NORMAL | (needextclean ? IO_EXT: 0);
  439                         if (journaltrunc)
  440                                 softdep_journal_freeblocks(ip, cred, length,
  441                                     flags);
  442                         else
  443                                 softdep_setup_freeblocks(ip, length, flags);
  444                         ASSERT_VOP_LOCKED(vp, "ffs_truncate1");
  445                         if (journaltrunc == 0) {
  446                                 UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
  447                                 error = ffs_update(vp, 0);
  448                         }
  449                         return (error);
  450                 }
  451         }
  452         /*
  453          * Shorten the size of the file. If the last block of the
  454          * shortened file is unallocated, we must allocate it.
  455          * Additionally, if the file is not being truncated to a
  456          * block boundary, the contents of the partial block
  457          * following the end of the file must be zero'ed in
  458          * case it ever becomes accessible again because of
  459          * subsequent file growth. Directories however are not
  460          * zero'ed as they should grow back initialized to empty.
  461          */
  462         offset = blkoff(fs, length);
  463         if (blkno != 0 && offset == 0) {
  464                 ip->i_size = length;
  465                 DIP_SET(ip, i_size, length);
  466                 UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
  467 #ifdef UFS_DIRHASH
  468                 if (vp->v_type == VDIR && ip->i_dirhash != NULL)
  469                         ufsdirhash_dirtrunc(ip, length);
  470 #endif
  471         } else {
  472                 lbn = lblkno(fs, length);
  473                 flags |= BA_CLRBUF;
  474                 error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp);
  475                 if (error)
  476                         return (error);
  477                 ffs_inode_bwrite(vp, bp, flags);
  478 
  479                 /*
  480                  * When we are doing soft updates and the UFS_BALLOC
  481                  * above fills in a direct block hole with a full sized
  482                  * block that will be truncated down to a fragment below,
  483                  * we must flush out the block dependency with an FSYNC
  484                  * so that we do not get a soft updates inconsistency
  485                  * when we create the fragment below.
  486                  */
  487                 if (DOINGSOFTDEP(vp) && lbn < UFS_NDADDR &&
  488                     fragroundup(fs, blkoff(fs, length)) < fs->fs_bsize &&
  489                     (error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0)
  490                         return (error);
  491 
  492                 error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp);
  493                 if (error)
  494                         return (error);
  495                 ip->i_size = length;
  496                 DIP_SET(ip, i_size, length);
  497 #ifdef UFS_DIRHASH
  498                 if (vp->v_type == VDIR && ip->i_dirhash != NULL)
  499                         ufsdirhash_dirtrunc(ip, length);
  500 #endif
  501                 size = blksize(fs, ip, lbn);
  502                 if (vp->v_type != VDIR && offset != 0)
  503                         bzero((char *)bp->b_data + offset,
  504                             (u_int)(size - offset));
  505                 /* Kirk's code has reallocbuf(bp, size, 1) here */
  506                 allocbuf(bp, size);
  507                 if (bp->b_bufsize == fs->fs_bsize)
  508                         bp->b_flags |= B_CLUSTEROK;
  509                 ffs_inode_bwrite(vp, bp, flags);
  510                 UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
  511         }
  512         /*
  513          * Calculate index into inode's block list of
  514          * last direct and indirect blocks (if any)
  515          * which we want to keep.  Lastblock is -1 when
  516          * the file is truncated to 0.
  517          */
  518         lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1;
  519         lastiblock[SINGLE] = lastblock - UFS_NDADDR;
  520         lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
  521         lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
  522         nblocks = btodb(fs->fs_bsize);
  523         /*
  524          * Update file and block pointers on disk before we start freeing
  525          * blocks.  If we crash before free'ing blocks below, the blocks
  526          * will be returned to the free list.  lastiblock values are also
  527          * normalized to -1 for calls to ffs_indirtrunc below.
  528          */
  529         for (level = TRIPLE; level >= SINGLE; level--) {
  530                 oldblks[UFS_NDADDR + level] = DIP(ip, i_ib[level]);
  531                 if (lastiblock[level] < 0) {
  532                         DIP_SET(ip, i_ib[level], 0);
  533                         lastiblock[level] = -1;
  534                 }
  535         }
  536         for (i = 0; i < UFS_NDADDR; i++) {
  537                 oldblks[i] = DIP(ip, i_db[i]);
  538                 if (i > lastblock)
  539                         DIP_SET(ip, i_db[i], 0);
  540         }
  541         UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
  542         allerror = ffs_update(vp, waitforupdate);
  543 
  544         /*
  545          * Having written the new inode to disk, save its new configuration
  546          * and put back the old block pointers long enough to process them.
  547          * Note that we save the new block configuration so we can check it
  548          * when we are done.
  549          */
  550         for (i = 0; i < UFS_NDADDR; i++) {
  551                 newblks[i] = DIP(ip, i_db[i]);
  552                 DIP_SET(ip, i_db[i], oldblks[i]);
  553         }
  554         for (i = 0; i < UFS_NIADDR; i++) {
  555                 newblks[UFS_NDADDR + i] = DIP(ip, i_ib[i]);
  556                 DIP_SET(ip, i_ib[i], oldblks[UFS_NDADDR + i]);
  557         }
  558         ip->i_size = osize;
  559         DIP_SET(ip, i_size, osize);
  560         UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
  561 
  562         error = vtruncbuf(vp, length, fs->fs_bsize);
  563         if (error && (allerror == 0))
  564                 allerror = error;
  565 
  566         /*
  567          * Indirect blocks first.
  568          */
  569         indir_lbn[SINGLE] = -UFS_NDADDR;
  570         indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1;
  571         indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1;
  572         for (level = TRIPLE; level >= SINGLE; level--) {
  573                 bn = DIP(ip, i_ib[level]);
  574                 if (bn != 0) {
  575                         error = ffs_indirtrunc(ip, indir_lbn[level],
  576                             fsbtodb(fs, bn), lastiblock[level], level, &count);
  577                         if (error)
  578                                 allerror = error;
  579                         blocksreleased += count;
  580                         if (lastiblock[level] < 0) {
  581                                 DIP_SET(ip, i_ib[level], 0);
  582                                 ffs_blkfree(ump, fs, ump->um_devvp, bn,
  583                                     fs->fs_bsize, ip->i_number,
  584                                     vp->v_type, NULL, SINGLETON_KEY);
  585                                 blocksreleased += nblocks;
  586                         }
  587                 }
  588                 if (lastiblock[level] >= 0)
  589                         goto done;
  590         }
  591 
  592         /*
  593          * All whole direct blocks or frags.
  594          */
  595         key = ffs_blkrelease_start(ump, ump->um_devvp, ip->i_number);
  596         for (i = UFS_NDADDR - 1; i > lastblock; i--) {
  597                 long bsize;
  598 
  599                 bn = DIP(ip, i_db[i]);
  600                 if (bn == 0)
  601                         continue;
  602                 DIP_SET(ip, i_db[i], 0);
  603                 bsize = blksize(fs, ip, i);
  604                 ffs_blkfree(ump, fs, ump->um_devvp, bn, bsize, ip->i_number,
  605                     vp->v_type, NULL, key);
  606                 blocksreleased += btodb(bsize);
  607         }
  608         ffs_blkrelease_finish(ump, key);
  609         if (lastblock < 0)
  610                 goto done;
  611 
  612         /*
  613          * Finally, look for a change in size of the
  614          * last direct block; release any frags.
  615          */
  616         bn = DIP(ip, i_db[lastblock]);
  617         if (bn != 0) {
  618                 long oldspace, newspace;
  619 
  620                 /*
  621                  * Calculate amount of space we're giving
  622                  * back as old block size minus new block size.
  623                  */
  624                 oldspace = blksize(fs, ip, lastblock);
  625                 ip->i_size = length;
  626                 DIP_SET(ip, i_size, length);
  627                 UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
  628                 newspace = blksize(fs, ip, lastblock);
  629                 if (newspace == 0)
  630                         panic("ffs_truncate: newspace");
  631                 if (oldspace - newspace > 0) {
  632                         /*
  633                          * Block number of space to be free'd is
  634                          * the old block # plus the number of frags
  635                          * required for the storage we're keeping.
  636                          */
  637                         bn += numfrags(fs, newspace);
  638                         ffs_blkfree(ump, fs, ump->um_devvp, bn,
  639                            oldspace - newspace, ip->i_number, vp->v_type,
  640                            NULL, SINGLETON_KEY);
  641                         blocksreleased += btodb(oldspace - newspace);
  642                 }
  643         }
  644 done:
  645 #ifdef INVARIANTS
  646         for (level = SINGLE; level <= TRIPLE; level++)
  647                 if (newblks[UFS_NDADDR + level] != DIP(ip, i_ib[level]))
  648                         panic("ffs_truncate1: level %d newblks %jd != i_ib %jd",
  649                             level, (intmax_t)newblks[UFS_NDADDR + level],
  650                             (intmax_t)DIP(ip, i_ib[level]));
  651         for (i = 0; i < UFS_NDADDR; i++)
  652                 if (newblks[i] != DIP(ip, i_db[i]))
  653                         panic("ffs_truncate2: blkno %d newblks %jd != i_db %jd",
  654                             i, (intmax_t)newblks[UFS_NDADDR + level],
  655                             (intmax_t)DIP(ip, i_ib[level]));
  656         BO_LOCK(bo);
  657         if (length == 0 &&
  658             (fs->fs_magic != FS_UFS2_MAGIC || ip->i_din2->di_extsize == 0) &&
  659             (bo->bo_dirty.bv_cnt > 0 || bo->bo_clean.bv_cnt > 0))
  660                 panic("ffs_truncate3: vp = %p, buffers: dirty = %d, clean = %d",
  661                         vp, bo->bo_dirty.bv_cnt, bo->bo_clean.bv_cnt);
  662         BO_UNLOCK(bo);
  663 #endif /* INVARIANTS */
  664         /*
  665          * Put back the real size.
  666          */
  667         ip->i_size = length;
  668         DIP_SET(ip, i_size, length);
  669         if (DIP(ip, i_blocks) >= blocksreleased)
  670                 DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased);
  671         else    /* sanity */
  672                 DIP_SET(ip, i_blocks, 0);
  673         UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
  674 #ifdef QUOTA
  675         (void) chkdq(ip, -blocksreleased, NOCRED, FORCE);
  676 #endif
  677         return (allerror);
  678 
  679 extclean:
  680         if (journaltrunc)
  681                 softdep_journal_freeblocks(ip, cred, length, IO_EXT);
  682         else
  683                 softdep_setup_freeblocks(ip, length, IO_EXT);
  684         return (ffs_update(vp, waitforupdate));
  685 }
  686 
  687 /*
  688  * Release blocks associated with the inode ip and stored in the indirect
  689  * block bn.  Blocks are free'd in LIFO order up to (but not including)
  690  * lastbn.  If level is greater than SINGLE, the block is an indirect block
  691  * and recursive calls to indirtrunc must be used to cleanse other indirect
  692  * blocks.
  693  */
  694 static int
  695 ffs_indirtrunc(struct inode *ip,
  696         ufs2_daddr_t lbn,
  697         ufs2_daddr_t dbn,
  698         ufs2_daddr_t lastbn,
  699         int level,
  700         ufs2_daddr_t *countp)
  701 {
  702         struct buf *bp;
  703         struct fs *fs;
  704         struct ufsmount *ump;
  705         struct vnode *vp;
  706         caddr_t copy = NULL;
  707         u_long key;
  708         int i, nblocks, error = 0, allerror = 0;
  709         ufs2_daddr_t nb, nlbn, last;
  710         ufs2_daddr_t blkcount, factor, blocksreleased = 0;
  711         ufs1_daddr_t *bap1 = NULL;
  712         ufs2_daddr_t *bap2 = NULL;
  713 #define BAP(ip, i) (I_IS_UFS1(ip) ? bap1[i] : bap2[i])
  714 
  715         fs = ITOFS(ip);
  716         ump = ITOUMP(ip);
  717 
  718         /*
  719          * Calculate index in current block of last
  720          * block to be kept.  -1 indicates the entire
  721          * block so we need not calculate the index.
  722          */
  723         factor = lbn_offset(fs, level);
  724         last = lastbn;
  725         if (lastbn > 0)
  726                 last /= factor;
  727         nblocks = btodb(fs->fs_bsize);
  728         /*
  729          * Get buffer of block pointers, zero those entries corresponding
  730          * to blocks to be free'd, and update on disk copy first.  Since
  731          * double(triple) indirect before single(double) indirect, calls
  732          * to VOP_BMAP() on these blocks will fail.  However, we already
  733          * have the on-disk address, so we just pass it to bread() instead
  734          * of having bread() attempt to calculate it using VOP_BMAP().
  735          */
  736         vp = ITOV(ip);
  737         error = ffs_breadz(ump, vp, lbn, dbn, (int)fs->fs_bsize, NULL, NULL, 0,
  738             NOCRED, 0, NULL, &bp);
  739         if (error) {
  740                 *countp = 0;
  741                 return (error);
  742         }
  743 
  744         if (I_IS_UFS1(ip))
  745                 bap1 = (ufs1_daddr_t *)bp->b_data;
  746         else
  747                 bap2 = (ufs2_daddr_t *)bp->b_data;
  748         if (lastbn != -1) {
  749                 copy = malloc(fs->fs_bsize, M_TEMP, M_WAITOK);
  750                 bcopy((caddr_t)bp->b_data, copy, (u_int)fs->fs_bsize);
  751                 for (i = last + 1; i < NINDIR(fs); i++)
  752                         if (I_IS_UFS1(ip))
  753                                 bap1[i] = 0;
  754                         else
  755                                 bap2[i] = 0;
  756                 if (DOINGASYNC(vp)) {
  757                         bdwrite(bp);
  758                 } else {
  759                         error = bwrite(bp);
  760                         if (error)
  761                                 allerror = error;
  762                 }
  763                 if (I_IS_UFS1(ip))
  764                         bap1 = (ufs1_daddr_t *)copy;
  765                 else
  766                         bap2 = (ufs2_daddr_t *)copy;
  767         }
  768 
  769         /*
  770          * Recursively free totally unused blocks.
  771          */
  772         key = ffs_blkrelease_start(ump, ITODEVVP(ip), ip->i_number);
  773         for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last;
  774             i--, nlbn += factor) {
  775                 nb = BAP(ip, i);
  776                 if (nb == 0)
  777                         continue;
  778                 if (level > SINGLE) {
  779                         if ((error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
  780                             (ufs2_daddr_t)-1, level - 1, &blkcount)) != 0)
  781                                 allerror = error;
  782                         blocksreleased += blkcount;
  783                 }
  784                 ffs_blkfree(ump, fs, ITODEVVP(ip), nb, fs->fs_bsize,
  785                     ip->i_number, vp->v_type, NULL, key);
  786                 blocksreleased += nblocks;
  787         }
  788         ffs_blkrelease_finish(ump, key);
  789 
  790         /*
  791          * Recursively free last partial block.
  792          */
  793         if (level > SINGLE && lastbn >= 0) {
  794                 last = lastbn % factor;
  795                 nb = BAP(ip, i);
  796                 if (nb != 0) {
  797                         error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
  798                             last, level - 1, &blkcount);
  799                         if (error)
  800                                 allerror = error;
  801                         blocksreleased += blkcount;
  802                 }
  803         }
  804         if (copy != NULL) {
  805                 free(copy, M_TEMP);
  806         } else {
  807                 bp->b_flags |= B_INVAL | B_NOCACHE;
  808                 brelse(bp);
  809         }
  810 
  811         *countp = blocksreleased;
  812         return (allerror);
  813 }
  814 
  815 int
  816 ffs_rdonly(struct inode *ip)
  817 {
  818 
  819         return (ITOFS(ip)->fs_ronly != 0);
  820 }

Cache object: ba907fe538f7d5e82a521a2862ccd8ec


[ 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.