155714Skris/*- 255714Skris * Copyright (c) 1982, 1986, 1989, 1993 355714Skris * The Regents of the University of California. All rights reserved. 455714Skris * 555714Skris * Redistribution and use in source and binary forms, with or without 655714Skris * modification, are permitted provided that the following conditions 755714Skris * are met: 855714Skris * 1. Redistributions of source code must retain the above copyright 955714Skris * notice, this list of conditions and the following disclaimer. 1055714Skris * 2. Redistributions in binary form must reproduce the above copyright 1155714Skris * notice, this list of conditions and the following disclaimer in the 1255714Skris * documentation and/or other materials provided with the distribution. 1355714Skris * 4. Neither the name of the University nor the names of its contributors 1455714Skris * may be used to endorse or promote products derived from this software 1555714Skris * without specific prior written permission. 1655714Skris * 1755714Skris * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1855714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1955714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2055714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2155714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2255714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2355714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2455714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2555714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2655714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2755714Skris * SUCH DAMAGE. 2855714Skris * 2955714Skris * @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95 3055714Skris */ 3155714Skris 3255714Skris#include <sys/cdefs.h> 3355714Skris__FBSDID("$FreeBSD$"); 3455714Skris 3555714Skris#include "opt_quota.h" 3655714Skris 3755714Skris#include <sys/param.h> 3855714Skris#include <sys/systm.h> 3955714Skris#include <sys/mount.h> 4055714Skris#include <sys/proc.h> 4155714Skris#include <sys/bio.h> 4255714Skris#include <sys/buf.h> 4355714Skris#include <sys/vnode.h> 4455714Skris#include <sys/malloc.h> 4555714Skris#include <sys/resourcevar.h> 4655714Skris#include <sys/rwlock.h> 4755714Skris#include <sys/vmmeter.h> 4855714Skris#include <sys/stat.h> 4955714Skris 5055714Skris#include <vm/vm.h> 5155714Skris#include <vm/vm_extern.h> 5255714Skris#include <vm/vm_object.h> 5355714Skris 5455714Skris#include <ufs/ufs/extattr.h> 5555714Skris#include <ufs/ufs/quota.h> 5655714Skris#include <ufs/ufs/ufsmount.h> 5755714Skris#include <ufs/ufs/inode.h> 5855714Skris#include <ufs/ufs/ufs_extern.h> 5955714Skris 6055714Skris#include <ufs/ffs/fs.h> 6155714Skris#include <ufs/ffs/ffs_extern.h> 6268651Skris 6368651Skrisstatic int ffs_indirtrunc(struct inode *, ufs2_daddr_t, ufs2_daddr_t, 6455714Skris ufs2_daddr_t, int, ufs2_daddr_t *); 6555714Skris 6655714Skris/* 6755714Skris * Update the access, modified, and inode change times as specified by the 6855714Skris * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. Write the inode 6955714Skris * to disk if the IN_MODIFIED flag is set (it may be set initially, or by 7055714Skris * the timestamp update). The IN_LAZYMOD flag is set to force a write 7155714Skris * later if not now. The IN_LAZYACCESS is set instead of IN_MODIFIED if the fs 7255714Skris * is currently being suspended (or is suspended) and vnode has been accessed. 73109998Smarkm * If we write now, then clear IN_MODIFIED, IN_LAZYACCESS and IN_LAZYMOD to 7455714Skris * reflect the presumably successful write, and if waitfor is set, then wait 7555714Skris * for the write to complete. 76160814Ssimon */ 7755714Skrisint 7855714Skrisffs_update(vp, waitfor) 79160814Ssimon struct vnode *vp; 80160814Ssimon int waitfor; 8155714Skris{ 8255714Skris struct fs *fs; 8355714Skris struct buf *bp; 8455714Skris struct inode *ip; 8555714Skris int flags, error; 8655714Skris 8755714Skris ASSERT_VOP_ELOCKED(vp, "ffs_update"); 88160814Ssimon ufs_itimes(vp); 8955714Skris ip = VTOI(vp); 9055714Skris if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0) 9155714Skris return (0); 92160814Ssimon ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED); 9355714Skris fs = ip->i_fs; 94160814Ssimon if (fs->fs_ronly && ip->i_ump->um_fsckpid == 0) 9555714Skris return (0); 9655714Skris /* 9755714Skris * If we are updating a snapshot and another process is currently 9855714Skris * writing the buffer containing the inode for this snapshot then 9955714Skris * a deadlock can occur when it tries to check the snapshot to see 10055714Skris * if that block needs to be copied. Thus when updating a snapshot 10155714Skris * we check to see if the buffer is already locked, and if it is 102160814Ssimon * we drop the snapshot lock until the buffer has been written 10355714Skris * and is available to us. We have to grab a reference to the 10455714Skris * snapshot vnode to prevent it from being removed while we are 10555714Skris * waiting for the buffer. 10655714Skris */ 10755714Skris flags = 0; 10855714Skris if (IS_SNAPSHOT(ip)) 10959191Skris flags = GB_LOCK_NOWAIT; 11059191Skrisloop: 11159191Skris error = breadn_flags(ip->i_devvp, 11255714Skris fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 11359191Skris (int) fs->fs_bsize, 0, 0, 0, NOCRED, flags, &bp); 11459191Skris if (error != 0) { 11559191Skris if (error != EBUSY) { 11659191Skris brelse(bp); 11759191Skris return (error); 11859191Skris } 11959191Skris KASSERT((IS_SNAPSHOT(ip)), ("EBUSY from non-snapshot")); 12059191Skris /* 12159191Skris * Wait for our inode block to become available. 12259191Skris * 12359191Skris * Hold a reference to the vnode to protect against 12455714Skris * ffs_snapgone(). Since we hold a reference, it can only 12555714Skris * get reclaimed (VI_DOOMED flag) in a forcible downgrade 126160814Ssimon * or unmount. For an unmount, the entire filesystem will be 12755714Skris * gone, so we cannot attempt to touch anything associated 12855714Skris * with it while the vnode is unlocked; all we can do is 129160814Ssimon * pause briefly and try again. If when we relock the vnode 13055714Skris * we discover that it has been reclaimed, updating it is no 13155714Skris * longer necessary and we can just return an error. 13255714Skris */ 13355714Skris vref(vp); 13455714Skris VOP_UNLOCK(vp, 0); 135160814Ssimon pause("ffsupd", 1); 136160814Ssimon vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 137160814Ssimon vrele(vp); 138160814Ssimon if ((vp->v_iflag & VI_DOOMED) != 0) 139160814Ssimon return (ENOENT); 140160814Ssimon goto loop; 141160814Ssimon } 14255714Skris if (DOINGSOFTDEP(vp)) 14355714Skris softdep_update_inodeblock(ip, bp, waitfor); 14455714Skris else if (ip->i_effnlink != ip->i_nlink) 14555714Skris panic("ffs_update: bad link cnt"); 14655714Skris if (ip->i_ump->um_fstype == UFS1) 14755714Skris *((struct ufs1_dinode *)bp->b_data + 14855714Skris ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1; 14955714Skris else 15055714Skris *((struct ufs2_dinode *)bp->b_data + 15155714Skris ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2; 15255714Skris if (waitfor && !DOINGASYNC(vp)) 15355714Skris error = bwrite(bp); 15455714Skris else if (vm_page_count_severe() || buf_dirty_count_severe()) { 15555714Skris bawrite(bp); 15655714Skris error = 0; 15755714Skris } else { 15855714Skris if (bp->b_bufsize == fs->fs_bsize) 15955714Skris bp->b_flags |= B_CLUSTEROK; 16055714Skris bdwrite(bp); 16155714Skris error = 0; 16255714Skris } 16355714Skris return (error); 16455714Skris} 16555714Skris 16655714Skris#define SINGLE 0 /* index of single indirect block */ 16755714Skris#define DOUBLE 1 /* index of double indirect block */ 16855714Skris#define TRIPLE 2 /* index of triple indirect block */ 16955714Skris/* 17055714Skris * Truncate the inode ip to at most length size, freeing the 17155714Skris * disk blocks. 17255714Skris */ 17355714Skrisint 17455714Skrisffs_truncate(vp, length, flags, cred) 17555714Skris struct vnode *vp; 17655714Skris off_t length; 17755714Skris int flags; 17855714Skris struct ucred *cred; 17955714Skris{ 18055714Skris struct inode *ip; 18155714Skris ufs2_daddr_t bn, lbn, lastblock, lastiblock[NIADDR], indir_lbn[NIADDR]; 18255714Skris ufs2_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR]; 18355714Skris ufs2_daddr_t count, blocksreleased = 0, datablocks; 18455714Skris struct bufobj *bo; 18555714Skris struct fs *fs; 18655714Skris struct buf *bp; 18755714Skris struct ufsmount *ump; 18855714Skris int softdeptrunc, journaltrunc; 18955714Skris int needextclean, extblocks; 19055714Skris int offset, size, level, nblocks; 19155714Skris int i, error, allerror; 19255714Skris off_t osize; 19355714Skris 19455714Skris ip = VTOI(vp); 19555714Skris fs = ip->i_fs; 19655714Skris ump = ip->i_ump; 19755714Skris bo = &vp->v_bufobj; 19855714Skris 19955714Skris ASSERT_VOP_LOCKED(vp, "ffs_truncate"); 20055714Skris 20155714Skris if (length < 0) 20255714Skris return (EINVAL); 20355714Skris if (length > fs->fs_maxfilesize) 20455714Skris return (EFBIG); 20555714Skris#ifdef QUOTA 20655714Skris error = getinoquota(ip); 20755714Skris if (error) 20855714Skris return (error); 20955714Skris#endif 21055714Skris /* 21155714Skris * Historically clients did not have to specify which data 21255714Skris * they were truncating. So, if not specified, we assume 21355714Skris * traditional behavior, e.g., just the normal data. 21455714Skris */ 21555714Skris if ((flags & (IO_EXT | IO_NORMAL)) == 0) 21655714Skris flags |= IO_NORMAL; 21755714Skris if (!DOINGSOFTDEP(vp) && !DOINGASYNC(vp)) 21855714Skris flags |= IO_SYNC; 21955714Skris /* 22055714Skris * If we are truncating the extended-attributes, and cannot 22155714Skris * do it with soft updates, then do it slowly here. If we are 22255714Skris * truncating both the extended attributes and the file contents 22355714Skris * (e.g., the file is being unlinked), then pick it off with 22455714Skris * soft updates below. 22555714Skris */ 22655714Skris allerror = 0; 22755714Skris needextclean = 0; 22855714Skris softdeptrunc = 0; 22955714Skris journaltrunc = DOINGSUJ(vp); 23055714Skris if (journaltrunc == 0 && DOINGSOFTDEP(vp) && length == 0) 23155714Skris softdeptrunc = !softdep_slowdown(vp); 23255714Skris extblocks = 0; 23355714Skris datablocks = DIP(ip, i_blocks); 23455714Skris if (fs->fs_magic == FS_UFS2_MAGIC && ip->i_din2->di_extsize > 0) { 23555714Skris extblocks = btodb(fragroundup(fs, ip->i_din2->di_extsize)); 23655714Skris datablocks -= extblocks; 23755714Skris } 23855714Skris if ((flags & IO_EXT) && extblocks > 0) { 23955714Skris if (length != 0) 24055714Skris panic("ffs_truncate: partial trunc of extdata"); 24155714Skris if (softdeptrunc || journaltrunc) { 24255714Skris if ((flags & IO_NORMAL) == 0) 24355714Skris goto extclean; 24455714Skris needextclean = 1; 24555714Skris } else { 24655714Skris if ((error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0) 24755714Skris return (error); 24855714Skris#ifdef QUOTA 24955714Skris (void) chkdq(ip, -extblocks, NOCRED, 0); 25055714Skris#endif 25155714Skris vinvalbuf(vp, V_ALT, 0, 0); 25255714Skris vn_pages_remove(vp, 25355714Skris OFF_TO_IDX(lblktosize(fs, -extblocks)), 0); 25455714Skris osize = ip->i_din2->di_extsize; 25555714Skris ip->i_din2->di_blocks -= extblocks; 25655714Skris ip->i_din2->di_extsize = 0; 25755714Skris for (i = 0; i < NXADDR; i++) { 25855714Skris oldblks[i] = ip->i_din2->di_extb[i]; 25955714Skris ip->i_din2->di_extb[i] = 0; 26055714Skris } 26155714Skris ip->i_flag |= IN_CHANGE; 26255714Skris if ((error = ffs_update(vp, !DOINGASYNC(vp)))) 26355714Skris return (error); 26455714Skris for (i = 0; i < NXADDR; i++) { 26555714Skris if (oldblks[i] == 0) 26655714Skris continue; 26755714Skris ffs_blkfree(ump, fs, ip->i_devvp, oldblks[i], 26855714Skris sblksize(fs, osize, i), ip->i_number, 26955714Skris vp->v_type, NULL); 27055714Skris } 27155714Skris } 27255714Skris } 27355714Skris if ((flags & IO_NORMAL) == 0) 27455714Skris return (0); 27555714Skris if (vp->v_type == VLNK && 27655714Skris (ip->i_size < vp->v_mount->mnt_maxsymlinklen || 27755714Skris datablocks == 0)) { 27855714Skris#ifdef INVARIANTS 27955714Skris if (length != 0) 28055714Skris panic("ffs_truncate: partial truncate of symlink"); 28155714Skris#endif 28255714Skris bzero(SHORTLINK(ip), (u_int)ip->i_size); 28355714Skris ip->i_size = 0; 28455714Skris DIP_SET(ip, i_size, 0); 28555714Skris ip->i_flag |= IN_CHANGE | IN_UPDATE; 28655714Skris if (needextclean) 28755714Skris goto extclean; 288160814Ssimon return (ffs_update(vp, !DOINGASYNC(vp))); 28955714Skris } 29055714Skris if (ip->i_size == length) { 29155714Skris ip->i_flag |= IN_CHANGE | IN_UPDATE; 29255714Skris if (needextclean) 29355714Skris goto extclean; 29455714Skris return (ffs_update(vp, 0)); 29555714Skris } 29655714Skris if (fs->fs_ronly) 29755714Skris panic("ffs_truncate: read-only filesystem"); 29855714Skris if (IS_SNAPSHOT(ip)) 29955714Skris ffs_snapremove(vp); 30055714Skris vp->v_lasta = vp->v_clen = vp->v_cstart = vp->v_lastw = 0; 30155714Skris osize = ip->i_size; 30255714Skris /* 30355714Skris * Lengthen the size of the file. We must ensure that the 30455714Skris * last byte of the file is allocated. Since the smallest 30555714Skris * value of osize is 0, length will be at least 1. 30655714Skris */ 30755714Skris if (osize < length) { 30855714Skris vnode_pager_setsize(vp, length); 30955714Skris flags |= BA_CLRBUF; 31055714Skris error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp); 31155714Skris if (error) { 31255714Skris vnode_pager_setsize(vp, osize); 31355714Skris return (error); 31455714Skris } 31555714Skris ip->i_size = length; 31655714Skris DIP_SET(ip, i_size, length); 31755714Skris if (bp->b_bufsize == fs->fs_bsize) 31855714Skris bp->b_flags |= B_CLUSTEROK; 31955714Skris if (flags & IO_SYNC) 32055714Skris bwrite(bp); 32155714Skris else if (DOINGASYNC(vp)) 32255714Skris bdwrite(bp); 32355714Skris else 32455714Skris bawrite(bp); 32555714Skris ip->i_flag |= IN_CHANGE | IN_UPDATE; 32655714Skris return (ffs_update(vp, !DOINGASYNC(vp))); 32755714Skris } 32855714Skris if (DOINGSOFTDEP(vp)) { 32955714Skris if (softdeptrunc == 0 && journaltrunc == 0) { 33055714Skris /* 33155714Skris * If a file is only partially truncated, then 33255714Skris * we have to clean up the data structures 33355714Skris * describing the allocation past the truncation 33455714Skris * point. Finding and deallocating those structures 33555714Skris * is a lot of work. Since partial truncation occurs 33655714Skris * rarely, we solve the problem by syncing the file 33755714Skris * so that it will have no data structures left. 33855714Skris */ 33955714Skris if ((error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0) 34055714Skris return (error); 34155714Skris } else { 34255714Skris flags = IO_NORMAL | (needextclean ? IO_EXT: 0); 34355714Skris if (journaltrunc) 34455714Skris softdep_journal_freeblocks(ip, cred, length, 34555714Skris flags); 34655714Skris else 34755714Skris softdep_setup_freeblocks(ip, length, flags); 34855714Skris ASSERT_VOP_LOCKED(vp, "ffs_truncate1"); 34955714Skris if (journaltrunc == 0) { 35068651Skris ip->i_flag |= IN_CHANGE | IN_UPDATE; 35155714Skris error = ffs_update(vp, 0); 35255714Skris } 35355714Skris return (error); 35455714Skris } 35555714Skris } 35655714Skris /* 35755714Skris * Shorten the size of the file. If the file is not being 35855714Skris * truncated to a block boundary, the contents of the 35955714Skris * partial block following the end of the file must be 36055714Skris * zero'ed in case it ever becomes accessible again because 36155714Skris * of subsequent file growth. Directories however are not 36255714Skris * zero'ed as they should grow back initialized to empty. 363160814Ssimon */ 364160814Ssimon offset = blkoff(fs, length); 365160814Ssimon if (offset == 0) { 366160814Ssimon ip->i_size = length; 367160814Ssimon DIP_SET(ip, i_size, length); 368160814Ssimon } else { 36955714Skris lbn = lblkno(fs, length); 37055714Skris flags |= BA_CLRBUF; 37155714Skris error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp); 37255714Skris if (error) 37355714Skris return (error); 37455714Skris /* 37555714Skris * When we are doing soft updates and the UFS_BALLOC 37655714Skris * above fills in a direct block hole with a full sized 37755714Skris * block that will be truncated down to a fragment below, 37855714Skris * we must flush out the block dependency with an FSYNC 37955714Skris * so that we do not get a soft updates inconsistency 38055714Skris * when we create the fragment below. 38155714Skris */ 38255714Skris if (DOINGSOFTDEP(vp) && lbn < NDADDR && 38355714Skris fragroundup(fs, blkoff(fs, length)) < fs->fs_bsize && 38455714Skris (error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0) 38555714Skris return (error); 38655714Skris ip->i_size = length; 38755714Skris DIP_SET(ip, i_size, length); 38855714Skris size = blksize(fs, ip, lbn); 38955714Skris if (vp->v_type != VDIR) 39055714Skris bzero((char *)bp->b_data + offset, 39155714Skris (u_int)(size - offset)); 39255714Skris /* Kirk's code has reallocbuf(bp, size, 1) here */ 39355714Skris allocbuf(bp, size); 39455714Skris if (bp->b_bufsize == fs->fs_bsize) 39555714Skris bp->b_flags |= B_CLUSTEROK; 39655714Skris if (flags & IO_SYNC) 39755714Skris bwrite(bp); 39855714Skris else if (DOINGASYNC(vp)) 39955714Skris bdwrite(bp); 40055714Skris else 40155714Skris bawrite(bp); 40255714Skris } 40355714Skris /* 40455714Skris * Calculate index into inode's block list of 40555714Skris * last direct and indirect blocks (if any) 40655714Skris * which we want to keep. Lastblock is -1 when 40755714Skris * the file is truncated to 0. 40855714Skris */ 40955714Skris lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1; 41055714Skris lastiblock[SINGLE] = lastblock - NDADDR; 41155714Skris lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); 41255714Skris lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); 41355714Skris nblocks = btodb(fs->fs_bsize); 41455714Skris /* 41555714Skris * Update file and block pointers on disk before we start freeing 41655714Skris * blocks. If we crash before free'ing blocks below, the blocks 41755714Skris * will be returned to the free list. lastiblock values are also 41855714Skris * normalized to -1 for calls to ffs_indirtrunc below. 41955714Skris */ 42055714Skris for (level = TRIPLE; level >= SINGLE; level--) { 42155714Skris oldblks[NDADDR + level] = DIP(ip, i_ib[level]); 42255714Skris if (lastiblock[level] < 0) { 42355714Skris DIP_SET(ip, i_ib[level], 0); 42455714Skris lastiblock[level] = -1; 42555714Skris } 42655714Skris } 42755714Skris for (i = 0; i < NDADDR; i++) { 42855714Skris oldblks[i] = DIP(ip, i_db[i]); 42955714Skris if (i > lastblock) 43055714Skris DIP_SET(ip, i_db[i], 0); 43155714Skris } 43255714Skris ip->i_flag |= IN_CHANGE | IN_UPDATE; 43355714Skris allerror = ffs_update(vp, !DOINGASYNC(vp)); 43455714Skris 43555714Skris /* 43655714Skris * Having written the new inode to disk, save its new configuration 43755714Skris * and put back the old block pointers long enough to process them. 43855714Skris * Note that we save the new block configuration so we can check it 43955714Skris * when we are done. 44055714Skris */ 44155714Skris for (i = 0; i < NDADDR; i++) { 44255714Skris newblks[i] = DIP(ip, i_db[i]); 44355714Skris DIP_SET(ip, i_db[i], oldblks[i]); 44455714Skris } 44555714Skris for (i = 0; i < NIADDR; i++) { 44655714Skris newblks[NDADDR + i] = DIP(ip, i_ib[i]); 44755714Skris DIP_SET(ip, i_ib[i], oldblks[NDADDR + i]); 44855714Skris } 44955714Skris ip->i_size = osize; 45055714Skris DIP_SET(ip, i_size, osize); 45155714Skris 45255714Skris error = vtruncbuf(vp, cred, length, fs->fs_bsize); 45355714Skris if (error && (allerror == 0)) 45455714Skris allerror = error; 45555714Skris 45655714Skris /* 45755714Skris * Indirect blocks first. 45855714Skris */ 45955714Skris indir_lbn[SINGLE] = -NDADDR; 46055714Skris indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1; 46155714Skris indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1; 46255714Skris for (level = TRIPLE; level >= SINGLE; level--) { 46355714Skris bn = DIP(ip, i_ib[level]); 46455714Skris if (bn != 0) { 46555714Skris error = ffs_indirtrunc(ip, indir_lbn[level], 46655714Skris fsbtodb(fs, bn), lastiblock[level], level, &count); 46755714Skris if (error) 46855714Skris allerror = error; 46955714Skris blocksreleased += count; 47055714Skris if (lastiblock[level] < 0) { 47155714Skris DIP_SET(ip, i_ib[level], 0); 47255714Skris ffs_blkfree(ump, fs, ip->i_devvp, bn, 47355714Skris fs->fs_bsize, ip->i_number, 47455714Skris vp->v_type, NULL); 47555714Skris blocksreleased += nblocks; 47655714Skris } 47755714Skris } 47855714Skris if (lastiblock[level] >= 0) 47955714Skris goto done; 48055714Skris } 48155714Skris 48255714Skris /* 48355714Skris * All whole direct blocks or frags. 48455714Skris */ 48555714Skris for (i = NDADDR - 1; i > lastblock; i--) { 48655714Skris long bsize; 48755714Skris 48855714Skris bn = DIP(ip, i_db[i]); 48955714Skris if (bn == 0) 49055714Skris continue; 49155714Skris DIP_SET(ip, i_db[i], 0); 49255714Skris bsize = blksize(fs, ip, i); 49355714Skris ffs_blkfree(ump, fs, ip->i_devvp, bn, bsize, ip->i_number, 49455714Skris vp->v_type, NULL); 49555714Skris blocksreleased += btodb(bsize); 49655714Skris } 49755714Skris if (lastblock < 0) 49855714Skris goto done; 49955714Skris 50055714Skris /* 50155714Skris * Finally, look for a change in size of the 50255714Skris * last direct block; release any frags. 50355714Skris */ 50455714Skris bn = DIP(ip, i_db[lastblock]); 50555714Skris if (bn != 0) { 50655714Skris long oldspace, newspace; 50755714Skris 50855714Skris /* 50955714Skris * Calculate amount of space we're giving 51055714Skris * back as old block size minus new block size. 51155714Skris */ 51255714Skris oldspace = blksize(fs, ip, lastblock); 51355714Skris ip->i_size = length; 51455714Skris DIP_SET(ip, i_size, length); 51555714Skris newspace = blksize(fs, ip, lastblock); 51655714Skris if (newspace == 0) 51755714Skris panic("ffs_truncate: newspace"); 51855714Skris if (oldspace - newspace > 0) { 51955714Skris /* 52055714Skris * Block number of space to be free'd is 52155714Skris * the old block # plus the number of frags 52255714Skris * required for the storage we're keeping. 52355714Skris */ 52455714Skris bn += numfrags(fs, newspace); 52555714Skris ffs_blkfree(ump, fs, ip->i_devvp, bn, 52655714Skris oldspace - newspace, ip->i_number, vp->v_type, NULL); 52755714Skris blocksreleased += btodb(oldspace - newspace); 52855714Skris } 52955714Skris } 53055714Skrisdone: 53155714Skris#ifdef INVARIANTS 53255714Skris for (level = SINGLE; level <= TRIPLE; level++) 53355714Skris if (newblks[NDADDR + level] != DIP(ip, i_ib[level])) 53455714Skris panic("ffs_truncate1"); 53555714Skris for (i = 0; i < NDADDR; i++) 53655714Skris if (newblks[i] != DIP(ip, i_db[i])) 53755714Skris panic("ffs_truncate2"); 53855714Skris BO_LOCK(bo); 53955714Skris if (length == 0 && 54055714Skris (fs->fs_magic != FS_UFS2_MAGIC || ip->i_din2->di_extsize == 0) && 54155714Skris (bo->bo_dirty.bv_cnt > 0 || bo->bo_clean.bv_cnt > 0)) 54255714Skris panic("ffs_truncate3"); 54355714Skris BO_UNLOCK(bo); 54455714Skris#endif /* INVARIANTS */ 54555714Skris /* 54655714Skris * Put back the real size. 54755714Skris */ 54855714Skris ip->i_size = length; 54955714Skris DIP_SET(ip, i_size, length); 55055714Skris if (DIP(ip, i_blocks) >= blocksreleased) 55155714Skris DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased); 55255714Skris else /* sanity */ 55355714Skris DIP_SET(ip, i_blocks, 0); 55455714Skris ip->i_flag |= IN_CHANGE; 55555714Skris#ifdef QUOTA 55655714Skris (void) chkdq(ip, -blocksreleased, NOCRED, 0); 55755714Skris#endif 55855714Skris return (allerror); 55955714Skris 56055714Skrisextclean: 56155714Skris if (journaltrunc) 56255714Skris softdep_journal_freeblocks(ip, cred, length, IO_EXT); 56355714Skris else 56455714Skris softdep_setup_freeblocks(ip, length, IO_EXT); 565160814Ssimon return (ffs_update(vp, !DOINGASYNC(vp))); 566160814Ssimon} 56755714Skris 56855714Skris/* 56955714Skris * Release blocks associated with the inode ip and stored in the indirect 57055714Skris * block bn. Blocks are free'd in LIFO order up to (but not including) 57155714Skris * lastbn. If level is greater than SINGLE, the block is an indirect block 572 * and recursive calls to indirtrunc must be used to cleanse other indirect 573 * blocks. 574 */ 575static int 576ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) 577 struct inode *ip; 578 ufs2_daddr_t lbn, lastbn; 579 ufs2_daddr_t dbn; 580 int level; 581 ufs2_daddr_t *countp; 582{ 583 struct buf *bp; 584 struct fs *fs = ip->i_fs; 585 struct vnode *vp; 586 caddr_t copy = NULL; 587 int i, nblocks, error = 0, allerror = 0; 588 ufs2_daddr_t nb, nlbn, last; 589 ufs2_daddr_t blkcount, factor, blocksreleased = 0; 590 ufs1_daddr_t *bap1 = NULL; 591 ufs2_daddr_t *bap2 = NULL; 592# define BAP(ip, i) (((ip)->i_ump->um_fstype == UFS1) ? bap1[i] : bap2[i]) 593 594 /* 595 * Calculate index in current block of last 596 * block to be kept. -1 indicates the entire 597 * block so we need not calculate the index. 598 */ 599 factor = lbn_offset(fs, level); 600 last = lastbn; 601 if (lastbn > 0) 602 last /= factor; 603 nblocks = btodb(fs->fs_bsize); 604 /* 605 * Get buffer of block pointers, zero those entries corresponding 606 * to blocks to be free'd, and update on disk copy first. Since 607 * double(triple) indirect before single(double) indirect, calls 608 * to bmap on these blocks will fail. However, we already have 609 * the on disk address, so we have to set the b_blkno field 610 * explicitly instead of letting bread do everything for us. 611 */ 612 vp = ITOV(ip); 613 bp = getblk(vp, lbn, (int)fs->fs_bsize, 0, 0, 0); 614 if ((bp->b_flags & B_CACHE) == 0) { 615 curthread->td_ru.ru_inblock++; /* pay for read */ 616 bp->b_iocmd = BIO_READ; 617 bp->b_flags &= ~B_INVAL; 618 bp->b_ioflags &= ~BIO_ERROR; 619 if (bp->b_bcount > bp->b_bufsize) 620 panic("ffs_indirtrunc: bad buffer size"); 621 bp->b_blkno = dbn; 622 vfs_busy_pages(bp, 0); 623 bp->b_iooffset = dbtob(bp->b_blkno); 624 bstrategy(bp); 625 error = bufwait(bp); 626 } 627 if (error) { 628 brelse(bp); 629 *countp = 0; 630 return (error); 631 } 632 633 if (ip->i_ump->um_fstype == UFS1) 634 bap1 = (ufs1_daddr_t *)bp->b_data; 635 else 636 bap2 = (ufs2_daddr_t *)bp->b_data; 637 if (lastbn != -1) { 638 copy = malloc(fs->fs_bsize, M_TEMP, M_WAITOK); 639 bcopy((caddr_t)bp->b_data, copy, (u_int)fs->fs_bsize); 640 for (i = last + 1; i < NINDIR(fs); i++) 641 if (ip->i_ump->um_fstype == UFS1) 642 bap1[i] = 0; 643 else 644 bap2[i] = 0; 645 if (DOINGASYNC(vp)) { 646 bdwrite(bp); 647 } else { 648 error = bwrite(bp); 649 if (error) 650 allerror = error; 651 } 652 if (ip->i_ump->um_fstype == UFS1) 653 bap1 = (ufs1_daddr_t *)copy; 654 else 655 bap2 = (ufs2_daddr_t *)copy; 656 } 657 658 /* 659 * Recursively free totally unused blocks. 660 */ 661 for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last; 662 i--, nlbn += factor) { 663 nb = BAP(ip, i); 664 if (nb == 0) 665 continue; 666 if (level > SINGLE) { 667 if ((error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb), 668 (ufs2_daddr_t)-1, level - 1, &blkcount)) != 0) 669 allerror = error; 670 blocksreleased += blkcount; 671 } 672 ffs_blkfree(ip->i_ump, fs, ip->i_devvp, nb, fs->fs_bsize, 673 ip->i_number, vp->v_type, NULL); 674 blocksreleased += nblocks; 675 } 676 677 /* 678 * Recursively free last partial block. 679 */ 680 if (level > SINGLE && lastbn >= 0) { 681 last = lastbn % factor; 682 nb = BAP(ip, i); 683 if (nb != 0) { 684 error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb), 685 last, level - 1, &blkcount); 686 if (error) 687 allerror = error; 688 blocksreleased += blkcount; 689 } 690 } 691 if (copy != NULL) { 692 free(copy, M_TEMP); 693 } else { 694 bp->b_flags |= B_INVAL | B_NOCACHE; 695 brelse(bp); 696 } 697 698 *countp = blocksreleased; 699 return (allerror); 700} 701 702int 703ffs_rdonly(struct inode *ip) 704{ 705 706 return (ip->i_ump->um_fs->fs_ronly != 0); 707} 708 709