static int /* ERRNO if error, 0 if successful. */ sam_inval_dev_call( void *arg, /* Pointer to arguments. */ int size, cred_t *credp) { sam_fsinval_arg_t args; dev_t rdev; if (secpolicy_fs_config(credp, NULL)) { return (EINVAL); } if (size != sizeof (args) || copyin(arg, (caddr_t)&args, sizeof (args))) { return (EFAULT); } rdev = expldev(args.rdev); bflush(rdev); binval(rdev); return (0); }
/* * The disk has been changed! */ void pc_diskchanged(struct pcfs *fsp) { struct pcnode *pcp, *npcp = NULL; struct pchead *hp; struct vnode *vp; extern vfs_t EIO_vfs; struct vfs *vfsp; /* * Eliminate all pcnodes (dir & file) associated with this fs. * If the node is internal, ie, no references outside of * pcfs itself, then release the associated vnode structure. * Invalidate the in core FAT. * Invalidate cached data blocks and blocks waiting for I/O. */ PC_DPRINTF1(1, "pc_diskchanged fsp=0x%p\n", (void *)fsp); vfsp = PCFSTOVFS(fsp); for (hp = pcdhead; hp < &pcdhead[NPCHASH]; hp++) { for (pcp = hp->pch_forw; pcp != (struct pcnode *)hp; pcp = npcp) { npcp = pcp -> pc_forw; vp = PCTOV(pcp); if ((vp->v_vfsp == vfsp) && !(pcp->pc_flags & PC_RELEHOLD)) { mutex_enter(&(vp)->v_lock); if (vp->v_count > 0) { mutex_exit(&(vp)->v_lock); continue; } mutex_exit(&(vp)->v_lock); VN_HOLD(vp); remque(pcp); vp->v_data = NULL; vp->v_vfsp = &EIO_vfs; vp->v_type = VBAD; VN_RELE(vp); if (!(pcp->pc_flags & PC_EXTERNAL)) { (void) pvn_vplist_dirty(vp, (u_offset_t)0, pcfs_putapage, B_INVAL | B_TRUNC, (struct cred *)NULL); vn_free(vp); } kmem_free(pcp, sizeof (struct pcnode)); fsp->pcfs_nrefs --; VFS_RELE(vfsp); } } } for (hp = pcfhead; fsp->pcfs_frefs && hp < &pcfhead[NPCHASH]; hp++) { for (pcp = hp->pch_forw; fsp->pcfs_frefs && pcp != (struct pcnode *)hp; pcp = npcp) { npcp = pcp -> pc_forw; vp = PCTOV(pcp); if ((vp->v_vfsp == vfsp) && !(pcp->pc_flags & PC_RELEHOLD)) { mutex_enter(&(vp)->v_lock); if (vp->v_count > 0) { mutex_exit(&(vp)->v_lock); continue; } mutex_exit(&(vp)->v_lock); VN_HOLD(vp); remque(pcp); vp->v_data = NULL; vp->v_vfsp = &EIO_vfs; vp->v_type = VBAD; VN_RELE(vp); if (!(pcp->pc_flags & PC_EXTERNAL)) { (void) pvn_vplist_dirty(vp, (u_offset_t)0, pcfs_putapage, B_INVAL | B_TRUNC, (struct cred *)NULL); vn_free(vp); } kmem_free(pcp, sizeof (struct pcnode)); fsp->pcfs_frefs--; fsp->pcfs_nrefs--; VFS_RELE(vfsp); } } } #ifdef undef if (fsp->pcfs_frefs) { rw_exit(&pcnodes_lock); panic("pc_diskchanged: frefs"); } if (fsp->pcfs_nrefs) { rw_exit(&pcnodes_lock); panic("pc_diskchanged: nrefs"); } #endif if (!(vfsp->vfs_flag & VFS_UNMOUNTED) && fsp->pcfs_fatp != (uchar_t *)0) { pc_invalfat(fsp); } else { binval(fsp->pcfs_xdev); } }