xref: /csrg-svn/sys/ufs/ffs/ufs_inode.c (revision 51509)
123399Smckusick /*
2*51509Sbostic  * Copyright (c) 1991 Regents of the University of California.
337736Smckusick  * All rights reserved.
423399Smckusick  *
544537Sbostic  * %sccs.include.redist.c%
637736Smckusick  *
7*51509Sbostic  *	@(#)ufs_inode.c	7.41 (Berkeley) 11/01/91
823399Smckusick  */
924Sbill 
10*51509Sbostic #include <sys/param.h>
11*51509Sbostic #include <sys/systm.h>
12*51509Sbostic #include <sys/proc.h>
13*51509Sbostic #include <sys/vnode.h>
14*51509Sbostic #include <sys/mount.h>
15*51509Sbostic #include <sys/kernel.h>
1624Sbill 
17*51509Sbostic #include <ufs/ufs/quota.h>
18*51509Sbostic #include <ufs/ufs/inode.h>
19*51509Sbostic #include <ufs/ufs/ufsmount.h>
20*51509Sbostic #include <ufs/ufs/ufs_extern.h>
2147571Skarels 
22*51509Sbostic u_long	nextgennumber;		/* Next generation number to assign. */
23*51509Sbostic int	prtactive;		/* 1 => print out reclaim of active vnodes */
2424Sbill 
25*51509Sbostic int
2639440Smckusick ufs_init()
2724Sbill {
28*51509Sbostic 	static int first = 1;
2924Sbill 
30*51509Sbostic 	if (!first)
31*51509Sbostic 		return (0);
32*51509Sbostic 	first = 0;
33*51509Sbostic 
34*51509Sbostic #ifdef DIAGNOSTIC
3539392Smckusick 	if (VN_MAXPRIVATE < sizeof(struct inode))
36*51509Sbostic 		panic("ufs_init: inode too small");
37*51509Sbostic #endif
38*51509Sbostic 	ufs_ihashinit();
3941313Smckusick 	dqinit();
4037736Smckusick 	return (0);
4137736Smckusick }
427334Skre 
4337736Smckusick /*
4439392Smckusick  * Unlock and decrement the reference count of an inode structure.
4524Sbill  */
46*51509Sbostic void
47*51509Sbostic ufs_iput(ip)
484818Swnj 	register struct inode *ip;
4924Sbill {
507118Smckusick 
518452Sroot 	if ((ip->i_flag & ILOCKED) == 0)
527118Smckusick 		panic("iput");
5316665Smckusick 	IUNLOCK(ip);
5437736Smckusick 	vrele(ITOV(ip));
557118Smckusick }
567118Smckusick 
5739392Smckusick /*
5839392Smckusick  * Last reference to an inode, write the inode out and if necessary,
5939392Smckusick  * truncate and deallocate the file.
6039392Smckusick  */
61*51509Sbostic int
6248037Smckusick ufs_inactive(vp, p)
6337736Smckusick 	struct vnode *vp;
6448037Smckusick 	struct proc *p;
657118Smckusick {
66*51509Sbostic 	register struct inode *ip;
67*51509Sbostic 	struct ufsmount *ump;
68*51509Sbostic 	int mode, error;
6924Sbill 
7039816Smckusick 	if (prtactive && vp->v_usecount != 0)
7139676Smckusick 		vprint("ufs_inactive: pushing active", vp);
72*51509Sbostic 
73*51509Sbostic 	/* Get rid of inodes related to stale file handles. */
74*51509Sbostic 	ip = VTOI(vp);
7539440Smckusick 	if (ip->i_mode == 0) {
7639676Smckusick 		if ((vp->v_flag & VXLOCK) == 0)
7739676Smckusick 			vgone(vp);
7839440Smckusick 		return (0);
7939440Smckusick 	}
80*51509Sbostic 
81*51509Sbostic 	error = 0;
82*51509Sbostic 	ump = VFSTOUFS(vp->v_mount);
8338226Smckusick 	ILOCK(ip);
8441397Smckusick 	if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
8541313Smckusick #ifdef QUOTA
8641313Smckusick 		if (!getinoquota(ip))
87*51509Sbostic 			(void)chkiq(ip, -1, NOCRED, 0);
8841313Smckusick #endif
89*51509Sbostic 		error = (ump->um_itrunc)(ip, (u_long)0, 0);
9037736Smckusick 		mode = ip->i_mode;
9137736Smckusick 		ip->i_mode = 0;
9244893Strent 		ip->i_rdev = 0;
9337736Smckusick 		ip->i_flag |= IUPD|ICHG;
94*51509Sbostic 		(ump->um_ifree)(ip, ip->i_number, mode);
9537736Smckusick 	}
96*51509Sbostic 	if (ip->i_flag&(IUPD|IACC|ICHG|IMOD))
97*51509Sbostic 		(ump->um_iupdat)(ip, &time, &time, 0);
9840033Smckusick 	IUNLOCK(ip);
9940033Smckusick 	ip->i_flag = 0;
10037736Smckusick 	/*
10139392Smckusick 	 * If we are done with the inode, reclaim it
10239392Smckusick 	 * so that it can be reused immediately.
10337736Smckusick 	 */
10441313Smckusick 	if (vp->v_usecount == 0 && ip->i_mode == 0)
10540033Smckusick 		vgone(vp);
10637736Smckusick 	return (error);
10724Sbill }
10824Sbill 
10924Sbill /*
11039392Smckusick  * Reclaim an inode so that it can be used for other purposes.
11124Sbill  */
112*51509Sbostic int
11339392Smckusick ufs_reclaim(vp)
11439392Smckusick 	register struct vnode *vp;
11539392Smckusick {
116*51509Sbostic 	register struct inode *ip;
11741313Smckusick 	int i;
11839392Smckusick 
11939816Smckusick 	if (prtactive && vp->v_usecount != 0)
12039676Smckusick 		vprint("ufs_reclaim: pushing active", vp);
12139392Smckusick 	/*
12239392Smckusick 	 * Remove the inode from its hash chain.
12339392Smckusick 	 */
124*51509Sbostic 	ip = VTOI(vp);
12539392Smckusick 	remque(ip);
12639392Smckusick 	ip->i_forw = ip;
12739392Smckusick 	ip->i_back = ip;
12839392Smckusick 	/*
12939392Smckusick 	 * Purge old data structures associated with the inode.
13039392Smckusick 	 */
13139392Smckusick 	cache_purge(vp);
13239392Smckusick 	if (ip->i_devvp) {
13339392Smckusick 		vrele(ip->i_devvp);
13439392Smckusick 		ip->i_devvp = 0;
13539392Smckusick 	}
13639392Smckusick #ifdef QUOTA
13741313Smckusick 	for (i = 0; i < MAXQUOTAS; i++) {
13841313Smckusick 		if (ip->i_dquot[i] != NODQUOT) {
13941313Smckusick 			dqrele(vp, ip->i_dquot[i]);
14041313Smckusick 			ip->i_dquot[i] = NODQUOT;
14141313Smckusick 		}
14241313Smckusick 	}
14339392Smckusick #endif
14439392Smckusick 	ip->i_flag = 0;
14539392Smckusick 	return (0);
14639392Smckusick }
14739392Smckusick 
14839392Smckusick /*
1494818Swnj  * Lock an inode. If its already locked, set the WANT bit and sleep.
1503617Sroot  */
151*51509Sbostic void
152*51509Sbostic ufs_ilock(ip)
1534818Swnj 	register struct inode *ip;
1543617Sroot {
1553617Sroot 
15637736Smckusick 	while (ip->i_flag & ILOCKED) {
15737736Smckusick 		ip->i_flag |= IWANT;
15847571Skarels 		if (ip->i_spare0 == curproc->p_pid)
15939795Smckusick 			panic("locking against myself");
16047571Skarels 		ip->i_spare1 = curproc->p_pid;
16137736Smckusick 		(void) sleep((caddr_t)ip, PINOD);
16237736Smckusick 	}
16339795Smckusick 	ip->i_spare1 = 0;
16447571Skarels 	ip->i_spare0 = curproc->p_pid;
16537736Smckusick 	ip->i_flag |= ILOCKED;
1663617Sroot }
1673617Sroot 
1683617Sroot /*
1694818Swnj  * Unlock an inode.  If WANT bit is on, wakeup.
1703617Sroot  */
171*51509Sbostic void
172*51509Sbostic ufs_iunlock(ip)
1734818Swnj 	register struct inode *ip;
1743617Sroot {
1753617Sroot 
17637736Smckusick 	if ((ip->i_flag & ILOCKED) == 0)
177*51509Sbostic 		vprint("ufs_iunlock: unlocked inode", ITOV(ip));
17839795Smckusick 	ip->i_spare0 = 0;
17937736Smckusick 	ip->i_flag &= ~ILOCKED;
18037736Smckusick 	if (ip->i_flag&IWANT) {
18137736Smckusick 		ip->i_flag &= ~IWANT;
18237736Smckusick 		wakeup((caddr_t)ip);
18337736Smckusick 	}
1843617Sroot }
185