123399Smckusick /*
263376Sbostic * Copyright (c) 1991, 1993
363376Sbostic * The Regents of the University of California. All rights reserved.
465774Sbostic * (c) UNIX System Laboratories, Inc.
565774Sbostic * All or some portions of this file are derived from material licensed
665774Sbostic * to the University of California by American Telephone and Telegraph
765774Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with
865774Sbostic * the permission of UNIX System Laboratories, Inc.
923399Smckusick *
1044537Sbostic * %sccs.include.redist.c%
1137736Smckusick *
12*67406Smckusick * @(#)ufs_inode.c 8.6 (Berkeley) 06/16/94
1323399Smckusick */
1424Sbill
1551509Sbostic #include <sys/param.h>
1651509Sbostic #include <sys/systm.h>
1751509Sbostic #include <sys/proc.h>
1851509Sbostic #include <sys/vnode.h>
1951509Sbostic #include <sys/mount.h>
2051509Sbostic #include <sys/kernel.h>
2151987Smckusick #include <sys/malloc.h>
2224Sbill
2351509Sbostic #include <ufs/ufs/quota.h>
2451509Sbostic #include <ufs/ufs/inode.h>
2551509Sbostic #include <ufs/ufs/ufsmount.h>
2651509Sbostic #include <ufs/ufs/ufs_extern.h>
2747571Skarels
2851509Sbostic u_long nextgennumber; /* Next generation number to assign. */
2951547Smckusick int prtactive = 0; /* 1 => print out reclaim of active vnodes */
3024Sbill
3151509Sbostic int
ufs_init()3239440Smckusick ufs_init()
3324Sbill {
3451509Sbostic static int first = 1;
3524Sbill
3651509Sbostic if (!first)
3751509Sbostic return (0);
3851509Sbostic first = 0;
3951509Sbostic
4051509Sbostic #ifdef DIAGNOSTIC
4151987Smckusick if ((sizeof(struct inode) - 1) & sizeof(struct inode))
4251987Smckusick printf("ufs_init: bad size %d\n", sizeof(struct inode));
4351509Sbostic #endif
4451509Sbostic ufs_ihashinit();
4567393Smkm #ifdef QUOTA
4641313Smckusick dqinit();
4767393Smkm #endif
4837736Smckusick return (0);
4937736Smckusick }
507334Skre
5137736Smckusick /*
5264598Sbostic * Last reference to an inode. If necessary, write or delete it.
5356746Smckusick */
5456746Smckusick int
ufs_inactive(ap)5556746Smckusick ufs_inactive(ap)
5656746Smckusick struct vop_inactive_args /* {
5756746Smckusick struct vnode *a_vp;
5856746Smckusick } */ *ap;
5956746Smckusick {
6056746Smckusick register struct vnode *vp = ap->a_vp;
6156746Smckusick register struct inode *ip = VTOI(vp);
6256746Smckusick struct timeval tv;
6356746Smckusick int mode, error;
6456746Smckusick extern int prtactive;
6556746Smckusick
6656746Smckusick if (prtactive && vp->v_usecount != 0)
6756746Smckusick vprint("ffs_inactive: pushing active", vp);
6856746Smckusick
6956746Smckusick /* Get rid of inodes related to stale file handles. */
7056746Smckusick if (ip->i_mode == 0) {
7156746Smckusick if ((vp->v_flag & VXLOCK) == 0)
7256746Smckusick vgone(vp);
7356746Smckusick return (0);
7456746Smckusick }
7556746Smckusick
7656746Smckusick error = 0;
7756746Smckusick #ifdef DIAGNOSTIC
7856746Smckusick if (VOP_ISLOCKED(vp))
7956746Smckusick panic("ffs_inactive: locked inode");
8057052Smckusick if (curproc)
8157052Smckusick ip->i_lockholder = curproc->p_pid;
8257052Smckusick else
8357052Smckusick ip->i_lockholder = -1;
8456746Smckusick #endif
8564598Sbostic ip->i_flag |= IN_LOCKED;
8656746Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
8756746Smckusick #ifdef QUOTA
8856746Smckusick if (!getinoquota(ip))
8956746Smckusick (void)chkiq(ip, -1, NOCRED, 0);
9056746Smckusick #endif
9156746Smckusick error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL);
9264598Sbostic ip->i_rdev = 0;
9356746Smckusick mode = ip->i_mode;
9456746Smckusick ip->i_mode = 0;
9564598Sbostic ip->i_flag |= IN_CHANGE | IN_UPDATE;
9656746Smckusick VOP_VFREE(vp, ip->i_number, mode);
9756746Smckusick }
9864598Sbostic if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) {
9956746Smckusick tv = time;
10056746Smckusick VOP_UPDATE(vp, &tv, &tv, 0);
10156746Smckusick }
10256746Smckusick VOP_UNLOCK(vp);
10356746Smckusick /*
10456746Smckusick * If we are done with the inode, reclaim it
10556746Smckusick * so that it can be reused immediately.
10656746Smckusick */
10756746Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0)
10856746Smckusick vgone(vp);
10956746Smckusick return (error);
11056746Smckusick }
11156746Smckusick
11256746Smckusick /*
11339392Smckusick * Reclaim an inode so that it can be used for other purposes.
11424Sbill */
11551509Sbostic int
ufs_reclaim(vp)116*67406Smckusick ufs_reclaim(vp)
117*67406Smckusick register struct vnode *vp;
11839392Smckusick {
11951509Sbostic register struct inode *ip;
120*67406Smckusick int i;
121*67406Smckusick extern int prtactive;
12239392Smckusick
12353864Sheideman if (prtactive && vp->v_usecount != 0)
12453864Sheideman vprint("ufs_reclaim: pushing active", vp);
12539392Smckusick /*
12639392Smckusick * Remove the inode from its hash chain.
12739392Smckusick */
12853864Sheideman ip = VTOI(vp);
12955413Smckusick ufs_ihashrem(ip);
13039392Smckusick /*
13139392Smckusick * Purge old data structures associated with the inode.
13239392Smckusick */
13353864Sheideman cache_purge(vp);
13439392Smckusick if (ip->i_devvp) {
13539392Smckusick vrele(ip->i_devvp);
13639392Smckusick ip->i_devvp = 0;
13739392Smckusick }
13839392Smckusick #ifdef QUOTA
13941313Smckusick for (i = 0; i < MAXQUOTAS; i++) {
14041313Smckusick if (ip->i_dquot[i] != NODQUOT) {
14153864Sheideman dqrele(vp, ip->i_dquot[i]);
14241313Smckusick ip->i_dquot[i] = NODQUOT;
14341313Smckusick }
14441313Smckusick }
14539392Smckusick #endif
14639392Smckusick return (0);
14739392Smckusick }
148