xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 52078)
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*52078Sbostic  *	@(#)lfs_inode.c	7.51 (Berkeley) 12/30/91
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 
2051498Sbostic #include <ufs/ufs/quota.h>
2151498Sbostic #include <ufs/ufs/inode.h>
2251498Sbostic #include <ufs/ufs/ufsmount.h>
2351498Sbostic #include <ufs/ufs/ufs_extern.h>
2447571Skarels 
2551498Sbostic #include <ufs/lfs/lfs.h>
2651498Sbostic #include <ufs/lfs/lfs_extern.h>
2724Sbill 
2851346Sbostic int
2951155Sbostic lfs_init()
3024Sbill {
3151857Sbostic #ifdef VERBOSE
3251857Sbostic 	printf("lfs_init\n");
3351857Sbostic #endif
3451484Sbostic 	return (ufs_init());
3524Sbill }
3624Sbill 
3724Sbill /*
3851484Sbostic  * Look up an LFS dinode number to find its incore vnode.  If not already
3951484Sbostic  * in core, read it in from the specified device.  Return the inode locked.
4051484Sbostic  * Detection and handling of mount points must be done by the calling routine.
4124Sbill  */
4251346Sbostic int
4351562Smckusick lfs_vget(mntp, ino, vpp)
4451562Smckusick 	struct mount *mntp;
454818Swnj 	ino_t ino;
4651562Smckusick 	struct vnode **vpp;
4724Sbill {
4851498Sbostic 	register struct lfs *fs;
4951484Sbostic 	register struct inode *ip;
5051484Sbostic 	struct buf *bp;
5151498Sbostic 	struct vnode *vp;
5251562Smckusick 	struct ufsmount *ump;
5351484Sbostic 	dev_t dev;
5451346Sbostic 	int error;
5524Sbill 
5651857Sbostic #ifdef VERBOSE
5751857Sbostic 	printf("lfs_vget\n");
5851857Sbostic #endif
5951562Smckusick 	ump = VFSTOUFS(mntp);
6051562Smckusick 	dev = ump->um_dev;
6151562Smckusick 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
6251484Sbostic 		return (0);
6351484Sbostic 
6451155Sbostic 	/* Allocate new vnode/inode. */
6551498Sbostic 	if (error = lfs_vcreate(mntp, ino, &vp)) {
6651562Smckusick 		*vpp = NULL;
6737736Smckusick 		return (error);
6837736Smckusick 	}
6937736Smckusick 	/*
7039440Smckusick 	 * Put it onto its hash chain and lock it so that other requests for
7139440Smckusick 	 * this inode will block if they arrive while we are sleeping waiting
7239440Smckusick 	 * for old data structures to be purged or for the contents of the
7339440Smckusick 	 * disk portion of this inode to be read.
7439440Smckusick 	 */
7551562Smckusick 	ip = VTOI(vp);
7651484Sbostic 	ufs_ihashins(ip);
7751155Sbostic 
7851484Sbostic 	/* Read in the disk contents for the inode, copy into the inode. */
7952018Smckusick 	ip->i_lfs = fs = ump->um_lfs;
8051562Smckusick 	if (error = bread(ump->um_devvp, lfs_itod(fs, ino),
8151484Sbostic 	    (int)fs->lfs_bsize, NOCRED, &bp)) {
8237736Smckusick 		/*
8351857Sbostic 		 * The inode does not contain anything useful, so it
8451857Sbostic 		 * would be misleading to leave it on its hash chain.
8551857Sbostic 		 * Iput() will return it to the free list.
8641334Smckusick 		 */
8741334Smckusick 		remque(ip);
8841334Smckusick 		ip->i_forw = ip;
8941334Smckusick 		ip->i_back = ip;
9051484Sbostic 
9151484Sbostic 		/* Unlock and discard unneeded inode. */
9251484Sbostic 		ufs_iput(ip);
9337736Smckusick 		brelse(bp);
9451562Smckusick 		*vpp = NULL;
9539440Smckusick 		return (error);
9637736Smckusick 	}
9751155Sbostic 	ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino);
9839440Smckusick 	brelse(bp);
9951155Sbostic 
10051498Sbostic 	/*
10151498Sbostic 	 * Initialize the vnode from the inode, check for aliases.  In all
10251498Sbostic 	 * cases re-init ip, the underlying vnode/inode may have changed.
10351498Sbostic 	 */
10451595Smckusick 	if (error = ufs_vinit(mntp, &lfs_specops, LFS_FIFOOPS, &vp)) {
10551484Sbostic 		ufs_iput(ip);
10651562Smckusick 		*vpp = NULL;
10751484Sbostic 		return (error);
10840289Smckusick 	}
10951562Smckusick 	/*
11051562Smckusick 	 * Finish inode initialization now that aliasing has been resolved.
11151562Smckusick 	 */
11251562Smckusick 	ip->i_devvp = ump->um_devvp;
11351562Smckusick 	VREF(ip->i_devvp);
11451562Smckusick 	*vpp = vp;
11537736Smckusick 	return (0);
11637736Smckusick }
1177334Skre 
11851346Sbostic int
11951562Smckusick lfs_update(vp, ta, tm, waitfor)
12051562Smckusick 	register struct vnode *vp;
12151484Sbostic 	struct timeval *ta, *tm;
12251484Sbostic         int waitfor;
1237118Smckusick {
12451562Smckusick 	struct inode *ip;
12551562Smckusick 
12651857Sbostic #ifdef VERBOSE
12751857Sbostic 	printf("lfs_update\n");
12851857Sbostic #endif
12951562Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
13051562Smckusick 		return (0);
13151562Smckusick 	ip = VTOI(vp);
13251562Smckusick 	if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0)
13351562Smckusick 		return (0);
13451562Smckusick 	if (ip->i_flag&IACC)
13551562Smckusick 		ip->i_atime = ta->tv_sec;
13652018Smckusick 	if (ip->i_flag&IUPD) {
13751562Smckusick 		ip->i_mtime = tm->tv_sec;
13852018Smckusick 		INCRQUAD((ip)->i_modrev);
13952018Smckusick 	}
14051562Smckusick 	if (ip->i_flag&ICHG)
14151562Smckusick 		ip->i_ctime = time.tv_sec;
14251562Smckusick 	ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
14351562Smckusick 
14438452Smckusick 	/*
14551484Sbostic 	 * XXX
14651562Smckusick 	 * I'm not real sure what to do here; once we have fsync and partial
14751562Smckusick 	 * segments working in the LFS context, this must be fixed to be
14851562Smckusick 	 * correct.  The contents of the inode have to be pushed back to
149*52078Sbostic 	 * stable storage.
15038452Smckusick 	 */
15151484Sbostic 	return (0);
15224Sbill }
15324Sbill 
15424Sbill /*
15551484Sbostic  * Truncate the inode ip to at most length size.
15610736Ssam  *
15710736Ssam  * NB: triple indirect blocks are untested.
15824Sbill  */
15951484Sbostic /* ARGSUSED */
16051484Sbostic int
16151562Smckusick lfs_truncate(ovp, length, flags)
16251562Smckusick 	struct vnode *ovp;
1639165Ssam 	u_long length;
16439676Smckusick 	int flags;
16524Sbill {
16651498Sbostic 	register struct lfs *fs;
16751562Smckusick 	register struct inode *oip;
16817942Smckusick 	struct buf *bp;
16951484Sbostic 	daddr_t lbn;
17051484Sbostic 	int error, offset, size;
1719165Ssam 
17251857Sbostic #ifdef VERBOSE
17351857Sbostic 	printf("lfs_truncate\n");
17451857Sbostic #endif
17551562Smckusick 	vnode_pager_setsize(ovp, length);
17651562Smckusick 	oip = VTOI(ovp);
17751484Sbostic 
17851484Sbostic 	/* If length is larger than the file, just update the times. */
17913000Ssam 	if (oip->i_size <= length) {
18013000Ssam 		oip->i_flag |= ICHG|IUPD;
18151183Sbostic 		ITIMES(oip, &time, &time);
18251183Sbostic 		return (0);
18313000Ssam 	}
18451484Sbostic 
1851203Sbill 	/*
18651484Sbostic 	 * Update the size of the file. If the file is not being truncated to
18751484Sbostic 	 * a block boundry, the contents of the partial block following the end
18851484Sbostic 	 * of the file must be zero'ed in case it ever become accessable again
18951484Sbostic 	 * because of subsequent file growth.
1901203Sbill 	 */
19151484Sbostic 	fs = oip->i_lfs;
19217942Smckusick 	offset = blkoff(fs, length);
19351484Sbostic 	if (offset == 0)
19417942Smckusick 		oip->i_size = length;
19551484Sbostic 	else {
19617942Smckusick 		lbn = lblkno(fs, length);
19741313Smckusick #ifdef QUOTA
19841313Smckusick 		if (error = getinoquota(oip))
19941313Smckusick 			return (error);
20051183Sbostic #endif
20151562Smckusick 		if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp))
20237736Smckusick 			return (error);
20317942Smckusick 		oip->i_size = length;
20451857Sbostic 		size = blksize(fs);
20551857Sbostic 		(void)vnode_pager_uncache(ovp);
20626272Skarels 		bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
20745112Smckusick 		allocbuf(bp, size);
208*52078Sbostic 		LFS_UBWRITE(bp);
20917942Smckusick 	}
210*52078Sbostic 	/*
211*52078Sbostic 	 * XXX
212*52078Sbostic 	 * Bzero inode block pointers here, for consistency with ffs.
213*52078Sbostic 	 * Segment usage information has to be updated when the blocks
214*52078Sbostic 	 * are free.
215*52078Sbostic 	 * Block count in the inode has to be fixed when blocks are
216*52078Sbostic 	 * free.
217*52078Sbostic 	 */
21851857Sbostic 	(void)vinvalbuf(ovp, length > 0);
21951857Sbostic 	return (0);
22024Sbill }
221