/*ARGSUSED*/ static void socket_vop_inactive(struct vnode *vp, struct cred *cr, caller_context_t *ct) { struct sonode *so = VTOSO(vp); ASSERT(vp->v_type == VSOCK); mutex_enter(&vp->v_lock); /* * If no one has reclaimed the vnode, remove from the * cache now. */ if (vp->v_count < 1) cmn_err(CE_PANIC, "socket_inactive: Bad v_count"); VN_RELE_LOCKED(vp); if (vp->v_count != 0) { mutex_exit(&vp->v_lock); return; } mutex_exit(&vp->v_lock); ASSERT(!vn_has_cached_data(vp)); /* socket specfic clean-up */ socket_destroy_internal(so, cr); }
/*ARGSUSED*/ int spec_sync(struct vfs *vfsp, short flag, struct cred *cr) { struct snode *sync_list; register struct snode **spp, *sp, *spnext; register struct vnode *vp; if (mutex_tryenter(&spec_syncbusy) == 0) return (0); if (flag & SYNC_ATTR) { mutex_exit(&spec_syncbusy); return (0); } mutex_enter(&stable_lock); sync_list = NULL; /* * Find all the snodes that are dirty and add them to the sync_list */ for (spp = stable; spp < &stable[STABLESIZE]; spp++) { for (sp = *spp; sp != NULL; sp = sp->s_next) { vp = STOV(sp); /* * Don't bother sync'ing a vp if it's * part of a virtual swap device. */ if (IS_SWAPVP(vp)) continue; if (vp->v_type == VBLK && vn_has_cached_data(vp)) { /* * Prevent vp from going away before we * we get a chance to do a VOP_PUTPAGE * via sync_list processing */ VN_HOLD(vp); sp->s_list = sync_list; sync_list = sp; } } } mutex_exit(&stable_lock); /* * Now write out all the snodes we marked asynchronously. */ for (sp = sync_list; sp != NULL; sp = spnext) { spnext = sp->s_list; vp = STOV(sp); (void) VOP_PUTPAGE(vp, (offset_t)0, (uint_t)0, B_ASYNC, cr); VN_RELE(vp); /* Release our hold on vnode */ } mutex_exit(&spec_syncbusy); return (0); }
int syncpcp(struct pcnode *pcp, int flags) { int err; if (!vn_has_cached_data(PCTOV(pcp))) err = 0; else err = VOP_PUTPAGE(PCTOV(pcp), 0, 0, flags, kcred, NULL); return (err); }
void pc_rele(struct pcnode *pcp) { struct pcfs *fsp; struct vnode *vp; int err; vp = PCTOV(pcp); PC_DPRINTF1(8, "pc_rele vp=0x%p\n", (void *)vp); fsp = VFSTOPCFS(vp->v_vfsp); ASSERT(fsp->pcfs_flags & PCFS_LOCKED); rw_enter(&pcnodes_lock, RW_WRITER); pcp->pc_flags |= PC_RELEHOLD; retry: if (vp->v_type != VDIR && (pcp->pc_flags & PC_INVAL) == 0) { /* * If the file was removed while active it may be safely * truncated now. */ if (pcp->pc_entry.pcd_filename[0] == PCD_ERASED) { (void) pc_truncate(pcp, 0); } else if (pcp->pc_flags & PC_CHG) { (void) pc_nodeupdate(pcp); } err = syncpcp(pcp, B_INVAL); if (err) { (void) syncpcp(pcp, B_INVAL | B_FORCE); } } if (vn_has_cached_data(vp)) { /* * pvn_vplist_dirty will abort all old pages */ (void) pvn_vplist_dirty(vp, (u_offset_t)0, pcfs_putapage, B_INVAL, (struct cred *)NULL); } (void) pc_syncfat(fsp); mutex_enter(&vp->v_lock); if (vn_has_cached_data(vp)) { mutex_exit(&vp->v_lock); goto retry; } ASSERT(!vn_has_cached_data(vp)); vp->v_count--; /* release our hold from vn_rele */ if (vp->v_count > 0) { /* Is this check still needed? */ PC_DPRINTF1(3, "pc_rele: pcp=0x%p HELD AGAIN!\n", (void *)pcp); mutex_exit(&vp->v_lock); pcp->pc_flags &= ~PC_RELEHOLD; rw_exit(&pcnodes_lock); return; } remque(pcp); rw_exit(&pcnodes_lock); /* * XXX - old code had a check for !(pcp->pc_flags & PC_INVAL) * here. Seems superfluous/incorrect, but then earlier on PC_INVAL * was never set anywhere in PCFS. Now it is, and we _have_ to drop * the file reference here. Else, we'd screw up umount/modunload. */ if ((vp->v_type == VREG)) { fsp->pcfs_frefs--; } fsp->pcfs_nrefs--; VFS_RELE(vp->v_vfsp); if (fsp->pcfs_nrefs < 0) { panic("pc_rele: nrefs count"); } if (fsp->pcfs_frefs < 0) { panic("pc_rele: frefs count"); } mutex_exit(&vp->v_lock); vn_invalid(vp); vn_free(vp); kmem_free(pcp, sizeof (struct pcnode)); }
/************************************************************************ * iumfs_free_node() * * 指定された vnode および iumnode を解放する * * 1. iumnode に関連づいたリソースを解放 * 2. iumnode 構造体を解放 * 3. vnode 構造体を解放 * * これが呼ばれるのは、iumfs_inactive() もしくは iumfs_unmount() 経由の * iumfs_free_all_node() だけ。つまり、v_count が 1(未参照状態)である * 事が確かな場合だけ。 * * 引数: * * vp: 解放する vnode 構造体のポインタ * cr : システムコールを呼び出したユーザのクレデンシャル * * 戻り値: * 無し * ************************************************************************/ void iumfs_free_node(vnode_t *vp, struct cred *cr) { iumnode_t *inp; // ファイルシステム型依存のノード情報(iumnode構造体) vnode_t *rootvp; // ファイルシステムのルートディレクトリの vnode。 iumfs_t *iumfsp; // ファイルシステム型依存のプライベートデータ構造体 vfs_t *vfsp; // ファイルシステム構造体 int err; DEBUG_PRINT((CE_CONT, "iumfs_free_node is called\n")); iumfsp = VNODE2IUMFS(vp); vfsp = VNODE2VFS(vp); inp = VNODE2IUMNODE(vp); DEBUG_PRINT((CE_CONT, "iumfs_free_node: vnode=%p, vp->v_count=%d\n", vp, vp->v_count)); /* * 最初にノードリンクリストから iumnode をはずす。誰かが利用中(EBUSY)だったらリターン。 * 仮にノードリストに入っていなかったとしても、(ありえないはずだが) vnode のフリーは行う。 */ if((err = iumfs_remove_node_from_list(vfsp, vp)) != 0){ if (err == ENOENT) cmn_err(CE_CONT, "iumfs_free_node: can't find vnode in the list. Free it anyway.\n"); else return; } // debug 用 rootvp = VNODE2ROOT(vp); if (rootvp != NULL && VN_CMP(rootvp, vp) != 0) { DEBUG_PRINT((CE_CONT, "iumfs_free_node: rootvnode is being freed\n")); mutex_enter(&(iumfsp->iumfs_lock)); iumfsp->rootvnode = NULL; mutex_exit(&(iumfsp->iumfs_lock)); } /* * もし iumnode にデータ(ディレクトリエントリ等) * を含んでいたらそれらも解放する。 */ if (inp->data != NULL) { kmem_free(inp->data, inp->dlen); } /* * この vnode に関連した page を無効にする */ err = pvn_vplist_dirty(vp, 0, iumfs_putapage, B_INVAL, cr); DEBUG_PRINT((CE_CONT, "iumfs_free_node: pvn_vplist_dirty returned with (%d)\n", err)); if (vn_has_cached_data(vp)) { cmn_err(CE_WARN, "iumfs_free_node: vnode still have cached\n"); } // iumnode を解放 mutex_destroy(&(inp)->i_dlock); rw_destroy(&(inp)->i_listlock); kmem_free(inp, sizeof (iumnode_t)); // vnode を解放 #ifdef SOL10 vn_free(vp); #else mutex_destroy(&(vp)->v_lock); kmem_free(vp, sizeof (vnode_t)); #endif DEBUG_PRINT((CE_CONT, "iumfs_free_node: return\n")); return; }