123399Smckusick /* 251509Sbostic * Copyright (c) 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423399Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*56746Smckusick * @(#)ufs_inode.c 7.50 (Berkeley) 11/13/92 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 /* 4539392Smckusick * Unlock and decrement the reference count of an inode structure. 4624Sbill */ 4751509Sbostic void 4851509Sbostic ufs_iput(ip) 494818Swnj register struct inode *ip; 5024Sbill { 517118Smckusick 528452Sroot if ((ip->i_flag & ILOCKED) == 0) 537118Smckusick panic("iput"); 5416665Smckusick IUNLOCK(ip); 5537736Smckusick vrele(ITOV(ip)); 567118Smckusick } 577118Smckusick 5839392Smckusick /* 59*56746Smckusick * Last reference to an inode, write the inode out and if necessary, 60*56746Smckusick * truncate and deallocate the file. 61*56746Smckusick */ 62*56746Smckusick int 63*56746Smckusick ufs_inactive(ap) 64*56746Smckusick struct vop_inactive_args /* { 65*56746Smckusick struct vnode *a_vp; 66*56746Smckusick } */ *ap; 67*56746Smckusick { 68*56746Smckusick register struct vnode *vp = ap->a_vp; 69*56746Smckusick register struct inode *ip = VTOI(vp); 70*56746Smckusick struct timeval tv; 71*56746Smckusick int mode, error; 72*56746Smckusick extern int prtactive; 73*56746Smckusick 74*56746Smckusick if (prtactive && vp->v_usecount != 0) 75*56746Smckusick vprint("ffs_inactive: pushing active", vp); 76*56746Smckusick 77*56746Smckusick /* Get rid of inodes related to stale file handles. */ 78*56746Smckusick if (ip->i_mode == 0) { 79*56746Smckusick if ((vp->v_flag & VXLOCK) == 0) 80*56746Smckusick vgone(vp); 81*56746Smckusick return (0); 82*56746Smckusick } 83*56746Smckusick 84*56746Smckusick error = 0; 85*56746Smckusick #ifdef DIAGNOSTIC 86*56746Smckusick if (VOP_ISLOCKED(vp)) 87*56746Smckusick panic("ffs_inactive: locked inode"); 88*56746Smckusick #endif 89*56746Smckusick ip->i_flag |= ILOCKED; 90*56746Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 91*56746Smckusick #ifdef QUOTA 92*56746Smckusick if (!getinoquota(ip)) 93*56746Smckusick (void)chkiq(ip, -1, NOCRED, 0); 94*56746Smckusick #endif 95*56746Smckusick error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); 96*56746Smckusick mode = ip->i_mode; 97*56746Smckusick ip->i_mode = 0; 98*56746Smckusick ip->i_rdev = 0; 99*56746Smckusick ip->i_flag |= IUPD|ICHG; 100*56746Smckusick VOP_VFREE(vp, ip->i_number, mode); 101*56746Smckusick } 102*56746Smckusick if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) { 103*56746Smckusick tv = time; 104*56746Smckusick VOP_UPDATE(vp, &tv, &tv, 0); 105*56746Smckusick } 106*56746Smckusick VOP_UNLOCK(vp); 107*56746Smckusick /* 108*56746Smckusick * If we are done with the inode, reclaim it 109*56746Smckusick * so that it can be reused immediately. 110*56746Smckusick */ 111*56746Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 112*56746Smckusick vgone(vp); 113*56746Smckusick return (error); 114*56746Smckusick } 115*56746Smckusick 116*56746Smckusick /* 11739392Smckusick * Reclaim an inode so that it can be used for other purposes. 11824Sbill */ 11951509Sbostic int 12054648Smckusick ufs_reclaim(ap) 12154648Smckusick struct vop_reclaim_args /* { 12254648Smckusick struct vnode *a_vp; 12354648Smckusick } */ *ap; 12439392Smckusick { 12553864Sheideman register struct vnode *vp = ap->a_vp; 12651509Sbostic register struct inode *ip; 12751987Smckusick int i, type; 12839392Smckusick 12953864Sheideman if (prtactive && vp->v_usecount != 0) 13053864Sheideman vprint("ufs_reclaim: pushing active", vp); 13139392Smckusick /* 13239392Smckusick * Remove the inode from its hash chain. 13339392Smckusick */ 13453864Sheideman ip = VTOI(vp); 13555413Smckusick ufs_ihashrem(ip); 13639392Smckusick /* 13739392Smckusick * Purge old data structures associated with the inode. 13839392Smckusick */ 13953864Sheideman cache_purge(vp); 14039392Smckusick if (ip->i_devvp) { 14139392Smckusick vrele(ip->i_devvp); 14239392Smckusick ip->i_devvp = 0; 14339392Smckusick } 14439392Smckusick #ifdef QUOTA 14541313Smckusick for (i = 0; i < MAXQUOTAS; i++) { 14641313Smckusick if (ip->i_dquot[i] != NODQUOT) { 14753864Sheideman dqrele(vp, ip->i_dquot[i]); 14841313Smckusick ip->i_dquot[i] = NODQUOT; 14941313Smckusick } 15041313Smckusick } 15139392Smckusick #endif 15253864Sheideman switch (vp->v_mount->mnt_stat.f_type) { 15351987Smckusick case MOUNT_UFS: 15451987Smckusick type = M_FFSNODE; 15551987Smckusick break; 15651987Smckusick case MOUNT_MFS: 15751987Smckusick type = M_MFSNODE; 15851987Smckusick break; 15951987Smckusick case MOUNT_LFS: 16051987Smckusick type = M_LFSNODE; 16151987Smckusick break; 16251987Smckusick default: 16351987Smckusick panic("ufs_reclaim: not ufs file"); 16451987Smckusick } 16553864Sheideman FREE(vp->v_data, type); 16653864Sheideman vp->v_data = NULL; 16739392Smckusick return (0); 16839392Smckusick } 16939392Smckusick 17039392Smckusick /* 1714818Swnj * Lock an inode. If its already locked, set the WANT bit and sleep. 1723617Sroot */ 17351509Sbostic void 17451509Sbostic ufs_ilock(ip) 1754818Swnj register struct inode *ip; 1763617Sroot { 17752037Smckusick struct proc *p = curproc; /* XXX */ 1783617Sroot 17937736Smckusick while (ip->i_flag & ILOCKED) { 18037736Smckusick ip->i_flag |= IWANT; 18152037Smckusick #ifdef DIAGNOSTIC 18252037Smckusick if (p) { 18352037Smckusick if (p->p_pid == ip->i_lockholder) 18452037Smckusick panic("locking against myself"); 18552037Smckusick ip->i_lockwaiter = p->p_pid; 18652037Smckusick } 18752037Smckusick #endif 18837736Smckusick (void) sleep((caddr_t)ip, PINOD); 18937736Smckusick } 19052037Smckusick #ifdef DIAGNOSTIC 19151987Smckusick ip->i_lockwaiter = 0; 19252037Smckusick if (p) 19352037Smckusick ip->i_lockholder = p->p_pid; 19452037Smckusick #endif 19537736Smckusick ip->i_flag |= ILOCKED; 1963617Sroot } 1973617Sroot 1983617Sroot /* 1994818Swnj * Unlock an inode. If WANT bit is on, wakeup. 2003617Sroot */ 20151509Sbostic void 20251509Sbostic ufs_iunlock(ip) 2034818Swnj register struct inode *ip; 2043617Sroot { 2053617Sroot 20637736Smckusick if ((ip->i_flag & ILOCKED) == 0) 20751509Sbostic vprint("ufs_iunlock: unlocked inode", ITOV(ip)); 20852037Smckusick #ifdef DIAGNOSTIC 20951987Smckusick ip->i_lockholder = 0; 21052037Smckusick #endif 21137736Smckusick ip->i_flag &= ~ILOCKED; 21237736Smckusick if (ip->i_flag&IWANT) { 21337736Smckusick ip->i_flag &= ~IWANT; 21437736Smckusick wakeup((caddr_t)ip); 21537736Smckusick } 2163617Sroot } 217