123399Smckusick /* 263376Sbostic * Copyright (c) 1991, 1993 363376Sbostic * The Regents of the University of California. All rights reserved. 4*65774Sbostic * (c) UNIX System Laboratories, Inc. 5*65774Sbostic * All or some portions of this file are derived from material licensed 6*65774Sbostic * to the University of California by American Telephone and Telegraph 7*65774Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8*65774Sbostic * the permission of UNIX System Laboratories, Inc. 923399Smckusick * 1044537Sbostic * %sccs.include.redist.c% 1137736Smckusick * 12*65774Sbostic * @(#)ufs_inode.c 8.4 (Berkeley) 01/21/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 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(); 4541313Smckusick dqinit(); 4637736Smckusick return (0); 4737736Smckusick } 487334Skre 4937736Smckusick /* 5064598Sbostic * Last reference to an inode. If necessary, write or delete it. 5156746Smckusick */ 5256746Smckusick int 5356746Smckusick ufs_inactive(ap) 5456746Smckusick struct vop_inactive_args /* { 5556746Smckusick struct vnode *a_vp; 5656746Smckusick } */ *ap; 5756746Smckusick { 5856746Smckusick register struct vnode *vp = ap->a_vp; 5956746Smckusick register struct inode *ip = VTOI(vp); 6056746Smckusick struct timeval tv; 6156746Smckusick int mode, error; 6256746Smckusick extern int prtactive; 6356746Smckusick 6456746Smckusick if (prtactive && vp->v_usecount != 0) 6556746Smckusick vprint("ffs_inactive: pushing active", vp); 6656746Smckusick 6756746Smckusick /* Get rid of inodes related to stale file handles. */ 6856746Smckusick if (ip->i_mode == 0) { 6956746Smckusick if ((vp->v_flag & VXLOCK) == 0) 7056746Smckusick vgone(vp); 7156746Smckusick return (0); 7256746Smckusick } 7356746Smckusick 7456746Smckusick error = 0; 7556746Smckusick #ifdef DIAGNOSTIC 7656746Smckusick if (VOP_ISLOCKED(vp)) 7756746Smckusick panic("ffs_inactive: locked inode"); 7857052Smckusick if (curproc) 7957052Smckusick ip->i_lockholder = curproc->p_pid; 8057052Smckusick else 8157052Smckusick ip->i_lockholder = -1; 8256746Smckusick #endif 8364598Sbostic ip->i_flag |= IN_LOCKED; 8456746Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 8556746Smckusick #ifdef QUOTA 8656746Smckusick if (!getinoquota(ip)) 8756746Smckusick (void)chkiq(ip, -1, NOCRED, 0); 8856746Smckusick #endif 8956746Smckusick error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); 9064598Sbostic ip->i_rdev = 0; 9156746Smckusick mode = ip->i_mode; 9256746Smckusick ip->i_mode = 0; 9364598Sbostic ip->i_flag |= IN_CHANGE | IN_UPDATE; 9456746Smckusick VOP_VFREE(vp, ip->i_number, mode); 9556746Smckusick } 9664598Sbostic if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) { 9756746Smckusick tv = time; 9856746Smckusick VOP_UPDATE(vp, &tv, &tv, 0); 9956746Smckusick } 10056746Smckusick VOP_UNLOCK(vp); 10156746Smckusick /* 10256746Smckusick * If we are done with the inode, reclaim it 10356746Smckusick * so that it can be reused immediately. 10456746Smckusick */ 10556746Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 10656746Smckusick vgone(vp); 10756746Smckusick return (error); 10856746Smckusick } 10956746Smckusick 11056746Smckusick /* 11139392Smckusick * Reclaim an inode so that it can be used for other purposes. 11224Sbill */ 11351509Sbostic int 11454648Smckusick ufs_reclaim(ap) 11554648Smckusick struct vop_reclaim_args /* { 11654648Smckusick struct vnode *a_vp; 11754648Smckusick } */ *ap; 11839392Smckusick { 11953864Sheideman register struct vnode *vp = ap->a_vp; 12051509Sbostic register struct inode *ip; 12151987Smckusick int i, type; 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 14653864Sheideman switch (vp->v_mount->mnt_stat.f_type) { 14751987Smckusick case MOUNT_UFS: 14851987Smckusick type = M_FFSNODE; 14951987Smckusick break; 15051987Smckusick case MOUNT_MFS: 15151987Smckusick type = M_MFSNODE; 15251987Smckusick break; 15351987Smckusick case MOUNT_LFS: 15451987Smckusick type = M_LFSNODE; 15551987Smckusick break; 15651987Smckusick default: 15751987Smckusick panic("ufs_reclaim: not ufs file"); 15851987Smckusick } 15953864Sheideman FREE(vp->v_data, type); 16053864Sheideman vp->v_data = NULL; 16139392Smckusick return (0); 16239392Smckusick } 163