xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 51595)
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*51595Smckusick  *	@(#)lfs_inode.c	7.48 (Berkeley) 11/08/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 {
3151484Sbostic 	return (ufs_init());
3224Sbill }
3324Sbill 
3424Sbill /*
3551484Sbostic  * Look up an LFS dinode number to find its incore vnode.  If not already
3651484Sbostic  * in core, read it in from the specified device.  Return the inode locked.
3751484Sbostic  * Detection and handling of mount points must be done by the calling routine.
3824Sbill  */
3951346Sbostic int
4051562Smckusick lfs_vget(mntp, ino, vpp)
4151562Smckusick 	struct mount *mntp;
424818Swnj 	ino_t ino;
4351562Smckusick 	struct vnode **vpp;
4424Sbill {
4551498Sbostic 	register struct lfs *fs;
4651484Sbostic 	register struct inode *ip;
4751484Sbostic 	struct buf *bp;
4851498Sbostic 	struct vnode *vp;
4951562Smckusick 	struct ufsmount *ump;
5051484Sbostic 	dev_t dev;
5151346Sbostic 	int error;
5224Sbill 
5351562Smckusick 	ump = VFSTOUFS(mntp);
5451562Smckusick 	dev = ump->um_dev;
5551562Smckusick 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
5651484Sbostic 		return (0);
5751484Sbostic 
5851155Sbostic 	/* Allocate new vnode/inode. */
5951498Sbostic 	if (error = lfs_vcreate(mntp, ino, &vp)) {
6051562Smckusick 		*vpp = NULL;
6137736Smckusick 		return (error);
6237736Smckusick 	}
6337736Smckusick 	/*
6439440Smckusick 	 * Put it onto its hash chain and lock it so that other requests for
6539440Smckusick 	 * this inode will block if they arrive while we are sleeping waiting
6639440Smckusick 	 * for old data structures to be purged or for the contents of the
6739440Smckusick 	 * disk portion of this inode to be read.
6839440Smckusick 	 */
6951562Smckusick 	ip = VTOI(vp);
7051484Sbostic 	ufs_ihashins(ip);
7151155Sbostic 
7251484Sbostic 	/* Read in the disk contents for the inode, copy into the inode. */
7351562Smckusick 	fs = ump->um_lfs;
7451562Smckusick 	if (error = bread(ump->um_devvp, lfs_itod(fs, ino),
7551484Sbostic 	    (int)fs->lfs_bsize, NOCRED, &bp)) {
7637736Smckusick 		/*
7741334Smckusick 		 * The inode does not contain anything useful, so it would
7851484Sbostic 		 * be misleading to leave it on its hash chain.  Iput() will
7951498Sbostic 		 * return it to the free list.
8041334Smckusick 		 */
8141334Smckusick 		remque(ip);
8241334Smckusick 		ip->i_forw = ip;
8341334Smckusick 		ip->i_back = ip;
8451484Sbostic 
8551484Sbostic 		/* Unlock and discard unneeded inode. */
8651484Sbostic 		ufs_iput(ip);
8737736Smckusick 		brelse(bp);
8851562Smckusick 		*vpp = NULL;
8939440Smckusick 		return (error);
9037736Smckusick 	}
9151155Sbostic 	ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino);
9239440Smckusick 	brelse(bp);
9351155Sbostic 
9451498Sbostic 	/*
9551498Sbostic 	 * Initialize the vnode from the inode, check for aliases.  In all
9651498Sbostic 	 * cases re-init ip, the underlying vnode/inode may have changed.
9751498Sbostic 	 */
98*51595Smckusick 	if (error = ufs_vinit(mntp, &lfs_specops, LFS_FIFOOPS, &vp)) {
9951484Sbostic 		ufs_iput(ip);
10051562Smckusick 		*vpp = NULL;
10151484Sbostic 		return (error);
10240289Smckusick 	}
10351562Smckusick 	/*
10451562Smckusick 	 * Finish inode initialization now that aliasing has been resolved.
10551562Smckusick 	 */
10651562Smckusick 	ip = VTOI(vp);
10751562Smckusick 	ip->i_lfs = ump->um_lfs;
10851562Smckusick 	ip->i_devvp = ump->um_devvp;
10951562Smckusick 	VREF(ip->i_devvp);
11051562Smckusick 	*vpp = vp;
11137736Smckusick 	return (0);
11237736Smckusick }
1137334Skre 
11451346Sbostic int
11551562Smckusick lfs_update(vp, ta, tm, waitfor)
11651562Smckusick 	register struct vnode *vp;
11751484Sbostic 	struct timeval *ta, *tm;
11851484Sbostic         int waitfor;
1197118Smckusick {
12051562Smckusick 	struct inode *ip;
12151562Smckusick 
12251562Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
12351562Smckusick 		return (0);
12451562Smckusick 	ip = VTOI(vp);
12551562Smckusick 	if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0)
12651562Smckusick 		return (0);
12751562Smckusick 	if (ip->i_flag&IACC)
12851562Smckusick 		ip->i_atime = ta->tv_sec;
12951562Smckusick 	if (ip->i_flag&IUPD)
13051562Smckusick 		ip->i_mtime = tm->tv_sec;
13151562Smckusick 	if (ip->i_flag&ICHG)
13251562Smckusick 		ip->i_ctime = time.tv_sec;
13351562Smckusick 	ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
13451562Smckusick 
13538452Smckusick 	/*
13651484Sbostic 	 * XXX
13751562Smckusick 	 * I'm not real sure what to do here; once we have fsync and partial
13851562Smckusick 	 * segments working in the LFS context, this must be fixed to be
13951562Smckusick 	 * correct.  The contents of the inode have to be pushed back to
14051562Smckusick 	 * stable storage; note that the ifile contains the access time of
14151562Smckusick 	 * the inode and must be updated as well.
14238452Smckusick 	 */
14351484Sbostic 	return (0);
14424Sbill }
14524Sbill 
14624Sbill /*
14751484Sbostic  * Truncate the inode ip to at most length size.
14810736Ssam  *
14910736Ssam  * NB: triple indirect blocks are untested.
15024Sbill  */
15151484Sbostic /* ARGSUSED */
15251484Sbostic int
15351562Smckusick lfs_truncate(ovp, length, flags)
15451562Smckusick 	struct vnode *ovp;
1559165Ssam 	u_long length;
15639676Smckusick 	int flags;
15724Sbill {
15851498Sbostic 	register struct lfs *fs;
15951562Smckusick 	register struct inode *oip;
16017942Smckusick 	struct buf *bp;
16151484Sbostic 	daddr_t lbn;
16251484Sbostic 	int error, offset, size;
1639165Ssam 
16451562Smckusick 	vnode_pager_setsize(ovp, length);
16551562Smckusick 	oip = VTOI(ovp);
16651484Sbostic 
16751484Sbostic 	/* If length is larger than the file, just update the times. */
16813000Ssam 	if (oip->i_size <= length) {
16913000Ssam 		oip->i_flag |= ICHG|IUPD;
17051183Sbostic 		ITIMES(oip, &time, &time);
17151183Sbostic 		return (0);
17213000Ssam 	}
17351484Sbostic 
1741203Sbill 	/*
17551484Sbostic 	 * Update the size of the file. If the file is not being truncated to
17651484Sbostic 	 * a block boundry, the contents of the partial block following the end
17751484Sbostic 	 * of the file must be zero'ed in case it ever become accessable again
17851484Sbostic 	 * because of subsequent file growth.
1791203Sbill 	 */
18051484Sbostic 	fs = oip->i_lfs;
18117942Smckusick 	offset = blkoff(fs, length);
18251484Sbostic 	if (offset == 0)
18317942Smckusick 		oip->i_size = length;
18451484Sbostic 	else {
18517942Smckusick 		lbn = lblkno(fs, length);
18641313Smckusick #ifdef QUOTA
18741313Smckusick 		if (error = getinoquota(oip))
18841313Smckusick 			return (error);
18951183Sbostic #endif
19051562Smckusick 		if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp))
19137736Smckusick 			return (error);
19217942Smckusick 		oip->i_size = length;
19351155Sbostic 		size = blksize(fs);				/* LFS */
19451562Smckusick 		(void) vnode_pager_uncache(ovp);
19526272Skarels 		bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
19645112Smckusick 		allocbuf(bp, size);
19751183Sbostic 		lfs_bwrite(bp);
19817942Smckusick 	}
19951484Sbostic 	/* BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY XXX */
20024Sbill }
201