xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 51562)
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*51562Smckusick  *	@(#)lfs_inode.c	7.47 (Berkeley) 11/05/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
40*51562Smckusick lfs_vget(mntp, ino, vpp)
41*51562Smckusick 	struct mount *mntp;
424818Swnj 	ino_t ino;
43*51562Smckusick 	struct vnode **vpp;
4424Sbill {
4551498Sbostic 	register struct lfs *fs;
4651484Sbostic 	register struct inode *ip;
4751484Sbostic 	struct buf *bp;
4851498Sbostic 	struct vnode *vp;
49*51562Smckusick 	struct ufsmount *ump;
5051484Sbostic 	dev_t dev;
5151346Sbostic 	int error;
52*51562Smckusick 	extern struct vnodeops lfs_fifoops, lfs_specops;
5324Sbill 
54*51562Smckusick 	ump = VFSTOUFS(mntp);
55*51562Smckusick 	dev = ump->um_dev;
56*51562Smckusick 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
5751484Sbostic 		return (0);
5851484Sbostic 
5951155Sbostic 	/* Allocate new vnode/inode. */
6051498Sbostic 	if (error = lfs_vcreate(mntp, ino, &vp)) {
61*51562Smckusick 		*vpp = NULL;
6237736Smckusick 		return (error);
6337736Smckusick 	}
6437736Smckusick 	/*
6539440Smckusick 	 * Put it onto its hash chain and lock it so that other requests for
6639440Smckusick 	 * this inode will block if they arrive while we are sleeping waiting
6739440Smckusick 	 * for old data structures to be purged or for the contents of the
6839440Smckusick 	 * disk portion of this inode to be read.
6939440Smckusick 	 */
70*51562Smckusick 	ip = VTOI(vp);
7151484Sbostic 	ufs_ihashins(ip);
7251155Sbostic 
7351484Sbostic 	/* Read in the disk contents for the inode, copy into the inode. */
74*51562Smckusick 	fs = ump->um_lfs;
75*51562Smckusick 	if (error = bread(ump->um_devvp, lfs_itod(fs, ino),
7651484Sbostic 	    (int)fs->lfs_bsize, NOCRED, &bp)) {
7737736Smckusick 		/*
7841334Smckusick 		 * The inode does not contain anything useful, so it would
7951484Sbostic 		 * be misleading to leave it on its hash chain.  Iput() will
8051498Sbostic 		 * return it to the free list.
8141334Smckusick 		 */
8241334Smckusick 		remque(ip);
8341334Smckusick 		ip->i_forw = ip;
8441334Smckusick 		ip->i_back = ip;
8551484Sbostic 
8651484Sbostic 		/* Unlock and discard unneeded inode. */
8751484Sbostic 		ufs_iput(ip);
8837736Smckusick 		brelse(bp);
89*51562Smckusick 		*vpp = NULL;
9039440Smckusick 		return (error);
9137736Smckusick 	}
9251155Sbostic 	ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino);
9339440Smckusick 	brelse(bp);
9451155Sbostic 
9551498Sbostic 	/*
9651498Sbostic 	 * Initialize the vnode from the inode, check for aliases.  In all
9751498Sbostic 	 * cases re-init ip, the underlying vnode/inode may have changed.
9851498Sbostic 	 */
99*51562Smckusick 	if (error = ufs_vinit(mntp, &lfs_specops, &lfs_fifoops, &vp)) {
10051484Sbostic 		ufs_iput(ip);
101*51562Smckusick 		*vpp = NULL;
10251484Sbostic 		return (error);
10340289Smckusick 	}
104*51562Smckusick 	/*
105*51562Smckusick 	 * Finish inode initialization now that aliasing has been resolved.
106*51562Smckusick 	 */
107*51562Smckusick 	ip = VTOI(vp);
108*51562Smckusick 	ip->i_lfs = ump->um_lfs;
109*51562Smckusick 	ip->i_devvp = ump->um_devvp;
110*51562Smckusick 	VREF(ip->i_devvp);
111*51562Smckusick 	*vpp = vp;
11237736Smckusick 	return (0);
11337736Smckusick }
1147334Skre 
11551346Sbostic int
116*51562Smckusick lfs_update(vp, ta, tm, waitfor)
117*51562Smckusick 	register struct vnode *vp;
11851484Sbostic 	struct timeval *ta, *tm;
11951484Sbostic         int waitfor;
1207118Smckusick {
121*51562Smckusick 	struct inode *ip;
122*51562Smckusick 
123*51562Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
124*51562Smckusick 		return (0);
125*51562Smckusick 	ip = VTOI(vp);
126*51562Smckusick 	if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0)
127*51562Smckusick 		return (0);
128*51562Smckusick 	if (ip->i_flag&IACC)
129*51562Smckusick 		ip->i_atime = ta->tv_sec;
130*51562Smckusick 	if (ip->i_flag&IUPD)
131*51562Smckusick 		ip->i_mtime = tm->tv_sec;
132*51562Smckusick 	if (ip->i_flag&ICHG)
133*51562Smckusick 		ip->i_ctime = time.tv_sec;
134*51562Smckusick 	ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
135*51562Smckusick 
13638452Smckusick 	/*
13751484Sbostic 	 * XXX
138*51562Smckusick 	 * I'm not real sure what to do here; once we have fsync and partial
139*51562Smckusick 	 * segments working in the LFS context, this must be fixed to be
140*51562Smckusick 	 * correct.  The contents of the inode have to be pushed back to
141*51562Smckusick 	 * stable storage; note that the ifile contains the access time of
142*51562Smckusick 	 * the inode and must be updated as well.
14338452Smckusick 	 */
14451484Sbostic 	return (0);
14524Sbill }
14624Sbill 
14724Sbill /*
14851484Sbostic  * Truncate the inode ip to at most length size.
14910736Ssam  *
15010736Ssam  * NB: triple indirect blocks are untested.
15124Sbill  */
15251484Sbostic /* ARGSUSED */
15351484Sbostic int
154*51562Smckusick lfs_truncate(ovp, length, flags)
155*51562Smckusick 	struct vnode *ovp;
1569165Ssam 	u_long length;
15739676Smckusick 	int flags;
15824Sbill {
15951498Sbostic 	register struct lfs *fs;
160*51562Smckusick 	register struct inode *oip;
16117942Smckusick 	struct buf *bp;
16251484Sbostic 	daddr_t lbn;
16351484Sbostic 	int error, offset, size;
1649165Ssam 
165*51562Smckusick 	vnode_pager_setsize(ovp, length);
166*51562Smckusick 	oip = VTOI(ovp);
16751484Sbostic 
16851484Sbostic 	/* If length is larger than the file, just update the times. */
16913000Ssam 	if (oip->i_size <= length) {
17013000Ssam 		oip->i_flag |= ICHG|IUPD;
17151183Sbostic 		ITIMES(oip, &time, &time);
17251183Sbostic 		return (0);
17313000Ssam 	}
17451484Sbostic 
1751203Sbill 	/*
17651484Sbostic 	 * Update the size of the file. If the file is not being truncated to
17751484Sbostic 	 * a block boundry, the contents of the partial block following the end
17851484Sbostic 	 * of the file must be zero'ed in case it ever become accessable again
17951484Sbostic 	 * because of subsequent file growth.
1801203Sbill 	 */
18151484Sbostic 	fs = oip->i_lfs;
18217942Smckusick 	offset = blkoff(fs, length);
18351484Sbostic 	if (offset == 0)
18417942Smckusick 		oip->i_size = length;
18551484Sbostic 	else {
18617942Smckusick 		lbn = lblkno(fs, length);
18741313Smckusick #ifdef QUOTA
18841313Smckusick 		if (error = getinoquota(oip))
18941313Smckusick 			return (error);
19051183Sbostic #endif
191*51562Smckusick 		if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp))
19237736Smckusick 			return (error);
19317942Smckusick 		oip->i_size = length;
19451155Sbostic 		size = blksize(fs);				/* LFS */
195*51562Smckusick 		(void) vnode_pager_uncache(ovp);
19626272Skarels 		bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
19745112Smckusick 		allocbuf(bp, size);
19851183Sbostic 		lfs_bwrite(bp);
19917942Smckusick 	}
20051484Sbostic 	/* BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY XXX */
20124Sbill }
202