/* * Reclaim an inode so that it can be used for other purposes. */ int ffs_reclaim(void *v) { struct vop_reclaim_args /* { struct vnode *a_vp; struct lwp *a_l; } */ *ap = v; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct mount *mp = vp->v_mount; struct ufsmount *ump = ip->i_ump; void *data; int error; fstrans_start(mp, FSTRANS_LAZY); /* * The inode must be freed and updated before being removed * from its hash chain. Other threads trying to gain a hold * on the inode will be stalled because it is locked (VI_XLOCK). */ error = UFS_WAPBL_BEGIN(mp); if (error) { fstrans_done(mp); return error; } if (ip->i_nlink <= 0 && ip->i_omode != 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) ffs_vfree(vp, ip->i_number, ip->i_omode); UFS_WAPBL_END(mp); if ((error = ufs_reclaim(vp)) != 0) { fstrans_done(mp); return (error); } if (ip->i_din.ffs1_din != NULL) { if (ump->um_fstype == UFS1) pool_cache_put(ffs_dinode1_cache, ip->i_din.ffs1_din); else pool_cache_put(ffs_dinode2_cache, ip->i_din.ffs2_din); } /* * To interlock with ffs_sync(). */ genfs_node_destroy(vp); mutex_enter(vp->v_interlock); data = vp->v_data; vp->v_data = NULL; mutex_exit(vp->v_interlock); /* * XXX MFS ends up here, too, to free an inode. Should we create * XXX a separate pool for MFS inodes? */ pool_cache_put(ffs_inode_cache, data); fstrans_done(mp); return (0); }
/* * Last reference to an inode. If necessary, write or delete it. * * ufs_inactive(struct vnode *a_vp) */ int ufs_inactive(struct vop_inactive_args *ap) { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); int mode, error = 0; if (prtactive && VREFCNT(vp) > 1) vprint("ufs_inactive: pushing active", vp); /* * Ignore inodes related to stale file handles. */ if (ip == NULL || ip->i_mode == 0) goto out; if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { #ifdef QUOTA if (!ufs_getinoquota(ip)) (void)ufs_chkiq(ip, -1, NOCRED, FORCE); #endif /* Must have a VM object to truncate */ error = ffs_truncate(vp, (off_t)0, 0, NOCRED); ip->i_rdev = 0; mode = ip->i_mode; ip->i_mode = 0; ip->i_flag |= IN_CHANGE | IN_UPDATE; ffs_vfree(vp, ip->i_number, mode); } if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) ffs_update(vp, 0); out: /* * If we are done with the inode, reclaim it * so that it can be reused immediately. */ if (ip == NULL || ip->i_mode == 0) vrecycle(vp); return (error); }