1139825Simp/*- 21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 4. Neither the name of the University nor the names of its contributors 141541Srgrimes * may be used to endorse or promote products derived from this software 151541Srgrimes * without specific prior written permission. 161541Srgrimes * 171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271541Srgrimes * SUCH DAMAGE. 281541Srgrimes * 2922521Sdyson * @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95 301541Srgrimes */ 311541Srgrimes 32116192Sobrien#include <sys/cdefs.h> 33116192Sobrien__FBSDID("$FreeBSD$"); 34116192Sobrien 3513260Swollman#include "opt_quota.h" 3613260Swollman 371541Srgrimes#include <sys/param.h> 381541Srgrimes#include <sys/systm.h> 391541Srgrimes#include <sys/mount.h> 401541Srgrimes#include <sys/proc.h> 4160041Sphk#include <sys/bio.h> 421541Srgrimes#include <sys/buf.h> 431541Srgrimes#include <sys/vnode.h> 441541Srgrimes#include <sys/malloc.h> 451541Srgrimes#include <sys/resourcevar.h> 46251171Sjeff#include <sys/rwlock.h> 4768885Sdillon#include <sys/vmmeter.h> 4863897Smckusick#include <sys/stat.h> 491541Srgrimes 501541Srgrimes#include <vm/vm.h> 5112662Sdg#include <vm/vm_extern.h> 52187467Skib#include <vm/vm_object.h> 531541Srgrimes 5459241Srwatson#include <ufs/ufs/extattr.h> 551541Srgrimes#include <ufs/ufs/quota.h> 5630492Sphk#include <ufs/ufs/ufsmount.h> 571541Srgrimes#include <ufs/ufs/inode.h> 5837362Sbde#include <ufs/ufs/ufs_extern.h> 591541Srgrimes 601541Srgrimes#include <ufs/ffs/fs.h> 611541Srgrimes#include <ufs/ffs/ffs_extern.h> 621541Srgrimes 6398542Smckusickstatic int ffs_indirtrunc(struct inode *, ufs2_daddr_t, ufs2_daddr_t, 6498542Smckusick ufs2_daddr_t, int, ufs2_daddr_t *); 651541Srgrimes 661541Srgrimes/* 671541Srgrimes * Update the access, modified, and inode change times as specified by the 6837363Sbde * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. Write the inode 6937363Sbde * to disk if the IN_MODIFIED flag is set (it may be set initially, or by 7037363Sbde * the timestamp update). The IN_LAZYMOD flag is set to force a write 71163194Skib * later if not now. The IN_LAZYACCESS is set instead of IN_MODIFIED if the fs 72163194Skib * is currently being suspended (or is suspended) and vnode has been accessed. 73163194Skib * If we write now, then clear IN_MODIFIED, IN_LAZYACCESS and IN_LAZYMOD to 74163194Skib * reflect the presumably successful write, and if waitfor is set, then wait 75163194Skib * for the write to complete. 761541Srgrimes */ 771541Srgrimesint 7842374Sbdeffs_update(vp, waitfor) 7930492Sphk struct vnode *vp; 8030492Sphk int waitfor; 811541Srgrimes{ 8296506Sphk struct fs *fs; 831541Srgrimes struct buf *bp; 841541Srgrimes struct inode *ip; 85232351Smckusick int flags, error; 861541Srgrimes 87163194Skib ASSERT_VOP_ELOCKED(vp, "ffs_update"); 8842350Sbde ufs_itimes(vp); 8930492Sphk ip = VTOI(vp); 9042354Sbde if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0) 911541Srgrimes return (0); 92163194Skib ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED); 9389384Smckusick fs = ip->i_fs; 94224061Smckusick if (fs->fs_ronly && ip->i_ump->um_fsckpid == 0) 951541Srgrimes return (0); 96232351Smckusick /* 97232351Smckusick * If we are updating a snapshot and another process is currently 98232351Smckusick * writing the buffer containing the inode for this snapshot then 99232351Smckusick * a deadlock can occur when it tries to check the snapshot to see 100232351Smckusick * if that block needs to be copied. Thus when updating a snapshot 101232351Smckusick * we check to see if the buffer is already locked, and if it is 102232351Smckusick * we drop the snapshot lock until the buffer has been written 103232351Smckusick * and is available to us. We have to grab a reference to the 104232351Smckusick * snapshot vnode to prevent it from being removed while we are 105232351Smckusick * waiting for the buffer. 106232351Smckusick */ 107232351Smckusick flags = 0; 108232351Smckusick if (IS_SNAPSHOT(ip)) 109232351Smckusick flags = GB_LOCK_NOWAIT; 110233629Smckusickloop: 111232351Smckusick error = breadn_flags(ip->i_devvp, 112232351Smckusick fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 113232351Smckusick (int) fs->fs_bsize, 0, 0, 0, NOCRED, flags, &bp); 114232351Smckusick if (error != 0) { 115232351Smckusick if (error != EBUSY) { 116232351Smckusick brelse(bp); 117232351Smckusick return (error); 118232351Smckusick } 119232351Smckusick KASSERT((IS_SNAPSHOT(ip)), ("EBUSY from non-snapshot")); 120233629Smckusick /* 121233629Smckusick * Wait for our inode block to become available. 122233629Smckusick * 123233629Smckusick * Hold a reference to the vnode to protect against 124233629Smckusick * ffs_snapgone(). Since we hold a reference, it can only 125233629Smckusick * get reclaimed (VI_DOOMED flag) in a forcible downgrade 126233629Smckusick * or unmount. For an unmount, the entire filesystem will be 127233629Smckusick * gone, so we cannot attempt to touch anything associated 128233629Smckusick * with it while the vnode is unlocked; all we can do is 129233629Smckusick * pause briefly and try again. If when we relock the vnode 130233629Smckusick * we discover that it has been reclaimed, updating it is no 131233629Smckusick * longer necessary and we can just return an error. 132233629Smckusick */ 133233629Smckusick vref(vp); 134232351Smckusick VOP_UNLOCK(vp, 0); 135233629Smckusick pause("ffsupd", 1); 136232351Smckusick vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 137232351Smckusick vrele(vp); 138233629Smckusick if ((vp->v_iflag & VI_DOOMED) != 0) 139233629Smckusick return (ENOENT); 140233629Smckusick goto loop; 1411541Srgrimes } 14234266Sjulian if (DOINGSOFTDEP(vp)) 14334266Sjulian softdep_update_inodeblock(ip, bp, waitfor); 14434266Sjulian else if (ip->i_effnlink != ip->i_nlink) 14534266Sjulian panic("ffs_update: bad link cnt"); 14698542Smckusick if (ip->i_ump->um_fstype == UFS1) 14798542Smckusick *((struct ufs1_dinode *)bp->b_data + 14898542Smckusick ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1; 14998542Smckusick else 15098542Smckusick *((struct ufs2_dinode *)bp->b_data + 15198542Smckusick ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2; 152232837Skib if (waitfor && !DOINGASYNC(vp)) 153232351Smckusick error = bwrite(bp); 154232835Skib else if (vm_page_count_severe() || buf_dirty_count_severe()) { 155232835Skib bawrite(bp); 156232835Skib error = 0; 15734266Sjulian } else { 15832286Sdyson if (bp->b_bufsize == fs->fs_bsize) 15932286Sdyson bp->b_flags |= B_CLUSTEROK; 1601541Srgrimes bdwrite(bp); 161232351Smckusick error = 0; 1621541Srgrimes } 163232351Smckusick return (error); 1641541Srgrimes} 1651541Srgrimes 1661541Srgrimes#define SINGLE 0 /* index of single indirect block */ 1671541Srgrimes#define DOUBLE 1 /* index of double indirect block */ 1681541Srgrimes#define TRIPLE 2 /* index of triple indirect block */ 1691541Srgrimes/* 170144659Sjeff * Truncate the inode ip to at most length size, freeing the 1711541Srgrimes * disk blocks. 1721541Srgrimes */ 1731549Srgrimesint 174234605Straszffs_truncate(vp, length, flags, cred) 17530474Sphk struct vnode *vp; 17630474Sphk off_t length; 17730474Sphk int flags; 17830474Sphk struct ucred *cred; 1791541Srgrimes{ 180144659Sjeff struct inode *ip; 18198542Smckusick ufs2_daddr_t bn, lbn, lastblock, lastiblock[NIADDR], indir_lbn[NIADDR]; 18298542Smckusick ufs2_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR]; 183100344Smckusick ufs2_daddr_t count, blocksreleased = 0, datablocks; 184177493Sjeff struct bufobj *bo; 18596506Sphk struct fs *fs; 1861541Srgrimes struct buf *bp; 187140703Sjeff struct ufsmount *ump; 188222958Sjeff int softdeptrunc, journaltrunc; 189222958Sjeff int needextclean, extblocks; 19098542Smckusick int offset, size, level, nblocks; 191100344Smckusick int i, error, allerror; 1921541Srgrimes off_t osize; 1931541Srgrimes 194144659Sjeff ip = VTOI(vp); 195144659Sjeff fs = ip->i_fs; 196144659Sjeff ump = ip->i_ump; 197177493Sjeff bo = &vp->v_bufobj; 198140703Sjeff 199142263Sjeff ASSERT_VOP_LOCKED(vp, "ffs_truncate"); 200142263Sjeff 20122521Sdyson if (length < 0) 2023768Sdg return (EINVAL); 203207141Sjeff if (length > fs->fs_maxfilesize) 204207141Sjeff return (EFBIG); 205222958Sjeff#ifdef QUOTA 206222958Sjeff error = getinoquota(ip); 207222958Sjeff if (error) 208222958Sjeff return (error); 209222958Sjeff#endif 210100344Smckusick /* 211100344Smckusick * Historically clients did not have to specify which data 212100344Smckusick * they were truncating. So, if not specified, we assume 213100344Smckusick * traditional behavior, e.g., just the normal data. 214100344Smckusick */ 215100344Smckusick if ((flags & (IO_EXT | IO_NORMAL)) == 0) 216100344Smckusick flags |= IO_NORMAL; 217209717Sjeff if (!DOINGSOFTDEP(vp) && !DOINGASYNC(vp)) 218209717Sjeff flags |= IO_SYNC; 219100344Smckusick /* 220100344Smckusick * If we are truncating the extended-attributes, and cannot 221100344Smckusick * do it with soft updates, then do it slowly here. If we are 222100344Smckusick * truncating both the extended attributes and the file contents 223100344Smckusick * (e.g., the file is being unlinked), then pick it off with 224100344Smckusick * soft updates below. 225100344Smckusick */ 226207141Sjeff allerror = 0; 227100344Smckusick needextclean = 0; 228222958Sjeff softdeptrunc = 0; 229222958Sjeff journaltrunc = DOINGSUJ(vp); 230222958Sjeff if (journaltrunc == 0 && DOINGSOFTDEP(vp) && length == 0) 231222958Sjeff softdeptrunc = !softdep_slowdown(vp); 232100344Smckusick extblocks = 0; 233144659Sjeff datablocks = DIP(ip, i_blocks); 234144659Sjeff if (fs->fs_magic == FS_UFS2_MAGIC && ip->i_din2->di_extsize > 0) { 235144659Sjeff extblocks = btodb(fragroundup(fs, ip->i_din2->di_extsize)); 236100344Smckusick datablocks -= extblocks; 237100344Smckusick } 238100344Smckusick if ((flags & IO_EXT) && extblocks > 0) { 239222958Sjeff if (length != 0) 240222958Sjeff panic("ffs_truncate: partial trunc of extdata"); 241222958Sjeff if (softdeptrunc || journaltrunc) { 242222958Sjeff if ((flags & IO_NORMAL) == 0) 243222958Sjeff goto extclean; 244100344Smckusick needextclean = 1; 245100344Smckusick } else { 246233438Smckusick if ((error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0) 247100344Smckusick return (error); 248100344Smckusick#ifdef QUOTA 249144659Sjeff (void) chkdq(ip, -extblocks, NOCRED, 0); 250100344Smckusick#endif 251183754Sattilio vinvalbuf(vp, V_ALT, 0, 0); 252225166Smm vn_pages_remove(vp, 253187490Skib OFF_TO_IDX(lblktosize(fs, -extblocks)), 0); 254222958Sjeff osize = ip->i_din2->di_extsize; 255222958Sjeff ip->i_din2->di_blocks -= extblocks; 256144659Sjeff ip->i_din2->di_extsize = 0; 257100344Smckusick for (i = 0; i < NXADDR; i++) { 258144659Sjeff oldblks[i] = ip->i_din2->di_extb[i]; 259144659Sjeff ip->i_din2->di_extb[i] = 0; 260100344Smckusick } 261187790Srwatson ip->i_flag |= IN_CHANGE; 262232836Skib if ((error = ffs_update(vp, !DOINGASYNC(vp)))) 263222958Sjeff return (error); 264100344Smckusick for (i = 0; i < NXADDR; i++) { 265100344Smckusick if (oldblks[i] == 0) 266100344Smckusick continue; 267144659Sjeff ffs_blkfree(ump, fs, ip->i_devvp, oldblks[i], 268223127Smckusick sblksize(fs, osize, i), ip->i_number, 269223127Smckusick vp->v_type, NULL); 270100344Smckusick } 271100344Smckusick } 272100344Smckusick } 273222958Sjeff if ((flags & IO_NORMAL) == 0) 274222958Sjeff return (0); 275144659Sjeff if (vp->v_type == VLNK && 276144659Sjeff (ip->i_size < vp->v_mount->mnt_maxsymlinklen || 277100344Smckusick datablocks == 0)) { 278173464Sobrien#ifdef INVARIANTS 2791541Srgrimes if (length != 0) 2801541Srgrimes panic("ffs_truncate: partial truncate of symlink"); 2811541Srgrimes#endif 282144659Sjeff bzero(SHORTLINK(ip), (u_int)ip->i_size); 283144659Sjeff ip->i_size = 0; 284144659Sjeff DIP_SET(ip, i_size, 0); 285144659Sjeff ip->i_flag |= IN_CHANGE | IN_UPDATE; 286100344Smckusick if (needextclean) 287222958Sjeff goto extclean; 288232836Skib return (ffs_update(vp, !DOINGASYNC(vp))); 2891541Srgrimes } 290144659Sjeff if (ip->i_size == length) { 291144659Sjeff ip->i_flag |= IN_CHANGE | IN_UPDATE; 292100344Smckusick if (needextclean) 293222958Sjeff goto extclean; 294232836Skib return (ffs_update(vp, 0)); 2951541Srgrimes } 29689413Smckusick if (fs->fs_ronly) 29789413Smckusick panic("ffs_truncate: read-only filesystem"); 298232351Smckusick if (IS_SNAPSHOT(ip)) 299144659Sjeff ffs_snapremove(vp); 300144659Sjeff vp->v_lasta = vp->v_clen = vp->v_cstart = vp->v_lastw = 0; 301207141Sjeff osize = ip->i_size; 302207141Sjeff /* 303207141Sjeff * Lengthen the size of the file. We must ensure that the 304207141Sjeff * last byte of the file is allocated. Since the smallest 305207141Sjeff * value of osize is 0, length will be at least 1. 306207141Sjeff */ 307207141Sjeff if (osize < length) { 308207141Sjeff vnode_pager_setsize(vp, length); 309207141Sjeff flags |= BA_CLRBUF; 310207141Sjeff error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp); 311207141Sjeff if (error) { 312207141Sjeff vnode_pager_setsize(vp, osize); 313222958Sjeff return (error); 314207141Sjeff } 315207141Sjeff ip->i_size = length; 316207141Sjeff DIP_SET(ip, i_size, length); 317207141Sjeff if (bp->b_bufsize == fs->fs_bsize) 318207141Sjeff bp->b_flags |= B_CLUSTEROK; 319207141Sjeff if (flags & IO_SYNC) 320207141Sjeff bwrite(bp); 321232836Skib else if (DOINGASYNC(vp)) 322232836Skib bdwrite(bp); 323207141Sjeff else 324207141Sjeff bawrite(bp); 325207141Sjeff ip->i_flag |= IN_CHANGE | IN_UPDATE; 326232836Skib return (ffs_update(vp, !DOINGASYNC(vp))); 327207141Sjeff } 328144659Sjeff if (DOINGSOFTDEP(vp)) { 329222958Sjeff if (softdeptrunc == 0 && journaltrunc == 0) { 33034266Sjulian /* 33134266Sjulian * If a file is only partially truncated, then 33234266Sjulian * we have to clean up the data structures 33334266Sjulian * describing the allocation past the truncation 33434266Sjulian * point. Finding and deallocating those structures 33534266Sjulian * is a lot of work. Since partial truncation occurs 33634266Sjulian * rarely, we solve the problem by syncing the file 33734266Sjulian * so that it will have no data structures left. 33834266Sjulian */ 339233438Smckusick if ((error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0) 340222958Sjeff return (error); 34134266Sjulian } else { 342222958Sjeff flags = IO_NORMAL | (needextclean ? IO_EXT: 0); 343222958Sjeff if (journaltrunc) 344222958Sjeff softdep_journal_freeblocks(ip, cred, length, 345222958Sjeff flags); 346222958Sjeff else 347222958Sjeff softdep_setup_freeblocks(ip, length, flags); 348142263Sjeff ASSERT_VOP_LOCKED(vp, "ffs_truncate1"); 349222958Sjeff if (journaltrunc == 0) { 350222958Sjeff ip->i_flag |= IN_CHANGE | IN_UPDATE; 351222958Sjeff error = ffs_update(vp, 0); 352222958Sjeff } 353222958Sjeff return (error); 35434266Sjulian } 35534266Sjulian } 3561541Srgrimes /* 3571541Srgrimes * Shorten the size of the file. If the file is not being 35836990Sjulian * truncated to a block boundary, the contents of the 3591541Srgrimes * partial block following the end of the file must be 36036990Sjulian * zero'ed in case it ever becomes accessible again because 36136990Sjulian * of subsequent file growth. Directories however are not 36236990Sjulian * zero'ed as they should grow back initialized to empty. 3631541Srgrimes */ 3641541Srgrimes offset = blkoff(fs, length); 3651541Srgrimes if (offset == 0) { 366144659Sjeff ip->i_size = length; 367144659Sjeff DIP_SET(ip, i_size, length); 3681541Srgrimes } else { 3691541Srgrimes lbn = lblkno(fs, length); 370100344Smckusick flags |= BA_CLRBUF; 371144659Sjeff error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp); 372207141Sjeff if (error) 373222958Sjeff return (error); 37487782Smckusick /* 37587782Smckusick * When we are doing soft updates and the UFS_BALLOC 37687782Smckusick * above fills in a direct block hole with a full sized 37787782Smckusick * block that will be truncated down to a fragment below, 37887782Smckusick * we must flush out the block dependency with an FSYNC 37987782Smckusick * so that we do not get a soft updates inconsistency 38087782Smckusick * when we create the fragment below. 38187782Smckusick */ 382144659Sjeff if (DOINGSOFTDEP(vp) && lbn < NDADDR && 38387782Smckusick fragroundup(fs, blkoff(fs, length)) < fs->fs_bsize && 384233438Smckusick (error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0) 385222958Sjeff return (error); 386144659Sjeff ip->i_size = length; 387144659Sjeff DIP_SET(ip, i_size, length); 388144659Sjeff size = blksize(fs, ip, lbn); 389144659Sjeff if (vp->v_type != VDIR) 39036990Sjulian bzero((char *)bp->b_data + offset, 39136990Sjulian (u_int)(size - offset)); 39236990Sjulian /* Kirk's code has reallocbuf(bp, size, 1) here */ 3937399Sdg allocbuf(bp, size); 39432286Sdyson if (bp->b_bufsize == fs->fs_bsize) 39532286Sdyson bp->b_flags |= B_CLUSTEROK; 396100344Smckusick if (flags & IO_SYNC) 3971541Srgrimes bwrite(bp); 398232836Skib else if (DOINGASYNC(vp)) 399232836Skib bdwrite(bp); 4001541Srgrimes else 4011541Srgrimes bawrite(bp); 4021541Srgrimes } 4031541Srgrimes /* 4041541Srgrimes * Calculate index into inode's block list of 4051541Srgrimes * last direct and indirect blocks (if any) 4061541Srgrimes * which we want to keep. Lastblock is -1 when 4071541Srgrimes * the file is truncated to 0. 4081541Srgrimes */ 4091541Srgrimes lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1; 4101541Srgrimes lastiblock[SINGLE] = lastblock - NDADDR; 4111541Srgrimes lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); 4121541Srgrimes lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); 4131541Srgrimes nblocks = btodb(fs->fs_bsize); 4141541Srgrimes /* 4151541Srgrimes * Update file and block pointers on disk before we start freeing 4161541Srgrimes * blocks. If we crash before free'ing blocks below, the blocks 4171541Srgrimes * will be returned to the free list. lastiblock values are also 4181541Srgrimes * normalized to -1 for calls to ffs_indirtrunc below. 4191541Srgrimes */ 42098542Smckusick for (level = TRIPLE; level >= SINGLE; level--) { 421144659Sjeff oldblks[NDADDR + level] = DIP(ip, i_ib[level]); 4221541Srgrimes if (lastiblock[level] < 0) { 423144659Sjeff DIP_SET(ip, i_ib[level], 0); 4241541Srgrimes lastiblock[level] = -1; 4251541Srgrimes } 42698542Smckusick } 42798542Smckusick for (i = 0; i < NDADDR; i++) { 428144659Sjeff oldblks[i] = DIP(ip, i_db[i]); 42998542Smckusick if (i > lastblock) 430144659Sjeff DIP_SET(ip, i_db[i], 0); 43198542Smckusick } 432144659Sjeff ip->i_flag |= IN_CHANGE | IN_UPDATE; 433232836Skib allerror = ffs_update(vp, !DOINGASYNC(vp)); 43434696Sdyson 4351541Srgrimes /* 4361541Srgrimes * Having written the new inode to disk, save its new configuration 4371541Srgrimes * and put back the old block pointers long enough to process them. 4381541Srgrimes * Note that we save the new block configuration so we can check it 4391541Srgrimes * when we are done. 4401541Srgrimes */ 44198542Smckusick for (i = 0; i < NDADDR; i++) { 442144659Sjeff newblks[i] = DIP(ip, i_db[i]); 443144659Sjeff DIP_SET(ip, i_db[i], oldblks[i]); 44498542Smckusick } 44598542Smckusick for (i = 0; i < NIADDR; i++) { 446144659Sjeff newblks[NDADDR + i] = DIP(ip, i_ib[i]); 447144659Sjeff DIP_SET(ip, i_ib[i], oldblks[NDADDR + i]); 44898542Smckusick } 449144659Sjeff ip->i_size = osize; 450144659Sjeff DIP_SET(ip, i_size, osize); 4511541Srgrimes 452234605Strasz error = vtruncbuf(vp, cred, length, fs->fs_bsize); 45334696Sdyson if (error && (allerror == 0)) 45434696Sdyson allerror = error; 45534696Sdyson 4561541Srgrimes /* 4571541Srgrimes * Indirect blocks first. 4581541Srgrimes */ 4591541Srgrimes indir_lbn[SINGLE] = -NDADDR; 4601541Srgrimes indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1; 4611541Srgrimes indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1; 4621541Srgrimes for (level = TRIPLE; level >= SINGLE; level--) { 463144659Sjeff bn = DIP(ip, i_ib[level]); 4641541Srgrimes if (bn != 0) { 465144659Sjeff error = ffs_indirtrunc(ip, indir_lbn[level], 4661541Srgrimes fsbtodb(fs, bn), lastiblock[level], level, &count); 4671541Srgrimes if (error) 4681541Srgrimes allerror = error; 4691541Srgrimes blocksreleased += count; 4701541Srgrimes if (lastiblock[level] < 0) { 471144659Sjeff DIP_SET(ip, i_ib[level], 0); 472144659Sjeff ffs_blkfree(ump, fs, ip->i_devvp, bn, 473223127Smckusick fs->fs_bsize, ip->i_number, 474223127Smckusick vp->v_type, NULL); 4751541Srgrimes blocksreleased += nblocks; 4761541Srgrimes } 4771541Srgrimes } 4781541Srgrimes if (lastiblock[level] >= 0) 4791541Srgrimes goto done; 4801541Srgrimes } 4811541Srgrimes 4821541Srgrimes /* 4831541Srgrimes * All whole direct blocks or frags. 4841541Srgrimes */ 4851541Srgrimes for (i = NDADDR - 1; i > lastblock; i--) { 48696506Sphk long bsize; 4871541Srgrimes 488144659Sjeff bn = DIP(ip, i_db[i]); 4891541Srgrimes if (bn == 0) 4901541Srgrimes continue; 491144659Sjeff DIP_SET(ip, i_db[i], 0); 492144659Sjeff bsize = blksize(fs, ip, i); 493207141Sjeff ffs_blkfree(ump, fs, ip->i_devvp, bn, bsize, ip->i_number, 494223127Smckusick vp->v_type, NULL); 4951541Srgrimes blocksreleased += btodb(bsize); 4961541Srgrimes } 4971541Srgrimes if (lastblock < 0) 4981541Srgrimes goto done; 4991541Srgrimes 5001541Srgrimes /* 5011541Srgrimes * Finally, look for a change in size of the 5021541Srgrimes * last direct block; release any frags. 5031541Srgrimes */ 504144659Sjeff bn = DIP(ip, i_db[lastblock]); 5051541Srgrimes if (bn != 0) { 5061541Srgrimes long oldspace, newspace; 5071541Srgrimes 5081541Srgrimes /* 5091541Srgrimes * Calculate amount of space we're giving 5101541Srgrimes * back as old block size minus new block size. 5111541Srgrimes */ 512144659Sjeff oldspace = blksize(fs, ip, lastblock); 513144659Sjeff ip->i_size = length; 514144659Sjeff DIP_SET(ip, i_size, length); 515144659Sjeff newspace = blksize(fs, ip, lastblock); 5161541Srgrimes if (newspace == 0) 5171826Sdg panic("ffs_truncate: newspace"); 5181541Srgrimes if (oldspace - newspace > 0) { 5191541Srgrimes /* 5201541Srgrimes * Block number of space to be free'd is 5211541Srgrimes * the old block # plus the number of frags 5221541Srgrimes * required for the storage we're keeping. 5231541Srgrimes */ 5241541Srgrimes bn += numfrags(fs, newspace); 525144659Sjeff ffs_blkfree(ump, fs, ip->i_devvp, bn, 526223127Smckusick oldspace - newspace, ip->i_number, vp->v_type, NULL); 5271541Srgrimes blocksreleased += btodb(oldspace - newspace); 5281541Srgrimes } 5291541Srgrimes } 5301541Srgrimesdone: 531173464Sobrien#ifdef INVARIANTS 5321541Srgrimes for (level = SINGLE; level <= TRIPLE; level++) 533144659Sjeff if (newblks[NDADDR + level] != DIP(ip, i_ib[level])) 5341826Sdg panic("ffs_truncate1"); 5351541Srgrimes for (i = 0; i < NDADDR; i++) 536144659Sjeff if (newblks[i] != DIP(ip, i_db[i])) 5371826Sdg panic("ffs_truncate2"); 538177493Sjeff BO_LOCK(bo); 5391541Srgrimes if (length == 0 && 540144659Sjeff (fs->fs_magic != FS_UFS2_MAGIC || ip->i_din2->di_extsize == 0) && 541177493Sjeff (bo->bo_dirty.bv_cnt > 0 || bo->bo_clean.bv_cnt > 0)) 5421826Sdg panic("ffs_truncate3"); 543177493Sjeff BO_UNLOCK(bo); 544173464Sobrien#endif /* INVARIANTS */ 5451541Srgrimes /* 5461541Srgrimes * Put back the real size. 5471541Srgrimes */ 548144659Sjeff ip->i_size = length; 549144659Sjeff DIP_SET(ip, i_size, length); 550246289Smckusick if (DIP(ip, i_blocks) >= blocksreleased) 551246289Smckusick DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased); 552246289Smckusick else /* sanity */ 553144659Sjeff DIP_SET(ip, i_blocks, 0); 554144659Sjeff ip->i_flag |= IN_CHANGE; 5551541Srgrimes#ifdef QUOTA 556144659Sjeff (void) chkdq(ip, -blocksreleased, NOCRED, 0); 5571541Srgrimes#endif 558222958Sjeff return (allerror); 559222958Sjeff 560222958Sjeffextclean: 561222958Sjeff if (journaltrunc) 562222958Sjeff softdep_journal_freeblocks(ip, cred, length, IO_EXT); 563222958Sjeff else 564222958Sjeff softdep_setup_freeblocks(ip, length, IO_EXT); 565300600Skib return (ffs_update(vp, (flags & IO_SYNC) != 0 || !DOINGASYNC(vp))); 5661541Srgrimes} 5671541Srgrimes 5681541Srgrimes/* 5691541Srgrimes * Release blocks associated with the inode ip and stored in the indirect 5701541Srgrimes * block bn. Blocks are free'd in LIFO order up to (but not including) 5711541Srgrimes * lastbn. If level is greater than SINGLE, the block is an indirect block 5721541Srgrimes * and recursive calls to indirtrunc must be used to cleanse other indirect 5731541Srgrimes * blocks. 5741541Srgrimes */ 5751541Srgrimesstatic int 5761541Srgrimesffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) 57796506Sphk struct inode *ip; 57898542Smckusick ufs2_daddr_t lbn, lastbn; 57998542Smckusick ufs2_daddr_t dbn; 5801541Srgrimes int level; 58198542Smckusick ufs2_daddr_t *countp; 5821541Srgrimes{ 5831541Srgrimes struct buf *bp; 58496506Sphk struct fs *fs = ip->i_fs; 5851541Srgrimes struct vnode *vp; 58698542Smckusick caddr_t copy = NULL; 58798542Smckusick int i, nblocks, error = 0, allerror = 0; 58898542Smckusick ufs2_daddr_t nb, nlbn, last; 58998542Smckusick ufs2_daddr_t blkcount, factor, blocksreleased = 0; 59098542Smckusick ufs1_daddr_t *bap1 = NULL; 59198542Smckusick ufs2_daddr_t *bap2 = NULL; 59298542Smckusick# define BAP(ip, i) (((ip)->i_ump->um_fstype == UFS1) ? bap1[i] : bap2[i]) 5931541Srgrimes 5941541Srgrimes /* 5951541Srgrimes * Calculate index in current block of last 5961541Srgrimes * block to be kept. -1 indicates the entire 5971541Srgrimes * block so we need not calculate the index. 5981541Srgrimes */ 599215113Skib factor = lbn_offset(fs, level); 6001541Srgrimes last = lastbn; 6011541Srgrimes if (lastbn > 0) 6021541Srgrimes last /= factor; 6031541Srgrimes nblocks = btodb(fs->fs_bsize); 6041541Srgrimes /* 6051541Srgrimes * Get buffer of block pointers, zero those entries corresponding 6061541Srgrimes * to blocks to be free'd, and update on disk copy first. Since 6071541Srgrimes * double(triple) indirect before single(double) indirect, calls 6081541Srgrimes * to bmap on these blocks will fail. However, we already have 6091541Srgrimes * the on disk address, so we have to set the b_blkno field 6101541Srgrimes * explicitly instead of letting bread do everything for us. 6111541Srgrimes */ 6121541Srgrimes vp = ITOV(ip); 613111856Sjeff bp = getblk(vp, lbn, (int)fs->fs_bsize, 0, 0, 0); 6146875Sdg if ((bp->b_flags & B_CACHE) == 0) { 615170174Sjeff curthread->td_ru.ru_inblock++; /* pay for read */ 61658345Sphk bp->b_iocmd = BIO_READ; 61758934Sphk bp->b_flags &= ~B_INVAL; 61858934Sphk bp->b_ioflags &= ~BIO_ERROR; 6191541Srgrimes if (bp->b_bcount > bp->b_bufsize) 6201541Srgrimes panic("ffs_indirtrunc: bad buffer size"); 6211541Srgrimes bp->b_blkno = dbn; 6225455Sdg vfs_busy_pages(bp, 0); 623121205Sphk bp->b_iooffset = dbtob(bp->b_blkno); 624136927Sphk bstrategy(bp); 62559762Sphk error = bufwait(bp); 6261541Srgrimes } 6271541Srgrimes if (error) { 6281541Srgrimes brelse(bp); 6291541Srgrimes *countp = 0; 6301541Srgrimes return (error); 6311541Srgrimes } 6321541Srgrimes 63398542Smckusick if (ip->i_ump->um_fstype == UFS1) 63498542Smckusick bap1 = (ufs1_daddr_t *)bp->b_data; 63598542Smckusick else 63698542Smckusick bap2 = (ufs2_daddr_t *)bp->b_data; 63719424Sdg if (lastbn != -1) { 638184205Sdes copy = malloc(fs->fs_bsize, M_TEMP, M_WAITOK); 63998542Smckusick bcopy((caddr_t)bp->b_data, copy, (u_int)fs->fs_bsize); 64098542Smckusick for (i = last + 1; i < NINDIR(fs); i++) 641132775Skan if (ip->i_ump->um_fstype == UFS1) 642132775Skan bap1[i] = 0; 643132775Skan else 644132775Skan bap2[i] = 0; 64548801Smckusick if (DOINGASYNC(vp)) { 646232836Skib bdwrite(bp); 64748801Smckusick } else { 64819424Sdg error = bwrite(bp); 64919424Sdg if (error) 65019424Sdg allerror = error; 65119424Sdg } 65298542Smckusick if (ip->i_ump->um_fstype == UFS1) 65398542Smckusick bap1 = (ufs1_daddr_t *)copy; 65498542Smckusick else 65598542Smckusick bap2 = (ufs2_daddr_t *)copy; 65612767Sdyson } 6571541Srgrimes 6581541Srgrimes /* 6591541Srgrimes * Recursively free totally unused blocks. 6601541Srgrimes */ 6611541Srgrimes for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last; 6621541Srgrimes i--, nlbn += factor) { 66398542Smckusick nb = BAP(ip, i); 6641541Srgrimes if (nb == 0) 6651541Srgrimes continue; 6661541Srgrimes if (level > SINGLE) { 66743311Sdillon if ((error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb), 66898542Smckusick (ufs2_daddr_t)-1, level - 1, &blkcount)) != 0) 6691541Srgrimes allerror = error; 6701541Srgrimes blocksreleased += blkcount; 6711541Srgrimes } 672140703Sjeff ffs_blkfree(ip->i_ump, fs, ip->i_devvp, nb, fs->fs_bsize, 673223127Smckusick ip->i_number, vp->v_type, NULL); 6741541Srgrimes blocksreleased += nblocks; 6751541Srgrimes } 6761541Srgrimes 6771541Srgrimes /* 6781541Srgrimes * Recursively free last partial block. 6791541Srgrimes */ 6801541Srgrimes if (level > SINGLE && lastbn >= 0) { 6811541Srgrimes last = lastbn % factor; 68298542Smckusick nb = BAP(ip, i); 6831541Srgrimes if (nb != 0) { 6843487Sphk error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb), 6853487Sphk last, level - 1, &blkcount); 6863487Sphk if (error) 6871541Srgrimes allerror = error; 6881541Srgrimes blocksreleased += blkcount; 6891541Srgrimes } 6901541Srgrimes } 69119424Sdg if (copy != NULL) { 692184205Sdes free(copy, M_TEMP); 69319424Sdg } else { 69419424Sdg bp->b_flags |= B_INVAL | B_NOCACHE; 69519424Sdg brelse(bp); 69619424Sdg } 69798542Smckusick 6981541Srgrimes *countp = blocksreleased; 6991541Srgrimes return (allerror); 7001541Srgrimes} 701183070Skib 702183070Skibint 703183070Skibffs_rdonly(struct inode *ip) 704183070Skib{ 705183070Skib 706183070Skib return (ip->i_ump->um_fs->fs_ronly != 0); 707183070Skib} 708183070Skib 709