예제 #1
0
/**
 *  cdev_open: - open a character special device node
 *  @inode: the character device inode
 *  @file: the user file pointer
 *
 *  cdev_open() is only used to open a stream from a character device node in an external
 *  filesystem.  This is never called for direct opens of a specfs device node (for direct opens see
 *  spec_dev_open() in strspecfs.c).  It is also not used for direct opens of fifos, pipes or
 *  sockets.  Those devices provide their own file operations to the main operating system.  The
 *  character device number from the inode is used to determine the shadow special file system
 *  (internal) inode and chain the open call.
 *
 *  This is the separation point where we convert the external device number to an internal device
 *  number.  The external device number is contained in inode->i_rdev.
 *
 *  @inode is the inode in the external filesystem.
 *
 *  @file->f_op is the external file operations (character device, fifo) and must be replaced with
 *	our file operations.
 *
 *  @file->f_dentry is the external filesystem dentry for the device node.
 *  @file->f_vfsmnt is the external filesystem vfsmnt for the device node.
 *  @file exists on the file->f_dentry->d_inode->i_sb->s_files list.
 *
 *  What we should be doing here is get a fresh new dentry.  Find our inode from the device number,
 *  add it to the dentry.  Set the dentry->d_sb to the specfs super block, set dentry->d_parent =
 *  dget(file->f_dentry->d_parent), but do not add the dentry to the child list on the parent
 *  directory, nor do we hash the dentry.  Next we do a dentry open on the on the dentry and a file
 *  pointer swap on return.
 *
 *  Instead of farting around with dentries and such, just lookup the inode in the specfs replace
 *  the file->f_ops and chain the open with the specfs inode passed to the new open procedure.  For
 *  FIFOs we pass the external filesystem inode instead.
 */
STATIC int
cdev_open(struct inode *inode, struct file *file)
{
	int err;
	struct cdevsw *cdev;
	struct devnode *cmin;
	major_t major;
	minor_t minor;
	modID_t modid;
	dev_t dev;
	int sflag;

#if defined HAVE_KFUNC_TO_KDEV_T
	minor = MINOR(kdev_t_to_nr(inode->i_rdev));
	major = MAJOR(kdev_t_to_nr(inode->i_rdev));
#else
	minor = MINOR(inode->i_rdev);
	major = MAJOR(inode->i_rdev);
#endif
	if (!(cdev = sdev_get(major))) {
		return (-ENXIO);
	}
	minor = cdev_minor(cdev, major, minor);
	major = cdev->d_major;
	modid = cdev->d_modid;
	dev = makedevice(modid, minor);
	sflag = DRVOPEN;
	if (cdev->d_flag & D_CLONE)
		sflag = CLONEOPEN;
	else if ((cmin = cmin_get(cdev, minor)) && cmin->n_flag & D_CLONE)
		sflag = CLONEOPEN;
	err = spec_open(file, cdev, dev, sflag);
	sdev_put(cdev);
	return (err);
}
예제 #2
0
/*
 *  clone_open: - open a clone device node
 *  @inode: the external filesystem inode
 *  @file: the external filesystem file pointer
 *
 *  clone_open() is only used to open a clone device from a character device node in an external
 *  filesystem.  This is never called for direct opens of a specfs device node (for direct opens see
 *  spec_dev_open() in strspecfs.c).  The character device number from the inode is used to
 *  determine the shadow special filesystem (internal) inode and chain the open call.
 *
 *  This is the separation point where we convert the external device number to an internal device
 *  number.  The external device number is contained in inode->i_rdev.
 */
STATIC int
clone_open(struct inode *inode, struct file *file)
{
	int err;
	struct cdevsw *cdev;
	major_t major;
	minor_t minor;
	modID_t modid, instance;

#if defined HAVE_KFUNC_TO_KDEV_T
	minor = MINOR(kdev_t_to_nr(inode->i_rdev));
	major = MAJOR(kdev_t_to_nr(inode->i_rdev));
#else
	minor = MINOR(inode->i_rdev);
	major = MAJOR(inode->i_rdev);
#endif
	minor = cdev_minor(&clone_cdev, major, minor);
	major = clone_cdev.d_major;
	modid = clone_cdev.d_modid;
	err = -ENXIO;
	if (!(cdev = sdev_get(minor))) {
		goto exit;
	}
	instance = cdev->d_modid;
	err = spec_open(file, cdev, makedevice(modid, instance), CLONEOPEN);
	sdev_put(cdev);
      exit:
	return (err);
}
예제 #3
0
/*ARGSUSED1*/
static int
ds1287_open(dev_t *devp, int flags, int otyp, cred_t *credp)
{
	struct ds1287 *softsp;
	int clone;

	if (otyp != OTYP_CHR)
		return (EINVAL);

	if ((softsp = ddi_get_soft_state(ds1287_state, instance)) ==
	    NULL)
		return (ENXIO);

	mutex_enter(&softsp->ds1287_mutex);
	for (clone = 1; clone < DS1287_MAX_CLONE; clone++)
		if (!softsp->clones[clone])
			break;

	if (clone == DS1287_MAX_CLONE) {
		cmn_err(CE_WARN, "ds1287_open: No more allocation left "
		    "to clone a minor.");
		mutex_exit(&softsp->ds1287_mutex);
		return (ENXIO);
	}

	*devp = makedevice(getmajor(*devp), (instance << 8) + clone);
	softsp->clones[clone] = 1;
	mutex_exit(&softsp->ds1287_mutex);

	return (0);
}
예제 #4
0
/*
 * Get the ZFS volume name out of the given path
 */
int
get_zfsvolname(char *volname, int len, char *path)
{
    struct stat64 stbuf;
    struct extmnttab ent;
    FILE *mntfp;
    int rv;

    *volname = '\0';
    if (stat64(path, &stbuf) != 0) {
        return (-1);
    }

    if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
        return (-1);
    }
    while ((rv = getextmntent(mntfp, &ent, 0)) == 0) {
        if (makedevice(ent.mnt_major, ent.mnt_minor) ==
                stbuf.st_dev)
            break;
    }

    if (rv == 0 &&
            strcmp(ent.mnt_fstype, MNTTYPE_ZFS) == 0)
        (void) strlcpy(volname, ent.mnt_special, len);
    else
        rv = -1;

    (void) fclose(mntfp);
    return (rv);
}
예제 #5
0
파일: log.c 프로젝트: andreiw/polaris
/* ARGSUSED */
static int
log_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cr)
{
	log_t *lp;
	minor_t minor;

	if (sflag & (MODOPEN | CLONEOPEN))
		return (ENXIO);

	switch (minor = getminor(*devp)) {
	case LOG_CONSMIN:		/* clone open of /dev/conslog */
		if (flag & FREAD)
			return (EINVAL);	/* write-only device */
		if (q->q_ptr)
			return (0);
		break;

	case LOG_LOGMIN:		/* clone open of /dev/log */
		break;

	default:
		return (ENXIO);
	}

	lp = log_alloc(minor);
	if (lp == NULL)
		return (ENXIO);
	*devp = makedevice(getmajor(*devp), lp->log_minor);
	q->q_ptr = lp;
	WR(q)->q_ptr = lp;
	lp->log_inuse = 1;
	qprocson(q);

	return (0);
}
예제 #6
0
파일: smbios.c 프로젝트: andreiw/polaris
/*ARGSUSED*/
static int
smb_open(dev_t *dp, int flag, int otyp, cred_t *cred)
{
	minor_t c;

	if (ksmbios == NULL)
		return (ENXIO);

	/*
	 * Locate and reserve a clone structure.  We skip clone 0 as that is
	 * the real minor number, and we assign a new minor to each clone.
	 */
	for (c = 1; c < smb_nclones; c++) {
		if (casptr(&smb_clones[c].c_hdl, NULL, ksmbios) == NULL)
			break;
	}

	if (c >= smb_nclones)
		return (EAGAIN);

	smb_clones[c].c_eplen = P2ROUNDUP(sizeof (smbios_entry_t), 16);
	smb_clones[c].c_stlen = smbios_buflen(smb_clones[c].c_hdl);

	*dp = makedevice(getemajor(*dp), c);

	(void) ddi_prop_update_int(*dp, smb_devi, "size",
	    smb_clones[c].c_eplen + smb_clones[c].c_stlen);

	return (0);
}
예제 #7
0
/*ARGSUSED*/
static int
ipmi_open(dev_t *devp, int flag, int otyp, cred_t *cred)
{
	minor_t minor;
	ipmi_device_t *dev;

	if (ipmi_attached == B_FALSE)
		return (ENXIO);

	if (ipmi_found == B_FALSE)
		return (ENODEV);

	/* exclusive opens are not supported */
	if (flag & FEXCL)
		return (ENOTSUP);

	if ((minor = (minor_t)id_alloc_nosleep(minor_ids)) == 0)
		return (ENODEV);

	/* Initialize the per file descriptor data. */
	dev = kmem_zalloc(sizeof (ipmi_device_t), KM_SLEEP);

	dev->ipmi_pollhead = kmem_zalloc(sizeof (pollhead_t), KM_SLEEP);

	TAILQ_INIT(&dev->ipmi_completed_requests);
	dev->ipmi_address = IPMI_BMC_SLAVE_ADDR;
	dev->ipmi_lun = IPMI_BMC_SMS_LUN;
	*devp = makedevice(getmajor(*devp), minor);
	dev->ipmi_dev = *devp;

	list_insert_head(&dev_list, dev);

	return (0);
}
예제 #8
0
 /* There are two minors 0 is the /dev/sad/admin driver and 1 is the /dev/sad/user driver.
    Permission for access to the /dev/sad/admin minor is performed by filesystem permission on the
    character device and a check on open. */
static streamscall int
sad_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
{
	major_t major = getmajor(*devp);
	minor_t minor = getminor(*devp);

	if (q->q_ptr)
		return (0);	/* already open */
	switch (sflag) {
	case CLONEOPEN:
		minor = 1;
		if (sads[minor].assigned != 0)
			break;
	case DRVOPEN:
		if (minor != 0 && minor != 1)
			break;
#ifdef HAVE_KMEMB_STRUCT_CRED_UID_VAL
		if (minor == 0 && crp->cr_uid.val != 0 && crp->cr_ruid.val != 0)
			return (-EACCES);
#else
		if (minor == 0 && crp->cr_uid != 0 && crp->cr_ruid != 0)
			return (-EACCES);
#endif
		*devp = makedevice(major, minor);
		sads[minor].assigned |= 1;
		q->q_ptr = WR(q)->q_ptr = &sads[minor];
		qprocson(q);
		return (0);
	}
	return (-ENXIO);
}
예제 #9
0
/*ARGSUSED*/
static int
devvt_create_rvp(struct sdev_node *ddv, char *nm,
    void **arg, cred_t *cred, void *whatever, char *whichever)
{
	minor_t min;
	major_t maj;
	struct vattr *vap = (struct vattr *)arg;

	if ((maj = vt_wc_attached()) == (major_t)-1)
		return (SDEV_VTOR_INVALID);

	if (strcmp(nm, DEVVT_ACTIVE_NAME) == 0) {
		(void) vt_getactive((char *)*arg, MAXPATHLEN);
		return (0);
	}

	if (strcmp(nm, DEVVT_CONSUSER_NAME) == 0) {
		(void) vt_getconsuser((char *)*arg, MAXPATHLEN);
		return (0);
	}
	if (devvt_str2minor(nm, &min) != 0)
		return (-1);

	if (vt_minor_valid(min) == B_FALSE)
		return (-1);

	*vap = devvt_vattr;
	vap->va_rdev = makedevice(maj, min);

	return (0);
}
예제 #10
0
static int
audio_stropen(queue_t *rq, dev_t *devp, int oflag, int sflag, cred_t *credp)
{
	int			rv;
	audio_client_t		*c;

	if (sflag != 0) {
		/* no direct clone or module opens */
		return (ENXIO);
	}

	/*
	 * Make sure its a STREAMS personality - only legacy Sun API uses
	 * STREAMS.
	 */
	switch (AUDIO_MN_TYPE_MASK & getminor(*devp)) {
	case AUDIO_MINOR_DEVAUDIO:
	case AUDIO_MINOR_DEVAUDIOCTL:
		break;
	default:
		return (ENOSTR);
	}

	if ((c = auimpl_client_create(*devp)) == NULL) {
		audio_dev_warn(NULL, "client create failed");
		return (ENXIO);
	}

	rq->q_ptr = WR(rq)->q_ptr = c;
	c->c_omode = oflag;
	c->c_pid = ddi_get_pid();
	c->c_cred = credp;
	c->c_rq = rq;
	c->c_wq = WR(rq);

	/*
	 * Call client/personality specific open handler.  Note that
	 * we "insist" that there is an open.  The personality layer
	 * will initialize/allocate any engines required.
	 *
	 * Hmm... do we need to pass in the cred?
	 */
	if ((rv = c->c_open(c, oflag)) != 0) {
		audio_dev_warn(c->c_dev, "open failed (rv %d)", rv);
		auimpl_client_destroy(c);
		return (rv);
	}

	/* we do device cloning! */
	*devp = makedevice(c->c_major, c->c_minor);

	qprocson(rq);

	/* now we can receive upcalls */
	auimpl_client_activate(c);

	atomic_inc_uint(&c->c_dev->d_serial);

	return (0);
}
예제 #11
0
파일: rsmops.c 프로젝트: pcd1193182/openzfs
/*
 * This opens and closes the appropriate device with minor number -
 * hopefully, it will cause the driver to attach and register a controller
 * with us
 */
static vnode_t *
rsmops_device_open(const char *major_name, const minor_t minor_num)
{
	major_t maj;
	vnode_t *vp;
	int ret;

	if (minor_num == (minor_t)-1) {
		return (NULL);
	}

	maj = ddi_name_to_major((char *)major_name);
	if (maj == (major_t)-1) {
		return (NULL);
	}

	vp = makespecvp(makedevice(maj, minor_num), VCHR);

	ret = VOP_OPEN(&vp, FREAD|FWRITE, CRED(), NULL);
	if (ret == 0) {
		return (vp);
	} else {
		VN_RELE(vp);
		return (NULL);
	}
}
예제 #12
0
static streamscall int
zap_qopen(queue_t *q, dev_t *devp, int oflags, int sflag, cred_t *crp)
{
	major_t cmajor = getmajor(*devp);
	minor_t cminor = getminor(*devp);
	struct zt_chan *chan;
	int err;

	if (q->q_ptr != NULL)
		return (0);	/* already open */
	if (sflag == DRVOPEN && cmajor == CMAJOR_0) {
		if (cminor == 0) {
			/* explicit open of control device */
		} else if (cminor == 253) {
			/* special timining device */
		} else if (cminor == 254) {
		} else if (cminor == 255) {
		} else if (cminor < ZT_MAX_CHANNELS) {
			chan = &chans[cminor];
		} else
			goto enxio;
	} else if (sflag == CLONEOPEN && cmajor == CMAJOR_0) {
		if ((cminor == 255 && !(chan = zt_alloc_pseudo())) || cminor != 255)
			goto enxio;
	} else
		goto enxio;
	*devp = makedevice(cmajor, chan->channo);
	if ((err = zt_specchan_open(NULL, qstream(q)->sd_file, chan->channo, 1)))
		return (err < 0 ? -err : err);
	q->q_ptr = WR(q)->q_ptr = (void *) chan;
	return (0);
      enxio:
	return (ENXIO);
}
예제 #13
0
파일: ctfs_root.c 프로젝트: andreiw/polaris
/*
 * ctfs_mount - the VFS_MOUNT entry point
 */
static int
ctfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
{
	ctfs_vfs_t *data;
	dev_t dev;
	gfs_dirent_t *dirent;
	int i;

	if (secpolicy_fs_mount(cr, mvp, vfsp) != 0)
		return (EPERM);

	if (mvp->v_type != VDIR)
		return (ENOTDIR);

	if ((uap->flags & MS_OVERLAY) == 0 &&
	    (mvp->v_count > 1 || (mvp->v_flag & VROOT)))
		return (EBUSY);

	data = kmem_alloc(sizeof (ctfs_vfs_t), KM_SLEEP);

	/*
	 * Initialize vfs fields not initialized by VFS_INIT/domount
	 */
	vfsp->vfs_bsize = DEV_BSIZE;
	vfsp->vfs_fstype = ctfs_fstype;
	do
		dev = makedevice(ctfs_major,
		    atomic_add_32_nv(&ctfs_minor, 1) & L_MAXMIN32);
	while (vfs_devismounted(dev));
	vfs_make_fsid(&vfsp->vfs_fsid, dev, ctfs_fstype);
	vfsp->vfs_data = data;
	vfsp->vfs_dev = dev;

	/*
	 * Dynamically create gfs_dirent_t array for the root directory.
	 */
	dirent = kmem_zalloc((ct_ntypes + 2) * sizeof (gfs_dirent_t), KM_SLEEP);
	for (i = 0; i < ct_ntypes; i++) {
		dirent[i].gfse_name = (char *)ct_types[i]->ct_type_name;
		dirent[i].gfse_ctor = ctfs_create_tdirnode;
		dirent[i].gfse_flags = GFS_CACHE_VNODE;
	}
	dirent[i].gfse_name = "all";
	dirent[i].gfse_ctor = ctfs_create_adirnode;
	dirent[i].gfse_flags = GFS_CACHE_VNODE;
	dirent[i+1].gfse_name = NULL;

	/*
	 * Create root vnode
	 */
	data->ctvfs_root = gfs_root_create(sizeof (ctfs_rootnode_t),
	    vfsp, ctfs_ops_root, CTFS_INO_ROOT, dirent, ctfs_root_do_inode,
	    CTFS_NAME_MAX, NULL, NULL);

	kmem_free(dirent, (ct_ntypes + 2) * sizeof (gfs_dirent_t));

	return (0);
}
예제 #14
0
static void
devvt_create_snode(struct sdev_node *ddv, char *nm, struct cred *cred, int type)
{
	int error;
	struct sdev_node *sdv = NULL;
	struct vattr vattr;
	struct vattr *vap = &vattr;
	major_t maj;
	minor_t min;

	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));

	if ((maj = vt_wc_attached()) == (major_t)-1)
		return;

	if (strcmp(nm, DEVVT_ACTIVE_NAME) != 0 &&
	    strcmp(nm, DEVVT_CONSUSER_NAME) != 0 &&
	    devvt_str2minor(nm, &min) != 0)
		return;

	error = sdev_mknode(ddv, nm, &sdv, NULL, NULL, NULL, cred, SDEV_INIT);
	if (error || !sdv) {
		return;
	}

	mutex_enter(&sdv->sdev_lookup_lock);
	SDEV_BLOCK_OTHERS(sdv, SDEV_LOOKUP);
	mutex_exit(&sdv->sdev_lookup_lock);

	if (type & SDEV_VATTR) {
		*vap = devvt_vattr;
		vap->va_rdev = makedevice(maj, min);
		error = sdev_mknode(ddv, nm, &sdv, vap, NULL,
		    NULL, cred, SDEV_READY);
	} else if (type & SDEV_VLINK) {
		char *link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);

		(void) vt_getactive(link, MAXPATHLEN);
		*vap = sdev_vattr_lnk;
		vap->va_size = strlen(link);
		error = sdev_mknode(ddv, nm, &sdv, vap, NULL,
		    (void *)link, cred, SDEV_READY);

		kmem_free(link, MAXPATHLEN);
	}

	if (error != 0) {
		SDEV_RELE(sdv);
		return;
	}

	mutex_enter(&sdv->sdev_lookup_lock);
	SDEV_UNBLOCK_OTHERS(sdv, SDEV_LOOKUP);
	mutex_exit(&sdv->sdev_lookup_lock);

}
예제 #15
0
static int
m3ua_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
{
	m3ua_t *m3ua, **m3p = &m3ua_devices;
	int cmajor = getmajor(*devp);
	int cminor = getmajor(*devp);

	trace();
	if (q->q_ptr != NULL)
		return (0);

	if (sflag == MODOPEN || WR(q)->q_next)
		return EIO;

	if (!cminor) {
		if (!m3ua_ctrlq)
			m3ua_ctrlq = q;
		else
			sflag = CLONEOPEN;
	}

	if (sflag == CLONEOPEN)
		cminor = 1;

	for (; cminor <= NMINORS && *m3p; m3p = &(*m3p)->next) {
		int dminor = getminor((*m3p)->devnum);

		if (cminor < dminor)
			break;
		if (cminor == dminor) {
			if (sflag == CLONEOPEN) {
				cminor++;
				continue;
			}
			return EIO;
		}
	}
	if (cminor > M3UA_MINOR)
		return ENXIO;

	*devp = makedevice(cmajor, cminor);

	if (!(m3ua = kmalloc(sizeof(*m3ua), GFP_KERNEL)))
		return ENOMEM;

	bzero(m3ua, sizeof(*m3ua));

	q->q_ptr = WR(q)->q_ptr;
	m3ua->rq = RD(q);
	m3ua->wq = WR(q);

	m3ua->state = FIXME;
	m3ua->devnum = *devp;

	return (0);
}
예제 #16
0
파일: zvol.c 프로젝트: andreiw/polaris
static void
zvol_size_changed(zvol_state_t *zv, dev_t dev)
{
	dev = makedevice(getmajor(dev), zv->zv_minor);

	VERIFY(ddi_prop_update_int64(dev, zfs_dip,
	    "Size", zv->zv_volsize) == DDI_SUCCESS);
	VERIFY(ddi_prop_update_int64(dev, zfs_dip,
	    "Nblocks", lbtodb(zv->zv_volsize)) == DDI_SUCCESS);
}
예제 #17
0
파일: cpc.c 프로젝트: apprisi/illumos-gate
/*ARGSUSED1*/
static int
kcpc_open(dev_t *dev, int flags, int otyp, cred_t *cr)
{
	processorid_t	cpuid;
	int		error;

	ASSERT(pcbe_ops != NULL);

	if ((error = secpolicy_cpc_cpu(cr)) != 0)
		return (error);
	if (getminor(*dev) != KCPC_MINOR_SHARED)
		return (ENXIO);
	if ((cpuid = curthread->t_bind_cpu) == PBIND_NONE)
		return (EINVAL);
	if (cpuid > max_cpuid)
		return (EINVAL);

	rw_enter(&kcpc_cpuctx_lock, RW_WRITER);
	if (++kcpc_cpuctx == 1) {
		ASSERT(kcpc_cpumap == NULL);

		/*
		 * Bail out if DTrace is already using the counters.
		 */
		if (dtrace_cpc_in_use) {
			kcpc_cpuctx--;
			rw_exit(&kcpc_cpuctx_lock);
			return (EAGAIN);
		}
		kcpc_cpumap = kmem_zalloc(BT_SIZEOFMAP(max_cpuid + 1),
		    KM_SLEEP);
		/*
		 * When this device is open for processor-based contexts,
		 * no further lwp-based contexts can be created.
		 *
		 * Since this is the first open, ensure that all existing
		 * contexts are invalidated.
		 */
		kcpc_invalidate_all();
	} else if (BT_TEST(kcpc_cpumap, cpuid)) {
		kcpc_cpuctx--;
		rw_exit(&kcpc_cpuctx_lock);
		return (EAGAIN);
	} else if (kcpc_hw_cpu_hook(cpuid, kcpc_cpumap) != 0) {
		kcpc_cpuctx--;
		rw_exit(&kcpc_cpuctx_lock);
		return (EACCES);
	}
	BT_SET(kcpc_cpumap, cpuid);
	rw_exit(&kcpc_cpuctx_lock);

	*dev = makedevice(getmajor(*dev), (minor_t)cpuid);

	return (0);
}
예제 #18
0
/**
 * User context entry points
 *
 * @remarks fFlags are the flags passed to open() or to ldi_open_by_name.  In
 *          the latter case the FKLYR flag is added to indicate that the caller
 *          is a kernel component rather than user land.
 */
static int vgdrvSolarisOpen(dev_t *pDev, int fFlags, int fType, cred_t *pCred)
{
    int                 rc;
    PVBOXGUESTSESSION   pSession = NULL;

    LogFlow(("vgdrvSolarisOpen:\n"));

    /*
     * Verify we are being opened as a character device.
     */
    if (fType != OTYP_CHR)
        return EINVAL;

    vboxguest_state_t *pState = NULL;
    unsigned iOpenInstance;
    for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++)
    {
        if (    !ddi_get_soft_state(g_pvgdrvSolarisState, iOpenInstance) /* faster */
            &&  ddi_soft_state_zalloc(g_pvgdrvSolarisState, iOpenInstance) == DDI_SUCCESS)
        {
            pState = ddi_get_soft_state(g_pvgdrvSolarisState, iOpenInstance);
            break;
        }
    }
    if (!pState)
    {
        Log(("vgdrvSolarisOpen: too many open instances."));
        return ENXIO;
    }

    /*
     * Create a new session.
     */
    if (!(fFlags & FKLYR))
        rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession);
    else
        rc = VGDrvCommonCreateKernelSession(&g_DevExt, &pSession);
    if (RT_SUCCESS(rc))
    {
        if (!(fFlags & FKLYR))
            pState->pvProcRef = proc_ref();
        else
            pState->pvProcRef = NULL;
        pState->pSession = pSession;
        *pDev = makedevice(getmajor(*pDev), iOpenInstance);
        Log(("vgdrvSolarisOpen: pSession=%p pState=%p pid=%d\n", pSession, pState, (int)RTProcSelf()));
        return 0;
    }

    /* Failed, clean up. */
    ddi_soft_state_free(g_pvgdrvSolarisState, iOpenInstance);

    LogRel((DEVICE_NAME "::Open: VGDrvCommonCreateUserSession failed. rc=%d\n", rc));
    return EFAULT;
}
예제 #19
0
/*ARGSUSED*/
static int
devpts_create_rvp(struct sdev_node *ddv, char *nm,
    void **arg, cred_t *cred, void *whatever, char *whichever)
{
	minor_t min;
	major_t maj;
	uid_t uid;
	gid_t gid;
	timestruc_t now;
	struct vattr *vap = (struct vattr *)arg;

	if (devpts_strtol(nm, &min) != 0) {
		sdcmn_err7(("devpts_create_rvp: not a valid minor: %s\n", nm));
		return (-1);
	}

	/*
	 * Check if pts driver is attached and if it is
	 * get the major number.
	 */
	maj = ptms_slave_attached();
	if (maj == (major_t)-1) {
		sdcmn_err7(("devpts_create_rvp: slave not attached\n"));
		return (-1);
	}

	/*
	 * Only allow creation of ptys allocated to our zone
	 */
	if (!ptms_minor_valid(min, &uid, &gid)) {
		sdcmn_err7(("devpts_create_rvp: %s not valid pty"
		    "or not valid in this zone\n", nm));
		return (-1);
	}


	/*
	 * This is a valid pty (at least at this point in time).
	 * Create the node by setting the attribute. The rest
	 * is taken care of by devname_lookup_func().
	 */
	*vap = devpts_vattr;
	vap->va_rdev = makedevice(maj, min);
	ASSERT(uid >= 0);
	ASSERT(gid >= 0);
	vap->va_uid = uid;
	vap->va_gid = gid;
	gethrestime(&now);
	vap->va_atime = now;
	vap->va_mtime = now;
	vap->va_ctime = now;

	return (0);
}
/* ARGSUSED3 */
int
ip_helper_stream_setup(queue_t *q, dev_t *devp, int flag, int sflag,
    cred_t *credp, boolean_t isv6)
{
	major_t			maj;
	ip_helper_minfo_t	*ip_minfop;

	ASSERT((flag & ~(FKLYR)) == IP_HELPER_STR);

	ASSERT(RD(q) == q);

	ip_minfop = kmem_alloc(sizeof (ip_helper_minfo_t), KM_SLEEP);
	ASSERT(ip_minfop != NULL);

	ip_minfop->ip_minfo_dev = 0;
	ip_minfop->ip_minfo_arena = NULL;

	/*
	 * Clone the device, allocate minor device number
	 */
	if (ip_minor_arena_la != NULL)
		ip_minfop->ip_minfo_dev = inet_minor_alloc(ip_minor_arena_la);

	if (ip_minfop->ip_minfo_dev == 0) {
		/*
		 * numbers in the large arena are exhausted
		 * Try small arena.
		 * Or this is a 32 bit system, 32 bit systems do not have
		 * ip_minor_arena_la
		 */
		ip_minfop->ip_minfo_dev = inet_minor_alloc(ip_minor_arena_sa);
		if (ip_minfop->ip_minfo_dev == 0) {
			return (EBUSY);
		}
		ip_minfop->ip_minfo_arena = ip_minor_arena_sa;
	} else {
		ip_minfop->ip_minfo_arena = ip_minor_arena_la;
	}


	ASSERT(ip_minfop->ip_minfo_dev != 0);
	ASSERT(ip_minfop->ip_minfo_arena != NULL);

	RD(q)->q_ptr = WR(q)->q_ptr = ip_minfop;

	maj = getemajor(*devp);
	*devp = makedevice(maj, (ulong_t)(ip_minfop->ip_minfo_dev));

	q->q_qinfo = &ip_helper_stream_rinit;
	WR(q)->q_qinfo = &ip_helper_stream_winit;
	qprocson(q);
	return (0);
}
예제 #21
0
/* ARGSUSED */
static int
evtchndrv_open(dev_t *devp, int flag, int otyp, cred_t *credp)
{
	struct evtsoftdata *ep;
	minor_t minor = getminor(*devp);

	if (otyp == OTYP_BLK)
		return (ENXIO);

	/*
	 * only allow open on minor = 0 - the clone device
	 */
	if (minor != 0)
		return (ENXIO);

	/*
	 * find a free slot and grab it
	 */
	mutex_enter(&evtchndrv_clone_tab_mutex);
	for (minor = 1; minor < evtchndrv_nclones; minor++) {
		if (evtchndrv_clone_tab[minor] == 0) {
			evtchndrv_clone_tab[minor] = 1;
			break;
		}
	}
	mutex_exit(&evtchndrv_clone_tab_mutex);
	if (minor == evtchndrv_nclones)
		return (EAGAIN);

	/* Allocate softstate structure */
	if (ddi_soft_state_zalloc(evtchndrv_statep,
	    EVTCHNDRV_MINOR2INST(minor)) != DDI_SUCCESS) {
		mutex_enter(&evtchndrv_clone_tab_mutex);
		evtchndrv_clone_tab[minor] = 0;
		mutex_exit(&evtchndrv_clone_tab_mutex);
		return (EAGAIN);
	}
	ep = EVTCHNDRV_INST2SOFTS(EVTCHNDRV_MINOR2INST(minor));

	/* ... and init it */
	ep->dip = evtchndrv_dip;

	cv_init(&ep->evtchn_wait, NULL, CV_DEFAULT, NULL);
	mutex_init(&ep->evtchn_lock, NULL, MUTEX_DEFAULT, NULL);

	ep->ring = kmem_alloc(PAGESIZE, KM_SLEEP);

	/* clone driver */
	*devp = makedevice(getmajor(*devp), minor);

	return (0);
}
예제 #22
0
파일: ip_to_dlpi.c 프로젝트: iHaD/openss7
int streamscall
ip2xinet_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
{
	mblk_t *bp;
	minor_t minor;
	struct stroptions *sop;

	/* already open */
	if (sflag != CLONEOPEN)
		return ENXIO;

	spin_lock(&ip2xinet_lock);

	/* Can only open one time */
	if (ip2xinet_numopen) {
		spin_unlock(&ip2xinet_lock);
		return ENXIO;
	} else
		ip2xinet_numopen = 1;

	if (q->q_count != 0)
		printk("ip2x level:q_count is %lu", (ulong) q->q_count);

	/* Set up the flow control parameters and send them up to the stream head.  */
	minor = getminor(*devp);
	if ((bp = allocb(sizeof(struct stroptions), BPRI_LO)) == NULL) {
		spin_unlock(&ip2xinet_lock);
		printk("%s: allocb failed", __FUNCTION__);
		return ENOMEM;
	}

	ip2xinet_status.myminor = minor;
	ip2xinet_status.ip2x_dlstate = DL_UNATTACHED;

	/* These are dummy to keep track of the fact the device is open */
	q->q_ptr = (char *) &ip2xinet_numopen;
	WR(q)->q_ptr = (char *) &ip2xinet_numopen;

	spin_unlock(&ip2xinet_lock);

	bp->b_datap->db_type = M_SETOPTS;
	bp->b_wptr += sizeof(struct stroptions);

	sop = (struct stroptions *) bp->b_rptr;
	sop->so_flags = SO_HIWAT | SO_LOWAT;
	sop->so_hiwat = ip2xinet_minfo.mi_hiwat;
	sop->so_lowat = ip2xinet_minfo.mi_lowat;
	putnext(q, bp);

	*devp = makedevice(getmajor(*devp), 0);
	return 0;
}
예제 #23
0
파일: ksyms.c 프로젝트: bahamas10/openzfs
/* ARGSUSED */
static int
ksyms_open(dev_t *devp, int flag, int otyp, struct cred *cred)
{
	minor_t clone;
	size_t size = 0;
	size_t realsize;
	char *addr;
	void *hptr = NULL;
	ksyms_buflist_hdr_t hdr;
	bzero(&hdr, sizeof (struct ksyms_buflist_hdr));
	list_create(&hdr.blist, PAGESIZE,
	    offsetof(ksyms_buflist_t, buflist_node));

	if (getminor(*devp) != 0)
		return (ENXIO);

	for (;;) {
		realsize = ksyms_snapshot(ksyms_bcopy, hptr, size);
		if (realsize <= size)
			break;
		size = realsize;
		size = ksyms_buflist_alloc(&hdr, size);
		if (size == 0)
			return (ENOMEM);
		hptr = (void *)&hdr;
	}

	addr = ksyms_mapin(&hdr, realsize);
	ksyms_buflist_free(&hdr);
	if (addr == NULL)
		return (EOVERFLOW);

	/*
	 * Reserve a clone entry.  Note that we don't use clone 0
	 * since that's the "real" minor number.
	 */
	for (clone = 1; clone < nksyms_clones; clone++) {
		if (atomic_cas_ptr(&ksyms_clones[clone].ksyms_base, 0, addr) ==
		    0) {
			ksyms_clones[clone].ksyms_size = realsize;
			*devp = makedevice(getemajor(*devp), clone);
			(void) ddi_prop_update_int(*devp, ksyms_devi,
			    "size", realsize);
			modunload_disable();
			return (0);
		}
	}
	cmn_err(CE_NOTE, "ksyms: too many open references");
	(void) as_unmap(curproc->p_as, addr, roundup(realsize, PAGESIZE));
	return (ENXIO);
}
예제 #24
0
static int
zfs_create_unique_device(dev_t *dev)
{
	major_t new_major;

	do {
		ASSERT3U(zfs_minor, <=, MAXMIN32);
		minor_t start = zfs_minor;
		do {
			mutex_enter(&zfs_dev_mtx);
			if (zfs_minor >= MAXMIN32) {
				/*
				 * If we're still using the real major
				 * keep out of /dev/zfs and /dev/zvol minor
				 * number space.  If we're using a getudev()'ed
				 * major number, we can use all of its minors.
				 */
				if (zfs_major == ddi_name_to_major(ZFS_DRIVER))
					zfs_minor = ZFS_MIN_MINOR;
				else
					zfs_minor = 0;
			} else {
				zfs_minor++;
			}
			*dev = makedevice(zfs_major, zfs_minor);
			mutex_exit(&zfs_dev_mtx);
		} while (vfs_devismounted(*dev) && zfs_minor != start);
		if (zfs_minor == start) {
			/*
			 * We are using all ~262,000 minor numbers for the
			 * current major number.  Create a new major number.
			 */
			if ((new_major = getudev()) == (major_t)-1) {
				cmn_err(CE_WARN,
				    "zfs_mount: Can't get unique major "
				    "device number.");
				return (-1);
			}
			mutex_enter(&zfs_dev_mtx);
			zfs_major = new_major;
			zfs_minor = 0;

			mutex_exit(&zfs_dev_mtx);
		} else {
			break;
		}
		/* CONSTANTCONDITION */
	} while (1);

	return (0);
}
예제 #25
0
파일: zvol.c 프로젝트: pscedu/zfs-fuse
static void
zvol_size_changed(uint64_t volsize, major_t maj, minor_t min)
{
	dev_t dev = makedevice(maj, min);

	VERIFY(ddi_prop_update_int64(dev, zfs_dip,
	    "Size", volsize) == DDI_SUCCESS);
	VERIFY(ddi_prop_update_int64(dev, zfs_dip,
	    "Nblocks", lbtodb(volsize)) == DDI_SUCCESS);

	/* Notify specfs to invalidate the cached size */
	spec_size_invalidate(dev, VBLK);
	spec_size_invalidate(dev, VCHR);
}
예제 #26
0
파일: sad.c 프로젝트: andreiw/polaris
/* ARGSUSED */
static int
sadopen(
	queue_t *qp,	/* pointer to read queue */
	dev_t *devp,	/* major/minor device of stream */
	int flag,	/* file open flags */
	int sflag,	/* stream open flags */
	cred_t *credp)	/* user credentials */
{
	int i;

	if (sflag)		/* no longer called from clone driver */
		return (EINVAL);

	/*
	 * Both USRMIN and ADMMIN are clone interfaces.
	 */
	for (i = 0; i < sadcnt; i++)
		if (saddev[i].sa_qp == NULL)
			break;
	if (i >= sadcnt)		/* no such device */
		return (ENXIO);

	switch (getminor(*devp)) {
	case USRMIN:			/* mere mortal */
		saddev[i].sa_flags = 0;
		break;

	case ADMMIN:			/* privileged user */
		saddev[i].sa_flags = SADPRIV;
		break;

	default:
		return (EINVAL);
	}

	saddev[i].sa_qp = qp;
	qp->q_ptr = (caddr_t)&saddev[i];
	WR(qp)->q_ptr = (caddr_t)&saddev[i];

	/*
	 * NOTE: should the ADMMIN or USRMIN minors change
	 * then so should the offset of 2 below
	 * Both USRMIN and ADMMIN are clone interfaces and
	 * therefore their minor numbers (0 and 1) are reserved.
	 */
	*devp = makedevice(getemajor(*devp), i + 2);
	qprocson(qp);
	return (0);
}
예제 #27
0
/* ARGSUSED */
static int
cryptoadm_open(dev_t *devp, int flag, int otyp, cred_t *credp)
{
	if (otyp != OTYP_CHR || cryptoadm_dip == NULL)
		return (ENXIO);

	/* exclusive opens are not supported */
	if (flag & FEXCL)
		return (ENOTSUP);

	*devp = makedevice(getmajor(*devp), 0);

	kcf_sched_start();

	return (0);
}
예제 #28
0
static int VBoxUSBMonSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred)
{
    vboxusbmon_state_t *pState = NULL;
    unsigned iOpenInstance;

    LogFunc((DEVICE_NAME ": VBoxUSBMonSolarisOpen\n"));

    /*
     * Verify we are being opened as a character device.
     */
    if (fType != OTYP_CHR)
        return EINVAL;

    /*
     * Verify that we're called after attach.
     */
    if (!g_pDip)
    {
        LogRel((DEVICE_NAME ": VBoxUSBMonSolarisOpen: Invalid state for opening\n"));
        return ENXIO;
    }

    for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++)
    {
        if (    !ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance) /* faster */
            &&  ddi_soft_state_zalloc(g_pVBoxUSBMonSolarisState, iOpenInstance) == DDI_SUCCESS)
        {
            pState = ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance);
            break;
        }
    }
    if (!pState)
    {
        LogRel((DEVICE_NAME ": VBoxUSBMonSolarisOpen: Too many open instances"));
        return ENXIO;
    }

    pState->Process = RTProcSelf();
    *pDev = makedevice(getmajor(*pDev), iOpenInstance);

    NOREF(fFlag);
    NOREF(pCred);

    return 0;
}
예제 #29
0
/*ARGSUSED*/
static int
opromopen(dev_t *devp, int flag, int otyp, cred_t *credp)
{
	int m;
	struct oprom_state *st = oprom_state;

	if (getminor(*devp) != 0)
		return (ENXIO);

	mutex_enter(&oprom_lock);
	for (m = 0; m < MAX_OPENS; m++)
		if (st->already_open)
			st++;
		else {
			st->already_open = 1;
			/*
			 * It's ours.
			 */
			st->current_id = (pnode_t)0;
			ASSERT(st->snapshot == NULL && st->size == 0);
			ASSERT(st->ioc_state == IOC_IDLE);
			break;
		}
	mutex_exit(&oprom_lock);

	if (m == MAX_OPENS)  {
		/*
		 * "Thank you for calling, but all our lines are
		 * busy at the moment.."
		 *
		 * We could get sophisticated here, and go into a
		 * sleep-retry loop .. but hey, I just can't see
		 * that many processes sitting in this driver.
		 *
		 * (And if it does become possible, then we should
		 * change the interface so that the 'state' is held
		 * external to the driver)
		 */
		return (EAGAIN);
	}

	*devp = makedevice(getmajor(*devp), (minor_t)m);

	return (0);
}
예제 #30
0
/*ARGSUSED*/
static int
nsmb_open(dev_t *dev, int flags, int otyp, cred_t *cr)
{
	smb_dev_t *sdp;
	minor_t m;

	mutex_enter(&dev_lck);

	for (m = last_minor + 1; m != last_minor; m++) {
		if (m > NSMB_MAX_MINOR)
			m = NSMB_MIN_MINOR;

		if (ddi_get_soft_state(statep, m) == NULL) {
			last_minor = m;
			goto found;
		}
	}

	/* No available minor units. */
	mutex_exit(&dev_lck);
	return (ENXIO);

found:
	/* NB: dev_lck still held */
	if (ddi_soft_state_zalloc(statep, m) == DDI_FAILURE) {
		mutex_exit(&dev_lck);
		return (ENXIO);
	}
	if ((sdp = ddi_get_soft_state(statep, m)) == NULL) {
		mutex_exit(&dev_lck);
		return (ENXIO);
	}
	*dev = makedevice(nsmb_major, m);
	mutex_exit(&dev_lck);

	sdp->sd_cred = cr;
	sdp->sd_smbfid = -1;
	sdp->sd_flags |= NSMBFL_OPEN;
	sdp->zoneid = crgetzoneid(cr);

	return (0);
}