123399Smckusick /* 263376Sbostic * Copyright (c) 1991, 1993 363376Sbostic * The Regents of the University of California. All rights reserved. 423399Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*64598Sbostic * @(#)ufs_inode.c 8.3 (Berkeley) 09/23/93 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 /* 45*64598Sbostic * Last reference to an inode. If necessary, write or delete it. 4656746Smckusick */ 4756746Smckusick int 4856746Smckusick ufs_inactive(ap) 4956746Smckusick struct vop_inactive_args /* { 5056746Smckusick struct vnode *a_vp; 5156746Smckusick } */ *ap; 5256746Smckusick { 5356746Smckusick register struct vnode *vp = ap->a_vp; 5456746Smckusick register struct inode *ip = VTOI(vp); 5556746Smckusick struct timeval tv; 5656746Smckusick int mode, error; 5756746Smckusick extern int prtactive; 5856746Smckusick 5956746Smckusick if (prtactive && vp->v_usecount != 0) 6056746Smckusick vprint("ffs_inactive: pushing active", vp); 6156746Smckusick 6256746Smckusick /* Get rid of inodes related to stale file handles. */ 6356746Smckusick if (ip->i_mode == 0) { 6456746Smckusick if ((vp->v_flag & VXLOCK) == 0) 6556746Smckusick vgone(vp); 6656746Smckusick return (0); 6756746Smckusick } 6856746Smckusick 6956746Smckusick error = 0; 7056746Smckusick #ifdef DIAGNOSTIC 7156746Smckusick if (VOP_ISLOCKED(vp)) 7256746Smckusick panic("ffs_inactive: locked inode"); 7357052Smckusick if (curproc) 7457052Smckusick ip->i_lockholder = curproc->p_pid; 7557052Smckusick else 7657052Smckusick ip->i_lockholder = -1; 7756746Smckusick #endif 78*64598Sbostic ip->i_flag |= IN_LOCKED; 7956746Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 8056746Smckusick #ifdef QUOTA 8156746Smckusick if (!getinoquota(ip)) 8256746Smckusick (void)chkiq(ip, -1, NOCRED, 0); 8356746Smckusick #endif 8456746Smckusick error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); 85*64598Sbostic ip->i_rdev = 0; 8656746Smckusick mode = ip->i_mode; 8756746Smckusick ip->i_mode = 0; 88*64598Sbostic ip->i_flag |= IN_CHANGE | IN_UPDATE; 8956746Smckusick VOP_VFREE(vp, ip->i_number, mode); 9056746Smckusick } 91*64598Sbostic if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) { 9256746Smckusick tv = time; 9356746Smckusick VOP_UPDATE(vp, &tv, &tv, 0); 9456746Smckusick } 9556746Smckusick VOP_UNLOCK(vp); 9656746Smckusick /* 9756746Smckusick * If we are done with the inode, reclaim it 9856746Smckusick * so that it can be reused immediately. 9956746Smckusick */ 10056746Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 10156746Smckusick vgone(vp); 10256746Smckusick return (error); 10356746Smckusick } 10456746Smckusick 10556746Smckusick /* 10639392Smckusick * Reclaim an inode so that it can be used for other purposes. 10724Sbill */ 10851509Sbostic int 10954648Smckusick ufs_reclaim(ap) 11054648Smckusick struct vop_reclaim_args /* { 11154648Smckusick struct vnode *a_vp; 11254648Smckusick } */ *ap; 11339392Smckusick { 11453864Sheideman register struct vnode *vp = ap->a_vp; 11551509Sbostic register struct inode *ip; 11651987Smckusick int i, type; 11739392Smckusick 11853864Sheideman if (prtactive && vp->v_usecount != 0) 11953864Sheideman vprint("ufs_reclaim: pushing active", vp); 12039392Smckusick /* 12139392Smckusick * Remove the inode from its hash chain. 12239392Smckusick */ 12353864Sheideman ip = VTOI(vp); 12455413Smckusick ufs_ihashrem(ip); 12539392Smckusick /* 12639392Smckusick * Purge old data structures associated with the inode. 12739392Smckusick */ 12853864Sheideman cache_purge(vp); 12939392Smckusick if (ip->i_devvp) { 13039392Smckusick vrele(ip->i_devvp); 13139392Smckusick ip->i_devvp = 0; 13239392Smckusick } 13339392Smckusick #ifdef QUOTA 13441313Smckusick for (i = 0; i < MAXQUOTAS; i++) { 13541313Smckusick if (ip->i_dquot[i] != NODQUOT) { 13653864Sheideman dqrele(vp, ip->i_dquot[i]); 13741313Smckusick ip->i_dquot[i] = NODQUOT; 13841313Smckusick } 13941313Smckusick } 14039392Smckusick #endif 14153864Sheideman switch (vp->v_mount->mnt_stat.f_type) { 14251987Smckusick case MOUNT_UFS: 14351987Smckusick type = M_FFSNODE; 14451987Smckusick break; 14551987Smckusick case MOUNT_MFS: 14651987Smckusick type = M_MFSNODE; 14751987Smckusick break; 14851987Smckusick case MOUNT_LFS: 14951987Smckusick type = M_LFSNODE; 15051987Smckusick break; 15151987Smckusick default: 15251987Smckusick panic("ufs_reclaim: not ufs file"); 15351987Smckusick } 15453864Sheideman FREE(vp->v_data, type); 15553864Sheideman vp->v_data = NULL; 15639392Smckusick return (0); 15739392Smckusick } 158