123399Smckusick /* 2*51509Sbostic * Copyright (c) 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423399Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*51509Sbostic * @(#)ufs_inode.c 7.41 (Berkeley) 11/01/91 823399Smckusick */ 924Sbill 10*51509Sbostic #include <sys/param.h> 11*51509Sbostic #include <sys/systm.h> 12*51509Sbostic #include <sys/proc.h> 13*51509Sbostic #include <sys/vnode.h> 14*51509Sbostic #include <sys/mount.h> 15*51509Sbostic #include <sys/kernel.h> 1624Sbill 17*51509Sbostic #include <ufs/ufs/quota.h> 18*51509Sbostic #include <ufs/ufs/inode.h> 19*51509Sbostic #include <ufs/ufs/ufsmount.h> 20*51509Sbostic #include <ufs/ufs/ufs_extern.h> 2147571Skarels 22*51509Sbostic u_long nextgennumber; /* Next generation number to assign. */ 23*51509Sbostic int prtactive; /* 1 => print out reclaim of active vnodes */ 2424Sbill 25*51509Sbostic int 2639440Smckusick ufs_init() 2724Sbill { 28*51509Sbostic static int first = 1; 2924Sbill 30*51509Sbostic if (!first) 31*51509Sbostic return (0); 32*51509Sbostic first = 0; 33*51509Sbostic 34*51509Sbostic #ifdef DIAGNOSTIC 3539392Smckusick if (VN_MAXPRIVATE < sizeof(struct inode)) 36*51509Sbostic panic("ufs_init: inode too small"); 37*51509Sbostic #endif 38*51509Sbostic ufs_ihashinit(); 3941313Smckusick dqinit(); 4037736Smckusick return (0); 4137736Smckusick } 427334Skre 4337736Smckusick /* 4439392Smckusick * Unlock and decrement the reference count of an inode structure. 4524Sbill */ 46*51509Sbostic void 47*51509Sbostic ufs_iput(ip) 484818Swnj register struct inode *ip; 4924Sbill { 507118Smckusick 518452Sroot if ((ip->i_flag & ILOCKED) == 0) 527118Smckusick panic("iput"); 5316665Smckusick IUNLOCK(ip); 5437736Smckusick vrele(ITOV(ip)); 557118Smckusick } 567118Smckusick 5739392Smckusick /* 5839392Smckusick * Last reference to an inode, write the inode out and if necessary, 5939392Smckusick * truncate and deallocate the file. 6039392Smckusick */ 61*51509Sbostic int 6248037Smckusick ufs_inactive(vp, p) 6337736Smckusick struct vnode *vp; 6448037Smckusick struct proc *p; 657118Smckusick { 66*51509Sbostic register struct inode *ip; 67*51509Sbostic struct ufsmount *ump; 68*51509Sbostic int mode, error; 6924Sbill 7039816Smckusick if (prtactive && vp->v_usecount != 0) 7139676Smckusick vprint("ufs_inactive: pushing active", vp); 72*51509Sbostic 73*51509Sbostic /* Get rid of inodes related to stale file handles. */ 74*51509Sbostic ip = VTOI(vp); 7539440Smckusick if (ip->i_mode == 0) { 7639676Smckusick if ((vp->v_flag & VXLOCK) == 0) 7739676Smckusick vgone(vp); 7839440Smckusick return (0); 7939440Smckusick } 80*51509Sbostic 81*51509Sbostic error = 0; 82*51509Sbostic ump = VFSTOUFS(vp->v_mount); 8338226Smckusick ILOCK(ip); 8441397Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 8541313Smckusick #ifdef QUOTA 8641313Smckusick if (!getinoquota(ip)) 87*51509Sbostic (void)chkiq(ip, -1, NOCRED, 0); 8841313Smckusick #endif 89*51509Sbostic error = (ump->um_itrunc)(ip, (u_long)0, 0); 9037736Smckusick mode = ip->i_mode; 9137736Smckusick ip->i_mode = 0; 9244893Strent ip->i_rdev = 0; 9337736Smckusick ip->i_flag |= IUPD|ICHG; 94*51509Sbostic (ump->um_ifree)(ip, ip->i_number, mode); 9537736Smckusick } 96*51509Sbostic if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) 97*51509Sbostic (ump->um_iupdat)(ip, &time, &time, 0); 9840033Smckusick IUNLOCK(ip); 9940033Smckusick ip->i_flag = 0; 10037736Smckusick /* 10139392Smckusick * If we are done with the inode, reclaim it 10239392Smckusick * so that it can be reused immediately. 10337736Smckusick */ 10441313Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 10540033Smckusick vgone(vp); 10637736Smckusick return (error); 10724Sbill } 10824Sbill 10924Sbill /* 11039392Smckusick * Reclaim an inode so that it can be used for other purposes. 11124Sbill */ 112*51509Sbostic int 11339392Smckusick ufs_reclaim(vp) 11439392Smckusick register struct vnode *vp; 11539392Smckusick { 116*51509Sbostic register struct inode *ip; 11741313Smckusick int i; 11839392Smckusick 11939816Smckusick if (prtactive && vp->v_usecount != 0) 12039676Smckusick vprint("ufs_reclaim: pushing active", vp); 12139392Smckusick /* 12239392Smckusick * Remove the inode from its hash chain. 12339392Smckusick */ 124*51509Sbostic ip = VTOI(vp); 12539392Smckusick remque(ip); 12639392Smckusick ip->i_forw = ip; 12739392Smckusick ip->i_back = ip; 12839392Smckusick /* 12939392Smckusick * Purge old data structures associated with the inode. 13039392Smckusick */ 13139392Smckusick cache_purge(vp); 13239392Smckusick if (ip->i_devvp) { 13339392Smckusick vrele(ip->i_devvp); 13439392Smckusick ip->i_devvp = 0; 13539392Smckusick } 13639392Smckusick #ifdef QUOTA 13741313Smckusick for (i = 0; i < MAXQUOTAS; i++) { 13841313Smckusick if (ip->i_dquot[i] != NODQUOT) { 13941313Smckusick dqrele(vp, ip->i_dquot[i]); 14041313Smckusick ip->i_dquot[i] = NODQUOT; 14141313Smckusick } 14241313Smckusick } 14339392Smckusick #endif 14439392Smckusick ip->i_flag = 0; 14539392Smckusick return (0); 14639392Smckusick } 14739392Smckusick 14839392Smckusick /* 1494818Swnj * Lock an inode. If its already locked, set the WANT bit and sleep. 1503617Sroot */ 151*51509Sbostic void 152*51509Sbostic ufs_ilock(ip) 1534818Swnj register struct inode *ip; 1543617Sroot { 1553617Sroot 15637736Smckusick while (ip->i_flag & ILOCKED) { 15737736Smckusick ip->i_flag |= IWANT; 15847571Skarels if (ip->i_spare0 == curproc->p_pid) 15939795Smckusick panic("locking against myself"); 16047571Skarels ip->i_spare1 = curproc->p_pid; 16137736Smckusick (void) sleep((caddr_t)ip, PINOD); 16237736Smckusick } 16339795Smckusick ip->i_spare1 = 0; 16447571Skarels ip->i_spare0 = curproc->p_pid; 16537736Smckusick ip->i_flag |= ILOCKED; 1663617Sroot } 1673617Sroot 1683617Sroot /* 1694818Swnj * Unlock an inode. If WANT bit is on, wakeup. 1703617Sroot */ 171*51509Sbostic void 172*51509Sbostic ufs_iunlock(ip) 1734818Swnj register struct inode *ip; 1743617Sroot { 1753617Sroot 17637736Smckusick if ((ip->i_flag & ILOCKED) == 0) 177*51509Sbostic vprint("ufs_iunlock: unlocked inode", ITOV(ip)); 17839795Smckusick ip->i_spare0 = 0; 17937736Smckusick ip->i_flag &= ~ILOCKED; 18037736Smckusick if (ip->i_flag&IWANT) { 18137736Smckusick ip->i_flag &= ~IWANT; 18237736Smckusick wakeup((caddr_t)ip); 18337736Smckusick } 1843617Sroot } 185