123399Smckusick /* 251498Sbostic * Copyright (c) 1986, 1989, 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423399Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*53505Sheideman * @(#)lfs_inode.c 7.63 (Berkeley) 05/14/92 823399Smckusick */ 924Sbill 1051484Sbostic #include <sys/param.h> 1151484Sbostic #include <sys/systm.h> 1251484Sbostic #include <sys/mount.h> 1351484Sbostic #include <sys/proc.h> 1451484Sbostic #include <sys/file.h> 1551484Sbostic #include <sys/buf.h> 1651484Sbostic #include <sys/vnode.h> 1751484Sbostic #include <sys/kernel.h> 1851484Sbostic #include <sys/malloc.h> 1924Sbill 2053477Smckusick #include <vm/vm.h> 2153477Smckusick 2251498Sbostic #include <ufs/ufs/quota.h> 2351498Sbostic #include <ufs/ufs/inode.h> 2451498Sbostic #include <ufs/ufs/ufsmount.h> 2551498Sbostic #include <ufs/ufs/ufs_extern.h> 2647571Skarels 2751498Sbostic #include <ufs/lfs/lfs.h> 2851498Sbostic #include <ufs/lfs/lfs_extern.h> 2924Sbill 3052834Sbostic static struct dinode *lfs_ifind __P((struct lfs *, ino_t, struct dinode *)); 3152834Sbostic 3251346Sbostic int 3351155Sbostic lfs_init() 3424Sbill { 3551857Sbostic #ifdef VERBOSE 3651857Sbostic printf("lfs_init\n"); 3751857Sbostic #endif 3851484Sbostic return (ufs_init()); 3924Sbill } 4024Sbill 4124Sbill /* 4251484Sbostic * Look up an LFS dinode number to find its incore vnode. If not already 4351484Sbostic * in core, read it in from the specified device. Return the inode locked. 4451484Sbostic * Detection and handling of mount points must be done by the calling routine. 4524Sbill */ 4651346Sbostic int 4751562Smckusick lfs_vget(mntp, ino, vpp) 4851562Smckusick struct mount *mntp; 494818Swnj ino_t ino; 5051562Smckusick struct vnode **vpp; 5124Sbill { 5251498Sbostic register struct lfs *fs; 5351484Sbostic register struct inode *ip; 5451484Sbostic struct buf *bp; 5552224Sbostic struct ifile *ifp; 5651498Sbostic struct vnode *vp; 5751562Smckusick struct ufsmount *ump; 5852224Sbostic daddr_t daddr; 5951484Sbostic dev_t dev; 6051346Sbostic int error; 6124Sbill 6251857Sbostic #ifdef VERBOSE 6351857Sbostic printf("lfs_vget\n"); 6451857Sbostic #endif 6551562Smckusick ump = VFSTOUFS(mntp); 6651562Smckusick dev = ump->um_dev; 6751562Smckusick if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 6851484Sbostic return (0); 6951484Sbostic 7052224Sbostic /* Translate the inode number to a disk address. */ 7152224Sbostic fs = ump->um_lfs; 7252224Sbostic if (ino == LFS_IFILE_INUM) 7352224Sbostic daddr = fs->lfs_idaddr; 7452224Sbostic else { 7552224Sbostic LFS_IENTRY(ifp, fs, ino, bp); 7652224Sbostic daddr = ifp->if_daddr; 7752224Sbostic brelse(bp); 7852224Sbostic if (daddr == LFS_UNUSED_DADDR) 7952224Sbostic return (ENOENT); 8052224Sbostic } 8152224Sbostic 8251155Sbostic /* Allocate new vnode/inode. */ 8351498Sbostic if (error = lfs_vcreate(mntp, ino, &vp)) { 8451562Smckusick *vpp = NULL; 8537736Smckusick return (error); 8637736Smckusick } 8752224Sbostic 8837736Smckusick /* 8939440Smckusick * Put it onto its hash chain and lock it so that other requests for 9039440Smckusick * this inode will block if they arrive while we are sleeping waiting 9139440Smckusick * for old data structures to be purged or for the contents of the 9239440Smckusick * disk portion of this inode to be read. 9339440Smckusick */ 9451562Smckusick ip = VTOI(vp); 9551484Sbostic ufs_ihashins(ip); 9651155Sbostic 9752224Sbostic /* 9852224Sbostic * XXX 9952224Sbostic * This may not need to be here, logically it should go down with 10052224Sbostic * the i_devvp initialization. 10152224Sbostic * Ask Kirk. 10252224Sbostic */ 10352224Sbostic ip->i_lfs = ump->um_lfs; 10452224Sbostic 10551484Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 10652224Sbostic if (error = 10752224Sbostic bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { 10837736Smckusick /* 10951857Sbostic * The inode does not contain anything useful, so it 11051857Sbostic * would be misleading to leave it on its hash chain. 11151857Sbostic * Iput() will return it to the free list. 11241334Smckusick */ 11341334Smckusick remque(ip); 11441334Smckusick ip->i_forw = ip; 11541334Smckusick ip->i_back = ip; 11651484Sbostic 11751484Sbostic /* Unlock and discard unneeded inode. */ 11851484Sbostic ufs_iput(ip); 11937736Smckusick brelse(bp); 12051562Smckusick *vpp = NULL; 12139440Smckusick return (error); 12237736Smckusick } 12351155Sbostic ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino); 12439440Smckusick brelse(bp); 12551155Sbostic 12651498Sbostic /* 12751498Sbostic * Initialize the vnode from the inode, check for aliases. In all 12851498Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 12951498Sbostic */ 13051595Smckusick if (error = ufs_vinit(mntp, &lfs_specops, LFS_FIFOOPS, &vp)) { 13151484Sbostic ufs_iput(ip); 13251562Smckusick *vpp = NULL; 13351484Sbostic return (error); 13440289Smckusick } 13551562Smckusick /* 13651562Smckusick * Finish inode initialization now that aliasing has been resolved. 13751562Smckusick */ 13851562Smckusick ip->i_devvp = ump->um_devvp; 13951562Smckusick VREF(ip->i_devvp); 14051562Smckusick *vpp = vp; 14137736Smckusick return (0); 14237736Smckusick } 1437334Skre 14452834Sbostic /* Search a block for a specific dinode. */ 14552834Sbostic static struct dinode * 14652834Sbostic lfs_ifind(fs, ino, dip) 14752834Sbostic struct lfs *fs; 14852834Sbostic ino_t ino; 14952834Sbostic register struct dinode *dip; 15052834Sbostic { 15152834Sbostic register int cnt; 15252834Sbostic 15352834Sbostic #ifdef VERBOSE 15452834Sbostic printf("lfs_ifind: inode %d\n", ino); 15552834Sbostic #endif 15652834Sbostic for (cnt = INOPB(fs); cnt--; ++dip) 15752834Sbostic if (dip->di_inum == ino) 15852834Sbostic return (dip); 15952834Sbostic 16052834Sbostic panic("lfs_ifind: dinode %u not found", ino); 16152834Sbostic /* NOTREACHED */ 16252834Sbostic } 16352834Sbostic 16451346Sbostic int 16551562Smckusick lfs_update(vp, ta, tm, waitfor) 16651562Smckusick register struct vnode *vp; 16751484Sbostic struct timeval *ta, *tm; 16851484Sbostic int waitfor; 1697118Smckusick { 17051562Smckusick struct inode *ip; 17151562Smckusick 17251857Sbostic #ifdef VERBOSE 17351857Sbostic printf("lfs_update\n"); 17451857Sbostic #endif 17551562Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 17651562Smckusick return (0); 17751562Smckusick ip = VTOI(vp); 17851562Smckusick if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0) 17951562Smckusick return (0); 18051562Smckusick if (ip->i_flag&IACC) 18153477Smckusick ip->i_atime.tv_sec = ta->tv_sec; 18252018Smckusick if (ip->i_flag&IUPD) { 18353477Smckusick ip->i_mtime.tv_sec = tm->tv_sec; 18452018Smckusick INCRQUAD((ip)->i_modrev); 18552018Smckusick } 18651562Smckusick if (ip->i_flag&ICHG) 18753477Smckusick ip->i_ctime.tv_sec = time.tv_sec; 18851562Smckusick ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); 18951562Smckusick 19052327Sbostic /* Push back the vnode and any dirty blocks it may have. */ 19152327Sbostic return (waitfor ? lfs_vflush(vp) : 0); 19224Sbill } 19324Sbill 19452222Sbostic /* Update segment usage information when removing a block. */ 19552225Sbostic #define UPDATE_SEGUSE \ 19652225Sbostic if (lastseg != -1) { \ 19752225Sbostic LFS_SEGENTRY(sup, fs, lastseg, sup_bp); \ 19852681Sstaelin sup->su_nbytes -= num << fs->lfs_bshift; \ 19952225Sbostic LFS_UBWRITE(sup_bp); \ 20052225Sbostic blocksreleased += num; \ 20152225Sbostic } 20252222Sbostic 20352222Sbostic #define SEGDEC { \ 20452222Sbostic if (daddr != UNASSIGNED) { \ 20552222Sbostic if (lastseg != (seg = datosn(fs, daddr))) { \ 20652222Sbostic UPDATE_SEGUSE; \ 20752222Sbostic num = 1; \ 20852222Sbostic lastseg = seg; \ 20952222Sbostic } else \ 21052222Sbostic ++num; \ 21152222Sbostic } \ 21252222Sbostic } 21352222Sbostic 21424Sbill /* 21552222Sbostic * Truncate the inode ip to at most length size. Update segment usage 21652222Sbostic * table information. 21724Sbill */ 21851484Sbostic /* ARGSUSED */ 21951484Sbostic int 22053242Smckusick lfs_truncate(vp, length, flags, cred) 22152222Sbostic struct vnode *vp; 22253233Smckusick off_t length; 22339676Smckusick int flags; 22453242Smckusick struct ucred *cred; 22524Sbill { 226*53505Sheideman register INDIR *inp; 22752222Sbostic register int i; 22852222Sbostic register daddr_t *daddrp; 22952225Sbostic struct buf *bp, *sup_bp; 23052327Sbostic struct ifile *ifp; 23152222Sbostic struct inode *ip; 23252222Sbostic struct lfs *fs; 23352222Sbostic INDIR a[NIADDR + 2], a_end[NIADDR + 2]; 23452222Sbostic SEGUSE *sup; 23552222Sbostic daddr_t daddr, lastblock, lbn, olastblock; 23653233Smckusick long off, blocksreleased; 23752222Sbostic int error, depth, lastseg, num, offset, seg, size; 2389165Ssam 23951857Sbostic #ifdef VERBOSE 24051857Sbostic printf("lfs_truncate\n"); 24151857Sbostic #endif 24253477Smckusick vnode_pager_setsize(vp, (u_long)length); 24352327Sbostic 24452222Sbostic ip = VTOI(vp); 24552327Sbostic fs = ip->i_lfs; 24652327Sbostic 24752327Sbostic /* If truncating the file to 0, update the version number. */ 24852327Sbostic if (length == 0) { 24952327Sbostic LFS_IENTRY(ifp, fs, ip->i_number, bp); 25052327Sbostic ++ifp->if_version; 25152327Sbostic LFS_UBWRITE(bp); 25252327Sbostic } 25352327Sbostic 25451484Sbostic /* If length is larger than the file, just update the times. */ 25552222Sbostic if (ip->i_size <= length) { 25652222Sbostic ip->i_flag |= ICHG|IUPD; 25752222Sbostic return (lfs_update(vp, &time, &time, 1)); 25813000Ssam } 25952327Sbostic 26052222Sbostic /* 26152222Sbostic * Calculate index into inode's block list of last direct and indirect 26252222Sbostic * blocks (if any) which we want to keep. Lastblock is 0 when the 26352222Sbostic * file is truncated to 0. 26452222Sbostic */ 26552222Sbostic lastblock = lblkno(fs, length + fs->lfs_bsize - 1); 26652222Sbostic olastblock = lblkno(fs, ip->i_size + fs->lfs_bsize - 1) - 1; 26751484Sbostic 2681203Sbill /* 26951484Sbostic * Update the size of the file. If the file is not being truncated to 27051484Sbostic * a block boundry, the contents of the partial block following the end 27151484Sbostic * of the file must be zero'ed in case it ever become accessable again 27251484Sbostic * because of subsequent file growth. 2731203Sbill */ 27417942Smckusick offset = blkoff(fs, length); 27551484Sbostic if (offset == 0) 27652222Sbostic ip->i_size = length; 27751484Sbostic else { 27817942Smckusick lbn = lblkno(fs, length); 27941313Smckusick #ifdef QUOTA 28052222Sbostic if (error = getinoquota(ip)) 28141313Smckusick return (error); 28251183Sbostic #endif 28352222Sbostic if (error = bread(vp, lbn, fs->lfs_bsize, NOCRED, &bp)) 28437736Smckusick return (error); 28552222Sbostic ip->i_size = length; 28651857Sbostic size = blksize(fs); 28752222Sbostic (void)vnode_pager_uncache(vp); 28826272Skarels bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset)); 28945112Smckusick allocbuf(bp, size); 29052078Sbostic LFS_UBWRITE(bp); 29117942Smckusick } 29252078Sbostic /* 29352222Sbostic * Modify sup->su_nbyte counters for each deleted block; keep track 29452222Sbostic * of number of blocks removed for ip->i_blocks. 29552222Sbostic */ 29652222Sbostic blocksreleased = 0; 29752222Sbostic num = 0; 29852222Sbostic lastseg = -1; 29952222Sbostic 30052222Sbostic for (lbn = olastblock; lbn >= lastblock;) { 30152222Sbostic lfs_bmaparray(vp, lbn, &daddr, a, &depth); 30252222Sbostic if (lbn == olastblock) 30352222Sbostic for (i = NIADDR + 2; i--;) 30452222Sbostic a_end[i] = a[i]; 30552222Sbostic switch (depth) { 30652222Sbostic case 0: /* Direct block. */ 30752222Sbostic daddr = ip->i_db[lbn]; 30852222Sbostic SEGDEC; 30952222Sbostic ip->i_db[lbn] = 0; 31052222Sbostic --lbn; 31152222Sbostic break; 31252222Sbostic #ifdef DIAGNOSTIC 31352222Sbostic case 1: /* An indirect block. */ 31452222Sbostic panic("lfs_truncate: lfs_bmaparray returned depth 1"); 31552222Sbostic /* NOTREACHED */ 31652222Sbostic #endif 31752222Sbostic default: /* Chain of indirect blocks. */ 318*53505Sheideman inp = a + --depth; 319*53505Sheideman if (inp->in_off > 0 && lbn != lastblock) { 320*53505Sheideman lbn -= inp->in_off < lbn - lastblock ? 321*53505Sheideman inp->in_off : lbn - lastblock; 32252222Sbostic break; 32352222Sbostic } 324*53505Sheideman for (; depth && (inp->in_off == 0 || lbn == lastblock); 325*53505Sheideman --inp, --depth) { 32652222Sbostic /* 32752222Sbostic * XXX 32852222Sbostic * The indirect block may not yet exist, so 32952222Sbostic * bread will create one just so we can free 33052222Sbostic * it. 33152222Sbostic */ 33252222Sbostic if (bread(vp, 333*53505Sheideman inp->in_lbn, fs->lfs_bsize, NOCRED, &bp)) 33452222Sbostic panic("lfs_truncate: bread bno %d", 335*53505Sheideman inp->in_lbn); 336*53505Sheideman daddrp = bp->b_un.b_daddr + inp->in_off; 337*53505Sheideman for (i = inp->in_off; 33852222Sbostic i++ <= a_end[depth].in_off;) { 33952222Sbostic daddr = *daddrp++; 34052222Sbostic SEGDEC; 34152222Sbostic } 34253144Sstaelin a_end[depth].in_off = NINDIR(fs) - 1; 343*53505Sheideman if (inp->in_off == 0) 34453144Sstaelin brelse (bp); 34553144Sstaelin else { 346*53505Sheideman bzero(bp->b_un.b_daddr + inp->in_off, 34752222Sbostic fs->lfs_bsize - 348*53505Sheideman inp->in_off * sizeof(daddr_t)); 34952222Sbostic LFS_UBWRITE(bp); 35053144Sstaelin } 35152222Sbostic } 35253144Sstaelin if (depth == 0 && a[1].in_off == 0) { 35352222Sbostic off = a[0].in_off; 35452222Sbostic daddr = ip->i_ib[off]; 35552222Sbostic SEGDEC; 35652222Sbostic ip->i_ib[off] = 0; 35752222Sbostic } 35852681Sstaelin if (lbn == lastblock || lbn <= NDADDR) 35952222Sbostic --lbn; 36052222Sbostic else { 36152222Sbostic lbn -= NINDIR(fs); 36252222Sbostic if (lbn < lastblock) 36352222Sbostic lbn = lastblock; 36452222Sbostic } 36552222Sbostic } 36652222Sbostic } 36752225Sbostic UPDATE_SEGUSE; 36852222Sbostic ip->i_blocks -= blocksreleased; 36952222Sbostic /* 37052078Sbostic * XXX 37152222Sbostic * Currently, we don't know when we allocate an indirect block, so 37252222Sbostic * ip->i_blocks isn't getting incremented appropriately. As a result, 37352222Sbostic * when we delete any indirect blocks, we get a bad number here. 37452078Sbostic */ 37552222Sbostic if (ip->i_blocks < 0) 37652222Sbostic ip->i_blocks = 0; 37752222Sbostic ip->i_flag |= ICHG|IUPD; 37852222Sbostic (void)vinvalbuf(vp, length > 0); 37952222Sbostic error = lfs_update(vp, &time, &time, MNT_WAIT); 38051857Sbostic return (0); 38124Sbill } 382