Exemple #1
0
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);
	}
}