xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 52018)
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*52018Smckusick  *	@(#)lfs_inode.c	7.50 (Berkeley) 12/19/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. */
79*52018Smckusick 	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;
136*52018Smckusick 	if (ip->i_flag&IUPD) {
13751562Smckusick 		ip->i_mtime = tm->tv_sec;
138*52018Smckusick 		INCRQUAD((ip)->i_modrev);
139*52018Smckusick 	}
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
14951562Smckusick 	 * stable storage; note that the ifile contains the access time of
15051562Smckusick 	 * the inode and must be updated as well.
15138452Smckusick 	 */
15251484Sbostic 	return (0);
15324Sbill }
15424Sbill 
15524Sbill /*
15651484Sbostic  * Truncate the inode ip to at most length size.
15710736Ssam  *
15810736Ssam  * NB: triple indirect blocks are untested.
15924Sbill  */
16051484Sbostic /* ARGSUSED */
16151484Sbostic int
16251562Smckusick lfs_truncate(ovp, length, flags)
16351562Smckusick 	struct vnode *ovp;
1649165Ssam 	u_long length;
16539676Smckusick 	int flags;
16624Sbill {
16751498Sbostic 	register struct lfs *fs;
16851562Smckusick 	register struct inode *oip;
16917942Smckusick 	struct buf *bp;
17051484Sbostic 	daddr_t lbn;
17151484Sbostic 	int error, offset, size;
1729165Ssam 
17351857Sbostic #ifdef VERBOSE
17451857Sbostic 	printf("lfs_truncate\n");
17551857Sbostic #endif
17651562Smckusick 	vnode_pager_setsize(ovp, length);
17751562Smckusick 	oip = VTOI(ovp);
17851484Sbostic 
17951484Sbostic 	/* If length is larger than the file, just update the times. */
18013000Ssam 	if (oip->i_size <= length) {
18113000Ssam 		oip->i_flag |= ICHG|IUPD;
18251183Sbostic 		ITIMES(oip, &time, &time);
18351183Sbostic 		return (0);
18413000Ssam 	}
18551484Sbostic 
1861203Sbill 	/*
18751484Sbostic 	 * Update the size of the file. If the file is not being truncated to
18851484Sbostic 	 * a block boundry, the contents of the partial block following the end
18951484Sbostic 	 * of the file must be zero'ed in case it ever become accessable again
19051484Sbostic 	 * because of subsequent file growth.
1911203Sbill 	 */
19251484Sbostic 	fs = oip->i_lfs;
19317942Smckusick 	offset = blkoff(fs, length);
19451484Sbostic 	if (offset == 0)
19517942Smckusick 		oip->i_size = length;
19651484Sbostic 	else {
19717942Smckusick 		lbn = lblkno(fs, length);
19841313Smckusick #ifdef QUOTA
19941313Smckusick 		if (error = getinoquota(oip))
20041313Smckusick 			return (error);
20151183Sbostic #endif
20251562Smckusick 		if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp))
20337736Smckusick 			return (error);
20417942Smckusick 		oip->i_size = length;
20551857Sbostic 		size = blksize(fs);
20651857Sbostic 		(void)vnode_pager_uncache(ovp);
20726272Skarels 		bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
20845112Smckusick 		allocbuf(bp, size);
20951183Sbostic 		lfs_bwrite(bp);
21017942Smckusick 	}
21151857Sbostic 	/* XXX: BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY. */
21251857Sbostic 	(void)vinvalbuf(ovp, length > 0);
21351857Sbostic 	return (0);
21424Sbill }
215