xref: /csrg-svn/sys/ufs/ffs/ufs_inode.c (revision 57052)
123399Smckusick /*
251509Sbostic  * Copyright (c) 1991 Regents of the University of California.
337736Smckusick  * All rights reserved.
423399Smckusick  *
544537Sbostic  * %sccs.include.redist.c%
637736Smckusick  *
7*57052Smckusick  *	@(#)ufs_inode.c	7.52 (Berkeley) 12/09/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 /*
4556746Smckusick  * Last reference to an inode, write the inode out and if necessary,
4656746Smckusick  * truncate and deallocate the file.
4756746Smckusick  */
4856746Smckusick int
4956746Smckusick ufs_inactive(ap)
5056746Smckusick 	struct vop_inactive_args /* {
5156746Smckusick 		struct vnode *a_vp;
5256746Smckusick 	} */ *ap;
5356746Smckusick {
5456746Smckusick 	register struct vnode *vp = ap->a_vp;
5556746Smckusick 	register struct inode *ip = VTOI(vp);
5656746Smckusick 	struct timeval tv;
5756746Smckusick 	int mode, error;
5856746Smckusick 	extern int prtactive;
5956746Smckusick 
6056746Smckusick 	if (prtactive && vp->v_usecount != 0)
6156746Smckusick 		vprint("ffs_inactive: pushing active", vp);
6256746Smckusick 
6356746Smckusick 	/* Get rid of inodes related to stale file handles. */
6456746Smckusick 	if (ip->i_mode == 0) {
6556746Smckusick 		if ((vp->v_flag & VXLOCK) == 0)
6656746Smckusick 			vgone(vp);
6756746Smckusick 		return (0);
6856746Smckusick 	}
6956746Smckusick 
7056746Smckusick 	error = 0;
7156746Smckusick #ifdef DIAGNOSTIC
7256746Smckusick 	if (VOP_ISLOCKED(vp))
7356746Smckusick 		panic("ffs_inactive: locked inode");
74*57052Smckusick 	if (curproc)
75*57052Smckusick 		ip->i_lockholder = curproc->p_pid;
76*57052Smckusick 	else
77*57052Smckusick 		ip->i_lockholder = -1;
7856746Smckusick #endif
7956746Smckusick 	ip->i_flag |= ILOCKED;
8056746Smckusick 	if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
8156746Smckusick #ifdef QUOTA
8256746Smckusick 		if (!getinoquota(ip))
8356746Smckusick 			(void)chkiq(ip, -1, NOCRED, 0);
8456746Smckusick #endif
8556746Smckusick 		error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL);
8656746Smckusick 		mode = ip->i_mode;
8756746Smckusick 		ip->i_mode = 0;
8856746Smckusick 		ip->i_rdev = 0;
8956746Smckusick 		ip->i_flag |= IUPD|ICHG;
9056746Smckusick 		VOP_VFREE(vp, ip->i_number, mode);
9156746Smckusick 	}
9256746Smckusick 	if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) {
9356746Smckusick 		tv = time;
9456746Smckusick 		VOP_UPDATE(vp, &tv, &tv, 0);
9556746Smckusick 	}
9656746Smckusick 	VOP_UNLOCK(vp);
9756746Smckusick 	/*
9856746Smckusick 	 * If we are done with the inode, reclaim it
9956746Smckusick 	 * so that it can be reused immediately.
10056746Smckusick 	 */
10156746Smckusick 	if (vp->v_usecount == 0 && ip->i_mode == 0)
10256746Smckusick 		vgone(vp);
10356746Smckusick 	return (error);
10456746Smckusick }
10556746Smckusick 
10656746Smckusick /*
10739392Smckusick  * Reclaim an inode so that it can be used for other purposes.
10824Sbill  */
10951509Sbostic int
11054648Smckusick ufs_reclaim(ap)
11154648Smckusick 	struct vop_reclaim_args /* {
11254648Smckusick 		struct vnode *a_vp;
11354648Smckusick 	} */ *ap;
11439392Smckusick {
11553864Sheideman 	register struct vnode *vp = ap->a_vp;
11651509Sbostic 	register struct inode *ip;
11751987Smckusick 	int i, type;
11839392Smckusick 
11953864Sheideman 	if (prtactive && vp->v_usecount != 0)
12053864Sheideman 		vprint("ufs_reclaim: pushing active", vp);
12139392Smckusick 	/*
12239392Smckusick 	 * Remove the inode from its hash chain.
12339392Smckusick 	 */
12453864Sheideman 	ip = VTOI(vp);
12555413Smckusick 	ufs_ihashrem(ip);
12639392Smckusick 	/*
12739392Smckusick 	 * Purge old data structures associated with the inode.
12839392Smckusick 	 */
12953864Sheideman 	cache_purge(vp);
13039392Smckusick 	if (ip->i_devvp) {
13139392Smckusick 		vrele(ip->i_devvp);
13239392Smckusick 		ip->i_devvp = 0;
13339392Smckusick 	}
13439392Smckusick #ifdef QUOTA
13541313Smckusick 	for (i = 0; i < MAXQUOTAS; i++) {
13641313Smckusick 		if (ip->i_dquot[i] != NODQUOT) {
13753864Sheideman 			dqrele(vp, ip->i_dquot[i]);
13841313Smckusick 			ip->i_dquot[i] = NODQUOT;
13941313Smckusick 		}
14041313Smckusick 	}
14139392Smckusick #endif
14253864Sheideman 	switch (vp->v_mount->mnt_stat.f_type) {
14351987Smckusick 	case MOUNT_UFS:
14451987Smckusick 		type = M_FFSNODE;
14551987Smckusick 		break;
14651987Smckusick 	case MOUNT_MFS:
14751987Smckusick 		type = M_MFSNODE;
14851987Smckusick 		break;
14951987Smckusick 	case MOUNT_LFS:
15051987Smckusick 		type = M_LFSNODE;
15151987Smckusick 		break;
15251987Smckusick 	default:
15351987Smckusick 		panic("ufs_reclaim: not ufs file");
15451987Smckusick 	}
15553864Sheideman 	FREE(vp->v_data, type);
15653864Sheideman 	vp->v_data = NULL;
15739392Smckusick 	return (0);
15839392Smckusick }
159