123399Smckusick /*
263371Sbostic * Copyright (c) 1982, 1986, 1989, 1993
363371Sbostic * The Regents of the University of California. All rights reserved.
423399Smckusick *
544537Sbostic * %sccs.include.redist.c%
637736Smckusick *
7*68846Smckusick * @(#)ffs_inode.c 8.13 (Berkeley) 04/21/95
823399Smckusick */
924Sbill
1051472Sbostic #include <sys/param.h>
1151472Sbostic #include <sys/systm.h>
1251472Sbostic #include <sys/mount.h>
1351472Sbostic #include <sys/proc.h>
1451472Sbostic #include <sys/file.h>
1551472Sbostic #include <sys/buf.h>
1651472Sbostic #include <sys/vnode.h>
1751472Sbostic #include <sys/kernel.h>
1851472Sbostic #include <sys/malloc.h>
1956481Smargo #include <sys/trace.h>
2056481Smargo #include <sys/resourcevar.h>
2124Sbill
2253471Smckusick #include <vm/vm.h>
2353471Smckusick
2451472Sbostic #include <ufs/ufs/quota.h>
2551472Sbostic #include <ufs/ufs/inode.h>
2651472Sbostic #include <ufs/ufs/ufsmount.h>
2751472Sbostic #include <ufs/ufs/ufs_extern.h>
2847571Skarels
2951472Sbostic #include <ufs/ffs/fs.h>
3051472Sbostic #include <ufs/ffs/ffs_extern.h>
3124Sbill
3268554Smckusick static int ffs_indirtrunc __P((struct inode *, ufs_daddr_t, ufs_daddr_t,
3368554Smckusick ufs_daddr_t, int, long *));
347334Skre
3524Sbill /*
3664510Sbostic * Update the access, modified, and inode change times as specified by the
3764510Sbostic * IACCESS, IUPDATE, and ICHANGE flags respectively. The IMODIFIED flag is
3864510Sbostic * used to specify that the inode needs to be updated but that the times have
3964510Sbostic * already been set. The access and modified times are taken from the second
4064510Sbostic * and third parameters; the inode change time is always taken from the current
4164510Sbostic * time. If waitfor is set, then wait for the disk write of the inode to
4264510Sbostic * complete.
4339392Smckusick */
4451472Sbostic int
ffs_update(ap)4554656Smckusick ffs_update(ap)
4654656Smckusick struct vop_update_args /* {
4754656Smckusick struct vnode *a_vp;
4864419Sbostic struct timeval *a_access;
4964419Sbostic struct timeval *a_modify;
5054656Smckusick int a_waitfor;
5154656Smckusick } */ *ap;
5224Sbill {
5364419Sbostic register struct fs *fs;
5437736Smckusick struct buf *bp;
5551544Smckusick struct inode *ip;
5637736Smckusick int error;
5724Sbill
5856941Storek ip = VTOI(ap->a_vp);
5956744Smckusick if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) {
6064604Sbostic ip->i_flag &=
6164604Sbostic ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
6251544Smckusick return (0);
6356744Smckusick }
6464604Sbostic if ((ip->i_flag &
6564604Sbostic (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)
6637736Smckusick return (0);
6764604Sbostic if (ip->i_flag & IN_ACCESS)
6868554Smckusick ip->i_atime = ap->a_access->tv_sec;
6964604Sbostic if (ip->i_flag & IN_UPDATE) {
7068554Smckusick ip->i_mtime = ap->a_modify->tv_sec;
7154130Smckusick ip->i_modrev++;
7252015Smckusick }
7364604Sbostic if (ip->i_flag & IN_CHANGE)
7468554Smckusick ip->i_ctime = time.tv_sec;
7564604Sbostic ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
7653912Smckusick fs = ip->i_fs;
7753472Smckusick /*
7853472Smckusick * Ensure that uid and gid are correct. This is a temporary
7953472Smckusick * fix until fsck has been changed to do the update.
8053472Smckusick */
8153912Smckusick if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
8253912Smckusick ip->i_din.di_ouid = ip->i_uid; /* XXX */
8353912Smckusick ip->i_din.di_ogid = ip->i_gid; /* XXX */
8453912Smckusick } /* XXX */
8564604Sbostic if (error = bread(ip->i_devvp,
8664604Sbostic fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
8751544Smckusick (int)fs->fs_bsize, NOCRED, &bp)) {
8851544Smckusick brelse(bp);
8951544Smckusick return (error);
9051544Smckusick }
9164604Sbostic *((struct dinode *)bp->b_data +
9264604Sbostic ino_to_fsbo(fs, ip->i_number)) = ip->i_din;
9368542Smckusick if (ap->a_waitfor && (ap->a_vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
9437736Smckusick return (bwrite(bp));
9551544Smckusick else {
9637736Smckusick bdwrite(bp);
9737736Smckusick return (0);
9837736Smckusick }
9924Sbill }
10024Sbill
10110736Ssam #define SINGLE 0 /* index of single indirect block */
10210736Ssam #define DOUBLE 1 /* index of double indirect block */
10310736Ssam #define TRIPLE 2 /* index of triple indirect block */
10424Sbill /*
10564604Sbostic * Truncate the inode oip to at most length size, freeing the
10664604Sbostic * disk blocks.
10724Sbill */
10854656Smckusick ffs_truncate(ap)
10954656Smckusick struct vop_truncate_args /* {
11054656Smckusick struct vnode *a_vp;
11154656Smckusick off_t a_length;
11254656Smckusick int a_flags;
11354656Smckusick struct ucred *a_cred;
11454656Smckusick struct proc *a_p;
11554656Smckusick } */ *ap;
11624Sbill {
11753865Sheideman register struct vnode *ovp = ap->a_vp;
11868554Smckusick ufs_daddr_t lastblock;
11951544Smckusick register struct inode *oip;
12068554Smckusick ufs_daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
12168554Smckusick ufs_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
12254656Smckusick off_t length = ap->a_length;
1236569Smckusic register struct fs *fs;
12417942Smckusick struct buf *bp;
12553234Smckusick int offset, size, level;
12656445Smargo long count, nblocks, vflags, blocksreleased = 0;
12754763Smckusick struct timeval tv;
12817942Smckusick register int i;
12939676Smckusick int aflags, error, allerror;
13053234Smckusick off_t osize;
1319165Ssam
13268113Smckusick if (length < 0)
13368113Smckusick return (EINVAL);
13467838Smckusick oip = VTOI(ovp);
13554763Smckusick tv = time;
13657425Smckusick if (ovp->v_type == VLNK &&
13757425Smckusick oip->i_size < ovp->v_mount->mnt_maxsymlinklen) {
13854532Smckusick #ifdef DIAGNOSTIC
13954656Smckusick if (length != 0)
14054532Smckusick panic("ffs_truncate: partial truncate of symlink");
14154532Smckusick #endif
14254532Smckusick bzero((char *)&oip->i_shortlink, (u_int)oip->i_size);
14354532Smckusick oip->i_size = 0;
14464604Sbostic oip->i_flag |= IN_CHANGE | IN_UPDATE;
14554763Smckusick return (VOP_UPDATE(ovp, &tv, &tv, 1));
14654532Smckusick }
14759114Smckusick if (oip->i_size == length) {
14864604Sbostic oip->i_flag |= IN_CHANGE | IN_UPDATE;
14958933Smckusick return (VOP_UPDATE(ovp, &tv, &tv, 0));
15013000Ssam }
15160916Smckusick #ifdef QUOTA
15260916Smckusick if (error = getinoquota(oip))
15360916Smckusick return (error);
15460916Smckusick #endif
15568113Smckusick fs = oip->i_fs;
15660916Smckusick osize = oip->i_size;
1571203Sbill /*
15860916Smckusick * Lengthen the size of the file. We must ensure that the
15960916Smckusick * last byte of the file is allocated. Since the smallest
16068113Smckusick * value of osize is 0, length will be at least 1.
16160916Smckusick */
16260916Smckusick if (osize < length) {
16368113Smckusick if (length > fs->fs_maxfilesize)
16468113Smckusick return (EFBIG);
16560916Smckusick offset = blkoff(fs, length - 1);
16660916Smckusick lbn = lblkno(fs, length - 1);
16760916Smckusick aflags = B_CLRBUF;
16860916Smckusick if (ap->a_flags & IO_SYNC)
16960916Smckusick aflags |= B_SYNC;
17060916Smckusick if (error = ffs_balloc(oip, lbn, offset + 1, ap->a_cred, &bp,
17160916Smckusick aflags))
17260916Smckusick return (error);
17360916Smckusick oip->i_size = length;
174*68846Smckusick vnode_pager_setsize(ovp, (u_long)length);
17560916Smckusick (void) vnode_pager_uncache(ovp);
17667272Smckusick if (aflags & B_SYNC)
17760916Smckusick bwrite(bp);
17860916Smckusick else
17960916Smckusick bawrite(bp);
18064604Sbostic oip->i_flag |= IN_CHANGE | IN_UPDATE;
18160916Smckusick return (VOP_UPDATE(ovp, &tv, &tv, 1));
18260916Smckusick }
18360916Smckusick /*
18460916Smckusick * Shorten the size of the file. If the file is not being
18517942Smckusick * truncated to a block boundry, the contents of the
18617942Smckusick * partial block following the end of the file must be
18717942Smckusick * zero'ed in case it ever become accessable again because
18817942Smckusick * of subsequent file growth.
18917942Smckusick */
19054656Smckusick offset = blkoff(fs, length);
19160916Smckusick if (offset == 0) {
19254656Smckusick oip->i_size = length;
19317942Smckusick } else {
19454656Smckusick lbn = lblkno(fs, length);
19539676Smckusick aflags = B_CLRBUF;
19653585Sheideman if (ap->a_flags & IO_SYNC)
19739676Smckusick aflags |= B_SYNC;
19860916Smckusick if (error = ffs_balloc(oip, lbn, offset, ap->a_cred, &bp,
19960916Smckusick aflags))
20041313Smckusick return (error);
20154656Smckusick oip->i_size = length;
20217942Smckusick size = blksize(fs, oip, lbn);
20353865Sheideman (void) vnode_pager_uncache(ovp);
20464510Sbostic bzero((char *)bp->b_data + offset, (u_int)(size - offset));
20560916Smckusick allocbuf(bp, size);
20667272Smckusick if (aflags & B_SYNC)
20739676Smckusick bwrite(bp);
20839676Smckusick else
20958317Smckusick bawrite(bp);
21017942Smckusick }
211*68846Smckusick vnode_pager_setsize(ovp, (u_long)length);
21217942Smckusick /*
21359114Smckusick * Calculate index into inode's block list of
21459114Smckusick * last direct and indirect blocks (if any)
21559114Smckusick * which we want to keep. Lastblock is -1 when
21659114Smckusick * the file is truncated to 0.
21759114Smckusick */
21859114Smckusick lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1;
21959114Smckusick lastiblock[SINGLE] = lastblock - NDADDR;
22059114Smckusick lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
22159114Smckusick lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
22259114Smckusick nblocks = btodb(fs->fs_bsize);
22359114Smckusick /*
22451472Sbostic * Update file and block pointers on disk before we start freeing
22551472Sbostic * blocks. If we crash before free'ing blocks below, the blocks
22651472Sbostic * will be returned to the free list. lastiblock values are also
22751472Sbostic * normalized to -1 for calls to ffs_indirtrunc below.
2286569Smckusic */
22958317Smckusick bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof oldblks);
23010736Ssam for (level = TRIPLE; level >= SINGLE; level--)
23110736Ssam if (lastiblock[level] < 0) {
23210736Ssam oip->i_ib[level] = 0;
23310736Ssam lastiblock[level] = -1;
2349165Ssam }
23510736Ssam for (i = NDADDR - 1; i > lastblock; i--)
23610736Ssam oip->i_db[i] = 0;
23764604Sbostic oip->i_flag |= IN_CHANGE | IN_UPDATE;
23858317Smckusick if (error = VOP_UPDATE(ovp, &tv, &tv, MNT_WAIT))
23958317Smckusick allerror = error;
24058317Smckusick /*
24158317Smckusick * Having written the new inode to disk, save its new configuration
24258317Smckusick * and put back the old block pointers long enough to process them.
24358317Smckusick * Note that we save the new block configuration so we can check it
24458317Smckusick * when we are done.
24558317Smckusick */
24658317Smckusick bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof newblks);
24758317Smckusick bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof oldblks);
24858317Smckusick oip->i_size = osize;
24956445Smargo vflags = ((length > 0) ? V_SAVE : 0) | V_SAVEMETA;
25057800Smckusick allerror = vinvalbuf(ovp, vflags, ap->a_cred, ap->a_p, 0, 0);
25110736Ssam
2526569Smckusic /*
25310736Ssam * Indirect blocks first.
2546569Smckusic */
25556445Smargo indir_lbn[SINGLE] = -NDADDR;
25656445Smargo indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1;
25756445Smargo indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1;
25810736Ssam for (level = TRIPLE; level >= SINGLE; level--) {
25958317Smckusick bn = oip->i_ib[level];
2609165Ssam if (bn != 0) {
26158317Smckusick error = ffs_indirtrunc(oip, indir_lbn[level],
26256481Smargo fsbtodb(fs, bn), lastiblock[level], level, &count);
26337736Smckusick if (error)
26437736Smckusick allerror = error;
26537736Smckusick blocksreleased += count;
26610736Ssam if (lastiblock[level] < 0) {
26758317Smckusick oip->i_ib[level] = 0;
26858317Smckusick ffs_blkfree(oip, bn, fs->fs_bsize);
26910736Ssam blocksreleased += nblocks;
27010736Ssam }
27110736Ssam }
27210736Ssam if (lastiblock[level] >= 0)
27310736Ssam goto done;
2749165Ssam }
27510736Ssam
2766569Smckusic /*
27710736Ssam * All whole direct blocks or frags.
2786569Smckusic */
2799165Ssam for (i = NDADDR - 1; i > lastblock; i--) {
28053234Smckusick register long bsize;
2819165Ssam
28258317Smckusick bn = oip->i_db[i];
2839165Ssam if (bn == 0)
28424Sbill continue;
28558317Smckusick oip->i_db[i] = 0;
28658317Smckusick bsize = blksize(fs, oip, i);
28758317Smckusick ffs_blkfree(oip, bn, bsize);
28824525Sbloom blocksreleased += btodb(bsize);
28924Sbill }
29010736Ssam if (lastblock < 0)
29110736Ssam goto done;
29210736Ssam
2931203Sbill /*
2949165Ssam * Finally, look for a change in size of the
2959165Ssam * last direct block; release any frags.
2961203Sbill */
29758317Smckusick bn = oip->i_db[lastblock];
29810736Ssam if (bn != 0) {
29953234Smckusick long oldspace, newspace;
30010736Ssam
3019165Ssam /*
3029165Ssam * Calculate amount of space we're giving
3039165Ssam * back as old block size minus new block size.
3049165Ssam */
30558317Smckusick oldspace = blksize(fs, oip, lastblock);
30658317Smckusick oip->i_size = length;
30758317Smckusick newspace = blksize(fs, oip, lastblock);
30810736Ssam if (newspace == 0)
30910736Ssam panic("itrunc: newspace");
31010736Ssam if (oldspace - newspace > 0) {
3119165Ssam /*
3129165Ssam * Block number of space to be free'd is
3139165Ssam * the old block # plus the number of frags
3149165Ssam * required for the storage we're keeping.
3159165Ssam */
31610736Ssam bn += numfrags(fs, newspace);
31758317Smckusick ffs_blkfree(oip, bn, oldspace - newspace);
31812645Ssam blocksreleased += btodb(oldspace - newspace);
3199165Ssam }
3209165Ssam }
3219165Ssam done:
32256619Smckusick #ifdef DIAGNOSTIC
32310736Ssam for (level = SINGLE; level <= TRIPLE; level++)
32458317Smckusick if (newblks[NDADDR + level] != oip->i_ib[level])
32510736Ssam panic("itrunc1");
32610736Ssam for (i = 0; i < NDADDR; i++)
32758317Smckusick if (newblks[i] != oip->i_db[i])
32810736Ssam panic("itrunc2");
32956619Smckusick if (length == 0 &&
33065235Smckusick (ovp->v_dirtyblkhd.lh_first || ovp->v_cleanblkhd.lh_first))
33156619Smckusick panic("itrunc3");
33256619Smckusick #endif /* DIAGNOSTIC */
33358317Smckusick /*
33458317Smckusick * Put back the real size.
33558317Smckusick */
33658317Smckusick oip->i_size = length;
33712645Ssam oip->i_blocks -= blocksreleased;
33812645Ssam if (oip->i_blocks < 0) /* sanity */
33912645Ssam oip->i_blocks = 0;
34064604Sbostic oip->i_flag |= IN_CHANGE;
3419165Ssam #ifdef QUOTA
34260916Smckusick (void) chkdq(oip, -blocksreleased, NOCRED, 0);
3439165Ssam #endif
34437736Smckusick return (allerror);
34524Sbill }
34624Sbill
3479165Ssam /*
34851472Sbostic * Release blocks associated with the inode ip and stored in the indirect
34951472Sbostic * block bn. Blocks are free'd in LIFO order up to (but not including)
35051472Sbostic * lastbn. If level is greater than SINGLE, the block is an indirect block
35151472Sbostic * and recursive calls to indirtrunc must be used to cleanse other indirect
35251472Sbostic * blocks.
35310736Ssam *
35410736Ssam * NB: triple indirect blocks are untested.
3559165Ssam */
35651472Sbostic static int
ffs_indirtrunc(ip,lbn,dbn,lastbn,level,countp)35756481Smargo ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
3586569Smckusic register struct inode *ip;
35968554Smckusick ufs_daddr_t lbn, lastbn;
36068554Smckusick ufs_daddr_t dbn;
36110736Ssam int level;
36237736Smckusick long *countp;
36324Sbill {
3649165Ssam register int i;
36531661Smckusick struct buf *bp;
36631661Smckusick register struct fs *fs = ip->i_fs;
36768554Smckusick register ufs_daddr_t *bap;
36856481Smargo struct vnode *vp;
36968554Smckusick ufs_daddr_t *copy, nb, nlbn, last;
37037736Smckusick long blkcount, factor;
37137736Smckusick int nblocks, blocksreleased = 0;
37256481Smargo int error = 0, allerror = 0;
37324Sbill
37410736Ssam /*
37510736Ssam * Calculate index in current block of last
37610736Ssam * block to be kept. -1 indicates the entire
37710736Ssam * block so we need not calculate the index.
37810736Ssam */
37910736Ssam factor = 1;
38010736Ssam for (i = SINGLE; i < level; i++)
38110736Ssam factor *= NINDIR(fs);
3829165Ssam last = lastbn;
38310736Ssam if (lastbn > 0)
38410736Ssam last /= factor;
38512645Ssam nblocks = btodb(fs->fs_bsize);
38610736Ssam /*
38756481Smargo * Get buffer of block pointers, zero those entries corresponding
38856481Smargo * to blocks to be free'd, and update on disk copy first. Since
38956481Smargo * double(triple) indirect before single(double) indirect, calls
39056481Smargo * to bmap on these blocks will fail. However, we already have
39156481Smargo * the on disk address, so we have to set the b_blkno field
39256481Smargo * explicitly instead of letting bread do everything for us.
39310736Ssam */
39456481Smargo vp = ITOV(ip);
39557800Smckusick bp = getblk(vp, lbn, (int)fs->fs_bsize, 0, 0);
39656481Smargo if (bp->b_flags & (B_DONE | B_DELWRI)) {
39756481Smargo /* Braces must be here in case trace evaluates to nothing. */
39856481Smargo trace(TR_BREADHIT, pack(vp, fs->fs_bsize), lbn);
39956481Smargo } else {
40056481Smargo trace(TR_BREADMISS, pack(vp, fs->fs_bsize), lbn);
40156481Smargo curproc->p_stats->p_ru.ru_inblock++; /* pay for read */
40256481Smargo bp->b_flags |= B_READ;
40356481Smargo if (bp->b_bcount > bp->b_bufsize)
40456481Smargo panic("ffs_indirtrunc: bad buffer size");
40556481Smargo bp->b_blkno = dbn;
40656481Smargo VOP_STRATEGY(bp);
40756481Smargo error = biowait(bp);
40856481Smargo }
40937736Smckusick if (error) {
41010736Ssam brelse(bp);
41137736Smckusick *countp = 0;
41237736Smckusick return (error);
41310736Ssam }
41456481Smargo
41568554Smckusick bap = (ufs_daddr_t *)bp->b_data;
41668554Smckusick MALLOC(copy, ufs_daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
41731661Smckusick bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize);
41810736Ssam bzero((caddr_t)&bap[last + 1],
41968554Smckusick (u_int)(NINDIR(fs) - (last + 1)) * sizeof (ufs_daddr_t));
42039676Smckusick if (last == -1)
42139676Smckusick bp->b_flags |= B_INVAL;
42237736Smckusick error = bwrite(bp);
42337736Smckusick if (error)
42437736Smckusick allerror = error;
42531661Smckusick bap = copy;
42610736Ssam
42710736Ssam /*
42810736Ssam * Recursively free totally unused blocks.
42910736Ssam */
43056445Smargo for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last;
43156481Smargo i--, nlbn += factor) {
43224Sbill nb = bap[i];
4339165Ssam if (nb == 0)
43424Sbill continue;
43537736Smckusick if (level > SINGLE) {
43668554Smckusick if (error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
43768554Smckusick (ufs_daddr_t)-1, level - 1, &blkcount))
43837736Smckusick allerror = error;
43937736Smckusick blocksreleased += blkcount;
44037736Smckusick }
44153234Smckusick ffs_blkfree(ip, nb, fs->fs_bsize);
4429165Ssam blocksreleased += nblocks;
44324Sbill }
44410736Ssam
44510736Ssam /*
44610736Ssam * Recursively free last partial block.
44710736Ssam */
44810736Ssam if (level > SINGLE && lastbn >= 0) {
44910736Ssam last = lastbn % factor;
4509165Ssam nb = bap[i];
45137736Smckusick if (nb != 0) {
45256481Smargo if (error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
45356481Smargo last, level - 1, &blkcount))
45437736Smckusick allerror = error;
45537736Smckusick blocksreleased += blkcount;
45637736Smckusick }
4579165Ssam }
45831661Smckusick FREE(copy, M_TEMP);
45937736Smckusick *countp = blocksreleased;
46037736Smckusick return (allerror);
46124Sbill }
462