xref: /csrg-svn/sys/ufs/ffs/ufs_inode.c (revision 56746)
123399Smckusick /*
251509Sbostic  * Copyright (c) 1991 Regents of the University of California.
337736Smckusick  * All rights reserved.
423399Smckusick  *
544537Sbostic  * %sccs.include.redist.c%
637736Smckusick  *
7*56746Smckusick  *	@(#)ufs_inode.c	7.50 (Berkeley) 11/13/92
823399Smckusick  */
924Sbill 
1051509Sbostic #include <sys/param.h>
1151509Sbostic #include <sys/systm.h>
1251509Sbostic #include <sys/proc.h>
1351509Sbostic #include <sys/vnode.h>
1451509Sbostic #include <sys/mount.h>
1551509Sbostic #include <sys/kernel.h>
1651987Smckusick #include <sys/malloc.h>
1724Sbill 
1851509Sbostic #include <ufs/ufs/quota.h>
1951509Sbostic #include <ufs/ufs/inode.h>
2051509Sbostic #include <ufs/ufs/ufsmount.h>
2151509Sbostic #include <ufs/ufs/ufs_extern.h>
2247571Skarels 
2351509Sbostic u_long	nextgennumber;		/* Next generation number to assign. */
2451547Smckusick int	prtactive = 0;		/* 1 => print out reclaim of active vnodes */
2524Sbill 
2651509Sbostic int
2739440Smckusick ufs_init()
2824Sbill {
2951509Sbostic 	static int first = 1;
3024Sbill 
3151509Sbostic 	if (!first)
3251509Sbostic 		return (0);
3351509Sbostic 	first = 0;
3451509Sbostic 
3551509Sbostic #ifdef DIAGNOSTIC
3651987Smckusick 	if ((sizeof(struct inode) - 1) & sizeof(struct inode))
3751987Smckusick 		printf("ufs_init: bad size %d\n", sizeof(struct inode));
3851509Sbostic #endif
3951509Sbostic 	ufs_ihashinit();
4041313Smckusick 	dqinit();
4137736Smckusick 	return (0);
4237736Smckusick }
437334Skre 
4437736Smckusick /*
4539392Smckusick  * Unlock and decrement the reference count of an inode structure.
4624Sbill  */
4751509Sbostic void
4851509Sbostic ufs_iput(ip)
494818Swnj 	register struct inode *ip;
5024Sbill {
517118Smckusick 
528452Sroot 	if ((ip->i_flag & ILOCKED) == 0)
537118Smckusick 		panic("iput");
5416665Smckusick 	IUNLOCK(ip);
5537736Smckusick 	vrele(ITOV(ip));
567118Smckusick }
577118Smckusick 
5839392Smckusick /*
59*56746Smckusick  * Last reference to an inode, write the inode out and if necessary,
60*56746Smckusick  * truncate and deallocate the file.
61*56746Smckusick  */
62*56746Smckusick int
63*56746Smckusick ufs_inactive(ap)
64*56746Smckusick 	struct vop_inactive_args /* {
65*56746Smckusick 		struct vnode *a_vp;
66*56746Smckusick 	} */ *ap;
67*56746Smckusick {
68*56746Smckusick 	register struct vnode *vp = ap->a_vp;
69*56746Smckusick 	register struct inode *ip = VTOI(vp);
70*56746Smckusick 	struct timeval tv;
71*56746Smckusick 	int mode, error;
72*56746Smckusick 	extern int prtactive;
73*56746Smckusick 
74*56746Smckusick 	if (prtactive && vp->v_usecount != 0)
75*56746Smckusick 		vprint("ffs_inactive: pushing active", vp);
76*56746Smckusick 
77*56746Smckusick 	/* Get rid of inodes related to stale file handles. */
78*56746Smckusick 	if (ip->i_mode == 0) {
79*56746Smckusick 		if ((vp->v_flag & VXLOCK) == 0)
80*56746Smckusick 			vgone(vp);
81*56746Smckusick 		return (0);
82*56746Smckusick 	}
83*56746Smckusick 
84*56746Smckusick 	error = 0;
85*56746Smckusick #ifdef DIAGNOSTIC
86*56746Smckusick 	if (VOP_ISLOCKED(vp))
87*56746Smckusick 		panic("ffs_inactive: locked inode");
88*56746Smckusick #endif
89*56746Smckusick 	ip->i_flag |= ILOCKED;
90*56746Smckusick 	if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
91*56746Smckusick #ifdef QUOTA
92*56746Smckusick 		if (!getinoquota(ip))
93*56746Smckusick 			(void)chkiq(ip, -1, NOCRED, 0);
94*56746Smckusick #endif
95*56746Smckusick 		error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL);
96*56746Smckusick 		mode = ip->i_mode;
97*56746Smckusick 		ip->i_mode = 0;
98*56746Smckusick 		ip->i_rdev = 0;
99*56746Smckusick 		ip->i_flag |= IUPD|ICHG;
100*56746Smckusick 		VOP_VFREE(vp, ip->i_number, mode);
101*56746Smckusick 	}
102*56746Smckusick 	if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) {
103*56746Smckusick 		tv = time;
104*56746Smckusick 		VOP_UPDATE(vp, &tv, &tv, 0);
105*56746Smckusick 	}
106*56746Smckusick 	VOP_UNLOCK(vp);
107*56746Smckusick 	/*
108*56746Smckusick 	 * If we are done with the inode, reclaim it
109*56746Smckusick 	 * so that it can be reused immediately.
110*56746Smckusick 	 */
111*56746Smckusick 	if (vp->v_usecount == 0 && ip->i_mode == 0)
112*56746Smckusick 		vgone(vp);
113*56746Smckusick 	return (error);
114*56746Smckusick }
115*56746Smckusick 
116*56746Smckusick /*
11739392Smckusick  * Reclaim an inode so that it can be used for other purposes.
11824Sbill  */
11951509Sbostic int
12054648Smckusick ufs_reclaim(ap)
12154648Smckusick 	struct vop_reclaim_args /* {
12254648Smckusick 		struct vnode *a_vp;
12354648Smckusick 	} */ *ap;
12439392Smckusick {
12553864Sheideman 	register struct vnode *vp = ap->a_vp;
12651509Sbostic 	register struct inode *ip;
12751987Smckusick 	int i, type;
12839392Smckusick 
12953864Sheideman 	if (prtactive && vp->v_usecount != 0)
13053864Sheideman 		vprint("ufs_reclaim: pushing active", vp);
13139392Smckusick 	/*
13239392Smckusick 	 * Remove the inode from its hash chain.
13339392Smckusick 	 */
13453864Sheideman 	ip = VTOI(vp);
13555413Smckusick 	ufs_ihashrem(ip);
13639392Smckusick 	/*
13739392Smckusick 	 * Purge old data structures associated with the inode.
13839392Smckusick 	 */
13953864Sheideman 	cache_purge(vp);
14039392Smckusick 	if (ip->i_devvp) {
14139392Smckusick 		vrele(ip->i_devvp);
14239392Smckusick 		ip->i_devvp = 0;
14339392Smckusick 	}
14439392Smckusick #ifdef QUOTA
14541313Smckusick 	for (i = 0; i < MAXQUOTAS; i++) {
14641313Smckusick 		if (ip->i_dquot[i] != NODQUOT) {
14753864Sheideman 			dqrele(vp, ip->i_dquot[i]);
14841313Smckusick 			ip->i_dquot[i] = NODQUOT;
14941313Smckusick 		}
15041313Smckusick 	}
15139392Smckusick #endif
15253864Sheideman 	switch (vp->v_mount->mnt_stat.f_type) {
15351987Smckusick 	case MOUNT_UFS:
15451987Smckusick 		type = M_FFSNODE;
15551987Smckusick 		break;
15651987Smckusick 	case MOUNT_MFS:
15751987Smckusick 		type = M_MFSNODE;
15851987Smckusick 		break;
15951987Smckusick 	case MOUNT_LFS:
16051987Smckusick 		type = M_LFSNODE;
16151987Smckusick 		break;
16251987Smckusick 	default:
16351987Smckusick 		panic("ufs_reclaim: not ufs file");
16451987Smckusick 	}
16553864Sheideman 	FREE(vp->v_data, type);
16653864Sheideman 	vp->v_data = NULL;
16739392Smckusick 	return (0);
16839392Smckusick }
16939392Smckusick 
17039392Smckusick /*
1714818Swnj  * Lock an inode. If its already locked, set the WANT bit and sleep.
1723617Sroot  */
17351509Sbostic void
17451509Sbostic ufs_ilock(ip)
1754818Swnj 	register struct inode *ip;
1763617Sroot {
17752037Smckusick 	struct proc *p = curproc;	/* XXX */
1783617Sroot 
17937736Smckusick 	while (ip->i_flag & ILOCKED) {
18037736Smckusick 		ip->i_flag |= IWANT;
18152037Smckusick #ifdef DIAGNOSTIC
18252037Smckusick 		if (p) {
18352037Smckusick 			if (p->p_pid == ip->i_lockholder)
18452037Smckusick 				panic("locking against myself");
18552037Smckusick 			ip->i_lockwaiter = p->p_pid;
18652037Smckusick 		}
18752037Smckusick #endif
18837736Smckusick 		(void) sleep((caddr_t)ip, PINOD);
18937736Smckusick 	}
19052037Smckusick #ifdef DIAGNOSTIC
19151987Smckusick 	ip->i_lockwaiter = 0;
19252037Smckusick 	if (p)
19352037Smckusick 		ip->i_lockholder = p->p_pid;
19452037Smckusick #endif
19537736Smckusick 	ip->i_flag |= ILOCKED;
1963617Sroot }
1973617Sroot 
1983617Sroot /*
1994818Swnj  * Unlock an inode.  If WANT bit is on, wakeup.
2003617Sroot  */
20151509Sbostic void
20251509Sbostic ufs_iunlock(ip)
2034818Swnj 	register struct inode *ip;
2043617Sroot {
2053617Sroot 
20637736Smckusick 	if ((ip->i_flag & ILOCKED) == 0)
20751509Sbostic 		vprint("ufs_iunlock: unlocked inode", ITOV(ip));
20852037Smckusick #ifdef DIAGNOSTIC
20951987Smckusick 	ip->i_lockholder = 0;
21052037Smckusick #endif
21137736Smckusick 	ip->i_flag &= ~ILOCKED;
21237736Smckusick 	if (ip->i_flag&IWANT) {
21337736Smckusick 		ip->i_flag &= ~IWANT;
21437736Smckusick 		wakeup((caddr_t)ip);
21537736Smckusick 	}
2163617Sroot }
217