1 /* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ufs_inode.c 7.51 (Berkeley) 11/14/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/proc.h> 13 #include <sys/vnode.h> 14 #include <sys/mount.h> 15 #include <sys/kernel.h> 16 #include <sys/malloc.h> 17 18 #include <ufs/ufs/quota.h> 19 #include <ufs/ufs/inode.h> 20 #include <ufs/ufs/ufsmount.h> 21 #include <ufs/ufs/ufs_extern.h> 22 23 u_long nextgennumber; /* Next generation number to assign. */ 24 int prtactive = 0; /* 1 => print out reclaim of active vnodes */ 25 26 int 27 ufs_init() 28 { 29 static int first = 1; 30 31 if (!first) 32 return (0); 33 first = 0; 34 35 #ifdef DIAGNOSTIC 36 if ((sizeof(struct inode) - 1) & sizeof(struct inode)) 37 printf("ufs_init: bad size %d\n", sizeof(struct inode)); 38 #endif 39 ufs_ihashinit(); 40 dqinit(); 41 return (0); 42 } 43 44 /* 45 * Last reference to an inode, write the inode out and if necessary, 46 * truncate and deallocate the file. 47 */ 48 int 49 ufs_inactive(ap) 50 struct vop_inactive_args /* { 51 struct vnode *a_vp; 52 } */ *ap; 53 { 54 register struct vnode *vp = ap->a_vp; 55 register struct inode *ip = VTOI(vp); 56 struct timeval tv; 57 int mode, error; 58 extern int prtactive; 59 60 if (prtactive && vp->v_usecount != 0) 61 vprint("ffs_inactive: pushing active", vp); 62 63 /* Get rid of inodes related to stale file handles. */ 64 if (ip->i_mode == 0) { 65 if ((vp->v_flag & VXLOCK) == 0) 66 vgone(vp); 67 return (0); 68 } 69 70 error = 0; 71 #ifdef DIAGNOSTIC 72 if (VOP_ISLOCKED(vp)) 73 panic("ffs_inactive: locked inode"); 74 #endif 75 ip->i_flag |= ILOCKED; 76 if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 77 #ifdef QUOTA 78 if (!getinoquota(ip)) 79 (void)chkiq(ip, -1, NOCRED, 0); 80 #endif 81 error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); 82 mode = ip->i_mode; 83 ip->i_mode = 0; 84 ip->i_rdev = 0; 85 ip->i_flag |= IUPD|ICHG; 86 VOP_VFREE(vp, ip->i_number, mode); 87 } 88 if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) { 89 tv = time; 90 VOP_UPDATE(vp, &tv, &tv, 0); 91 } 92 VOP_UNLOCK(vp); 93 /* 94 * If we are done with the inode, reclaim it 95 * so that it can be reused immediately. 96 */ 97 if (vp->v_usecount == 0 && ip->i_mode == 0) 98 vgone(vp); 99 return (error); 100 } 101 102 /* 103 * Reclaim an inode so that it can be used for other purposes. 104 */ 105 int 106 ufs_reclaim(ap) 107 struct vop_reclaim_args /* { 108 struct vnode *a_vp; 109 } */ *ap; 110 { 111 register struct vnode *vp = ap->a_vp; 112 register struct inode *ip; 113 int i, type; 114 115 if (prtactive && vp->v_usecount != 0) 116 vprint("ufs_reclaim: pushing active", vp); 117 /* 118 * Remove the inode from its hash chain. 119 */ 120 ip = VTOI(vp); 121 ufs_ihashrem(ip); 122 /* 123 * Purge old data structures associated with the inode. 124 */ 125 cache_purge(vp); 126 if (ip->i_devvp) { 127 vrele(ip->i_devvp); 128 ip->i_devvp = 0; 129 } 130 #ifdef QUOTA 131 for (i = 0; i < MAXQUOTAS; i++) { 132 if (ip->i_dquot[i] != NODQUOT) { 133 dqrele(vp, ip->i_dquot[i]); 134 ip->i_dquot[i] = NODQUOT; 135 } 136 } 137 #endif 138 switch (vp->v_mount->mnt_stat.f_type) { 139 case MOUNT_UFS: 140 type = M_FFSNODE; 141 break; 142 case MOUNT_MFS: 143 type = M_MFSNODE; 144 break; 145 case MOUNT_LFS: 146 type = M_LFSNODE; 147 break; 148 default: 149 panic("ufs_reclaim: not ufs file"); 150 } 151 FREE(vp->v_data, type); 152 vp->v_data = NULL; 153 return (0); 154 } 155