Lines Matching +full:slice +full:- +full:per +full:- +full:line
74 #define VDS_NAME "virtual-disk-server"
80 #define VD_CHANNEL_ENDPOINT "channel-endpoint"
82 #define VD_BLOCK_DEVICE_PROP "vds-block-device"
83 #define VD_BLOCK_DEVICE_OPTS "vds-block-device-opts"
113 * By Solaris convention, slice/partition 2 represents the entire disk;
124 (vdsk)->vdisk_bsize, (vdsk)->vdisk_size)
168 * The list can be extended by adding a "driver-type-list" entry in vds.conf
171 * driver-type-list="<driver>:<type>", ... ,"<driver>:<type>";
177 * Invalid entries in "driver-type-list" will be ignored.
179 * For example, the following line in vds.conf:
181 * driver-type-list="foo:disk","bar:volume";
185 * When a list is defined in vds.conf, it is checked before the built-in list
195 { "md", VD_DRIVER_VOLUME }, /* Solaris - SVM */
200 { "vxio", VD_DRIVER_VOLUME }, /* Veritas - VxVM */
210 * concatenation of string literals and C99 variable-length-argument-list
219 (vd->dring + (i)*vd->descriptor_size))
223 (((vd)->xfer_mode == VIO_DESC_MODE) ? "in-band client" : \
224 (((vd)->xfer_mode == VIO_DRING_MODE_V1_0) ? "dring client" : \
225 (((vd)->xfer_mode == 0) ? "null client" : \
239 #define VD_DSKIMG(vd) ((vd)->vdisk_type == VD_DISK_TYPE_DISK && \
240 ((vd)->file || (vd)->volume))
244 ((((id) + 1) >= vd->dring_len)? 0 : (id) + 1)
254 * the appropriate 'cfg-handle' value before being passed to the MDEG.
258 { MDET_PROP_VAL, "cfg-handle", NULL },
266 * in changes to 'virtual-device-port' nodes identified by their
274 static mdeg_node_match_t vd_match = {"virtual-device-port",
280 #define VD_OPT_RDONLY 0x1 /* read-only */
281 #define VD_OPT_SLICE 0x2 /* single slice */
293 { "slice", VD_OPT_SLICE },
308 elem->hdr.dstate, \
309 elem->payload.operation, \
310 elem->payload.status, \
311 elem->payload.nbytes, \
312 elem->payload.addr, \
313 elem->payload.ncookies);
344 switch (msg->tag.vio_msgtype) { in vd_decode_tag()
355 switch (msg->tag.vio_subtype) { in vd_decode_tag()
366 switch (msg->tag.vio_subtype_env) { in vd_decode_tag()
381 msg->tag.vio_msgtype, msg->tag.vio_subtype, in vd_decode_tag()
382 msg->tag.vio_subtype_env, tstr, sstr, estr); in vd_decode_tag()
414 * Types of descriptor-processing tasks
452 ldi_handle_t ldi_handle[V_NUMPAR]; /* LDI slice handles */
459 vd_disk_type_t vdisk_type; /* slice or entire disk */
462 boolean_t is_atapi_dev; /* Is this an IDE CD-ROM dev? */
473 int efi_reserved; /* EFI reserved slice */
474 caddr_t flabel; /* fake label for slice type */
477 struct dk_geom dk_geom; /* synthetic for slice type */
478 struct extvtoc vtoc; /* synthetic for slice type */
505 * Macros to manipulate the fake label (flabel) for single slice disks.
522 ((struct dk_label *)(void *)((vd)->flabel))
525 ((efi_gpt_t *)(void *)((vd)->flabel + (lba)))
527 ((efi_gpe_t *)(void *)((vd)->flabel + 2 * (lba)))
553 #define VD_IDENTITY_IN ((int (*)(void *, size_t, void *))-1)
554 #define VD_IDENTITY_OUT ((void (*)(void *, void *))-1)
590 * access by releasing any SCSI-2 reservation or resetting the disk. If these
596 * should trigger a reset SCSI buses and hopefully clear any SCSI-2 reservation.
603 * slice disks whether or not they have the "slice" option set. This is
606 * "slice" option was available.
630 * When a backend is exported as a single-slice disk then we entirely fake
633 * single-slice disks will be exported with a VTOC label; and if it is set
634 * to VD_DISK_LABEL_EFI then all single-slice disks will be exported with
651 * single-slice disks are exported as disks with only one slice instead of
701 * full_size - the size to convert in bytes.
702 * size - the converted size.
703 * unit - the unit of the converted size: 'K' (kilobyte),
732 * Convert virtual disk I/O parameters (slice, block, length) to
737 * vd - disk on which the operation is performed.
738 * slice - slice to which is the I/O parameters apply.
741 * blkp - pointer to the starting block relative to the
742 * slice; return the starting block relative to
744 * lenp - pointer to the number of bytes requested; return
748 * 0 - I/O parameters have been successfully converted;
750 * ENODATA - no data are available for the given I/O parameters;
752 * of the slice.
753 * EINVAL - I/O parameters are invalid.
756 vd_dskimg_io_params(vd_t *vd, int slice, size_t *blkp, size_t *lenp) in vd_dskimg_io_params() argument
762 ASSERT(vd->file || VD_DSKIMG(vd)); in vd_dskimg_io_params()
764 ASSERT(vd->vdisk_bsize == DEV_BSIZE); in vd_dskimg_io_params()
767 * If a file is exported as a slice then we don't care about the vtoc. in vd_dskimg_io_params()
772 if (vd->vdisk_type == VD_DISK_TYPE_SLICE || slice == VD_SLICE_NONE) { in vd_dskimg_io_params()
775 if (offset >= vd->dskimg_size) { in vd_dskimg_io_params()
778 offset, vd->dskimg_size); in vd_dskimg_io_params()
781 maxlen = vd->dskimg_size - offset; in vd_dskimg_io_params()
783 ASSERT(slice >= 0 && slice < V_NUMPAR); in vd_dskimg_io_params()
791 if (vd->vdisk_label == VD_DISK_LABEL_UNK && in vd_dskimg_io_params()
792 vio_ver_is_supported(vd->version, 1, 1)) { in vd_dskimg_io_params()
794 if (vd->vdisk_label == VD_DISK_LABEL_UNK) { in vd_dskimg_io_params()
796 "from slice %d", slice); in vd_dskimg_io_params()
801 if (vd->vdisk_label == VD_DISK_LABEL_VTOC) { in vd_dskimg_io_params()
802 ASSERT(vd->vtoc.v_sectorsz == DEV_BSIZE); in vd_dskimg_io_params()
804 ASSERT(vd->vdisk_label == VD_DISK_LABEL_EFI); in vd_dskimg_io_params()
807 if (blk >= vd->slices[slice].nblocks) { in vd_dskimg_io_params()
808 /* address past the end of the slice */ in vd_dskimg_io_params()
810 blk, vd->slices[slice].nblocks); in vd_dskimg_io_params()
814 offset = (vd->slices[slice].start + blk) * DEV_BSIZE; in vd_dskimg_io_params()
815 maxlen = (vd->slices[slice].nblocks - blk) * DEV_BSIZE; in vd_dskimg_io_params()
834 if ((offset + len) > vd->dskimg_size) { in vd_dskimg_io_params()
836 "dskimg_size (0x%lx)", offset, len, vd->dskimg_size); in vd_dskimg_io_params()
853 * exported as single-slice disk. Read or write to volumes exported as
854 * single slice disks are done by directly using the ldi interface.
857 * vd - disk on which the operation is performed.
858 * slice - slice on which the operation is performed,
861 * operation - operation to execute: read (VD_OP_BREAD) or
863 * data - buffer where data are read to or written from.
864 * blk - starting block for the operation.
865 * len - number of bytes to read or write.
868 * n >= 0 - success, n indicates the number of bytes read
870 * -1 - error.
873 vd_dskimg_rw(vd_t *vd, int slice, int operation, caddr_t data, size_t offset, in vd_dskimg_rw() argument
880 ASSERT(vd->file || VD_DSKIMG(vd)); in vd_dskimg_rw()
882 ASSERT(vd->vdisk_bsize == DEV_BSIZE); in vd_dskimg_rw()
884 if ((status = vd_dskimg_io_params(vd, slice, &offset, &len)) != 0) in vd_dskimg_rw()
885 return ((status == ENODATA)? 0: -1); in vd_dskimg_rw()
887 if (vd->volume) { in vd_dskimg_rw()
894 buf.b_edev = vd->dev[0]; in vd_dskimg_rw()
907 if (ldi_strategy(vd->ldi_handle[0], &buf) != 0) { in vd_dskimg_rw()
909 return (-1); in vd_dskimg_rw()
914 return (-1); in vd_dskimg_rw()
921 return (len - resid); in vd_dskimg_rw()
924 ASSERT(vd->file); in vd_dskimg_rw()
927 vd->file_vnode, data, len, offset * DEV_BSIZE, UIO_SYSSPACE, FSYNC, in vd_dskimg_rw()
931 return (-1); in vd_dskimg_rw()
943 * configuration. The default label has all slice sizes set to 0 (except
944 * slice 2 which is the entire disk) to force the user to write a valid
948 * disk_size - the disk size in bytes
949 * bsize - the disk block size in bytes
950 * label - the returned default label.
980 * +-----------+--------+---------+--------+ in vd_build_default_label()
981 * | disk_size | < 2MB | 2MB-4GB | >= 8GB | in vd_build_default_label()
982 * +-----------+--------+---------+--------+ in vd_build_default_label()
985 * +-----------+--------+---------+--------+ in vd_build_default_label()
991 * ncyl = pcyl - acyl in vd_build_default_label()
1001 label->dkl_nhead = 96; in vd_build_default_label()
1002 label->dkl_nsect = 768; in vd_build_default_label()
1006 label->dkl_nhead = 1; in vd_build_default_label()
1007 label->dkl_nsect = 600; in vd_build_default_label()
1011 label->dkl_nhead = 1; in vd_build_default_label()
1012 label->dkl_nsect = 200; in vd_build_default_label()
1015 label->dkl_pcyl = disk_size / in vd_build_default_label()
1016 (label->dkl_nsect * label->dkl_nhead * bsize); in vd_build_default_label()
1018 if (label->dkl_pcyl == 0) in vd_build_default_label()
1019 label->dkl_pcyl = 1; in vd_build_default_label()
1021 label->dkl_acyl = 0; in vd_build_default_label()
1023 if (label->dkl_pcyl > 2) in vd_build_default_label()
1024 label->dkl_acyl = 2; in vd_build_default_label()
1026 label->dkl_ncyl = label->dkl_pcyl - label->dkl_acyl; in vd_build_default_label()
1027 label->dkl_write_reinstruct = 0; in vd_build_default_label()
1028 label->dkl_read_reinstruct = 0; in vd_build_default_label()
1029 label->dkl_rpm = 7200; in vd_build_default_label()
1030 label->dkl_apc = 0; in vd_build_default_label()
1031 label->dkl_intrlv = 0; in vd_build_default_label()
1034 PR0("setup: ncyl=%d nhead=%d nsec=%d\n", label->dkl_pcyl, in vd_build_default_label()
1035 label->dkl_nhead, label->dkl_nsect); in vd_build_default_label()
1037 (label->dkl_pcyl * label->dkl_nhead * in vd_build_default_label()
1038 label->dkl_nsect * bsize)); in vd_build_default_label()
1046 (void) snprintf(label->dkl_asciilabel, LEN_DKL_ASCII, in vd_build_default_label()
1047 "SUN-DiskImage-%ld%cB cyl %d alt %d hd %d sec %d", in vd_build_default_label()
1049 label->dkl_ncyl, label->dkl_acyl, label->dkl_nhead, in vd_build_default_label()
1050 label->dkl_nsect); in vd_build_default_label()
1053 label->dkl_vtoc.v_version = V_EXTVERSION; in vd_build_default_label()
1054 label->dkl_vtoc.v_nparts = V_NUMPAR; in vd_build_default_label()
1055 label->dkl_vtoc.v_sanity = VTOC_SANE; in vd_build_default_label()
1056 label->dkl_vtoc.v_part[VD_ENTIRE_DISK_SLICE].p_tag = V_BACKUP; in vd_build_default_label()
1057 label->dkl_map[VD_ENTIRE_DISK_SLICE].dkl_cylno = 0; in vd_build_default_label()
1058 label->dkl_map[VD_ENTIRE_DISK_SLICE].dkl_nblk = label->dkl_ncyl * in vd_build_default_label()
1059 label->dkl_nhead * label->dkl_nsect; in vd_build_default_label()
1060 label->dkl_magic = DKL_MAGIC; in vd_build_default_label()
1061 label->dkl_cksum = vd_lbl2cksum(label); in vd_build_default_label()
1073 * vd - disk on which the operation is performed.
1074 * label - the data to be written.
1077 * 0 - success.
1078 * n > 0 - error, n indicates the errno code.
1096 if (label->dkl_acyl == 0) { in vd_dskimg_set_vtoc()
1101 cyl = label->dkl_ncyl + label->dkl_acyl - 1; in vd_dskimg_set_vtoc()
1102 head = label->dkl_nhead - 1; in vd_dskimg_set_vtoc()
1104 blk = (cyl * ((label->dkl_nhead * label->dkl_nsect) - label->dkl_apc)) + in vd_dskimg_set_vtoc()
1105 (head * label->dkl_nsect); in vd_dskimg_set_vtoc()
1115 if (sec >= label->dkl_nsect) { in vd_dskimg_set_vtoc()
1143 * vd - disk on which the operation is performed.
1144 * blkp - pointer to the block number
1147 * 0 - success
1148 * ENOSPC - disk has no space to store a device id
1157 if (vd->vdisk_label == VD_DISK_LABEL_UNK) { in vd_dskimg_get_devid_block()
1165 if (vd->vdisk_label == VD_DISK_LABEL_EFI) { in vd_dskimg_get_devid_block()
1168 * the reserved slice in vd_dskimg_get_devid_block()
1170 if (vd->efi_reserved == -1) { in vd_dskimg_get_devid_block()
1171 PR0("EFI disk has no reserved slice"); in vd_dskimg_get_devid_block()
1175 *blkp = vd->slices[vd->efi_reserved].start; in vd_dskimg_get_devid_block()
1179 ASSERT(vd->vdisk_label == VD_DISK_LABEL_VTOC); in vd_dskimg_get_devid_block()
1182 if (vd->dk_geom.dkg_acyl < 2) { in vd_dskimg_get_devid_block()
1184 "(acyl=%u)", vd->dk_geom.dkg_acyl); in vd_dskimg_get_devid_block()
1189 cyl = vd->dk_geom.dkg_ncyl + vd->dk_geom.dkg_acyl - 2; in vd_dskimg_get_devid_block()
1190 spc = vd->dk_geom.dkg_nhead * vd->dk_geom.dkg_nsect; in vd_dskimg_get_devid_block()
1191 head = vd->dk_geom.dkg_nhead - 1; in vd_dskimg_get_devid_block()
1193 *blkp = (cyl * (spc - vd->dk_geom.dkg_apc)) + in vd_dskimg_get_devid_block()
1194 (head * vd->dk_geom.dkg_nsect) + 1; in vd_dskimg_get_devid_block()
1200 * Return the checksum of a disk block containing an on-disk devid.
1210 for (i = 0; i < ((DEV_BSIZE - sizeof (int)) / sizeof (int)); i++) in vd_dkdevid2cksum()
1224 * vd - disk on which the operation is performed.
1225 * devid - the return address of the device ID.
1228 * 0 - success
1229 * EIO - I/O error while trying to access the disk image
1230 * EINVAL - no valid device id was found
1231 * ENOSPC - disk has no space to store a device id
1241 ASSERT(vd->vdisk_bsize == DEV_BSIZE); in vd_dskimg_read_devid()
1257 if ((dkdevid->dkd_rev_hi != DK_DEVID_REV_MSB) || in vd_dskimg_read_devid()
1258 (dkdevid->dkd_rev_lo != DK_DEVID_REV_LSB)) { in vd_dskimg_read_devid()
1275 if (ddi_devid_valid((ddi_devid_t)&dkdevid->dkd_devid) != DDI_SUCCESS) { in vd_dskimg_read_devid()
1283 sz = ddi_devid_sizeof((ddi_devid_t)&dkdevid->dkd_devid); in vd_dskimg_read_devid()
1285 bcopy(&dkdevid->dkd_devid, *devid, sz); in vd_dskimg_read_devid()
1301 * vd - disk on which the operation is performed.
1302 * devid - the device ID to store.
1305 * 0 - success
1306 * EIO - I/O error while trying to access the disk image
1307 * ENOSPC - disk has no space to store a device id
1317 ASSERT(vd->vdisk_bsize == DEV_BSIZE); in vd_dskimg_write_devid()
1330 dkdevid->dkd_rev_hi = DK_DEVID_REV_MSB; in vd_dskimg_write_devid()
1331 dkdevid->dkd_rev_lo = DK_DEVID_REV_LSB; in vd_dskimg_write_devid()
1334 bcopy(devid, &dkdevid->dkd_devid, ddi_devid_sizeof(devid)); in vd_dskimg_write_devid()
1364 * vd - disk on which the operation is performed.
1365 * operation - operation to execute: read (VD_OP_BREAD) or
1367 * data - buffer where data are read to or written from.
1368 * blk - starting block for the operation.
1369 * len - number of bytes to read or write.
1372 * 0 - success
1373 * n != 0 - error.
1384 ASSERT(!vd->file); in vd_do_scsi_rdwr()
1385 ASSERT(!vd->volume); in vd_do_scsi_rdwr()
1386 ASSERT(vd->vdisk_bsize > 0); in vd_do_scsi_rdwr()
1388 max_sectors = vd->max_xfer_sz; in vd_do_scsi_rdwr()
1389 nblk = (len / vd->vdisk_bsize); in vd_do_scsi_rdwr()
1391 if (len % vd->vdisk_bsize != 0) in vd_do_scsi_rdwr()
1412 if (blk < (2 << 20) && nsectors <= 0xff && !vd->is_atapi_dev) { in vd_do_scsi_rdwr()
1429 ucmd.uscsi_buflen = nsectors * vd->backend_bsize; in vd_do_scsi_rdwr()
1444 status = ldi_ioctl(vd->ldi_handle[VD_ENTIRE_DISK_SLICE], in vd_do_scsi_rdwr()
1445 USCSICMD, (intptr_t)&ucmd, (vd->open_flags | FKIOCTL), in vd_do_scsi_rdwr()
1473 nblk -= nsectors; in vd_do_scsi_rdwr()
1474 data += nsectors * vd->vdisk_bsize; in vd_do_scsi_rdwr()
1491 * vd - disk on which the operation is performed.
1492 * operation - operation to execute: read (VD_OP_BREAD) or
1494 * data - buffer where data are read to or written from.
1495 * blk - starting block for the operation.
1496 * len - number of bytes to read or write.
1499 * 0 - success
1500 * n != 0 - error.
1513 if (vd->backend_bsize == 0) { in vd_scsi_rdwr()
1529 if (vd->vdisk_bsize == vd->backend_bsize) in vd_scsi_rdwr()
1532 if (vd->vdisk_bsize > vd->backend_bsize) in vd_scsi_rdwr()
1551 * |<--------------->| in vd_scsi_rdwr()
1553 * --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+- virtual disk: in vd_scsi_rdwr()
1555 * --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+- vd->vdisk_bsize in vd_scsi_rdwr()
1559 * --+-----+-----+-----+-----+-----+-----+-----+-- physical disk: in vd_scsi_rdwr()
1561 * --+-----+-----+-----+-----+-----+-----+-----+-- vd->backend_bsize in vd_scsi_rdwr()
1563 * |<--------------------->| in vd_scsi_rdwr()
1568 pblk = (vblk * vd->vdisk_bsize) / vd->backend_bsize; in vd_scsi_rdwr()
1569 delta = (vblk * vd->vdisk_bsize) - (pblk * vd->backend_bsize); in vd_scsi_rdwr()
1570 pnblk = ((delta + vlen - 1) / vd->backend_bsize) + 1; in vd_scsi_rdwr()
1571 plen = pnblk * vd->backend_bsize; in vd_scsi_rdwr()
1590 * a single-slice disk.
1593 * vd - single-slice disk to read from
1594 * data - buffer where data should be read to
1595 * offset - offset in byte where the read should start
1596 * length - number of bytes to read
1599 * n >= 0 - success, n indicates the number of bytes read
1600 * -1 - error
1606 uint_t limit = vd->flabel_limit * vd->vdisk_bsize; in vd_slice_flabel_read()
1608 ASSERT(vd->vdisk_type == VD_DISK_TYPE_SLICE); in vd_slice_flabel_read()
1609 ASSERT(vd->flabel != NULL); in vd_slice_flabel_read()
1616 if (offset < vd->flabel_size) { in vd_slice_flabel_read()
1618 if (offset + length <= vd->flabel_size) { in vd_slice_flabel_read()
1619 bcopy(vd->flabel + offset, data, length); in vd_slice_flabel_read()
1623 n = vd->flabel_size - offset; in vd_slice_flabel_read()
1624 bcopy(vd->flabel + offset, data, n); in vd_slice_flabel_read()
1630 bzero(data, length - n); in vd_slice_flabel_read()
1634 bzero(data, limit - offset - n); in vd_slice_flabel_read()
1635 return (limit - offset); in vd_slice_flabel_read()
1644 * a single-slice disk. Write operations are actually faked and return
1649 * vd - single-slice disk to write to
1650 * data - buffer where data should be written from
1651 * offset - offset in byte where the write should start
1652 * length - number of bytes to written
1655 * n >= 0 - success, n indicates the number of bytes written
1656 * -1 - error
1661 uint_t limit = vd->flabel_limit * vd->vdisk_bsize; in vd_slice_flabel_write()
1666 ASSERT(vd->vdisk_type == VD_DISK_TYPE_SLICE); in vd_slice_flabel_write()
1667 ASSERT(vd->flabel != NULL); in vd_slice_flabel_write()
1677 if (vd->vdisk_label == VD_DISK_LABEL_VTOC && in vd_slice_flabel_write()
1678 offset == 0 && length == vd->vdisk_bsize) { in vd_slice_flabel_write()
1682 if (label->dkl_magic != DKL_MAGIC || in vd_slice_flabel_write()
1683 label->dkl_cksum != vd_lbl2cksum(label)) in vd_slice_flabel_write()
1684 return (-1); in vd_slice_flabel_write()
1694 return (-1); in vd_slice_flabel_write()
1702 * This function simulates a raw read or write operation to a single-slice
1717 * In case of an error, for example if the slice is empty or parameters
1718 * are invalid, then the function returns a non-zero value different
1723 * vd - single-slice disk on which the operation is performed
1724 * slice - slice on which the operation is performed,
1727 * operation - operation to execute: read (VD_OP_BREAD) or
1729 * datap - pointer to the buffer where data are read to
1732 * blkp - pointer to the starting block for the operation.
1735 * lengthp - pointer to the number of bytes to read or write.
1740 * 0 - read/write operation is completed
1741 * EAGAIN - read/write operation is not completed
1742 * other values - error
1745 vd_slice_fake_rdwr(vd_t *vd, int slice, int operation, caddr_t *datap, in vd_slice_fake_rdwr() argument
1754 size_t bsize = vd->vdisk_bsize; in vd_slice_fake_rdwr()
1756 ASSERT(vd->vdisk_type == VD_DISK_TYPE_SLICE); in vd_slice_fake_rdwr()
1757 ASSERT(slice != 0); in vd_slice_fake_rdwr()
1764 * If this is not a raw I/O or an I/O from a full disk slice then in vd_slice_fake_rdwr()
1765 * this is an I/O to/from an empty slice. in vd_slice_fake_rdwr()
1767 if (slice != VD_SLICE_NONE && in vd_slice_fake_rdwr()
1768 (slice != VD_ENTIRE_DISK_SLICE || in vd_slice_fake_rdwr()
1769 vd->vdisk_label != VD_DISK_LABEL_VTOC) && in vd_slice_fake_rdwr()
1770 (slice != VD_EFI_WD_SLICE || in vd_slice_fake_rdwr()
1771 vd->vdisk_label != VD_DISK_LABEL_EFI)) { in vd_slice_fake_rdwr()
1784 if (n == -1) in vd_slice_fake_rdwr()
1792 length -= n; in vd_slice_fake_rdwr()
1800 if (vd->vdisk_label == VD_DISK_LABEL_VTOC && in vd_slice_fake_rdwr()
1801 slice == VD_ENTIRE_DISK_SLICE) { in vd_slice_fake_rdwr()
1806 if (vd->vdisk_label == VD_DISK_LABEL_EFI) { in vd_slice_fake_rdwr()
1808 ablk = vd->vdisk_size - asize; in vd_slice_fake_rdwr()
1810 ASSERT(vd->vdisk_label == VD_DISK_LABEL_VTOC); in vd_slice_fake_rdwr()
1811 ASSERT(vd->dk_geom.dkg_apc == 0); in vd_slice_fake_rdwr()
1813 csize = vd->dk_geom.dkg_nhead * vd->dk_geom.dkg_nsect; in vd_slice_fake_rdwr()
1814 ablk = vd->dk_geom.dkg_ncyl * csize; in vd_slice_fake_rdwr()
1815 asize = vd->dk_geom.dkg_acyl * csize; in vd_slice_fake_rdwr()
1842 alen -= (ablk - aoff); in vd_slice_fake_rdwr()
1847 alen = ablk + asize - aoff; in vd_slice_fake_rdwr()
1853 bzero(data + (aoff - blk) * bsize, alen); in vd_slice_fake_rdwr()
1855 if (vd->vdisk_label == VD_DISK_LABEL_VTOC) { in vd_slice_fake_rdwr()
1858 ablk += (label->dkl_acyl - 1) * csize + in vd_slice_fake_rdwr()
1859 (label->dkl_nhead - 1) * label->dkl_nsect; in vd_slice_fake_rdwr()
1866 (ablk + sec - blk) * bsize, in vd_slice_fake_rdwr()
1873 length -= alen; in vd_slice_fake_rdwr()
1878 ASSERT(length == 0 || blk >= vd->flabel_limit); in vd_slice_fake_rdwr()
1885 *blkp = blk - vd->flabel_limit; in vd_slice_fake_rdwr()
1896 if (vd->file) { in vd_flush_write()
1897 status = VOP_FSYNC(vd->file_vnode, FSYNC, kcred, NULL); in vd_flush_write()
1899 status = ldi_ioctl(vd->ldi_handle[0], DKIOCFLUSHWRITECACHE, in vd_flush_write()
1900 (intptr_t)NULL, vd->open_flags | FKIOCTL, kcred, &rval); in vd_flush_write()
1910 vd_task_t *task = (vd_task_t *)buf->b_private; in vd_bio_task()
1911 vd_t *vd = task->vd; in vd_bio_task()
1915 ASSERT(vd->vdisk_bsize == DEV_BSIZE); in vd_bio_task()
1917 if (vd->zvol) { in vd_bio_task()
1919 status = ldi_strategy(vd->ldi_handle[0], buf); in vd_bio_task()
1923 ASSERT(vd->file); in vd_bio_task()
1925 status = vn_rdwr((buf->b_flags & B_READ)? UIO_READ : UIO_WRITE, in vd_bio_task()
1926 vd->file_vnode, buf->b_un.b_addr, buf->b_bcount, in vd_bio_task()
1927 buf->b_lblkno * DEV_BSIZE, UIO_SYSSPACE, 0, in vd_bio_task()
1931 buf->b_resid = resid; in vd_bio_task()
1950 ASSERT((bp->b_flags & B_DONE) == 0); in vd_biodone()
1951 ASSERT(SEMA_HELD(&bp->b_sem)); in vd_biodone()
1953 bp->b_flags |= B_DONE; in vd_biodone()
1954 sema_v(&bp->b_io); in vd_biodone()
1961 * EINPROGRESS - operation was successfully started
1962 * EIO - encountered LDC (aka. task error)
1963 * 0 - operation completed successfully
1966 * sets request->status = <disk operation status>
1972 vd_t *vd = task->vd; in vd_start_bio()
1973 vd_dring_payload_t *request = task->request; in vd_start_bio()
1974 struct buf *buf = &task->buf; in vd_start_bio()
1976 int slice; in vd_start_bio() local
1984 slice = request->slice; in vd_start_bio()
1986 ASSERT(slice == VD_SLICE_NONE || slice < vd->nslices); in vd_start_bio()
1987 ASSERT((request->operation == VD_OP_BREAD) || in vd_start_bio()
1988 (request->operation == VD_OP_BWRITE)); in vd_start_bio()
1990 if (request->nbytes == 0) { in vd_start_bio()
1992 request->status = EINVAL; in vd_start_bio()
1997 (request->operation == VD_OP_BREAD) ? "Read" : "Write", in vd_start_bio()
1998 request->nbytes, request->addr); in vd_start_bio()
2004 if (request->operation == VD_OP_BWRITE && !(vd->open_flags & FWRITE)) { in vd_start_bio()
2005 PR0("write fails because backend is opened read-only"); in vd_start_bio()
2006 request->nbytes = 0; in vd_start_bio()
2007 request->status = EROFS; in vd_start_bio()
2014 status = ldc_mem_map(task->mhdl, request->cookie, request->ncookies, in vd_start_bio()
2015 mtype, (request->operation == VD_OP_BREAD) ? LDC_MEM_W : LDC_MEM_R, in vd_start_bio()
2023 * The buffer size has to be 8-byte aligned, so the client should have in vd_start_bio()
2024 * sent a buffer which size is roundup to the next 8-byte aligned value. in vd_start_bio()
2026 buflen = P2ROUNDUP(request->nbytes, 8); in vd_start_bio()
2028 status = ldc_mem_acquire(task->mhdl, 0, buflen); in vd_start_bio()
2030 (void) ldc_mem_unmap(task->mhdl); in vd_start_bio()
2035 offset = request->addr; in vd_start_bio()
2036 nbytes = request->nbytes; in vd_start_bio()
2040 request->nbytes = 0; in vd_start_bio()
2042 if (vd->vdisk_type == VD_DISK_TYPE_SLICE) { in vd_start_bio()
2044 if (slice != 0) { in vd_start_bio()
2046 rv = vd_slice_fake_rdwr(vd, slice, request->operation, in vd_start_bio()
2050 request->nbytes = nbytes - length; in vd_start_bio()
2053 request->status = 0; in vd_start_bio()
2058 request->nbytes = 0; in vd_start_bio()
2059 request->status = EIO; in vd_start_bio()
2070 * We need to continue the I/O from the slice backend to in vd_start_bio()
2074 * The backend is entirely mapped to slice 0 so we just in vd_start_bio()
2075 * have to complete the I/O from that slice. in vd_start_bio()
2077 slice = 0; in vd_start_bio()
2080 } else if (vd->volume || vd->file) { in vd_start_bio()
2082 rv = vd_dskimg_io_params(vd, slice, &offset, &length); in vd_start_bio()
2084 request->status = (rv == ENODATA)? 0: EIO; in vd_start_bio()
2087 slice = 0; in vd_start_bio()
2089 } else if (slice == VD_SLICE_NONE) { in vd_start_bio()
2097 * In the future if we have non-SCSI disks we would need in vd_start_bio()
2102 rv = vd_scsi_rdwr(vd, request->operation, bufaddr, offset, in vd_start_bio()
2105 request->status = EIO; in vd_start_bio()
2107 request->nbytes = length; in vd_start_bio()
2108 request->status = 0; in vd_start_bio()
2115 buf->b_flags = B_BUSY; in vd_start_bio()
2116 buf->b_bcount = length; in vd_start_bio()
2117 buf->b_lblkno = offset; in vd_start_bio()
2118 buf->b_bufsize = buflen; in vd_start_bio()
2119 buf->b_edev = vd->dev[slice]; in vd_start_bio()
2120 buf->b_un.b_addr = bufaddr; in vd_start_bio()
2121 buf->b_iodone = vd_biodone; in vd_start_bio()
2123 if (vd->file || vd->zvol) { in vd_start_bio()
2132 if (request->operation == VD_OP_BREAD) { in vd_start_bio()
2133 buf->b_flags |= B_READ; in vd_start_bio()
2145 buf->b_flags |= B_WRITE | B_ASYNC; in vd_start_bio()
2158 task->write_index = vd->write_index; in vd_start_bio()
2159 vd->write_queue[task->write_index] = buf; in vd_start_bio()
2160 vd->write_index = in vd_start_bio()
2161 VD_WRITE_INDEX_NEXT(vd, vd->write_index); in vd_start_bio()
2164 buf->b_private = task; in vd_start_bio()
2166 ASSERT(vd->ioq != NULL); in vd_start_bio()
2168 request->status = 0; in vd_start_bio()
2169 (void) ddi_taskq_dispatch(task->vd->ioq, vd_bio_task, buf, in vd_start_bio()
2174 if (request->operation == VD_OP_BREAD) { in vd_start_bio()
2175 buf->b_flags |= B_READ; in vd_start_bio()
2177 buf->b_flags |= B_WRITE; in vd_start_bio()
2181 buf->b_lblkno = offset << vd->vio_bshift; in vd_start_bio()
2183 request->status = ldi_strategy(vd->ldi_handle[slice], buf); in vd_start_bio()
2197 if (request->status == 0) in vd_start_bio()
2204 rv = ldc_mem_release(task->mhdl, 0, buflen); in vd_start_bio()
2209 rv = ldc_mem_unmap(task->mhdl); in vd_start_bio()
2252 mutex_enter(&vd->lock); in vd_need_reset()
2253 vd->reset_state = B_TRUE; in vd_need_reset()
2254 vd->reset_ldc = reset_ldc; in vd_need_reset()
2255 mutex_exit(&vd->lock); in vd_need_reset()
2261 * "vd_recv_msg", as it waits for tasks - otherwise a deadlock can occur.
2268 mutex_enter(&vd->lock); in vd_reset_if_needed()
2269 if (!vd->reset_state) { in vd_reset_if_needed()
2270 ASSERT(!vd->reset_ldc); in vd_reset_if_needed()
2271 mutex_exit(&vd->lock); in vd_reset_if_needed()
2274 mutex_exit(&vd->lock); in vd_reset_if_needed()
2280 * out from under it; defer checking vd->reset_ldc, as one of the in vd_reset_if_needed()
2283 if (vd->ioq != NULL) in vd_reset_if_needed()
2284 ddi_taskq_wait(vd->ioq); in vd_reset_if_needed()
2285 ddi_taskq_wait(vd->completionq); in vd_reset_if_needed()
2292 if ((vd->initialized & VD_DRING) && in vd_reset_if_needed()
2293 ((status = ldc_mem_dring_unmap(vd->dring_handle)) != 0)) in vd_reset_if_needed()
2299 if (vd->vio_msgp != NULL) { in vd_reset_if_needed()
2300 kmem_free(vd->vio_msgp, vd->max_msglen); in vd_reset_if_needed()
2301 vd->vio_msgp = NULL; in vd_reset_if_needed()
2305 if (vd->inband_task.msg != NULL) { in vd_reset_if_needed()
2306 kmem_free(vd->inband_task.msg, vd->max_msglen); in vd_reset_if_needed()
2307 vd->inband_task.msg = NULL; in vd_reset_if_needed()
2310 mutex_enter(&vd->lock); in vd_reset_if_needed()
2312 if (vd->reset_ldc) in vd_reset_if_needed()
2314 if (vd->reset_ldc && ((status = ldc_down(vd->ldc_handle)) != 0)) in vd_reset_if_needed()
2320 vd->initialized &= ~(VD_SID | VD_SEQ_NUM | VD_DRING); in vd_reset_if_needed()
2321 vd->state = VD_STATE_INIT; in vd_reset_if_needed()
2322 vd->max_msglen = sizeof (vio_msg_t); /* baseline vio message size */ in vd_reset_if_needed()
2325 vd->vio_msgp = kmem_alloc(vd->max_msglen, KM_SLEEP); in vd_reset_if_needed()
2328 (void) ldc_up(vd->ldc_handle); in vd_reset_if_needed()
2330 vd->reset_state = B_FALSE; in vd_reset_if_needed()
2331 vd->reset_ldc = B_FALSE; in vd_reset_if_needed()
2333 mutex_exit(&vd->lock); in vd_reset_if_needed()
2346 status = ddi_taskq_dispatch(vd->startq, vd_recv_msg, vd, DDI_SLEEP); in vd_mark_in_reset()
2362 if (vd->reset_state) in vd_mark_elem_done()
2366 if ((status = VIO_DRING_ACQUIRE(&otd, vd->dring_mtype, in vd_mark_elem_done()
2367 vd->dring_handle, idx, idx)) != 0) { in vd_mark_elem_done()
2377 accepted = (elem->hdr.dstate == VIO_DESC_ACCEPTED); in vd_mark_elem_done()
2379 elem->payload.nbytes = elem_nbytes; in vd_mark_elem_done()
2380 elem->payload.status = elem_status; in vd_mark_elem_done()
2381 elem->hdr.dstate = VIO_DESC_DONE; in vd_mark_elem_done()
2388 if ((status = VIO_DRING_RELEASE(vd->dring_mtype, in vd_mark_elem_done()
2389 vd->dring_handle, idx, idx)) != 0) { in vd_mark_elem_done()
2405 * 0 - operation completed successfully
2406 * EIO - encountered LDC / task error
2409 * sets request->status = <disk operation status>
2416 vd_t *vd = task->vd; in vd_complete_bio()
2417 vd_dring_payload_t *request = task->request; in vd_complete_bio()
2418 struct buf *buf = &task->buf; in vd_complete_bio()
2424 ASSERT(task->msg != NULL); in vd_complete_bio()
2425 ASSERT(task->msglen >= sizeof (*task->msg)); in vd_complete_bio()
2427 if (buf->b_flags & B_DONE) { in vd_complete_bio()
2434 request->status = geterror(buf); in vd_complete_bio()
2442 request->status = biowait(buf); in vd_complete_bio()
2445 if (buf->b_flags & B_ASYNC) { in vd_complete_bio()
2453 ASSERT(task->request->operation == VD_OP_BWRITE); in vd_complete_bio()
2455 wid = task->write_index; in vd_complete_bio()
2458 if (vd->write_queue[wid] != NULL) { in vd_complete_bio()
2460 vd->write_queue[wid] = NULL; in vd_complete_bio()
2470 while (vd->write_queue[wid] != NULL) { in vd_complete_bio()
2471 (void) biowait(vd->write_queue[wid]); in vd_complete_bio()
2472 vd->write_queue[wid] = NULL; in vd_complete_bio()
2481 request->status = vd_flush_write(vd); in vd_complete_bio()
2486 request->status = 0; in vd_complete_bio()
2492 request->nbytes += buf->b_bcount - buf->b_resid; in vd_complete_bio()
2495 if (!vd->reset_state) in vd_complete_bio()
2496 status = ldc_mem_release(task->mhdl, 0, buf->b_bufsize); in vd_complete_bio()
2507 status = ldc_mem_unmap(task->mhdl); in vd_complete_bio()
2529 * arg - opaque pointer to structure containing task to be completed
2540 ASSERT(task->vd != NULL); in vd_notify()
2548 (task->msg->tag.vio_subtype == VIO_SUBTYPE_ACK) ? "ACK" : "NACK"); in vd_notify()
2550 status = send_msg(task->vd->ldc_handle, task->msg, task->msglen); in vd_notify()
2555 vd_mark_in_reset(task->vd); in vd_notify()
2559 vd_need_reset(task->vd, B_TRUE); in vd_notify()
2572 * task - structure containing the request sent from client
2581 vd_t *vd = task->vd; in vd_complete_notify()
2582 vd_dring_payload_t *request = task->request; in vd_complete_notify()
2585 if (!vd->reset_state && (vd->xfer_mode == VIO_DRING_MODE_V1_0)) { in vd_complete_notify()
2586 status = vd_mark_elem_done(vd, task->index, in vd_complete_notify()
2587 request->status, request->nbytes); in vd_complete_notify()
2599 if ((status != 0) || (task->status != 0)) in vd_complete_notify()
2600 task->msg->tag.vio_subtype = VIO_SUBTYPE_NACK; in vd_complete_notify()
2606 if (task->type == VD_NONFINAL_RANGE_TASK) { in vd_complete_notify()
2616 if (!vd->reset_state) in vd_complete_notify()
2627 * arg - opaque pointer to structure containing task to be completed
2676 data_len = vd_buf_len - (sizeof (vd_efi_t) - sizeof (uint64_t)); in vd_get_efi_in()
2677 if (vd_efi->length > data_len) in vd_get_efi_in()
2680 dk_efi->dki_lba = vd_efi->lba; in vd_get_efi_in()
2681 dk_efi->dki_length = vd_efi->length; in vd_get_efi_in()
2682 dk_efi->dki_data = kmem_zalloc(vd_efi->length, KM_SLEEP); in vd_get_efi_in()
2693 len = vd_efi->length; in vd_get_efi_out()
2695 kmem_free(dk_efi->dki_data, len); in vd_get_efi_out()
2705 data_len = vd_buf_len - (sizeof (vd_efi_t) - sizeof (uint64_t)); in vd_set_efi_in()
2706 if (vd_efi->length > data_len) in vd_set_efi_in()
2709 dk_efi->dki_data = kmem_alloc(vd_efi->length, KM_SLEEP); in vd_set_efi_in()
2720 kmem_free(dk_efi->dki_data, vd_efi->length); in vd_set_efi_out()
2732 vd_scsi_len += P2ROUNDUP(vd_scsi->cdb_len, sizeof (uint64_t)); in vd_scsicmd_in()
2733 vd_scsi_len += P2ROUNDUP(vd_scsi->sense_len, sizeof (uint64_t)); in vd_scsicmd_in()
2734 vd_scsi_len += P2ROUNDUP(vd_scsi->datain_len, sizeof (uint64_t)); in vd_scsicmd_in()
2735 vd_scsi_len += P2ROUNDUP(vd_scsi->dataout_len, sizeof (uint64_t)); in vd_scsicmd_in()
2743 uscsi->uscsi_flags = vd_scsi_debug; in vd_scsicmd_in()
2745 if (vd_scsi->options & VD_SCSI_OPT_NORETRY) { in vd_scsicmd_in()
2746 uscsi->uscsi_flags |= USCSI_ISOLATE; in vd_scsicmd_in()
2747 uscsi->uscsi_flags |= USCSI_DIAGNOSE; in vd_scsicmd_in()
2751 switch (vd_scsi->task_attribute) { in vd_scsicmd_in()
2753 uscsi->uscsi_flags |= USCSI_HEAD; in vd_scsicmd_in()
2756 uscsi->uscsi_flags |= USCSI_HTAG; in vd_scsicmd_in()
2759 uscsi->uscsi_flags |= USCSI_OTAG; in vd_scsicmd_in()
2762 uscsi->uscsi_flags |= USCSI_NOTAG; in vd_scsicmd_in()
2767 uscsi->uscsi_timeout = vd_scsi->timeout; in vd_scsicmd_in()
2770 uscsi->uscsi_cdb = (caddr_t)VD_SCSI_DATA_CDB(vd_scsi); in vd_scsicmd_in()
2771 uscsi->uscsi_cdblen = vd_scsi->cdb_len; in vd_scsicmd_in()
2774 if (vd_scsi->sense_len != 0) { in vd_scsicmd_in()
2775 uscsi->uscsi_flags |= USCSI_RQENABLE; in vd_scsicmd_in()
2776 uscsi->uscsi_rqbuf = (caddr_t)VD_SCSI_DATA_SENSE(vd_scsi); in vd_scsicmd_in()
2777 uscsi->uscsi_rqlen = vd_scsi->sense_len; in vd_scsicmd_in()
2780 if (vd_scsi->datain_len != 0 && vd_scsi->dataout_len != 0) { in vd_scsicmd_in()
2785 /* request data-in */ in vd_scsicmd_in()
2786 if (vd_scsi->datain_len != 0) { in vd_scsicmd_in()
2787 uscsi->uscsi_flags |= USCSI_READ; in vd_scsicmd_in()
2788 uscsi->uscsi_buflen = vd_scsi->datain_len; in vd_scsicmd_in()
2789 uscsi->uscsi_bufaddr = (char *)VD_SCSI_DATA_IN(vd_scsi); in vd_scsicmd_in()
2792 /* request data-out */ in vd_scsicmd_in()
2793 if (vd_scsi->dataout_len != 0) { in vd_scsicmd_in()
2794 uscsi->uscsi_buflen = vd_scsi->dataout_len; in vd_scsicmd_in()
2795 uscsi->uscsi_bufaddr = (char *)VD_SCSI_DATA_OUT(vd_scsi); in vd_scsicmd_in()
2808 vd_scsi->cmd_status = uscsi->uscsi_status; in vd_scsicmd_out()
2811 if ((uscsi->uscsi_flags & USCSI_RQENABLE) && in vd_scsicmd_out()
2812 (uscsi->uscsi_status == STATUS_CHECK || in vd_scsicmd_out()
2813 uscsi->uscsi_status == STATUS_TERMINATED)) { in vd_scsicmd_out()
2814 vd_scsi->sense_status = uscsi->uscsi_rqstatus; in vd_scsicmd_out()
2815 if (uscsi->uscsi_rqstatus == STATUS_GOOD) in vd_scsicmd_out()
2816 vd_scsi->sense_len -= uscsi->uscsi_rqresid; in vd_scsicmd_out()
2818 vd_scsi->sense_len = 0; in vd_scsicmd_out()
2820 vd_scsi->sense_len = 0; in vd_scsicmd_out()
2823 if (uscsi->uscsi_status != STATUS_GOOD) { in vd_scsicmd_out()
2824 vd_scsi->dataout_len = 0; in vd_scsicmd_out()
2825 vd_scsi->datain_len = 0; in vd_scsicmd_out()
2829 if (uscsi->uscsi_flags & USCSI_READ) { in vd_scsicmd_out()
2831 vd_scsi->datain_len -= uscsi->uscsi_resid; in vd_scsicmd_out()
2832 vd_scsi->dataout_len = 0; in vd_scsicmd_out()
2835 vd_scsi->datain_len = 0; in vd_scsicmd_out()
2836 vd_scsi->dataout_len -= uscsi->uscsi_resid; in vd_scsicmd_out()
2846 count = (sizeof (struct dk_label)) / (sizeof (short)) - 1; in vd_lbl2cksum()
2849 while (count--) { in vd_lbl2cksum()
2865 ASSERT(vtoc->v_nparts == V_NUMPAR); in vd_vtocgeom_to_label()
2866 ASSERT(vtoc->v_sanity == VTOC_SANE); in vd_vtocgeom_to_label()
2870 label->dkl_ncyl = geom->dkg_ncyl; in vd_vtocgeom_to_label()
2871 label->dkl_acyl = geom->dkg_acyl; in vd_vtocgeom_to_label()
2872 label->dkl_pcyl = geom->dkg_pcyl; in vd_vtocgeom_to_label()
2873 label->dkl_nhead = geom->dkg_nhead; in vd_vtocgeom_to_label()
2874 label->dkl_nsect = geom->dkg_nsect; in vd_vtocgeom_to_label()
2875 label->dkl_intrlv = geom->dkg_intrlv; in vd_vtocgeom_to_label()
2876 label->dkl_apc = geom->dkg_apc; in vd_vtocgeom_to_label()
2877 label->dkl_rpm = geom->dkg_rpm; in vd_vtocgeom_to_label()
2878 label->dkl_write_reinstruct = geom->dkg_write_reinstruct; in vd_vtocgeom_to_label()
2879 label->dkl_read_reinstruct = geom->dkg_read_reinstruct; in vd_vtocgeom_to_label()
2881 label->dkl_vtoc.v_nparts = V_NUMPAR; in vd_vtocgeom_to_label()
2882 label->dkl_vtoc.v_sanity = VTOC_SANE; in vd_vtocgeom_to_label()
2883 label->dkl_vtoc.v_version = vtoc->v_version; in vd_vtocgeom_to_label()
2885 label->dkl_vtoc.v_timestamp[i] = vtoc->timestamp[i]; in vd_vtocgeom_to_label()
2886 label->dkl_vtoc.v_part[i].p_tag = vtoc->v_part[i].p_tag; in vd_vtocgeom_to_label()
2887 label->dkl_vtoc.v_part[i].p_flag = vtoc->v_part[i].p_flag; in vd_vtocgeom_to_label()
2888 label->dkl_map[i].dkl_cylno = vtoc->v_part[i].p_start / in vd_vtocgeom_to_label()
2889 (label->dkl_nhead * label->dkl_nsect); in vd_vtocgeom_to_label()
2890 label->dkl_map[i].dkl_nblk = vtoc->v_part[i].p_size; in vd_vtocgeom_to_label()
2895 * elements are of type long in vtoc (so 64-bit) and of type in vd_vtocgeom_to_label()
2896 * int in dk_vtoc (so 32-bit). in vd_vtocgeom_to_label()
2898 label->dkl_vtoc.v_bootinfo[0] = vtoc->v_bootinfo[0]; in vd_vtocgeom_to_label()
2899 label->dkl_vtoc.v_bootinfo[1] = vtoc->v_bootinfo[1]; in vd_vtocgeom_to_label()
2900 label->dkl_vtoc.v_bootinfo[2] = vtoc->v_bootinfo[2]; in vd_vtocgeom_to_label()
2901 bcopy(vtoc->v_asciilabel, label->dkl_asciilabel, LEN_DKL_ASCII); in vd_vtocgeom_to_label()
2902 bcopy(vtoc->v_volume, label->dkl_vtoc.v_volume, LEN_DKL_VVOL); in vd_vtocgeom_to_label()
2904 /* re-compute checksum */ in vd_vtocgeom_to_label()
2905 label->dkl_magic = DKL_MAGIC; in vd_vtocgeom_to_label()
2906 label->dkl_cksum = vd_lbl2cksum(label); in vd_vtocgeom_to_label()
2921 geom->dkg_ncyl = label->dkl_ncyl; in vd_label_to_vtocgeom()
2922 geom->dkg_acyl = label->dkl_acyl; in vd_label_to_vtocgeom()
2923 geom->dkg_nhead = label->dkl_nhead; in vd_label_to_vtocgeom()
2924 geom->dkg_nsect = label->dkl_nsect; in vd_label_to_vtocgeom()
2925 geom->dkg_intrlv = label->dkl_intrlv; in vd_label_to_vtocgeom()
2926 geom->dkg_apc = label->dkl_apc; in vd_label_to_vtocgeom()
2927 geom->dkg_rpm = label->dkl_rpm; in vd_label_to_vtocgeom()
2928 geom->dkg_pcyl = label->dkl_pcyl; in vd_label_to_vtocgeom()
2929 geom->dkg_write_reinstruct = label->dkl_write_reinstruct; in vd_label_to_vtocgeom()
2930 geom->dkg_read_reinstruct = label->dkl_read_reinstruct; in vd_label_to_vtocgeom()
2932 vtoc->v_sanity = label->dkl_vtoc.v_sanity; in vd_label_to_vtocgeom()
2933 vtoc->v_version = label->dkl_vtoc.v_version; in vd_label_to_vtocgeom()
2934 vtoc->v_sectorsz = DEV_BSIZE; in vd_label_to_vtocgeom()
2935 vtoc->v_nparts = label->dkl_vtoc.v_nparts; in vd_label_to_vtocgeom()
2937 for (i = 0; i < vtoc->v_nparts; i++) { in vd_label_to_vtocgeom()
2938 vtoc->v_part[i].p_tag = label->dkl_vtoc.v_part[i].p_tag; in vd_label_to_vtocgeom()
2939 vtoc->v_part[i].p_flag = label->dkl_vtoc.v_part[i].p_flag; in vd_label_to_vtocgeom()
2940 vtoc->v_part[i].p_start = label->dkl_map[i].dkl_cylno * in vd_label_to_vtocgeom()
2941 (label->dkl_nhead * label->dkl_nsect); in vd_label_to_vtocgeom()
2942 vtoc->v_part[i].p_size = label->dkl_map[i].dkl_nblk; in vd_label_to_vtocgeom()
2943 vtoc->timestamp[i] = label->dkl_vtoc.v_timestamp[i]; in vd_label_to_vtocgeom()
2948 * elements are of type long in vtoc (so 64-bit) and of type in vd_label_to_vtocgeom()
2949 * int in dk_vtoc (so 32-bit). in vd_label_to_vtocgeom()
2951 vtoc->v_bootinfo[0] = label->dkl_vtoc.v_bootinfo[0]; in vd_label_to_vtocgeom()
2952 vtoc->v_bootinfo[1] = label->dkl_vtoc.v_bootinfo[1]; in vd_label_to_vtocgeom()
2953 vtoc->v_bootinfo[2] = label->dkl_vtoc.v_bootinfo[2]; in vd_label_to_vtocgeom()
2954 bcopy(label->dkl_asciilabel, vtoc->v_asciilabel, LEN_DKL_ASCII); in vd_label_to_vtocgeom()
2955 bcopy(label->dkl_vtoc.v_volume, vtoc->v_volume, LEN_DKL_VVOL); in vd_label_to_vtocgeom()
2959 * Check if a geometry is valid for a single-slice disk. A geometry is
2966 ASSERT(vd->vdisk_type == VD_DISK_TYPE_SLICE); in vd_slice_geom_isvalid()
2967 ASSERT(vd->vdisk_label == VD_DISK_LABEL_VTOC); in vd_slice_geom_isvalid()
2969 if (geom->dkg_ncyl != vd->dk_geom.dkg_ncyl || in vd_slice_geom_isvalid()
2970 geom->dkg_acyl != vd->dk_geom.dkg_acyl || in vd_slice_geom_isvalid()
2971 geom->dkg_nsect != vd->dk_geom.dkg_nsect || in vd_slice_geom_isvalid()
2972 geom->dkg_pcyl != vd->dk_geom.dkg_pcyl) in vd_slice_geom_isvalid()
2979 * Check if a vtoc is valid for a single-slice disk. A vtoc is considered
2989 ASSERT(vd->vdisk_type == VD_DISK_TYPE_SLICE); in vd_slice_vtoc_isvalid()
2990 ASSERT(vd->vdisk_label == VD_DISK_LABEL_VTOC); in vd_slice_vtoc_isvalid()
2992 if (vtoc->v_sanity != vd->vtoc.v_sanity || in vd_slice_vtoc_isvalid()
2993 vtoc->v_version != vd->vtoc.v_version || in vd_slice_vtoc_isvalid()
2994 vtoc->v_nparts != vd->vtoc.v_nparts || in vd_slice_vtoc_isvalid()
2995 strcmp(vtoc->v_volume, vd->vtoc.v_volume) != 0 || in vd_slice_vtoc_isvalid()
2996 strcmp(vtoc->v_asciilabel, vd->vtoc.v_asciilabel) != 0) in vd_slice_vtoc_isvalid()
2999 /* slice 2 should be unchanged */ in vd_slice_vtoc_isvalid()
3000 if (vtoc->v_part[VD_ENTIRE_DISK_SLICE].p_start != in vd_slice_vtoc_isvalid()
3001 vd->vtoc.v_part[VD_ENTIRE_DISK_SLICE].p_start || in vd_slice_vtoc_isvalid()
3002 vtoc->v_part[VD_ENTIRE_DISK_SLICE].p_size != in vd_slice_vtoc_isvalid()
3003 vd->vtoc.v_part[VD_ENTIRE_DISK_SLICE].p_size) in vd_slice_vtoc_isvalid()
3007 * Slice 0 should be mostly unchanged and cover most of the disk. in vd_slice_vtoc_isvalid()
3009 * of this slice mainly because we can't exactly know how it will in vd_slice_vtoc_isvalid()
3012 * We allow slice 0 to be defined as starting on any of the first in vd_slice_vtoc_isvalid()
3015 csize = vd->dk_geom.dkg_nhead * vd->dk_geom.dkg_nsect; in vd_slice_vtoc_isvalid()
3017 if (vtoc->v_part[0].p_start > 4 * csize || in vd_slice_vtoc_isvalid()
3018 vtoc->v_part[0].p_size > vtoc->v_part[VD_ENTIRE_DISK_SLICE].p_size) in vd_slice_vtoc_isvalid()
3021 if (vd->vtoc.v_part[0].p_size >= 4 * csize && in vd_slice_vtoc_isvalid()
3022 vtoc->v_part[0].p_size < vd->vtoc.v_part[0].p_size - 4 *csize) in vd_slice_vtoc_isvalid()
3025 /* any other slice should have a size of 0 */ in vd_slice_vtoc_isvalid()
3026 for (i = 1; i < vtoc->v_nparts; i++) { in vd_slice_vtoc_isvalid()
3028 vtoc->v_part[i].p_size != 0) in vd_slice_vtoc_isvalid()
3036 * Handle ioctls to a disk slice.
3039 * 0 - Indicates that there are no errors in disk operations
3040 * ENOTSUP - Unknown disk label type or unsupported DKIO ioctl
3041 * EINVAL - Not enough room to copy the EFI label
3052 ASSERT(vd->vdisk_type == VD_DISK_TYPE_SLICE); in vd_do_slice_ioctl()
3057 switch (vd->vdisk_label) { in vd_do_slice_ioctl()
3059 /* ioctls for a single slice disk with a VTOC label */ in vd_do_slice_ioctl()
3066 bcopy(&vd->dk_geom, ioctl_arg, sizeof (vd->dk_geom)); in vd_do_slice_ioctl()
3071 bcopy(&vd->vtoc, ioctl_arg, sizeof (vd->vtoc)); in vd_do_slice_ioctl()
3102 /* ioctls for a single slice disk with an EFI label */ in vd_do_slice_ioctl()
3111 len = dk_ioc->dki_length; in vd_do_slice_ioctl()
3112 lba = dk_ioc->dki_lba; in vd_do_slice_ioctl()
3122 (caddr_t)dk_ioc->dki_data, in vd_do_slice_ioctl()
3123 lba * vd->vdisk_bsize, len); in vd_do_slice_ioctl()
3178 bzero(&vd->vtoc, sizeof (struct extvtoc)); in vd_dskimg_validate_efi()
3179 bzero(&vd->dk_geom, sizeof (struct dk_geom)); in vd_dskimg_validate_efi()
3180 bzero(vd->slices, sizeof (vd_slice_t) * VD_MAXPART); in vd_dskimg_validate_efi()
3182 vd->efi_reserved = -1; in vd_dskimg_validate_efi()
3184 nparts = gpt->efi_gpt_NumberOfPartitionEntries; in vd_dskimg_validate_efi()
3193 vd->slices[i].start = gpe[i].efi_gpe_StartingLBA; in vd_dskimg_validate_efi()
3194 vd->slices[i].nblocks = gpe[i].efi_gpe_EndingLBA - in vd_dskimg_validate_efi()
3199 vd->efi_reserved = i; in vd_dskimg_validate_efi()
3203 ASSERT(vd->vdisk_size != 0); in vd_dskimg_validate_efi()
3204 vd->slices[VD_EFI_WD_SLICE].start = 0; in vd_dskimg_validate_efi()
3205 vd->slices[VD_EFI_WD_SLICE].nblocks = vd->vdisk_size; in vd_dskimg_validate_efi()
3226 * vd - disk on which the operation is performed.
3229 * 0 - success.
3230 * EIO - error reading the label from the disk image.
3231 * EINVAL - unknown disk label.
3232 * ENOTSUP - geometry not applicable (EFI label).
3238 struct dk_geom *geom = &vd->dk_geom; in vd_dskimg_validate_geometry()
3239 struct extvtoc *vtoc = &vd->vtoc; in vd_dskimg_validate_geometry()
3255 vd->vdisk_label = VD_DISK_LABEL_EFI; in vd_dskimg_validate_geometry()
3259 vd->vdisk_label = VD_DISK_LABEL_UNK; in vd_dskimg_validate_geometry()
3260 vd_build_default_label(vd->dskimg_size, vd->vdisk_bsize, in vd_dskimg_validate_geometry()
3264 vd->vdisk_label = VD_DISK_LABEL_VTOC; in vd_dskimg_validate_geometry()
3271 bzero(vd->slices, sizeof (vd_slice_t) * VD_MAXPART); in vd_dskimg_validate_geometry()
3272 if (vd->vdisk_label != VD_DISK_LABEL_UNK) { in vd_dskimg_validate_geometry()
3273 for (i = 0; i < vtoc->v_nparts; i++) { in vd_dskimg_validate_geometry()
3274 vd->slices[i].start = vtoc->v_part[i].p_start; in vd_dskimg_validate_geometry()
3275 vd->slices[i].nblocks = vtoc->v_part[i].p_size; in vd_dskimg_validate_geometry()
3286 * 0 - Indicates that there are no errors
3287 * != 0 - Disk operation returned an error
3309 bcopy(&vd->dk_geom, geom, sizeof (struct dk_geom)); in vd_do_dskimg_ioctl()
3319 bcopy(&vd->vtoc, vtoc, sizeof (struct extvtoc)); in vd_do_dskimg_ioctl()
3326 if (geom->dkg_nhead == 0 || geom->dkg_nsect == 0) in vd_do_dskimg_ioctl()
3335 bcopy(ioctl_arg, &vd->dk_geom, sizeof (vd->dk_geom)); in vd_do_dskimg_ioctl()
3340 ASSERT(vd->dk_geom.dkg_nhead != 0 && in vd_do_dskimg_ioctl()
3341 vd->dk_geom.dkg_nsect != 0); in vd_do_dskimg_ioctl()
3344 if (vtoc->v_sanity != VTOC_SANE || in vd_do_dskimg_ioctl()
3345 vtoc->v_sectorsz != DEV_BSIZE || in vd_do_dskimg_ioctl()
3346 vtoc->v_nparts != V_NUMPAR) in vd_do_dskimg_ioctl()
3349 vd_vtocgeom_to_label(vtoc, &vd->dk_geom, &label); in vd_do_dskimg_ioctl()
3365 (caddr_t)efi->dki_data, efi->dki_lba, efi->dki_length) < 0) in vd_do_dskimg_ioctl()
3375 (caddr_t)efi->dki_data, efi->dki_lba, efi->dki_length) < 0) in vd_do_dskimg_ioctl()
3395 if (vd_dskimg_write_devid(vd, vd->dskimg_devid) != 0) { in vd_do_dskimg_ioctl()
3412 if (vd->vdisk_type == VD_DISK_TYPE_SLICE) { in vd_backend_ioctl()
3414 /* slice, file or volume exported as a single slice disk */ in vd_backend_ioctl()
3425 status = ldi_ioctl(vd->ldi_handle[0], cmd, (intptr_t)arg, in vd_backend_ioctl()
3426 vd->open_flags | FKIOCTL, kcred, &rval); in vd_backend_ioctl()
3430 * extended VTOC. Some drivers (in particular non-Sun drivers) in vd_backend_ioctl()
3439 status = ldi_ioctl(vd->ldi_handle[0], cmd, in vd_backend_ioctl()
3440 (intptr_t)&vtoc, vd->open_flags | FKIOCTL, in vd_backend_ioctl()
3450 status = ldi_ioctl(vd->ldi_handle[0], cmd, in vd_backend_ioctl()
3451 (intptr_t)&vtoc, vd->open_flags | FKIOCTL, in vd_backend_ioctl()
3474 * 0 - ioctl operation completed successfully
3475 * != 0 - The LDC error value encountered
3479 * sets request->status to the return value of the ioctl function.
3485 size_t nbytes = request->nbytes; /* modifiable copy */ in vd_do_ioctl()
3488 ASSERT(request->slice < vd->nslices); in vd_do_ioctl()
3489 PR0("Performing %s", ioctl->operation_name); in vd_do_ioctl()
3492 if (ioctl->copyin != NULL) { in vd_do_ioctl()
3495 if ((status = ldc_mem_copy(vd->ldc_handle, buf, 0, &nbytes, in vd_do_ioctl()
3496 request->cookie, request->ncookies, in vd_do_ioctl()
3504 if (ioctl->copyin == VD_IDENTITY_IN) { in vd_do_ioctl()
3506 ioctl->arg = buf; in vd_do_ioctl()
3509 status = (ioctl->copyin)(buf, nbytes, in vd_do_ioctl()
3510 (void *)ioctl->arg); in vd_do_ioctl()
3512 request->status = status; in vd_do_ioctl()
3518 if (ioctl->operation == VD_OP_SCSICMD) { in vd_do_ioctl()
3519 struct uscsi_cmd *uscsi = (struct uscsi_cmd *)ioctl->arg; in vd_do_ioctl()
3522 if (!(vd->open_flags & FWRITE) && in vd_do_ioctl()
3523 !(uscsi->uscsi_flags & USCSI_READ)) { in vd_do_ioctl()
3524 PR0("uscsi fails because backend is opened read-only"); in vd_do_ioctl()
3525 request->status = EROFS; in vd_do_ioctl()
3533 request->status = vd_backend_ioctl(vd, ioctl->cmd, ioctl->arg); in vd_do_ioctl()
3535 if (request->status != 0) { in vd_do_ioctl()
3536 PR0("ioctl(%s) = errno %d", ioctl->cmd_name, request->status); in vd_do_ioctl()
3537 if (ioctl->operation == VD_OP_SCSICMD && in vd_do_ioctl()
3538 ((struct uscsi_cmd *)ioctl->arg)->uscsi_status != 0) in vd_do_ioctl()
3547 request->status = 0; in vd_do_ioctl()
3553 if (ioctl->copyout != NULL) { in vd_do_ioctl()
3558 if (ioctl->copyout != VD_IDENTITY_OUT) in vd_do_ioctl()
3559 (ioctl->copyout)((void *)ioctl->arg, buf); in vd_do_ioctl()
3561 if ((status = ldc_mem_copy(vd->ldc_handle, buf, 0, &nbytes, in vd_do_ioctl()
3562 request->cookie, request->ncookies, in vd_do_ioctl()
3582 * arg - opaque pointer to structure containing task to be completed
3593 ASSERT(task->status == EINPROGRESS); in vd_complete()
3594 ASSERT(task->completef != NULL); in vd_complete()
3596 task->status = task->completef(task); in vd_complete()
3597 if (task->status) in vd_complete()
3598 PR0("%s: Error %d completing task", __func__, task->status); in vd_complete()
3613 vd_t *vd = task->vd; in vd_ioctl()
3614 vd_dring_payload_t *request = task->request; in vd_ioctl()
3616 /* Command (no-copy) operations */ in vd_ioctl()
3621 /* "Get" (copy-out) operations */ in vd_ioctl()
3636 /* "Set" (copy-in) operations */ in vd_ioctl()
3660 ASSERT(request->slice < vd->nslices); in vd_ioctl()
3667 if (request->operation == ioctl[i].operation) { in vd_ioctl()
3668 /* LDC memory operations require 8-byte multiples */ in vd_ioctl()
3671 if (request->operation == VD_OP_GET_EFI || in vd_ioctl()
3672 request->operation == VD_OP_SET_EFI || in vd_ioctl()
3673 request->operation == VD_OP_SCSICMD) { in vd_ioctl()
3674 if (request->nbytes >= ioctl[i].nbytes) in vd_ioctl()
3678 ioctl[i].nbytes, request->nbytes); in vd_ioctl()
3682 if (request->nbytes != ioctl[i].nbytes) { in vd_ioctl()
3685 request->nbytes); in vd_ioctl()
3695 if (!(vd->open_flags & FWRITE) && ioctl[i].write) { in vd_ioctl()
3696 PR0("%s fails because backend is opened read-only", in vd_ioctl()
3698 request->status = EROFS; in vd_ioctl()
3702 if (request->nbytes) in vd_ioctl()
3703 buf = kmem_zalloc(request->nbytes, KM_SLEEP); in vd_ioctl()
3705 if (request->nbytes) in vd_ioctl()
3706 kmem_free(buf, request->nbytes); in vd_ioctl()
3714 vd_t *vd = task->vd; in vd_get_devid()
3715 vd_dring_payload_t *request = task->request; in vd_get_devid()
3721 PR1("Get Device ID, nbytes=%ld", request->nbytes); in vd_get_devid()
3723 if (vd->vdisk_type == VD_DISK_TYPE_SLICE) { in vd_get_devid()
3725 * We don't support devid for single-slice disks because we in vd_get_devid()
3732 request->status = ENOTSUP; in vd_get_devid()
3737 if (vd->dskimg_devid == NULL) { in vd_get_devid()
3739 request->status = ENOENT; in vd_get_devid()
3742 sz = ddi_devid_sizeof(vd->dskimg_devid); in vd_get_devid()
3744 bcopy(vd->dskimg_devid, devid, sz); in vd_get_devid()
3747 if (ddi_lyr_get_devid(vd->dev[request->slice], in vd_get_devid()
3750 request->status = ENOENT; in vd_get_devid()
3755 bufid_len = request->nbytes - sizeof (vd_devid_t) + 1; in vd_get_devid()
3763 bufbytes = request->nbytes; in vd_get_devid()
3766 vd_devid->length = devid_len; in vd_get_devid()
3767 vd_devid->type = DEVID_GETTYPE(devid); in vd_get_devid()
3771 bcopy(devid->did_id, vd_devid->id, len); in vd_get_devid()
3773 request->status = 0; in vd_get_devid()
3775 /* LDC memory operations require 8-byte multiples */ in vd_get_devid()
3776 ASSERT(request->nbytes % sizeof (uint64_t) == 0); in vd_get_devid()
3778 if ((status = ldc_mem_copy(vd->ldc_handle, (caddr_t)vd_devid, 0, in vd_get_devid()
3779 &request->nbytes, request->cookie, request->ncookies, in vd_get_devid()
3784 PR1("post mem_copy: nbytes=%ld", request->nbytes); in vd_get_devid()
3801 status = ldi_ioctl(vd->ldi_handle[0], USCSICMD, (intptr_t)&uscsi, in vd_scsi_reset()
3802 (vd->open_flags | FKIOCTL), kcred, &rval); in vd_scsi_reset()
3810 vd_t *vd = task->vd; in vd_reset()
3811 vd_dring_payload_t *request = task->request; in vd_reset()
3813 ASSERT(request->operation == VD_OP_RESET); in vd_reset()
3814 ASSERT(vd->scsi); in vd_reset()
3818 if (request->nbytes != 0) { in vd_reset()
3820 request->nbytes); in vd_reset()
3824 request->status = vd_scsi_reset(vd); in vd_reset()
3834 vd_t *vd = task->vd; in vd_get_capacity()
3835 vd_dring_payload_t *request = task->request; in vd_get_capacity()
3838 ASSERT(request->operation == VD_OP_GET_CAPACITY); in vd_get_capacity()
3842 nbytes = request->nbytes; in vd_get_capacity()
3856 ASSERT(vd->vdisk_size != 0); in vd_get_capacity()
3858 request->status = 0; in vd_get_capacity()
3860 vd_cap.vdisk_block_size = vd->vdisk_bsize; in vd_get_capacity()
3861 vd_cap.vdisk_size = vd->vdisk_size; in vd_get_capacity()
3863 if ((rv = ldc_mem_copy(vd->ldc_handle, (char *)&vd_cap, 0, &nbytes, in vd_get_capacity()
3864 request->cookie, request->ncookies, LDC_COPY_OUT)) != 0) { in vd_get_capacity()
3878 vd_t *vd = task->vd; in vd_get_access()
3879 vd_dring_payload_t *request = task->request; in vd_get_access()
3881 ASSERT(request->operation == VD_OP_GET_ACCESS); in vd_get_access()
3882 ASSERT(vd->scsi); in vd_get_access()
3886 nbytes = request->nbytes; in vd_get_access()
3894 request->status = ldi_ioctl(vd->ldi_handle[request->slice], MHIOCSTATUS, in vd_get_access()
3895 (intptr_t)NULL, (vd->open_flags | FKIOCTL), kcred, &rval); in vd_get_access()
3897 if (request->status != 0) in vd_get_access()
3902 if ((rv = ldc_mem_copy(vd->ldc_handle, (char *)&access, 0, &nbytes, in vd_get_access()
3903 request->cookie, request->ncookies, LDC_COPY_OUT)) != 0) { in vd_get_access()
3917 vd_t *vd = task->vd; in vd_set_access()
3918 vd_dring_payload_t *request = task->request; in vd_set_access()
3920 ASSERT(request->operation == VD_OP_SET_ACCESS); in vd_set_access()
3921 ASSERT(vd->scsi); in vd_set_access()
3923 nbytes = request->nbytes; in vd_set_access()
3931 if ((rv = ldc_mem_copy(vd->ldc_handle, (char *)&flags, 0, &nbytes, in vd_set_access()
3932 request->cookie, request->ncookies, LDC_COPY_IN)) != 0) { in vd_set_access()
3939 request->status = ldi_ioctl(vd->ldi_handle[request->slice], in vd_set_access()
3940 MHIOCRELEASE, (intptr_t)NULL, (vd->open_flags | FKIOCTL), in vd_set_access()
3942 if (request->status == 0) in vd_set_access()
3943 vd->ownership = B_FALSE; in vd_set_access()
3948 * As per the VIO spec, the PREEMPT and PRESERVE flags are only valid in vd_set_access()
3953 request->status = EINVAL; in vd_set_access()
3966 request->status = ldi_ioctl(vd->ldi_handle[request->slice], in vd_set_access()
3967 MHIOCTKOWN, (intptr_t)NULL, (vd->open_flags | FKIOCTL), in vd_set_access()
3982 request->status = ldi_ioctl(vd->ldi_handle[request->slice], in vd_set_access()
3983 MHIOCQRESERVE, (intptr_t)NULL, (vd->open_flags | FKIOCTL), in vd_set_access()
3985 if (request->status != 0) in vd_set_access()
3987 request->status = ldi_ioctl(vd->ldi_handle[request->slice], in vd_set_access()
3988 MHIOCTKOWN, (intptr_t)NULL, (vd->open_flags | FKIOCTL), in vd_set_access()
4000 request->status = ldi_ioctl(vd->ldi_handle[request->slice], in vd_set_access()
4001 MHIOCQRESERVE, (intptr_t)NULL, (vd->open_flags | FKIOCTL), in vd_set_access()
4003 if (request->status == 0) in vd_set_access()
4010 request->status = ldi_ioctl(vd->ldi_handle[request->slice], in vd_set_access()
4011 MHIOCQRESERVE, (intptr_t)NULL, (vd->open_flags | FKIOCTL), in vd_set_access()
4018 request->status = ldi_ioctl(vd->ldi_handle[request->slice], in vd_set_access()
4019 MHIOCQRESERVE, (intptr_t)NULL, (vd->open_flags | FKIOCTL), in vd_set_access()
4024 if (request->status == 0) in vd_set_access()
4025 vd->ownership = B_TRUE; in vd_set_access()
4027 PR0("VD_OP_SET_ACCESS: error %d", request->status); in vd_set_access()
4037 if (vd->file || vd->volume || !vd->ownership) in vd_reset_access()
4041 status = ldi_ioctl(vd->ldi_handle[0], MHIOCRELEASE, (intptr_t)NULL, in vd_reset_access()
4042 (vd->open_flags | FKIOCTL), kcred, &rval); in vd_reset_access()
4049 vd->ownership = B_FALSE; in vd_reset_access()
4066 status = ldi_ioctl(vd->ldi_handle[0], MHIOCRELEASE, (intptr_t)NULL, in vd_reset_access()
4067 (vd->open_flags | FKIOCTL), kcred, &rval); in vd_reset_access()
4070 vd->ownership = B_FALSE; in vd_reset_access()
4087 ", rebooting the system", vd->device_path); in vd_reset_access()
4090 panic(VD_RESET_ACCESS_FAILURE_MSG, vd->device_path); in vd_reset_access()
4093 cmn_err(CE_WARN, VD_RESET_ACCESS_FAILURE_MSG, vd->device_path); in vd_reset_access()
4129 * task - structure containing the request sent from client
4132 * 0 - success
4133 * ENOTSUP - Unknown/Unsupported VD_OP_XXX operation
4134 * EINVAL - Invalid disk slice
4135 * != 0 - some other non-zero return value from start function
4141 vd_t *vd = task->vd; in vd_do_process_task()
4142 vd_dring_payload_t *request = task->request; in vd_do_process_task()
4149 if (request->operation == vds_operation[i].operation) { in vd_do_process_task()
4153 task->completef = vds_operation[i].complete; in vd_do_process_task()
4164 if ((VD_OP_SUPPORTED(vd->operations, request->operation) == B_FALSE) || in vd_do_process_task()
4166 PR0("Unsupported operation %u", request->operation); in vd_do_process_task()
4167 request->status = ENOTSUP; in vd_do_process_task()
4171 /* Range-check slice */ in vd_do_process_task()
4172 if (request->slice >= vd->nslices && in vd_do_process_task()
4173 ((vd->vdisk_type != VD_DISK_TYPE_DISK && vd_slice_single_slice) || in vd_do_process_task()
4174 request->slice != VD_SLICE_NONE)) { in vd_do_process_task()
4175 PR0("Invalid \"slice\" %u (max %u) for virtual disk", in vd_do_process_task()
4176 request->slice, (vd->nslices - 1)); in vd_do_process_task()
4177 request->status = EINVAL; in vd_do_process_task()
4189 * This function is called by both the in-band and descriptor ring
4203 * task - structure containing the request sent from client
4206 * 0 - successful synchronous request.
4207 * != 0 - transport error (e.g. LDC errors, vDisk protocol)
4208 * EINPROGRESS - task will be finished in a completion handler
4213 vd_t *vd = task->vd; in vd_process_task()
4218 task->status = vd_do_process_task(task); in vd_process_task()
4228 * returned an error - in both cases all that needs to happen is the in vd_process_task()
4233 if (task->status == EINPROGRESS) { in vd_process_task()
4235 (void) ddi_taskq_dispatch(vd->completionq, vd_complete, in vd_process_task()
4240 if (!vd->reset_state && (vd->xfer_mode == VIO_DRING_MODE_V1_0)) { in vd_process_task()
4242 status = vd_mark_elem_done(vd, task->index, in vd_process_task()
4243 task->request->status, task->request->nbytes); in vd_process_task()
4250 return (task->status); in vd_process_task()
4260 return ((tag->vio_msgtype == type) && in vd_msgtype()
4261 (tag->vio_subtype == subtype) && in vd_msgtype()
4262 (tag->vio_subtype_env == env)) ? B_TRUE : B_FALSE; in vd_msgtype()
4275 (vds_version[i].major < vds_version[i-1].major)); in vds_supported_version()
4284 if (ver_msg->ver_major == vds_version[i].major) { in vds_supported_version()
4285 if (ver_msg->ver_minor > vds_version[i].minor) { in vds_supported_version()
4287 ver_msg->ver_minor, vds_version[i].minor); in vds_supported_version()
4288 ver_msg->ver_minor = vds_version[i].minor; in vds_supported_version()
4300 if (ver_msg->ver_major > vds_version[i].major) { in vds_supported_version()
4301 ver_msg->ver_major = vds_version[i].major; in vds_supported_version()
4302 ver_msg->ver_minor = vds_version[i].minor; in vds_supported_version()
4317 ver_msg->ver_major = 0; in vds_supported_version()
4318 ver_msg->ver_minor = 0; in vds_supported_version()
4326 * not expect to receive version-message ACKs or NACKs (and will treat such
4335 ASSERT(msglen >= sizeof (msg->tag)); in vd_process_ver_msg()
4337 if (!vd_msgtype(&msg->tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, in vd_process_ver_msg()
4343 PR0("Expected %lu-byte version message; " in vd_process_ver_msg()
4348 if (ver_msg->dev_class != VDEV_DISK) { in vd_process_ver_msg()
4350 VDEV_DISK, ver_msg->dev_class); in vd_process_ver_msg()
4358 ver_msg->dev_class = VDEV_DISK_SERVER; in vd_process_ver_msg()
4375 ASSERT(!(vd->initialized & VD_SID)); in vd_process_ver_msg()
4376 vd->sid = ver_msg->tag.vio_sid; in vd_process_ver_msg()
4377 vd->initialized |= VD_SID; in vd_process_ver_msg()
4384 vd->version.major = ver_msg->ver_major; in vd_process_ver_msg()
4385 vd->version.minor = ver_msg->ver_minor; in vd_process_ver_msg()
4388 ver_msg->ver_major, ver_msg->ver_minor); in vd_process_ver_msg()
4395 vd->operations = 0; /* clear field */ in vd_set_exported_operations()
4402 if (vio_ver_is_supported(vd->version, 1, 1)) { in vd_set_exported_operations()
4403 ASSERT(vd->open_flags & FREAD); in vd_set_exported_operations()
4404 vd->operations |= VD_OP_MASK_READ | (1 << VD_OP_GET_CAPACITY); in vd_set_exported_operations()
4406 if (vd->open_flags & FWRITE) in vd_set_exported_operations()
4407 vd->operations |= VD_OP_MASK_WRITE; in vd_set_exported_operations()
4409 if (vd->scsi) in vd_set_exported_operations()
4410 vd->operations |= VD_OP_MASK_SCSI; in vd_set_exported_operations()
4416 * use "options=ro" when doing an ldm add-vdsdev in vd_set_exported_operations()
4418 vd->operations &= ~VD_OP_MASK_WRITE; in vd_set_exported_operations()
4420 } else if (vio_ver_is_supported(vd->version, 1, 0)) { in vd_set_exported_operations()
4421 vd->operations = VD_OP_MASK_READ | VD_OP_MASK_WRITE; in vd_set_exported_operations()
4425 ASSERT(vd->operations != 0); in vd_set_exported_operations()
4435 ASSERT(msglen >= sizeof (msg->tag)); in vd_process_attr_msg()
4437 if (!vd_msgtype(&msg->tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, in vd_process_attr_msg()
4444 PR0("Expected %lu-byte attribute message; " in vd_process_attr_msg()
4449 if (attr_msg->max_xfer_sz == 0) { in vd_process_attr_msg()
4454 if ((attr_msg->xfer_mode != VIO_DESC_MODE) && in vd_process_attr_msg()
4455 (attr_msg->xfer_mode != VIO_DRING_MODE_V1_0)) { in vd_process_attr_msg()
4465 if ((vd->initialized & VD_DISK_READY) == 0) { in vd_process_attr_msg()
4466 PR0("Retry setting up disk (%s)", vd->device_path); in vd_process_attr_msg()
4475 /* if vdisk is no longer enabled - return error */ in vd_process_attr_msg()
4484 vd->initialized |= VD_DISK_READY; in vd_process_attr_msg()
4485 ASSERT(vd->nslices > 0 && vd->nslices <= V_NUMPAR); in vd_process_attr_msg()
4487 ((vd->vdisk_type == VD_DISK_TYPE_DISK) ? "disk" : "slice"), in vd_process_attr_msg()
4488 (vd->volume ? "yes" : "no"), in vd_process_attr_msg()
4489 (vd->file ? "yes" : "no"), in vd_process_attr_msg()
4490 vd->nslices); in vd_process_attr_msg()
4494 vd->xfer_mode = attr_msg->xfer_mode; in vd_process_attr_msg()
4496 if (vd->xfer_mode == VIO_DESC_MODE) { in vd_process_attr_msg()
4500 * for up to n-1 more cookies, where "n" is the number of full in vd_process_attr_msg()
4506 size_t max_xfer_bytes = attr_msg->vdisk_block_size ? in vd_process_attr_msg()
4507 attr_msg->vdisk_block_size * attr_msg->max_xfer_sz : in vd_process_attr_msg()
4508 attr_msg->max_xfer_sz; in vd_process_attr_msg()
4517 * accommodate in-band-descriptor messages with all in vd_process_attr_msg()
4520 vd->max_msglen = MAX(vd->max_msglen, max_inband_msglen); in vd_process_attr_msg()
4523 * Initialize the data structure for processing in-band I/O in vd_process_attr_msg()
4526 vd->inband_task.vd = vd; in vd_process_attr_msg()
4527 vd->inband_task.msg = kmem_alloc(vd->max_msglen, KM_SLEEP); in vd_process_attr_msg()
4528 vd->inband_task.index = 0; in vd_process_attr_msg()
4529 vd->inband_task.type = VD_FINAL_RANGE_TASK; /* range == 1 */ in vd_process_attr_msg()
4533 attr_msg->vdisk_block_size = vd->vdisk_bsize; in vd_process_attr_msg()
4534 attr_msg->max_xfer_sz = vd->max_xfer_sz; in vd_process_attr_msg()
4536 attr_msg->vdisk_size = vd->vdisk_size; in vd_process_attr_msg()
4537 attr_msg->vdisk_type = (vd_slice_single_slice)? vd->vdisk_type : in vd_process_attr_msg()
4539 attr_msg->vdisk_media = vd->vdisk_media; in vd_process_attr_msg()
4543 attr_msg->operations = vd->operations; in vd_process_attr_msg()
4547 ASSERT(vd->dring_task == NULL); in vd_process_attr_msg()
4562 ASSERT(msglen >= sizeof (msg->tag)); in vd_process_dring_reg_msg()
4564 if (!vd_msgtype(&msg->tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, in vd_process_dring_reg_msg()
4566 PR0("Message is not a register-dring message"); in vd_process_dring_reg_msg()
4571 PR0("Expected at least %lu-byte register-dring message; " in vd_process_dring_reg_msg()
4577 (reg_msg->ncookies - 1)*(sizeof (reg_msg->cookie[0])); in vd_process_dring_reg_msg()
4579 PR0("Expected %lu-byte register-dring message; " in vd_process_dring_reg_msg()
4584 if (vd->initialized & VD_DRING) { in vd_process_dring_reg_msg()
4589 if (reg_msg->num_descriptors > INT32_MAX) { in vd_process_dring_reg_msg()
4590 PR0("reg_msg->num_descriptors = %u; must be <= %u (%s)", in vd_process_dring_reg_msg()
4591 reg_msg->ncookies, INT32_MAX, STRINGIZE(INT32_MAX)); in vd_process_dring_reg_msg()
4595 if (reg_msg->ncookies != 1) { in vd_process_dring_reg_msg()
4599 * "cookie" requires increasing the value of vd->max_msglen in vd_process_dring_reg_msg()
4609 PR0("reg_msg->ncookies = %u != 1", reg_msg->ncookies); in vd_process_dring_reg_msg()
4618 status = ldc_mem_dring_map(vd->ldc_handle, reg_msg->cookie, in vd_process_dring_reg_msg()
4619 reg_msg->ncookies, reg_msg->num_descriptors, in vd_process_dring_reg_msg()
4620 reg_msg->descriptor_size, mtype, &vd->dring_handle); in vd_process_dring_reg_msg()
4628 * ldc_mem_dring_nextcookie() successfully ncookies-1 times after a in vd_process_dring_reg_msg()
4631 ASSERT(reg_msg->ncookies == 1); in vd_process_dring_reg_msg()
4634 ldc_mem_dring_info(vd->dring_handle, &dring_minfo)) != 0) { in vd_process_dring_reg_msg()
4636 if ((status = ldc_mem_dring_unmap(vd->dring_handle)) != 0) in vd_process_dring_reg_msg()
4648 vd->initialized |= VD_DRING; in vd_process_dring_reg_msg()
4649 vd->dring_ident = 1; /* "There Can Be Only One" */ in vd_process_dring_reg_msg()
4650 vd->dring = dring_minfo.vaddr; in vd_process_dring_reg_msg()
4651 vd->descriptor_size = reg_msg->descriptor_size; in vd_process_dring_reg_msg()
4652 vd->dring_len = reg_msg->num_descriptors; in vd_process_dring_reg_msg()
4653 vd->dring_mtype = dring_minfo.mtype; in vd_process_dring_reg_msg()
4654 reg_msg->dring_ident = vd->dring_ident; in vd_process_dring_reg_msg()
4656 vd->descriptor_size, vd->dring_len); in vd_process_dring_reg_msg()
4662 vd->dring_task = in vd_process_dring_reg_msg()
4663 kmem_zalloc((sizeof (*vd->dring_task)) * vd->dring_len, KM_SLEEP); in vd_process_dring_reg_msg()
4664 for (int i = 0; i < vd->dring_len; i++) { in vd_process_dring_reg_msg()
4665 vd->dring_task[i].vd = vd; in vd_process_dring_reg_msg()
4666 vd->dring_task[i].index = i; in vd_process_dring_reg_msg()
4668 status = ldc_mem_alloc_handle(vd->ldc_handle, in vd_process_dring_reg_msg()
4669 &(vd->dring_task[i].mhdl)); in vd_process_dring_reg_msg()
4680 vd->dring_task[i].request = kmem_zalloc((vd->descriptor_size - in vd_process_dring_reg_msg()
4682 vd->dring_task[i].msg = kmem_alloc(vd->max_msglen, KM_SLEEP); in vd_process_dring_reg_msg()
4685 if (vd->file || vd->zvol) { in vd_process_dring_reg_msg()
4686 vd->write_queue = in vd_process_dring_reg_msg()
4687 kmem_zalloc(sizeof (buf_t *) * vd->dring_len, KM_SLEEP); in vd_process_dring_reg_msg()
4699 ASSERT(msglen >= sizeof (msg->tag)); in vd_process_dring_unreg_msg()
4701 if (!vd_msgtype(&msg->tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, in vd_process_dring_unreg_msg()
4703 PR0("Message is not an unregister-dring message"); in vd_process_dring_unreg_msg()
4708 PR0("Expected %lu-byte unregister-dring message; " in vd_process_dring_unreg_msg()
4713 if (unreg_msg->dring_ident != vd->dring_ident) { in vd_process_dring_unreg_msg()
4715 vd->dring_ident, unreg_msg->dring_ident); in vd_process_dring_unreg_msg()
4725 ASSERT(msglen >= sizeof (msg->tag)); in process_rdx_msg()
4727 if (!vd_msgtype(&msg->tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_RDX)) { in process_rdx_msg()
4733 PR0("Expected %lu-byte RDX message; received %lu bytes", in process_rdx_msg()
4745 if ((vd->initialized & VD_SEQ_NUM) && (seq_num != vd->seq_num + 1)) { in vd_check_seq_num()
4747 seq_num, (vd->seq_num + 1)); in vd_check_seq_num()
4753 vd->seq_num = seq_num; in vd_check_seq_num()
4754 vd->initialized |= VD_SEQ_NUM; /* superfluous after first time... */ in vd_check_seq_num()
4759 * Return the expected size of an inband-descriptor message with all the
4766 (msg->payload.ncookies - 1)*(sizeof (msg->payload.cookie[0]))); in expected_inband_size()
4770 * Process an in-band descriptor message: used with clients like OBP, with
4781 ASSERT(msglen >= sizeof (msg->tag)); in vd_process_desc_msg()
4783 if (!vd_msgtype(&msg->tag, VIO_TYPE_DATA, VIO_SUBTYPE_INFO, in vd_process_desc_msg()
4785 PR1("Message is not an in-band-descriptor message"); in vd_process_desc_msg()
4790 PR0("Expected at least %lu-byte descriptor message; " in vd_process_desc_msg()
4796 PR0("Expected %lu-byte descriptor message; " in vd_process_desc_msg()
4801 if (vd_check_seq_num(vd, desc_msg->hdr.seq_num) != 0) in vd_process_desc_msg()
4805 * Valid message: Set up the in-band descriptor task and process the in vd_process_desc_msg()
4810 PR1("Valid in-band-descriptor message"); in vd_process_desc_msg()
4811 msg->tag.vio_subtype = VIO_SUBTYPE_ACK; in vd_process_desc_msg()
4813 ASSERT(vd->inband_task.msg != NULL); in vd_process_desc_msg()
4815 bcopy(msg, vd->inband_task.msg, msglen); in vd_process_desc_msg()
4816 vd->inband_task.msglen = msglen; in vd_process_desc_msg()
4822 desc_msg = (vd_dring_inband_msg_t *)vd->inband_task.msg; in vd_process_desc_msg()
4823 vd->inband_task.request = &desc_msg->payload; in vd_process_desc_msg()
4825 return (vd_process_task(&vd->inband_task)); in vd_process_desc_msg()
4838 if ((status = VIO_DRING_ACQUIRE(&otd, vd->dring_mtype, in vd_process_element()
4839 vd->dring_handle, idx, idx)) != 0) { in vd_process_element()
4842 ready = (elem->hdr.dstate == VIO_DESC_READY); in vd_process_element()
4844 elem->hdr.dstate = VIO_DESC_ACCEPTED; in vd_process_element()
4845 bcopy(&elem->payload, vd->dring_task[idx].request, in vd_process_element()
4846 (vd->descriptor_size - sizeof (vio_dring_entry_hdr_t))); in vd_process_element()
4851 if ((status = VIO_DRING_RELEASE(vd->dring_mtype, in vd_process_element()
4852 vd->dring_handle, idx, idx)) != 0) { in vd_process_element()
4862 vd->dring_task[idx].type = type; in vd_process_element()
4865 bcopy(msg, vd->dring_task[idx].msg, msglen); in vd_process_element()
4867 vd->dring_task[idx].msglen = msglen; in vd_process_element()
4868 return (vd_process_task(&vd->dring_task[idx])); in vd_process_element()
4888 msg->tag.vio_subtype = VIO_SUBTYPE_ACK; in vd_process_element_range()
4893 nelem = ((end < start) ? end + vd->dring_len : end) - start + 1; in vd_process_element_range()
4894 for (i = start, n = nelem; n > 0; i = (i + 1) % vd->dring_len, n--) { in vd_process_element_range()
4895 ((vio_dring_msg_t *)msg)->end_idx = i; in vd_process_element_range()
4905 * If some, but not all, operations of a multi-element range are in in vd_process_element_range()
4913 if (vd->ioq != NULL) in vd_process_element_range()
4914 ddi_taskq_wait(vd->ioq); in vd_process_element_range()
4915 ddi_taskq_wait(vd->completionq); in vd_process_element_range()
4927 ASSERT(msglen >= sizeof (msg->tag)); in vd_process_dring_msg()
4929 if (!vd_msgtype(&msg->tag, VIO_TYPE_DATA, VIO_SUBTYPE_INFO, in vd_process_dring_msg()
4931 PR1("Message is not a dring-data message"); in vd_process_dring_msg()
4936 PR0("Expected %lu-byte dring message; received %lu bytes", in vd_process_dring_msg()
4941 if (vd_check_seq_num(vd, dring_msg->seq_num) != 0) in vd_process_dring_msg()
4944 if (dring_msg->dring_ident != vd->dring_ident) { in vd_process_dring_msg()
4946 vd->dring_ident, dring_msg->dring_ident); in vd_process_dring_msg()
4950 if (dring_msg->start_idx >= vd->dring_len) { in vd_process_dring_msg()
4952 dring_msg->start_idx, vd->dring_len); in vd_process_dring_msg()
4956 if ((dring_msg->end_idx < 0) || in vd_process_dring_msg()
4957 (dring_msg->end_idx >= vd->dring_len)) { in vd_process_dring_msg()
4959 dring_msg->end_idx, vd->dring_len); in vd_process_dring_msg()
4965 dring_msg->start_idx, dring_msg->end_idx); in vd_process_dring_msg()
4966 return (vd_process_element_range(vd, dring_msg->start_idx, in vd_process_dring_msg()
4967 dring_msg->end_idx, msg, msglen)); in vd_process_dring_msg()
4995 PR1("RCVD %lu-byte message", *nbytes); in recv_msg()
5005 PR1("Processing (%x/%x/%x) message", msg->tag.vio_msgtype, in vd_do_process_msg()
5006 msg->tag.vio_subtype, msg->tag.vio_subtype_env); in vd_do_process_msg()
5015 if ((msg->tag.vio_sid != vd->sid) && (vd->initialized & VD_SID)) { in vd_do_process_msg()
5016 PR0("Expected SID %u, received %u", vd->sid, in vd_do_process_msg()
5017 msg->tag.vio_sid); in vd_do_process_msg()
5021 PR1("\tWhile in state %d (%s)", vd->state, vd_decode_state(vd->state)); in vd_do_process_msg()
5026 switch (vd->state) { in vd_do_process_msg()
5032 vd->state = VD_STATE_VER; in vd_do_process_msg()
5040 vd->state = VD_STATE_ATTR; in vd_do_process_msg()
5044 switch (vd->xfer_mode) { in vd_do_process_msg()
5049 /* Ready to receive in-band descriptors */ in vd_do_process_msg()
5050 vd->state = VD_STATE_DATA; in vd_do_process_msg()
5053 case VIO_DRING_MODE_V1_0: /* expect register-dring message */ in vd_do_process_msg()
5059 vd->state = VD_STATE_DRING; in vd_do_process_msg()
5068 case VD_STATE_DRING: /* expect RDX, register-dring, or unreg-dring */ in vd_do_process_msg()
5071 vd->state = VD_STATE_DATA; in vd_do_process_msg()
5079 * If another register-dring message is received, stay in in vd_do_process_msg()
5089 * Acknowledge an unregister-dring message, but reset the in vd_do_process_msg()
5098 switch (vd->xfer_mode) { in vd_do_process_msg()
5099 case VIO_DESC_MODE: /* expect in-band-descriptor message */ in vd_do_process_msg()
5102 case VIO_DRING_MODE_V1_0: /* expect dring-data or unreg-dring */ in vd_do_process_msg()
5104 * Typically expect dring-data messages, so handle in vd_do_process_msg()
5112 * Acknowledge an unregister-dring message, but reset in vd_do_process_msg()
5142 * message processing can proceed based on tag-specified message type in vd_process_msg()
5145 PR0("Received short (%lu-byte) message", msglen); in vd_process_msg()
5157 /* "ack" valid, successfully-processed messages */ in vd_process_msg()
5158 msg->tag.vio_subtype = VIO_SUBTYPE_ACK; in vd_process_msg()
5170 msg->tag.vio_subtype = VIO_SUBTYPE_NACK; in vd_process_msg()
5175 msg->tag.vio_subtype = VIO_SUBTYPE_NACK; in vd_process_msg()
5181 PR1("\tResulting in state %d (%s)", vd->state, in vd_process_msg()
5182 vd_decode_state(vd->state)); in vd_process_msg()
5195 (void) ddi_taskq_dispatch(vd->completionq, vd_serial_notify, in vd_process_msg()
5203 ddi_taskq_wait(vd->completionq); in vd_process_msg()
5220 mutex_enter(&vd->lock); in vd_enabled()
5221 enabled = vd->enabled; in vd_enabled()
5222 mutex_exit(&vd->lock); in vd_enabled()
5244 vd_reset_if_needed(vd); /* can change vd->max_msglen */ in vd_recv_msg()
5247 * check if channel is UP - else break out of loop in vd_recv_msg()
5249 status = ldc_status(vd->ldc_handle, &lstatus); in vd_recv_msg()
5256 ASSERT(vd->max_msglen != 0); in vd_recv_msg()
5258 msgsize = vd->max_msglen; /* stable copy for alloc/free */ in vd_recv_msg()
5261 status = recv_msg(vd->ldc_handle, vd->vio_msgp, &msglen); in vd_recv_msg()
5264 rv = vd_process_msg(vd, (void *)vd->vio_msgp, msglen); in vd_recv_msg()
5266 if (msgsize != vd->max_msglen) { in vd_recv_msg()
5268 msgsize, vd->max_msglen); in vd_recv_msg()
5269 kmem_free(vd->vio_msgp, msgsize); in vd_recv_msg()
5270 vd->vio_msgp = in vd_recv_msg()
5271 kmem_alloc(vd->max_msglen, KM_SLEEP); in vd_recv_msg()
5312 status = ddi_taskq_dispatch(vd->startq, vd_recv_msg, vd, in vd_handle_ldc_events()
5323 if (vd->state != VD_STATE_INIT) { in vd_handle_ldc_events()
5326 status = ddi_taskq_dispatch(vd->startq, vd_recv_msg, in vd_handle_ldc_events()
5336 (void) ldc_up(vd->ldc_handle); in vd_handle_ldc_events()
5346 status = ddi_taskq_dispatch(vd->startq, vd_recv_msg, in vd_handle_ldc_events()
5360 status = ddi_taskq_dispatch(vd->startq, vd_recv_msg, vd, in vd_handle_ldc_events()
5410 mod_hash_walk(vds->vd_table, vds_check_for_vd, &vd_present); in vds_detach()
5417 if (vds->initialized & VDS_MDEG) { in vds_detach()
5418 (void) mdeg_unregister(vds->mdeg); in vds_detach()
5419 kmem_free(vds->ispecp->specp, sizeof (vds_prop_template)); in vds_detach()
5420 kmem_free(vds->ispecp, sizeof (mdeg_node_spec_t)); in vds_detach()
5421 vds->ispecp = NULL; in vds_detach()
5422 vds->mdeg = 0; in vds_detach()
5427 if (vds->initialized & VDS_LDI) in vds_detach()
5428 (void) ldi_ident_release(vds->ldi_ident); in vds_detach()
5429 mod_hash_destroy_hash(vds->vd_table); in vds_detach()
5441 * vd - disk on which the operation is performed.
5444 * B_TRUE - The disk image is an ISO 9660 compliant image
5445 * B_FALSE - just a regular disk image
5458 * short-circuit the check and avoid reading the disk image. in vd_dskimg_is_iso_image()
5460 if (vd->vdisk_media == VD_MEDIA_DVD || vd->vdisk_media == VD_MEDIA_CD) in vd_dskimg_is_iso_image()
5466 * Standard Identifier and is set to CD001 for a CD-ROM compliant in vd_dskimg_is_iso_image()
5469 sec = (ISO_VOLDESC_SEC * ISO_SECTOR_SIZE) / vd->vdisk_bsize; in vd_dskimg_is_iso_image()
5491 * vd - disk on which the operation is performed.
5494 * B_TRUE - The virtual disk is backed by an ATAPI device
5495 * B_FALSE - not an ATAPI device (presumably SCSI)
5504 ASSERT(vd->ldi_handle[0] != NULL); in vd_is_atapi_device()
5505 ASSERT(!vd->file); in vd_is_atapi_device()
5507 rv = ldi_prop_lookup_string(vd->ldi_handle[0], in vd_is_atapi_device()
5510 PR0("'variant' property exists for %s", vd->device_path); in vd_is_atapi_device()
5516 rv = ldi_prop_exists(vd->ldi_handle[0], LDI_DEV_T_ANY, "atapi"); in vd_is_atapi_device()
5518 PR0("'atapi' property exists for %s", vd->device_path); in vd_is_atapi_device()
5529 major_t major = getmajor(vd->dev[0]); in vd_setup_full_disk()
5530 minor_t minor = getminor(vd->dev[0]) - VD_ENTIRE_DISK_SLICE; in vd_setup_full_disk()
5532 ASSERT(vd->vdisk_type == VD_DISK_TYPE_DISK); in vd_setup_full_disk()
5538 if (!vd->scsi) { in vd_setup_full_disk()
5541 vd->device_path, status); in vd_setup_full_disk()
5550 vd->vdisk_size = VD_SIZE_UNKNOWN; in vd_setup_full_disk()
5551 vd->vdisk_bsize = 0; in vd_setup_full_disk()
5552 vd->backend_bsize = 0; in vd_setup_full_disk()
5553 vd->vdisk_media = VD_MEDIA_FIXED; in vd_setup_full_disk()
5556 /* Move dev number and LDI handle to entire-disk-slice array elements */ in vd_setup_full_disk()
5557 vd->dev[VD_ENTIRE_DISK_SLICE] = vd->dev[0]; in vd_setup_full_disk()
5558 vd->dev[0] = 0; in vd_setup_full_disk()
5559 vd->ldi_handle[VD_ENTIRE_DISK_SLICE] = vd->ldi_handle[0]; in vd_setup_full_disk()
5560 vd->ldi_handle[0] = NULL; in vd_setup_full_disk()
5563 for (int slice = 0; slice < vd->nslices; slice++) { in vd_setup_full_disk() local
5565 * Skip the entire-disk slice, as it's already open and its in vd_setup_full_disk()
5568 if (slice == VD_ENTIRE_DISK_SLICE) in vd_setup_full_disk()
5570 ASSERT(vd->dev[slice] == 0); in vd_setup_full_disk()
5571 ASSERT(vd->ldi_handle[slice] == NULL); in vd_setup_full_disk()
5574 * Construct the device number for the current slice in vd_setup_full_disk()
5576 vd->dev[slice] = makedevice(major, (minor + slice)); in vd_setup_full_disk()
5582 * slices being accessed by a client. Failure to open a slice in vd_setup_full_disk()
5584 * attempt (and should be able) to access any slice immediately. in vd_setup_full_disk()
5590 * slice does not fail. in vd_setup_full_disk()
5592 PR0("Opening device major %u, minor %u = slice %u", in vd_setup_full_disk()
5593 major, minor, slice); in vd_setup_full_disk()
5597 * opening an empty slice. So in case of a failure, we try the in vd_setup_full_disk()
5600 status = ldi_open_by_dev(&vd->dev[slice], OTYP_BLK, in vd_setup_full_disk()
5601 vd->open_flags, kcred, &vd->ldi_handle[slice], in vd_setup_full_disk()
5602 vd->vds->ldi_ident); in vd_setup_full_disk()
5605 status = ldi_open_by_dev(&vd->dev[slice], OTYP_BLK, in vd_setup_full_disk()
5606 vd->open_flags | FNDELAY, kcred, in vd_setup_full_disk()
5607 &vd->ldi_handle[slice], vd->vds->ldi_ident); in vd_setup_full_disk()
5612 "for slice %u", status, slice); in vd_setup_full_disk()
5614 vd->ldi_handle[slice] = NULL; in vd_setup_full_disk()
5623 * When a slice or a volume is exported as a single-slice disk, we want
5624 * the disk backend (i.e. the slice or volume) to be entirely mapped as
5625 * a slice without the addition of any metadata.
5629 * flabel +--- flabel_limit
5630 * <-> V
5632 * +-+---+--------------------------+--+
5633 * virtual disk: |L|XXX| slice 0 |AA|
5634 * +-+---+--------------------------+--+
5637 * VTOC LABEL--+ : :
5638 * +--------------------------+
5639 * disk backend: | slice/volume/file |
5640 * +--------------------------+
5643 * N is the number of blocks in the slice/volume/file.
5646 * simluated at the beginning and at the end of the disk (blocks 0-C
5647 * and D-E).
5649 * The first blocks (0 to C-1) are emulated and can not be changed. Blocks C
5650 * to D defines slice 0 and are mapped to the backend. Finally we emulate 2
5651 * alternate cylinders at the end of the disk (blocks D-E). In summary we have:
5653 * - block 0 (L) returns a fake VTOC label
5654 * - blocks 1 to C-1 (X) are unused and return 0
5655 * - blocks C to D-1 are mapped to the exported slice or volume
5656 * - blocks D and E (A) are blocks defining alternate cylinders (2 cylinders)
5665 char *device_path = vd->device_path; in vd_setup_partition_vtoc()
5669 /* Initialize dk_geom structure for single-slice device */ in vd_setup_partition_vtoc()
5670 if (vd->dk_geom.dkg_nsect == 0) { in vd_setup_partition_vtoc()
5671 PRN("%s geometry claims 0 sectors per track", device_path); in vd_setup_partition_vtoc()
5674 if (vd->dk_geom.dkg_nhead == 0) { in vd_setup_partition_vtoc()
5680 csize = vd->dk_geom.dkg_nhead * vd->dk_geom.dkg_nsect; in vd_setup_partition_vtoc()
5686 vd->dk_geom.dkg_ncyl = vd->vdisk_size / csize + 1; in vd_setup_partition_vtoc()
5689 vd->dk_geom.dkg_acyl = 2; in vd_setup_partition_vtoc()
5690 vd->dk_geom.dkg_pcyl = vd->dk_geom.dkg_ncyl + vd->dk_geom.dkg_acyl; in vd_setup_partition_vtoc()
5693 /* Initialize vtoc structure for single-slice device */ in vd_setup_partition_vtoc()
5694 bzero(vd->vtoc.v_part, sizeof (vd->vtoc.v_part)); in vd_setup_partition_vtoc()
5695 vd->vtoc.v_part[0].p_tag = V_UNASSIGNED; in vd_setup_partition_vtoc()
5696 vd->vtoc.v_part[0].p_flag = 0; in vd_setup_partition_vtoc()
5701 vd->vtoc.v_part[0].p_start = csize; /* start on cylinder 1 */ in vd_setup_partition_vtoc()
5702 vd->vtoc.v_part[0].p_size = (vd->vdisk_size / csize) * csize; in vd_setup_partition_vtoc()
5705 vd->vtoc.v_nparts = 1; in vd_setup_partition_vtoc()
5706 bcopy(VD_ASCIILABEL, vd->vtoc.v_asciilabel, in vd_setup_partition_vtoc()
5708 sizeof (vd->vtoc.v_asciilabel))); in vd_setup_partition_vtoc()
5709 bcopy(VD_VOLUME_NAME, vd->vtoc.v_volume, in vd_setup_partition_vtoc()
5710 MIN(sizeof (VD_VOLUME_NAME), sizeof (vd->vtoc.v_volume))); in vd_setup_partition_vtoc()
5713 vd->nslices = V_NUMPAR; in vd_setup_partition_vtoc()
5714 vd->vtoc.v_nparts = V_NUMPAR; in vd_setup_partition_vtoc()
5716 /* define slice 2 representing the entire disk */ in vd_setup_partition_vtoc()
5717 vd->vtoc.v_part[VD_ENTIRE_DISK_SLICE].p_tag = V_BACKUP; in vd_setup_partition_vtoc()
5718 vd->vtoc.v_part[VD_ENTIRE_DISK_SLICE].p_flag = 0; in vd_setup_partition_vtoc()
5719 vd->vtoc.v_part[VD_ENTIRE_DISK_SLICE].p_start = 0; in vd_setup_partition_vtoc()
5720 vd->vtoc.v_part[VD_ENTIRE_DISK_SLICE].p_size = in vd_setup_partition_vtoc()
5721 vd->dk_geom.dkg_ncyl * csize; in vd_setup_partition_vtoc()
5723 vd_get_readable_size(vd->vdisk_size * vd->vdisk_bsize, in vd_setup_partition_vtoc()
5731 vd->dk_geom.dkg_bcyl = 0; in vd_setup_partition_vtoc()
5732 vd->dk_geom.dkg_intrlv = 1; in vd_setup_partition_vtoc()
5733 vd->dk_geom.dkg_write_reinstruct = 0; in vd_setup_partition_vtoc()
5734 vd->dk_geom.dkg_read_reinstruct = 0; in vd_setup_partition_vtoc()
5740 (void) snprintf(vd->vtoc.v_asciilabel, LEN_DKL_ASCII, in vd_setup_partition_vtoc()
5741 "SUN-DiskSlice-%ld%cB cyl %d alt %d hd %d sec %d", in vd_setup_partition_vtoc()
5743 vd->dk_geom.dkg_ncyl, vd->dk_geom.dkg_acyl, in vd_setup_partition_vtoc()
5744 vd->dk_geom.dkg_nhead, vd->dk_geom.dkg_nsect); in vd_setup_partition_vtoc()
5745 bzero(vd->vtoc.v_volume, sizeof (vd->vtoc.v_volume)); in vd_setup_partition_vtoc()
5748 vd->flabel_limit = (uint_t)csize; in vd_setup_partition_vtoc()
5749 vd->flabel_size = VD_LABEL_VTOC_SIZE(vd->vdisk_bsize); in vd_setup_partition_vtoc()
5750 vd->flabel = kmem_zalloc(vd->flabel_size, KM_SLEEP); in vd_setup_partition_vtoc()
5751 vd_vtocgeom_to_label(&vd->vtoc, &vd->dk_geom, in vd_setup_partition_vtoc()
5756 vd->vdisk_size += csize * 3; in vd_setup_partition_vtoc()
5762 * When a slice, volume or file is exported as a single-slice disk, we want
5763 * the disk backend (i.e. the slice, volume or file) to be entirely mapped
5764 * as a slice without the addition of any metadata.
5769 * flabel +--- flabel_limit
5770 * <------> v
5772 * +-+-+--+-------+--------------------------+-------+
5773 * virtual disk: |X|T|EE|XXXXXXX| slice 0 |RRRRRRR|
5774 * +-+-+--+-------+--------------------------+-------+
5777 * GPT-+ +-GPE : :
5778 * +--------------------------+
5779 * disk backend: | slice/volume/file |
5780 * +--------------------------+
5783 * N is the number of blocks in the slice/volume/file.
5786 * simluated at the beginning and at the end of the disk (blocks 0-34
5787 * and 34+N-P).
5790 * to 34+N defines slice 0 and are mapped to the exported backend, and we
5794 * - block 0 (X) is unused and return 0
5795 * - block 1 (T) returns a fake EFI GPT (via DKIOCGETEFI)
5796 * - blocks 2 to L-1 (E) defines a fake EFI GPE (via DKIOCGETEFI)
5797 * - blocks L to 33 (X) are unused and return 0
5798 * - blocks 34 to 34+N are mapped to the exported slice, volume or file
5799 * - blocks 34+N+1 to P define a fake reserved partition and backup label, it
5816 ASSERT(vd->vdisk_bsize > 0); in vd_setup_partition_efi()
5818 bsize = vd->vdisk_bsize; in vd_setup_partition_efi()
5824 vd->flabel_limit = (uint_t)first_u_lba; in vd_setup_partition_efi()
5825 vd->flabel_size = VD_LABEL_EFI_SIZE(bsize); in vd_setup_partition_efi()
5826 vd->flabel = kmem_zalloc(vd->flabel_size, KM_SLEEP); in vd_setup_partition_efi()
5834 vd->vdisk_size += first_u_lba; in vd_setup_partition_efi()
5836 s0_end = vd->vdisk_size - 1; in vd_setup_partition_efi()
5838 gpt->efi_gpt_Signature = LE_64(EFI_SIGNATURE); in vd_setup_partition_efi()
5839 gpt->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT); in vd_setup_partition_efi()
5840 gpt->efi_gpt_HeaderSize = LE_32(EFI_HEADER_SIZE); in vd_setup_partition_efi()
5841 gpt->efi_gpt_FirstUsableLBA = LE_64(first_u_lba); in vd_setup_partition_efi()
5842 gpt->efi_gpt_PartitionEntryLBA = LE_64(2ULL); in vd_setup_partition_efi()
5843 gpt->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t)); in vd_setup_partition_efi()
5850 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(1); in vd_setup_partition_efi()
5853 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(VD_MAXPART); in vd_setup_partition_efi()
5854 vd->nslices = V_NUMPAR; in vd_setup_partition_efi()
5857 UUID_LE_CONVERT(gpe[VD_MAXPART - 1].efi_gpe_PartitionTypeGUID, in vd_setup_partition_efi()
5859 gpe[VD_MAXPART - 1].efi_gpe_StartingLBA = in vd_setup_partition_efi()
5861 gpe[VD_MAXPART - 1].efi_gpe_EndingLBA = in vd_setup_partition_efi()
5864 /* adjust the vdisk_size to include the reserved slice */ in vd_setup_partition_efi()
5865 vd->vdisk_size += EFI_MIN_RESV_SIZE; in vd_setup_partition_efi()
5868 gpt->efi_gpt_LastUsableLBA = LE_64(vd->vdisk_size - 1); in vd_setup_partition_efi()
5871 vd->vdisk_size += (EFI_MIN_ARRAY_SIZE / bsize) + 1; in vd_setup_partition_efi()
5872 gpt->efi_gpt_AlternateLBA = LE_64(vd->vdisk_size - 1); in vd_setup_partition_efi()
5874 CRC32(crc, gpe, sizeof (efi_gpe_t) * VD_MAXPART, -1U, crc32_table); in vd_setup_partition_efi()
5875 gpt->efi_gpt_PartitionEntryArrayCRC32 = LE_32(~crc); in vd_setup_partition_efi()
5877 CRC32(crc, gpt, EFI_HEADER_SIZE, -1U, crc32_table); in vd_setup_partition_efi()
5878 gpt->efi_gpt_HeaderCRC32 = LE_32(~crc); in vd_setup_partition_efi()
5884 * Setup for a virtual disk whose backend is a file (exported as a single slice
5893 char *file_path = vd->device_path; in vd_setup_backend_vnode()
5897 ASSERT(!vd->volume); in vd_setup_backend_vnode()
5899 if ((status = vn_open(file_path, UIO_SYSSPACE, vd->open_flags | FOFFMAX, in vd_setup_backend_vnode()
5900 0, &vd->file_vnode, 0, 0)) != 0) { in vd_setup_backend_vnode()
5902 status == EROFS) && (!(vd->initialized & VD_SETUP_ERROR) && in vd_setup_backend_vnode()
5903 !(DEVI_IS_ATTACHING(vd->vds->dip)))) { in vd_setup_backend_vnode()
5910 * We set vd->file now so that vds_destroy_vd will take care of in vd_setup_backend_vnode()
5913 vd->file = B_TRUE; in vd_setup_backend_vnode()
5915 vd->max_xfer_sz = maxphys / DEV_BSIZE; /* default transfer size */ in vd_setup_backend_vnode()
5920 dev = vd->file_vnode->v_vfsp->vfs_dev; in vd_setup_backend_vnode()
5925 vd->vds->ldi_ident); in vd_setup_backend_vnode()
5932 (intptr_t)&dk_cinfo, (vd->open_flags | FKIOCTL), kcred, in vd_setup_backend_vnode()
5941 vd->max_xfer_sz = dk_cinfo.dki_maxtransfer; in vd_setup_backend_vnode()
5949 file_path, getmajor(dev), getminor(dev), vd->max_xfer_sz); in vd_setup_backend_vnode()
5951 if (vd->vdisk_type == VD_DISK_TYPE_SLICE) in vd_setup_backend_vnode()
5967 vd->device_path, status); in vd_setup_slice_image()
5971 vd->vdisk_media = VD_MEDIA_FIXED; in vd_setup_slice_image()
5972 vd->vdisk_label = (vd_slice_label == VD_DISK_LABEL_UNK)? in vd_setup_slice_image()
5975 if (vd->vdisk_label == VD_DISK_LABEL_EFI || in vd_setup_slice_image()
5976 vd->dskimg_size >= 2 * ONE_TERABYTE) { in vd_setup_slice_image()
5982 * adjust the vtoc so that it defines a single-slice in vd_setup_slice_image()
5985 vd_build_default_label(vd->dskimg_size, vd->vdisk_bsize, in vd_setup_slice_image()
5987 vd_label_to_vtocgeom(&label, &vd->vtoc, &vd->dk_geom); in vd_setup_slice_image()
5998 char *backend_path = vd->device_path; in vd_setup_disk_image()
6007 if (vd->dskimg_size < sizeof (struct dk_label)) { in vd_setup_disk_image()
6026 * in the ISO-9600 format). CDs can store up to just under 1Gb in vd_setup_disk_image()
6028 if ((vd->vdisk_size * vd->vdisk_bsize) > ONE_GIGABYTE) in vd_setup_disk_image()
6029 vd->vdisk_media = VD_MEDIA_DVD; in vd_setup_disk_image()
6031 vd->vdisk_media = VD_MEDIA_CD; in vd_setup_disk_image()
6033 vd->vdisk_media = VD_MEDIA_FIXED; in vd_setup_disk_image()
6038 if (vd->vdisk_label != VD_DISK_LABEL_UNK) { in vd_setup_disk_image()
6040 status = vd_dskimg_read_devid(vd, &vd->dskimg_devid); in vd_setup_disk_image()
6054 vd->dskimg_devid = NULL; in vd_setup_disk_image()
6066 if (ddi_devid_init(vd->vds->dip, DEVID_FAB, 0, 0, in vd_setup_disk_image()
6067 &vd->dskimg_devid) != DDI_SUCCESS) { in vd_setup_disk_image()
6069 vd->dskimg_devid = NULL; in vd_setup_disk_image()
6078 if (vd->vdisk_label != VD_DISK_LABEL_UNK) { in vd_setup_disk_image()
6079 if (vd_dskimg_write_devid(vd, vd->dskimg_devid) != 0) { in vd_setup_disk_image()
6081 ddi_devid_free(vd->dskimg_devid); in vd_setup_disk_image()
6082 vd->dskimg_devid = NULL; in vd_setup_disk_image()
6095 * vd - pointer to structure containing the vDisk info
6096 * flags - open flags
6099 * 0 - success
6100 * != 0 - some other non-zero return value from ldi(9F) functions
6106 char *device_path = vd->device_path; in vd_open_using_ldi_by_name()
6110 &vd->ldi_handle[0], vd->vds->ldi_ident); in vd_open_using_ldi_by_name()
6113 * The open can fail for example if we are opening an empty slice. in vd_open_using_ldi_by_name()
6119 kcred, &vd->ldi_handle[0], vd->vds->ldi_ident); in vd_open_using_ldi_by_name()
6123 vd->ldi_handle[0] = NULL; in vd_open_using_ldi_by_name()
6132 * slice or volume device) exported as a full disk or as a slice. In these
6140 char *device_path = vd->device_path; in vd_setup_backend_ldi()
6143 ASSERT(vd->ldi_handle[0] != NULL); in vd_setup_backend_ldi()
6144 ASSERT(vd->dev[0] != NULL); in vd_setup_backend_ldi()
6146 vd->file = B_FALSE; in vd_setup_backend_ldi()
6149 if ((status = ldi_ioctl(vd->ldi_handle[0], DKIOCINFO, in vd_setup_backend_ldi()
6150 (intptr_t)&dk_cinfo, (vd->open_flags | FKIOCTL), kcred, in vd_setup_backend_ldi()
6157 PRN("slice %u >= maximum slice %u for %s", in vd_setup_backend_ldi()
6163 * The device has been opened read-only by vd_identify_dev(), re-open in vd_setup_backend_ldi()
6164 * it read-write if the write flag is set and we don't have an optical in vd_setup_backend_ldi()
6165 * device such as a CD-ROM, which, for now, we do not permit writes to in vd_setup_backend_ldi()
6170 * to distinguish between read-only and writable discs. in vd_setup_backend_ldi()
6174 vd->open_flags &= ~FWRITE; in vd_setup_backend_ldi()
6176 } else if (vd->open_flags & FWRITE) { in vd_setup_backend_ldi()
6178 (void) ldi_close(vd->ldi_handle[0], vd->open_flags & ~FWRITE, in vd_setup_backend_ldi()
6180 status = vd_open_using_ldi_by_name(vd, vd->open_flags); in vd_setup_backend_ldi()
6189 vd->max_xfer_sz = dk_cinfo.dki_maxtransfer; in vd_setup_backend_ldi()
6192 * We need to work out if it's an ATAPI (IDE CD-ROM) or SCSI device so in vd_setup_backend_ldi()
6195 vd->is_atapi_dev = vd_is_atapi_device(vd); in vd_setup_backend_ldi()
6202 * disk slice (slice 2) and if this slice is exported as a full disk in vd_setup_backend_ldi()
6203 * and not as a single slice disk. A CD or DVD device is exported in vd_setup_backend_ldi()
6205 * full disk as long as the "slice" option is not specified. in vd_setup_backend_ldi()
6207 if (vd->vdisk_type == VD_DISK_TYPE_DISK) { in vd_setup_backend_ldi()
6209 if (vd->volume) { in vd_setup_backend_ldi()
6216 ASSERT(!vd->volume); in vd_setup_backend_ldi()
6218 vd->scsi = B_TRUE; in vd_setup_backend_ldi()
6224 * Export a single slice disk. in vd_setup_backend_ldi()
6226 * The exported device can be either a volume device or a disk slice. If in vd_setup_backend_ldi()
6227 * it is a disk slice different from slice 2 then it is always exported in vd_setup_backend_ldi()
6228 * as a single slice disk even if the "slice" option is not specified. in vd_setup_backend_ldi()
6229 * If it is disk slice 2 or a volume device then it is exported as a in vd_setup_backend_ldi()
6230 * single slice disk only if the "slice" option is specified. in vd_setup_backend_ldi()
6240 char *device_path = vd->device_path; in vd_setup_single_slice_disk()
6243 vd->vdisk_media = VD_MEDIA_FIXED; in vd_setup_single_slice_disk()
6245 if (vd->volume) { in vd_setup_single_slice_disk()
6246 ASSERT(vd->vdisk_type == VD_DISK_TYPE_SLICE); in vd_setup_single_slice_disk()
6250 * We export the slice as a single slice disk even if the "slice" in vd_setup_single_slice_disk()
6253 vd->vdisk_type = VD_DISK_TYPE_SLICE; in vd_setup_single_slice_disk()
6254 vd->nslices = 1; in vd_setup_single_slice_disk()
6263 * When exporting a slice or a device as a single slice disk, we don't in vd_setup_single_slice_disk()
6266 * table (either a VTOC or EFI), which presents only one slice, to in vd_setup_single_slice_disk()
6272 vd->vdisk_size >= ONE_TERABYTE / vd->vdisk_bsize) { in vd_setup_single_slice_disk()
6273 vd->vdisk_label = VD_DISK_LABEL_EFI; in vd_setup_single_slice_disk()
6275 status = ldi_ioctl(vd->ldi_handle[0], DKIOCGEXTVTOC, in vd_setup_single_slice_disk()
6276 (intptr_t)&vd->vtoc, (vd->open_flags | FKIOCTL), in vd_setup_single_slice_disk()
6280 /* try with the non-extended vtoc ioctl */ in vd_setup_single_slice_disk()
6281 status = ldi_ioctl(vd->ldi_handle[0], DKIOCGVTOC, in vd_setup_single_slice_disk()
6282 (intptr_t)&vtoc, (vd->open_flags | FKIOCTL), in vd_setup_single_slice_disk()
6284 vtoctoextvtoc(vtoc, vd->vtoc); in vd_setup_single_slice_disk()
6288 status = ldi_ioctl(vd->ldi_handle[0], DKIOCGGEOM, in vd_setup_single_slice_disk()
6289 (intptr_t)&vd->dk_geom, (vd->open_flags | FKIOCTL), in vd_setup_single_slice_disk()
6297 vd->vdisk_label = VD_DISK_LABEL_VTOC; in vd_setup_single_slice_disk()
6301 vd->vdisk_label = VD_DISK_LABEL_VTOC; in vd_setup_single_slice_disk()
6302 vd_build_default_label(vd->vdisk_size * vd->vdisk_bsize, in vd_setup_single_slice_disk()
6303 vd->vdisk_bsize, &label); in vd_setup_single_slice_disk()
6304 vd_label_to_vtocgeom(&label, &vd->vtoc, &vd->dk_geom); in vd_setup_single_slice_disk()
6307 vd->vdisk_label = VD_DISK_LABEL_EFI; in vd_setup_single_slice_disk()
6311 if (vd->vdisk_label == VD_DISK_LABEL_VTOC) { in vd_setup_single_slice_disk()
6328 * - vdisk_bsize: block size for the virtual disk used by the VIO protocol. Its
6330 * CD/DVD. When the backend is a disk or a disk slice then it has the value
6335 * - vdisk_size: size of the virtual disk expressed as a number of vdisk_bsize
6341 * - backend_bsize: block size of the backend device. backend_bsize has the same
6346 * - dskimg_size: size of the backend when the backend is a disk image. This
6350 * - vio_bshift: number of bit to shift to convert a VIO block number (which
6354 * - vdisk_media: media of the virtual disk. This function only sets this
6368 if (vd->file) { in vd_backend_check_size()
6370 /* file (slice or full disk) */ in vd_backend_check_size()
6372 rv = VOP_GETATTR(vd->file_vnode, &vattr, 0, kcred, NULL); in vd_backend_check_size()
6374 PR0("VOP_GETATTR(%s) = errno %d", vd->device_path, rv); in vd_backend_check_size()
6381 } else if (vd->volume) { in vd_backend_check_size()
6383 /* volume (slice or full disk) */ in vd_backend_check_size()
6384 rv = ldi_get_size(vd->ldi_handle[0], &backend_size); in vd_backend_check_size()
6386 PR0("ldi_get_size() failed for %s", vd->device_path); in vd_backend_check_size()
6394 /* physical disk or slice */ in vd_backend_check_size()
6395 rv = ldi_ioctl(vd->ldi_handle[0], DKIOCGMEDIAINFO, in vd_backend_check_size()
6396 (intptr_t)&minfo, (vd->open_flags | FKIOCTL), in vd_backend_check_size()
6400 vd->device_path, rv); in vd_backend_check_size()
6404 if (vd->vdisk_type == VD_DISK_TYPE_SLICE) { in vd_backend_check_size()
6405 rv = ldi_get_size(vd->ldi_handle[0], &backend_size); in vd_backend_check_size()
6408 vd->device_path); in vd_backend_check_size()
6412 ASSERT(vd->vdisk_type == VD_DISK_TYPE_DISK); in vd_backend_check_size()
6434 old_size = vd->vdisk_size; in vd_backend_check_size()
6439 vd->vdisk_bsize == vdisk_bsize) in vd_backend_check_size()
6451 vd->vio_bshift = nshift; in vd_backend_check_size()
6452 vd->vdisk_size = new_size; in vd_backend_check_size()
6453 vd->vdisk_bsize = vdisk_bsize; in vd_backend_check_size()
6454 vd->backend_bsize = backend_bsize; in vd_backend_check_size()
6456 if (vd->file || vd->volume) in vd_backend_check_size()
6457 vd->dskimg_size = backend_size; in vd_backend_check_size()
6460 * If we are exporting a single-slice disk and the size of the backend in vd_backend_check_size()
6465 if (vd->vdisk_type == VD_DISK_TYPE_SLICE) { in vd_backend_check_size()
6466 /* slice or file or device exported as a slice */ in vd_backend_check_size()
6467 if (vd->vdisk_label == VD_DISK_LABEL_VTOC) { in vd_backend_check_size()
6471 "(err = %d)", vd->device_path, rv); in vd_backend_check_size()
6478 "(err = %d)", vd->device_path, rv); in vd_backend_check_size()
6483 } else if (!vd->file && !vd->volume) { in vd_backend_check_size()
6485 ASSERT(vd->vdisk_type == VD_DISK_TYPE_DISK); in vd_backend_check_size()
6486 vd->vdisk_media = media; in vd_backend_check_size()
6498 * vd - pointer to structure containing the vDisk info
6499 * dtype - return the driver type of the device
6502 * 0 - success
6503 * != 0 - some other non-zero return value from ldi(9F) functions
6509 char *device_path = vd->device_path; in vd_identify_dev()
6512 vds_t *vds = vd->vds; in vd_identify_dev()
6514 status = vd_open_using_ldi_by_name(vd, vd->open_flags & ~FWRITE); in vd_identify_dev()
6521 if ((status = ldi_get_dev(vd->ldi_handle[0], &vd->dev[0])) != 0) { in vd_identify_dev()
6529 * so that we can override the built-in list using vds.conf. in vd_identify_dev()
6531 drv_name = ddi_major_to_name(getmajor(vd->dev[0])); in vd_identify_dev()
6535 for (i = 0; i < vds->num_drivers; i++) { in vd_identify_dev()
6536 if (vds->driver_types[i].type == VD_DRIVER_UNKNOWN) { in vd_identify_dev()
6540 if (strcmp(drv_name, vds->driver_types[i].name) == 0) { in vd_identify_dev()
6541 drv_type = vds->driver_types[i].type; in vd_identify_dev()
6546 /* check built-in list */ in vd_identify_dev()
6560 vd->zvol = B_TRUE; in vd_identify_dev()
6573 char *path = vd->device_path; in vd_setup_vd()
6583 switch (vnp->v_type) { in vd_setup_vd()
6587 * single slice disk using the vnode interface. in vd_setup_vd()
6590 vd->volume = B_FALSE; in vd_setup_vd()
6598 * LDI interface, and it is exported either as a single-slice in vd_setup_vd()
6599 * disk or as a full disk depending on the "slice" option and in vd_setup_vd()
6602 * - A volume device is exported as a single-slice disk if the in vd_setup_vd()
6603 * "slice" is specified, otherwise it is exported as a full in vd_setup_vd()
6606 * - A disk slice (different from slice 2) is always exported in vd_setup_vd()
6607 * as a single slice disk using the LDI interface. in vd_setup_vd()
6609 * - The slice 2 of a disk is exported as a single slice disk in vd_setup_vd()
6610 * if the "slice" option is specified, otherwise the entire in vd_setup_vd()
6613 * - The slice of a CD or DVD is exported as single slice disk in vd_setup_vd()
6614 * if the "slice" option is specified, otherwise the entire in vd_setup_vd()
6619 if ((dip = ddi_hold_devi_by_instance(getmajor(vnp->v_rdev), in vd_setup_vd()
6620 dev_to_instance(vnp->v_rdev), 0)) == NULL) { in vd_setup_vd()
6646 vd->volume = B_TRUE; in vd_setup_vd()
6651 * "slice" option is set or not. If the "slice" option is set in vd_setup_vd()
6652 * then the volume device will be exported as a single slice, in vd_setup_vd()
6658 if (vd->volume && vd_volume_force_slice) { in vd_setup_vd()
6659 vd->vdisk_type = VD_DISK_TYPE_SLICE; in vd_setup_vd()
6660 vd->nslices = 1; in vd_setup_vd()
6680 if (!(vd->initialized & VD_SETUP_ERROR) && in vd_setup_vd()
6681 !(DEVI_IS_ATTACHING(vd->vds->dip))) { in vd_setup_vd()
6690 vd->initialized |= VD_SETUP_ERROR; in vd_setup_vd()
6692 } else if (vd->initialized & VD_SETUP_ERROR) { in vd_setup_vd()
6695 vd->initialized &= ~VD_SETUP_ERROR; in vd_setup_vd()
6706 if ((vd->file || vd->zvol) && vd->ioq == NULL) { in vd_setup_vd()
6707 (void) snprintf(tq_name, sizeof (tq_name), "vd_ioq%lu", vd->id); in vd_setup_vd()
6709 if ((vd->ioq = ddi_taskq_create(vd->vds->dip, tq_name, in vd_setup_vd()
6740 vd->id = id; in vds_do_init_vd()
6741 vd->vds = vds; in vds_do_init_vd()
6742 (void) strncpy(vd->device_path, device_path, MAXPATHLEN); in vds_do_init_vd()
6745 vd->open_flags = FREAD; in vds_do_init_vd()
6748 vd->open_flags |= FWRITE; in vds_do_init_vd()
6751 vd->open_flags |= FEXCL; in vds_do_init_vd()
6755 vd->vdisk_type = VD_DISK_TYPE_SLICE; in vds_do_init_vd()
6756 vd->nslices = 1; in vds_do_init_vd()
6758 vd->vdisk_type = VD_DISK_TYPE_DISK; in vds_do_init_vd()
6759 vd->nslices = V_NUMPAR; in vds_do_init_vd()
6763 vd->vdisk_label = VD_DISK_LABEL_UNK; in vds_do_init_vd()
6767 vd->initialized |= VD_DISK_READY; in vds_do_init_vd()
6769 ASSERT(vd->nslices > 0 && vd->nslices <= V_NUMPAR); in vds_do_init_vd()
6771 ((vd->vdisk_type == VD_DISK_TYPE_DISK) ? "disk" : "slice"), in vds_do_init_vd()
6772 (vd->volume ? "yes" : "no"), (vd->file ? "yes" : "no"), in vds_do_init_vd()
6773 vd->nslices); in vds_do_init_vd()
6780 if (ddi_get_soft_iblock_cookie(vds->dip, DDI_SOFTINT_MED, in vds_do_init_vd()
6786 mutex_init(&vd->lock, NULL, MUTEX_DRIVER, iblock); in vds_do_init_vd()
6787 vd->initialized |= VD_LOCKING; in vds_do_init_vd()
6793 if ((vd->startq = ddi_taskq_create(vds->dip, tq_name, 1, in vds_do_init_vd()
6800 if ((vd->completionq = ddi_taskq_create(vds->dip, tq_name, 1, in vds_do_init_vd()
6807 vd->max_msglen = sizeof (vio_msg_t); /* baseline vio message size */ in vds_do_init_vd()
6808 vd->vio_msgp = kmem_alloc(vd->max_msglen, KM_SLEEP); in vds_do_init_vd()
6810 vd->enabled = 1; /* before callback can dispatch to startq */ in vds_do_init_vd()
6815 ldc_attr.instance = ddi_get_instance(vds->dip); in vds_do_init_vd()
6818 if ((status = ldc_init(ldc_id, &ldc_attr, &vd->ldc_handle)) != 0) { in vds_do_init_vd()
6823 vd->initialized |= VD_LDC; in vds_do_init_vd()
6825 if ((status = ldc_reg_callback(vd->ldc_handle, vd_handle_ldc_events, in vds_do_init_vd()
6832 if ((status = ldc_open(vd->ldc_handle)) != 0) { in vds_do_init_vd()
6838 if ((status = ldc_up(vd->ldc_handle)) != 0) { in vds_do_init_vd()
6843 status = ldc_mem_alloc_handle(vd->ldc_handle, &(vd->inband_task.mhdl)); in vds_do_init_vd()
6850 /* Add the successfully-initialized vdisk to the server's table */ in vds_do_init_vd()
6851 if (mod_hash_insert(vds->vd_table, (mod_hash_key_t)id, vd) != 0) { in vds_do_init_vd()
6857 vd->state = VD_STATE_INIT; in vds_do_init_vd()
6865 if (vdp->dring_task != NULL) { in vd_free_dring_task()
6866 ASSERT(vdp->dring_len != 0); in vd_free_dring_task()
6868 for (int i = 0; i < vdp->dring_len; i++) { in vd_free_dring_task()
6869 (void) ldc_mem_free_handle(vdp->dring_task[i].mhdl); in vd_free_dring_task()
6870 kmem_free(vdp->dring_task[i].request, in vd_free_dring_task()
6871 (vdp->descriptor_size - in vd_free_dring_task()
6873 vdp->dring_task[i].request = NULL; in vd_free_dring_task()
6874 kmem_free(vdp->dring_task[i].msg, vdp->max_msglen); in vd_free_dring_task()
6875 vdp->dring_task[i].msg = NULL; in vd_free_dring_task()
6877 kmem_free(vdp->dring_task, in vd_free_dring_task()
6878 (sizeof (*vdp->dring_task)) * vdp->dring_len); in vd_free_dring_task()
6879 vdp->dring_task = NULL; in vd_free_dring_task()
6882 if (vdp->write_queue != NULL) { in vd_free_dring_task()
6883 kmem_free(vdp->write_queue, sizeof (buf_t *) * vdp->dring_len); in vd_free_dring_task()
6884 vdp->write_queue = NULL; in vd_free_dring_task()
6903 if (vd->initialized & VD_LOCKING) { in vds_destroy_vd()
6904 mutex_enter(&vd->lock); in vds_destroy_vd()
6905 vd->enabled = 0; in vds_destroy_vd()
6906 mutex_exit(&vd->lock); in vds_destroy_vd()
6910 if (vd->startq != NULL) in vds_destroy_vd()
6911 ddi_taskq_destroy(vd->startq); /* waits for queued tasks */ in vds_destroy_vd()
6914 if (vd->ioq != NULL) in vds_destroy_vd()
6915 ddi_taskq_destroy(vd->ioq); in vds_destroy_vd()
6918 if (vd->completionq != NULL) in vds_destroy_vd()
6919 ddi_taskq_destroy(vd->completionq); /* waits for tasks */ in vds_destroy_vd()
6924 (void) ldc_mem_free_handle(vd->inband_task.mhdl); in vds_destroy_vd()
6927 if (vd->initialized & VD_LDC) { in vds_destroy_vd()
6929 if (vd->initialized & VD_DRING) in vds_destroy_vd()
6930 (void) ldc_mem_dring_unmap(vd->dring_handle); in vds_destroy_vd()
6932 /* close LDC channel - retry on EAGAIN */ in vds_destroy_vd()
6933 while ((rv = ldc_close(vd->ldc_handle)) == EAGAIN) { in vds_destroy_vd()
6941 (void) ldc_unreg_callback(vd->ldc_handle); in vds_destroy_vd()
6942 (void) ldc_fini(vd->ldc_handle); in vds_destroy_vd()
6951 (void) ldc_set_cb_mode(vd->ldc_handle, LDC_CB_DISABLE); in vds_destroy_vd()
6952 while (ldc_unreg_callback(vd->ldc_handle) == EAGAIN) in vds_destroy_vd()
6958 if (vd->vio_msgp != NULL) { in vds_destroy_vd()
6959 kmem_free(vd->vio_msgp, vd->max_msglen); in vds_destroy_vd()
6960 vd->vio_msgp = NULL; in vds_destroy_vd()
6964 if (vd->inband_task.msg != NULL) { in vds_destroy_vd()
6965 kmem_free(vd->inband_task.msg, vd->max_msglen); in vds_destroy_vd()
6966 vd->inband_task.msg = NULL; in vds_destroy_vd()
6969 if (vd->file) { in vds_destroy_vd()
6971 (void) VOP_CLOSE(vd->file_vnode, vd->open_flags, 1, in vds_destroy_vd()
6973 VN_RELE(vd->file_vnode); in vds_destroy_vd()
6975 /* Close any open backing-device slices */ in vds_destroy_vd()
6976 for (uint_t slice = 0; slice < V_NUMPAR; slice++) { in vds_destroy_vd() local
6977 if (vd->ldi_handle[slice] != NULL) { in vds_destroy_vd()
6978 PR0("Closing slice %u", slice); in vds_destroy_vd()
6979 (void) ldi_close(vd->ldi_handle[slice], in vds_destroy_vd()
6980 vd->open_flags, kcred); in vds_destroy_vd()
6986 if (vd->dskimg_devid != NULL) in vds_destroy_vd()
6987 ddi_devid_free(vd->dskimg_devid); in vds_destroy_vd()
6990 if (vd->flabel) { in vds_destroy_vd()
6991 kmem_free(vd->flabel, vd->flabel_size); in vds_destroy_vd()
6992 vd->flabel = NULL; in vds_destroy_vd()
6993 vd->flabel_size = 0; in vds_destroy_vd()
6997 if (vd->initialized & VD_LOCKING) in vds_destroy_vd()
6998 mutex_destroy(&vd->lock); in vds_destroy_vd()
7031 return (-1); in vds_do_get_ldc_id()
7038 return (-1); in vds_do_get_ldc_id()
7058 return (-1); in vds_get_ldc_id()
7074 * of strings in the vds-block-device-opts property of the vds node
7079 * The vds-block-device-opts property is optional. If a vds has no such
7083 * md - machine description.
7084 * vd_node - vds node in the machine description for which
7086 * options - the returned options.
7131 if (vds->driver_types != NULL) { in vds_driver_types_free()
7132 kmem_free(vds->driver_types, sizeof (vd_driver_type_t) * in vds_driver_types_free()
7133 vds->num_drivers); in vds_driver_types_free()
7134 vds->driver_types = NULL; in vds_driver_types_free()
7135 vds->num_drivers = 0; in vds_driver_types_free()
7148 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, vds->dip, in vds_driver_types_update()
7149 DDI_PROP_DONTPASS, "driver-type-list", &list, &num) != in vds_driver_types_update()
7155 * is in the driver-type-list from vds.conf. However only valid in vds_driver_types_update()
7156 * entries will be populated (i.e. entries from driver-type-list in vds_driver_types_update()
7161 vds->num_drivers = num; in vds_driver_types_update()
7162 vds->driver_types = kmem_zalloc(sizeof (vd_driver_type_t) * num, in vds_driver_types_update()
7170 PRN("vds.conf: driver-type-list, entry %d (%s): " in vds_driver_types_update()
7176 len = (uintptr_t)s - (uintptr_t)list[i]; in vds_driver_types_update()
7179 PRN("vds.conf: driver-type-list, entry %d (%s): " in vds_driver_types_update()
7186 PRN("vds.conf: driver-type-list, entry %d (%s): " in vds_driver_types_update()
7194 vds->driver_types[i].type = VD_DRIVER_DISK; in vds_driver_types_update()
7198 vds->driver_types[i].type = VD_DRIVER_VOLUME; in vds_driver_types_update()
7201 PRN("vds.conf: driver-type-list, entry %d (%s): " in vds_driver_types_update()
7207 (void) strncpy(vds->driver_types[i].name, list[i], len); in vds_driver_types_update()
7209 PR0("driver-type-list, entry %d (%s) added", in vds_driver_types_update()
7249 if (mod_hash_destroy(vds->vd_table, (mod_hash_key_t)id) != 0) in vds_add_vd()
7267 if (mod_hash_destroy(vds->vd_table, (mod_hash_key_t)id) != 0) in vds_remove_vd()
7342 if (mod_hash_destroy(vds->vd_table, (mod_hash_key_t)prev_id) != 0) in vds_change_vd()
7345 /* Re-initialize vdisk with new state */ in vds_change_vd()
7364 for (i = 0; i < md->removed.nelem; i++) in vds_process_md()
7365 vds_remove_vd(vds, md->removed.mdp, md->removed.mdep[i]); in vds_process_md()
7366 for (i = 0; i < md->match_curr.nelem; i++) in vds_process_md()
7367 vds_change_vd(vds, md->match_prev.mdp, md->match_prev.mdep[i], in vds_process_md()
7368 md->match_curr.mdp, md->match_curr.mdep[i]); in vds_process_md()
7369 for (i = 0; i < md->added.nelem; i++) in vds_process_md()
7370 vds_add_vd(vds, md->added.mdp, md->added.mdep[i]); in vds_process_md()
7387 * The "cfg-handle" property of a vds node in an MD contains the MD's in vds_do_attach()
7389 * stores the value of the "cfg-handle" MD property as the value of in vds_do_attach()
7393 * registering with the MD event-generation framework. If the "reg" in vds_do_attach()
7405 VD_REG_PROP, -1); in vds_do_attach()
7418 vds->dip = dip; in vds_do_attach()
7419 vds->vd_table = mod_hash_create_ptrhash("vds_vd_table", VDS_NCHAINS, in vds_do_attach()
7422 ASSERT(vds->vd_table != NULL); in vds_do_attach()
7424 if ((status = ldi_ident_from_dip(dip, &vds->ldi_ident)) != 0) { in vds_do_attach()
7428 vds->initialized |= VDS_LDI; in vds_do_attach()
7439 ispecp->namep = "virtual-device"; in vds_do_attach()
7440 ispecp->specp = pspecp; in vds_do_attach()
7443 &vds->mdeg) != MDEG_SUCCESS) { in vds_do_attach()
7450 vds->ispecp = ispecp; in vds_do_attach()
7451 vds->initialized |= VDS_MDEG; in vds_do_attach()
7453 /* Prevent auto-detaching so driver is available whenever MD changes */ in vds_do_attach()