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.52 (Berkeley) 12/09/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 if (curproc) 75 ip->i_lockholder = curproc->p_pid; 76 else 77 ip->i_lockholder = -1; 78 #endif 79 ip->i_flag |= ILOCKED; 80 if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 81 #ifdef QUOTA 82 if (!getinoquota(ip)) 83 (void)chkiq(ip, -1, NOCRED, 0); 84 #endif 85 error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); 86 mode = ip->i_mode; 87 ip->i_mode = 0; 88 ip->i_rdev = 0; 89 ip->i_flag |= IUPD|ICHG; 90 VOP_VFREE(vp, ip->i_number, mode); 91 } 92 if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) { 93 tv = time; 94 VOP_UPDATE(vp, &tv, &tv, 0); 95 } 96 VOP_UNLOCK(vp); 97 /* 98 * If we are done with the inode, reclaim it 99 * so that it can be reused immediately. 100 */ 101 if (vp->v_usecount == 0 && ip->i_mode == 0) 102 vgone(vp); 103 return (error); 104 } 105 106 /* 107 * Reclaim an inode so that it can be used for other purposes. 108 */ 109 int 110 ufs_reclaim(ap) 111 struct vop_reclaim_args /* { 112 struct vnode *a_vp; 113 } */ *ap; 114 { 115 register struct vnode *vp = ap->a_vp; 116 register struct inode *ip; 117 int i, type; 118 119 if (prtactive && vp->v_usecount != 0) 120 vprint("ufs_reclaim: pushing active", vp); 121 /* 122 * Remove the inode from its hash chain. 123 */ 124 ip = VTOI(vp); 125 ufs_ihashrem(ip); 126 /* 127 * Purge old data structures associated with the inode. 128 */ 129 cache_purge(vp); 130 if (ip->i_devvp) { 131 vrele(ip->i_devvp); 132 ip->i_devvp = 0; 133 } 134 #ifdef QUOTA 135 for (i = 0; i < MAXQUOTAS; i++) { 136 if (ip->i_dquot[i] != NODQUOT) { 137 dqrele(vp, ip->i_dquot[i]); 138 ip->i_dquot[i] = NODQUOT; 139 } 140 } 141 #endif 142 switch (vp->v_mount->mnt_stat.f_type) { 143 case MOUNT_UFS: 144 type = M_FFSNODE; 145 break; 146 case MOUNT_MFS: 147 type = M_MFSNODE; 148 break; 149 case MOUNT_LFS: 150 type = M_LFSNODE; 151 break; 152 default: 153 panic("ufs_reclaim: not ufs file"); 154 } 155 FREE(vp->v_data, type); 156 vp->v_data = NULL; 157 return (0); 158 } 159