fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int (*ioctl)(dev_t, int, intptr_t, int, cred_t *, int *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ldi_handle_t lh; /* Solaris layered driver handle */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte raw_maj_t *major; /* pointer to major structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int plen; /* length of kmem_alloc for pathname */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int fd_hwm = 0; /* first never used entry in _nsc_raw_files */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int _raw_strategy(struct buf *); /* forward decl */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Validate parameters */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Lookup path */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (lookupname(path, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Validate resulting vnode */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Release vnode */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_zalloc(sizeof (*_nsc_raw_files) * maxdevs, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_init(&_nsc_raw_lock, NULL, MUTEX_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Free the memory allocated for strategy pointers */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(_nsc_raw_files, sizeof (*_nsc_raw_files) * _nsc_raw_maxdevs);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* must be called with the _nsc_raw_lock held */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Walk through the linked list */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Found major number */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The earlier ldi_open call has locked the driver
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * for this major number into memory, so just index into
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the devopsp array to get the dev_ops pointer which
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * must be valid.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "nskern: cannot find dev_ops for major %d", umaj);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "nsc_raw: held driver (%d) after %d attempts",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* DEBUG */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte maj = kmem_zalloc(sizeof (raw_maj_t), KM_NOSLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "nskern: no strategy function for "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "disk driver (major %d)",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * nsc_get_strategy returns the strategy function associated with
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the major number umaj. NULL is returned if no strategy is found.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (maj = _nsc_raw_majors; maj != NULL; maj = maj->next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Found major number */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (maj = _nsc_raw_majors; maj != NULL; maj = maj->next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Multiple opens, single close.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte_raw_open(char *path, int flag, blind_t *cdp, void *iodev)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "nskern: no nskernd daemon running!");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "nskern: _raw_open() before _nsc_init_raw()!");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "nskern: unable to alloc memory in _raw_open()");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Lookup the vnode to extract the dev_t info,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * then release the vnode.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((rdev = ldi_get_dev_t_from_path(path)) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See if this device is already opened
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (cd = 0, cdi = _nsc_raw_files; cd < fd_hwm; cd++, cdi++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "_raw_open: too many open devices");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* already set up - just return */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Layered driver
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We use xxx_open_by_dev() since this guarantees that a
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * specfs vnode is created and used, not a standard filesystem
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * vnode. This is necessary since in a cluster PXFS will block
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * vnode operations during switchovers, so we have to use the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * underlying specfs vnode not the PXFS vnode.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((rc = ldi_ident_from_dev(cdi->rdev, &li)) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rc != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * grab the major_t related information
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Out of memory */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "_raw_open: cannot alloc major number structure");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * _raw_close
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Multiple opens, single close.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rc != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (physio(_raw_strategy, 0, fd, B_READ, minphys, uiop));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (physio(_raw_strategy, 0, fd, B_WRITE, minphys, uiop));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cd == -1 || _nsc_raw_files[cd].major == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return ((*_nsc_raw_files[cd].major->strategy)(bp));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Return largest i/o size.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte_raw_maxfbas(dev_t dev, int flag, nsc_size_t *ptr)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Control device or system.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "unrecognised nsc_control: %x", cmd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (EINVAL); /* no control commands understood */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte_raw_get_bsize(dev_t dev, uint64_t *bsizep, int *partitionp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cd = __raw_get_cd(dev)) == -1 || !_nsc_raw_files[cd].in_use)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rc = (*ops->devo_getinfo)(NULL, DDI_INFO_DEVT2DEVINFO,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, DDI_KERNEL_IOCTL)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte flags = FKIOCTL | FREAD | FWRITE | DATAMODEL_NATIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dki_info = kmem_alloc(sizeof (*dki_info), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* DKIOCINFO */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rc != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* return partition number */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* DKIOCGVTOC */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* DKIOCGVTOC failed, but there might be an EFI label */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* do we have an EFI partition table? */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* DKIOCPARTITION */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rc == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* found EFI, return size */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* both DKIOCGVTOC and DKIOCPARTITION failed - error */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (vtoc->v_version != V_VERSION && vtoc->v_version != 0) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *bsizep = (uint64_t)vtoc->v_part[(int)dki_info->dki_partition].p_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Ugly, ugly, ugly.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Some volume managers (Veritas) don't support layered ioctls
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (no FKIOCTL support, no DDI_KERNEL_IOCTL property defined) AND
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * do not support the properties for bdev_Size()/bdev_size().
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the underlying driver has specified DDI_KERNEL_IOCTL, then we use
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the FKIOCTL technique. Otherwise ...
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The only reliable way to get the partition size, is to bounce the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * command through user land (nskernd).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Then, SunCluster PXFS blocks access at the vnode level to device
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * nodes during failover / switchover, so a read_vtoc() function call
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * from user land deadlocks. So, we end up coming back into the kernel
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to go directly to the underlying device driver - that's what
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * nskern_bsize() is doing below.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * There has to be a better way ...
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte_raw_init_dev(dev_t fd, uint64_t *sizep, int *partitionp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* try the in-kernel way */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rc == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* fallback to the the slow way */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strncpy(nsk->char1, _nsc_raw_files[cd].path, NSC_MAXPATH);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rc == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (_raw_init_dev(fd, &_nsc_raw_files[cd].size,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the comment above _raw_init_dev().
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortenskern_bsize(struct nscioc_bsize *bsize, int *rvp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ddi_mmap_get_model() returns the model for this user thread
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * which is what we want - get_udatamodel() is not public.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* DKIOCINFO */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DKIOCINFO, (intptr_t)bsize->dki_info, flag, cred, rvp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* DKIOCGVTOC */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DKIOCGVTOC, (intptr_t)bsize->vtoc, flag, cred, rvp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* do we have an EFI partition table? */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DKIOCPARTITION, (intptr_t)bsize->p64, flag, cred, rvp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Private function for sv to use.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((*partitionp = _nsc_raw_files[cd].partition) != -1) {