1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _VDSK_COMMON_H 28 #define _VDSK_COMMON_H 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 /* 35 * This header file contains the private LDoms Virtual Disk (vDisk) definitions 36 * common to both the server (vds) and the client (vdc) 37 */ 38 39 #include <sys/efi_partition.h> 40 #include <sys/machparam.h> 41 #include <sys/vtoc.h> 42 43 #include <sys/ldc.h> 44 #include <sys/vio_common.h> 45 #include <sys/vio_mailbox.h> 46 47 /* 48 * vDisk definitions 49 */ 50 51 /* 52 * The number of Descriptor Ring entries 53 * 54 * Constraints: 55 * - overall DRing size must be greater than 8K (MMU_PAGESIZE) 56 * - overall DRing size should be 8K aligned (desirable but not enforced) 57 * - DRing entry must be 8 byte aligned 58 */ 59 #define VD_DRING_LEN 512 60 61 /* 62 * 63 */ 64 #define VD_DRING_ENTRY_SZ (sizeof (vd_dring_entry_t) + \ 65 (sizeof (ldc_mem_cookie_t) * (VD_MAX_COOKIES - 1))) 66 67 /* 68 * The maximum block size we can transmit using one Descriptor Ring entry 69 * 70 * Currently no FS uses more than 128K and it doesn't look like they 71 * will either as there is no perf gain to be had by larger values. 72 * ( see ZFS comment at definition of SPA_MAXBLOCKSIZE ). 73 * 74 * We choose 256K to give us some headroom. 75 */ 76 #define VD_MAX_BLOCK_SIZE (256 * 1024) 77 78 #define VD_MAX_COOKIES ((VD_MAX_BLOCK_SIZE / PAGESIZE) + 1) 79 #define VD_USEC_TIMEOUT 20000 80 #define VD_LDC_IDS_PROP "ldc-ids" 81 #define VD_LDC_MTU 256 82 83 /* 84 * Flags used by ioctl routines to indicate if a copyin/copyout is needed 85 */ 86 #define VD_COPYOUT 0x1 87 #define VD_COPYIN 0x2 88 89 /* 90 * vDisk operations on physical devices 91 */ 92 #define VD_OP_BREAD 0x01 /* Block Read */ 93 #define VD_OP_BWRITE 0x02 /* Block Write */ 94 #define VD_OP_FLUSH 0x03 /* Flush disk write cache contents */ 95 #define VD_OP_GET_WCE 0x04 /* Get disk W$ status */ 96 #define VD_OP_SET_WCE 0x05 /* Enable/Disable disk W$ */ 97 #define VD_OP_GET_VTOC 0x06 /* Get VTOC */ 98 #define VD_OP_SET_VTOC 0x07 /* Set VTOC */ 99 #define VD_OP_GET_DISKGEOM 0x08 /* Get disk geometry */ 100 #define VD_OP_SET_DISKGEOM 0x09 /* Set disk geometry */ 101 #define VD_OP_SCSICMD 0x0a /* SCSI control command */ 102 #define VD_OP_GET_DEVID 0x0b /* Get device id */ 103 #define VD_OP_GET_EFI 0x0c /* Get EFI */ 104 #define VD_OP_SET_EFI 0x0d /* Set EFI */ 105 #define VD_OP_RESET 0x0e /* Reset disk */ 106 #define VD_OP_GET_ACCESS 0x0f /* Get disk access */ 107 #define VD_OP_SET_ACCESS 0x10 /* Set disk access */ 108 #define VD_OP_GET_CAPACITY 0x11 /* Get disk capacity */ 109 #define VD_OP_MASK 0xFF /* mask of all possible operations */ 110 #define VD_OP_COUNT 0x11 /* Number of operations */ 111 112 /* 113 * Status for the VD_OP_GET_ACCESS operation 114 */ 115 #define VD_ACCESS_DENIED 0x00 /* access is not allowed */ 116 #define VD_ACCESS_ALLOWED 0x01 /* access is allowed */ 117 118 /* 119 * Flags for the VD_OP_SET_ACCESS operation 120 */ 121 #define VD_ACCESS_SET_CLEAR 0x00 /* clear exclusive access rights */ 122 #define VD_ACCESS_SET_EXCLUSIVE 0x01 /* set exclusive access rights */ 123 #define VD_ACCESS_SET_PREEMPT 0x02 /* forcefully set access rights */ 124 #define VD_ACCESS_SET_PRESERVE 0x04 /* preserve access rights */ 125 126 /* 127 * This is a mask of all the basic operations supported by all 128 * disk types (v1.0). 129 */ 130 #define VD_OP_MASK_READ \ 131 ((1 << VD_OP_BREAD) | \ 132 (1 << VD_OP_GET_WCE) | \ 133 (1 << VD_OP_GET_VTOC) | \ 134 (1 << VD_OP_GET_DISKGEOM) | \ 135 (1 << VD_OP_GET_DEVID) | \ 136 (1 << VD_OP_GET_EFI)) 137 138 #define VD_OP_MASK_WRITE \ 139 ((1 << VD_OP_BWRITE) | \ 140 (1 << VD_OP_FLUSH) | \ 141 (1 << VD_OP_SET_WCE) | \ 142 (1 << VD_OP_SET_VTOC) | \ 143 (1 << VD_OP_SET_DISKGEOM) | \ 144 (1 << VD_OP_SET_EFI)) 145 146 /* 147 * Mask for additional operations provided for SCSI disks (v1.1) 148 */ 149 #define VD_OP_MASK_SCSI \ 150 ((1 << VD_OP_SCSICMD) | \ 151 (1 << VD_OP_RESET) | \ 152 (1 << VD_OP_GET_ACCESS) | \ 153 (1 << VD_OP_SET_ACCESS)) 154 155 /* 156 * macro to check if the operation 'op' is supported by checking the list 157 * of operations supported which is exported by the vDisk server. 158 */ 159 #define VD_OP_SUPPORTED(ops_bitmask, op) ((ops_bitmask) & (1 << (op))) 160 161 /* 162 * Slice for absolute disk transaction. 163 */ 164 #define VD_SLICE_NONE 0xFF 165 166 /* 167 * EFI disks do not have a slice 7. Actually that slice is used to represent 168 * the whole disk. 169 */ 170 #define VD_EFI_WD_SLICE 7 171 172 /* 173 * Definitions of the various ways vds can export disk support to vdc. 174 */ 175 typedef enum vd_disk_type { 176 VD_DISK_TYPE_UNK = 0, /* Unknown device type */ 177 VD_DISK_TYPE_SLICE, /* slice in block device */ 178 VD_DISK_TYPE_DISK /* entire disk (slice 2) */ 179 } vd_disk_type_t; 180 181 /* 182 * Definitions of the various disk label that vDisk supports. 183 */ 184 typedef enum vd_disk_label { 185 VD_DISK_LABEL_UNK = 0, /* Unknown disk label */ 186 VD_DISK_LABEL_VTOC, /* VTOC disk label */ 187 VD_DISK_LABEL_EFI /* EFI disk label */ 188 } vd_disk_label_t; 189 190 /* 191 * vDisk Descriptor payload 192 */ 193 typedef struct vd_dring_payload { 194 uint64_t req_id; /* The request ID being processed */ 195 uint8_t operation; /* operation for server to perform */ 196 uint8_t slice; /* The disk slice being accessed */ 197 uint16_t resv1; /* padding */ 198 uint32_t status; /* "errno" of server operation */ 199 uint64_t addr; /* LP64 diskaddr_t (block I/O) */ 200 uint64_t nbytes; /* LP64 size_t */ 201 uint32_t ncookies; /* Number of cookies used */ 202 uint32_t resv2; /* padding */ 203 204 ldc_mem_cookie_t cookie[1]; /* variable sized array */ 205 } vd_dring_payload_t; 206 207 208 /* 209 * vDisk Descriptor entry 210 */ 211 typedef struct vd_dring_entry { 212 vio_dring_entry_hdr_t hdr; /* common header */ 213 vd_dring_payload_t payload; /* disk specific data */ 214 } vd_dring_entry_t; 215 216 /* 217 * vDisk logical partition 218 */ 219 typedef struct vd_slice { 220 daddr_t start; /* block number of slice start */ 221 daddr_t nblocks; /* number of blocks in the slice */ 222 } vd_slice_t; 223 224 225 /* 226 * vDisk control operation structures 227 */ 228 229 /* 230 * vDisk geometry definition (VD_OP_GET_DISKGEOM and VD_OP_SET_DISKGEOM) 231 */ 232 typedef struct vd_geom { 233 uint16_t ncyl; /* number of data cylinders */ 234 uint16_t acyl; /* number of alternate cylinders */ 235 uint16_t bcyl; /* cyl offset for fixed head area */ 236 uint16_t nhead; /* number of heads */ 237 uint16_t nsect; /* number of data sectors per track */ 238 uint16_t intrlv; /* interleave factor */ 239 uint16_t apc; /* alternates per cyl (SCSI only) */ 240 uint16_t rpm; /* revolutions per minute */ 241 uint16_t pcyl; /* number of physical cylinders */ 242 uint16_t write_reinstruct; /* # sectors to skip, writes */ 243 uint16_t read_reinstruct; /* # sectors to skip, reads */ 244 } vd_geom_t; 245 246 247 /* 248 * vDisk partition definition 249 */ 250 typedef struct vd_partition { 251 uint16_t id_tag; /* ID tag of partition */ 252 uint16_t perm; /* permission flags for partition */ 253 uint32_t reserved; /* padding */ 254 uint64_t start; /* block number of partition start */ 255 uint64_t nblocks; /* number of blocks in partition */ 256 } vd_partition_t; 257 258 /* 259 * vDisk VTOC definition (VD_OP_GET_VTOC and VD_OP_SET_VTOC) 260 */ 261 #define VD_VOLNAME_LEN 8 /* length of volume_name field */ 262 #define VD_ASCIILABEL_LEN 128 /* length of ascii_label field */ 263 typedef struct vd_vtoc { 264 char volume_name[VD_VOLNAME_LEN]; /* volume name */ 265 uint16_t sector_size; /* sector size in bytes */ 266 uint16_t num_partitions; /* number of partitions */ 267 char ascii_label[VD_ASCIILABEL_LEN]; /* ASCII label */ 268 vd_partition_t partition[V_NUMPAR]; /* partition headers */ 269 } vd_vtoc_t; 270 271 272 /* 273 * vDisk EFI definition (VD_OP_GET_EFI and VD_OP_SET_EFI) 274 */ 275 typedef struct vd_efi { 276 uint64_t lba; /* lba of the request */ 277 uint64_t length; /* length of data */ 278 char data[1]; /* data of the request */ 279 } vd_efi_t; 280 281 282 /* 283 * vDisk DEVID definition (VD_OP_GET_DEVID) 284 */ 285 #define VD_DEVID_SIZE(l) (sizeof (vd_devid_t) - 1 + l) 286 #define VD_DEVID_DEFAULT_LEN 128 287 288 typedef struct vd_devid { 289 uint16_t reserved; /* padding */ 290 uint16_t type; /* type of device id */ 291 uint32_t length; /* length the device id */ 292 char id[1]; /* device id */ 293 } vd_devid_t; 294 295 /* 296 * vDisk CAPACITY definition (VD_OP_GET_CAPACITY) 297 */ 298 typedef struct vd_capacity { 299 uint32_t vdisk_block_size; /* block size in bytes */ 300 uint32_t reserved; /* reserved */ 301 uint64_t vdisk_size; /* disk size in blocks */ 302 } vd_capacity_t; 303 304 /* Identifier for unknown disk size */ 305 #define VD_SIZE_UNKNOWN -1 306 307 /* 308 * vDisk SCSI definition (VD_OP_SCSICMD) 309 */ 310 typedef struct vd_scsi { 311 uint8_t cmd_status; /* command completion status */ 312 uint8_t sense_status; /* sense command completion status */ 313 uint8_t task_attribute; /* task attribute */ 314 uint8_t task_priority; /* task priority */ 315 uint8_t crn; /* command reference number */ 316 uint8_t reserved; /* reserved */ 317 uint16_t timeout; /* command timeout */ 318 uint64_t options; /* options */ 319 uint64_t cdb_len; /* CDB data length */ 320 uint64_t sense_len; /* sense request length */ 321 uint64_t datain_len; /* data in buffer length */ 322 uint64_t dataout_len; /* data out buffer length */ 323 char data[1]; /* data (CDB, sense, data in/out */ 324 } vd_scsi_t; 325 326 /* Minimum size of the vd_scsi structure */ 327 #define VD_SCSI_SIZE (sizeof (vd_scsi_t) - sizeof (uint64_t)) 328 329 /* 330 * Macros to access data buffers in a vd_scsi structure. When using these 331 * macros, the vd_scsi structure needs to be populated with the sizes of 332 * data buffers allocated in the structure. 333 */ 334 #define VD_SCSI_DATA_CDB(vscsi) \ 335 ((union scsi_cdb *)(uintptr_t)((vscsi)->data)) 336 337 #define VD_SCSI_DATA_SENSE(vscsi) \ 338 ((struct scsi_extended_sense *)(uintptr_t)((vscsi)->data + \ 339 P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)))) 340 341 #define VD_SCSI_DATA_IN(vscsi) \ 342 ((uintptr_t)((vscsi)->data + \ 343 P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)) + \ 344 P2ROUNDUP((vscsi)->sense_len, sizeof (uint64_t)))) 345 346 #define VD_SCSI_DATA_OUT(vscsi) \ 347 ((uintptr_t)((vscsi)->data + \ 348 P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)) + \ 349 P2ROUNDUP((vscsi)->sense_len, sizeof (uint64_t)) + \ 350 P2ROUNDUP((vscsi)->datain_len, sizeof (uint64_t)))) 351 352 /* vDisk SCSI task attribute */ 353 #define VD_SCSI_TASK_SIMPLE 0x01 /* simple task */ 354 #define VD_SCSI_TASK_ORDERED 0x02 /* ordered task */ 355 #define VD_SCSI_TASK_HQUEUE 0x03 /* head of queue task */ 356 #define VD_SCSI_TASK_ACA 0x04 /* ACA task */ 357 358 /* vDisk SCSI options */ 359 #define VD_SCSI_OPT_CRN 0x01 /* request has a CRN */ 360 #define VD_SCSI_OPT_NORETRY 0x02 /* do not attempt any retry */ 361 362 /* 363 * Copy the contents of a vd_geom_t to the contents of a dk_geom struct 364 */ 365 #define VD_GEOM2DK_GEOM(vd_geom, dk_geom) \ 366 { \ 367 bzero((dk_geom), sizeof (*(dk_geom))); \ 368 (dk_geom)->dkg_ncyl = (vd_geom)->ncyl; \ 369 (dk_geom)->dkg_acyl = (vd_geom)->acyl; \ 370 (dk_geom)->dkg_bcyl = (vd_geom)->bcyl; \ 371 (dk_geom)->dkg_nhead = (vd_geom)->nhead; \ 372 (dk_geom)->dkg_nsect = (vd_geom)->nsect; \ 373 (dk_geom)->dkg_intrlv = (vd_geom)->intrlv; \ 374 (dk_geom)->dkg_apc = (vd_geom)->apc; \ 375 (dk_geom)->dkg_rpm = (vd_geom)->rpm; \ 376 (dk_geom)->dkg_pcyl = (vd_geom)->pcyl; \ 377 (dk_geom)->dkg_write_reinstruct = (vd_geom)->write_reinstruct; \ 378 (dk_geom)->dkg_read_reinstruct = (vd_geom)->read_reinstruct; \ 379 } 380 381 /* 382 * Copy the contents of a vd_vtoc_t to the contents of a vtoc struct 383 */ 384 #define VD_VTOC2VTOC(vd_vtoc, vtoc) \ 385 { \ 386 bzero((vtoc), sizeof (*(vtoc))); \ 387 bcopy((vd_vtoc)->volume_name, (vtoc)->v_volume, \ 388 MIN(sizeof ((vd_vtoc)->volume_name), \ 389 sizeof ((vtoc)->v_volume))); \ 390 bcopy((vd_vtoc)->ascii_label, (vtoc)->v_asciilabel, \ 391 MIN(sizeof ((vd_vtoc)->ascii_label), \ 392 sizeof ((vtoc)->v_asciilabel))); \ 393 (vtoc)->v_sanity = VTOC_SANE; \ 394 (vtoc)->v_version = V_VERSION; \ 395 (vtoc)->v_sectorsz = (vd_vtoc)->sector_size; \ 396 (vtoc)->v_nparts = (vd_vtoc)->num_partitions; \ 397 for (int i = 0; i < (vd_vtoc)->num_partitions; i++) { \ 398 (vtoc)->v_part[i].p_tag = (vd_vtoc)->partition[i].id_tag; \ 399 (vtoc)->v_part[i].p_flag = (vd_vtoc)->partition[i].perm; \ 400 (vtoc)->v_part[i].p_start = (vd_vtoc)->partition[i].start; \ 401 (vtoc)->v_part[i].p_size = (vd_vtoc)->partition[i].nblocks; \ 402 } \ 403 } 404 405 /* 406 * Copy the contents of a dk_geom struct to the contents of a vd_geom_t 407 */ 408 #define DK_GEOM2VD_GEOM(dk_geom, vd_geom) \ 409 { \ 410 bzero((vd_geom), sizeof (*(vd_geom))); \ 411 (vd_geom)->ncyl = (dk_geom)->dkg_ncyl; \ 412 (vd_geom)->acyl = (dk_geom)->dkg_acyl; \ 413 (vd_geom)->bcyl = (dk_geom)->dkg_bcyl; \ 414 (vd_geom)->nhead = (dk_geom)->dkg_nhead; \ 415 (vd_geom)->nsect = (dk_geom)->dkg_nsect; \ 416 (vd_geom)->intrlv = (dk_geom)->dkg_intrlv; \ 417 (vd_geom)->apc = (dk_geom)->dkg_apc; \ 418 (vd_geom)->rpm = (dk_geom)->dkg_rpm; \ 419 (vd_geom)->pcyl = (dk_geom)->dkg_pcyl; \ 420 (vd_geom)->write_reinstruct = (dk_geom)->dkg_write_reinstruct; \ 421 (vd_geom)->read_reinstruct = (dk_geom)->dkg_read_reinstruct; \ 422 } 423 424 /* 425 * Copy the contents of a vtoc struct to the contents of a vd_vtoc_t 426 */ 427 #define VTOC2VD_VTOC(vtoc, vd_vtoc) \ 428 { \ 429 bzero((vd_vtoc), sizeof (*(vd_vtoc))); \ 430 bcopy((vtoc)->v_volume, (vd_vtoc)->volume_name, \ 431 MIN(sizeof ((vtoc)->v_volume), \ 432 sizeof ((vd_vtoc)->volume_name))); \ 433 bcopy((vtoc)->v_asciilabel, (vd_vtoc)->ascii_label, \ 434 MIN(sizeof ((vtoc)->v_asciilabel), \ 435 sizeof ((vd_vtoc)->ascii_label))); \ 436 (vd_vtoc)->sector_size = (vtoc)->v_sectorsz; \ 437 (vd_vtoc)->num_partitions = (vtoc)->v_nparts; \ 438 for (int i = 0; i < (vtoc)->v_nparts; i++) { \ 439 (vd_vtoc)->partition[i].id_tag = (vtoc)->v_part[i].p_tag; \ 440 (vd_vtoc)->partition[i].perm = (vtoc)->v_part[i].p_flag; \ 441 (vd_vtoc)->partition[i].start = (vtoc)->v_part[i].p_start; \ 442 (vd_vtoc)->partition[i].nblocks = (vtoc)->v_part[i].p_size; \ 443 } \ 444 } 445 446 /* 447 * Copy the contents of a vd_efi_t to the contents of a dk_efi_t. 448 * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly 449 * initialized prior to using this macro. 450 */ 451 #define VD_EFI2DK_EFI(vd_efi, dk_efi) \ 452 { \ 453 (dk_efi)->dki_lba = (vd_efi)->lba; \ 454 (dk_efi)->dki_length = (vd_efi)->length; \ 455 bcopy((vd_efi)->data, (dk_efi)->dki_data, (dk_efi)->dki_length); \ 456 } 457 458 /* 459 * Copy the contents of dk_efi_t to the contents of vd_efi_t. 460 * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly 461 * initialized prior to using this macro. 462 */ 463 #define DK_EFI2VD_EFI(dk_efi, vd_efi) \ 464 { \ 465 (vd_efi)->lba = (dk_efi)->dki_lba; \ 466 (vd_efi)->length = (dk_efi)->dki_length; \ 467 bcopy((dk_efi)->dki_data, (vd_efi)->data, (vd_efi)->length); \ 468 } 469 470 #define VD_MEDIATYPE2DK_MEDIATYPE(mt) \ 471 ((mt) == VD_MEDIA_FIXED ? DK_FIXED_DISK : \ 472 (mt) == VD_MEDIA_CD ? DK_CDROM : \ 473 (mt) == VD_MEDIA_DVD ? DK_DVDROM : \ 474 DK_UNKNOWN) 475 476 /* 477 * If the media type returned by the DKIOCGMEDIAINFO ioctl is greater than 478 * 0xFFFF then this is not an optical media and we consider that this is 479 * a fixed media. 480 * 481 * Otherwise, we have an optical media. If this is a SCSI media then the media 482 * type is actually the profile number returned by the SCSI GET CONFIGURATION 483 * command. In that case, the possible values we can have are described in the 484 * SCSI Multi-Media Commands (MMC) documentation. 485 * 486 * Not all SCSI optical media profile numbers are defined in Solaris. However 487 * undefined profiles are essentially different variants of DVD (like Blu-Ray 488 * or HD-DVD). So we consider that any optical media that we can not explicitly 489 * identify is a DVD. 490 */ 491 #define DK_MEDIA_OPTICAL_MAX 0xFFFF 492 493 #define DK_MEDIATYPE2VD_MEDIATYPE(mt) \ 494 (((mt) > DK_MEDIA_OPTICAL_MAX)? VD_MEDIA_FIXED : \ 495 (mt) == DK_REMOVABLE_DISK ? VD_MEDIA_FIXED : \ 496 (mt) == DK_MO_ERASABLE ? VD_MEDIA_FIXED : \ 497 (mt) == DK_MO_WRITEONCE ? VD_MEDIA_FIXED : \ 498 (mt) == DK_AS_MO ? VD_MEDIA_FIXED : \ 499 (mt) == DK_CDROM ? VD_MEDIA_CD : \ 500 (mt) == DK_CDR ? VD_MEDIA_CD : \ 501 (mt) == DK_CDRW ? VD_MEDIA_CD : \ 502 VD_MEDIA_DVD) 503 504 /* 505 * Hooks for EFI support 506 */ 507 508 /* 509 * The EFI alloc_and_read() function will use some ioctls to get EFI data 510 * but the device reference we will use is different depending if the command 511 * is issued from the vDisk server side (vds) or from the vDisk client side 512 * (vdc). The vd_efi_dev structure is filled by vdc/vds to indicate the ioctl 513 * function to call back and to provide information about the virtual disk. 514 */ 515 typedef int (*vd_efi_ioctl_func)(void *, int, uintptr_t); 516 517 typedef struct vd_efi_dev { 518 void *vdisk; /* opaque pointer to the vdisk */ 519 size_t block_size; /* vdisk block size */ 520 size_t disk_size; /* vdisk size in blocks */ 521 vd_efi_ioctl_func vdisk_ioctl; /* vdisk ioctl function */ 522 } vd_efi_dev_t; 523 524 #define VDSK_EFI_DEV_SET(efi_dev, vdsk, ioctl, bsize, dsize) \ 525 (efi_dev).vdisk = vdsk; \ 526 (efi_dev).vdisk_ioctl = ioctl; \ 527 (efi_dev).block_size = bsize; \ 528 (efi_dev).disk_size = dsize; 529 530 531 int vd_efi_alloc_and_read(vd_efi_dev_t *dev, efi_gpt_t **gpt, efi_gpe_t **gpe); 532 void vd_efi_free(vd_efi_dev_t *dev, efi_gpt_t *gpt, efi_gpe_t *gpe); 533 534 /* 535 * Macros to update the I/O statistics kstat consumed by iostat(1m). 536 */ 537 538 /* 539 * Given a pointer to the instance private data of a vDisk driver (vd), 540 * the type of operation and the number of bytes read/written, this macro 541 * updates the I/O statistics in the kstat. 542 */ 543 #define VD_UPDATE_IO_STATS(vd, op, len) \ 544 { \ 545 ASSERT((vd) != NULL); \ 546 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 547 ASSERT(((op) == VD_OP_BREAD) || ((op) == VD_OP_BWRITE));\ 548 if ((vd)->io_stats != NULL) { \ 549 kstat_io_t *kip = KSTAT_IO_PTR((vd)->io_stats); \ 550 if ((op) == VD_OP_BREAD) { \ 551 kip->reads++; \ 552 kip->nread += (len); \ 553 } else { \ 554 kip->writes++; \ 555 kip->nwritten += (len); \ 556 } \ 557 } \ 558 } 559 560 /* 561 * These wrapper macros take a pointer to the I/O statistics kstat and 562 * update the queue length statistics. These are 'safe' wrappers which 563 * check to see if the kstat was created when the vDisk instance was 564 * added (i.e. is not NULL). 565 */ 566 #define VD_KSTAT_WAITQ_ENTER(vd) \ 567 if ((vd)->io_stats != NULL) { \ 568 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 569 kstat_waitq_enter(KSTAT_IO_PTR((vd)->io_stats)); \ 570 } 571 572 #define VD_KSTAT_WAITQ_EXIT(vd) \ 573 if ((vd)->io_stats != NULL) { \ 574 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 575 kstat_waitq_exit(KSTAT_IO_PTR((vd)->io_stats)); \ 576 } 577 578 #define VD_KSTAT_WAITQ_TO_RUNQ(vd) \ 579 if ((vd)->io_stats != NULL) { \ 580 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 581 kstat_waitq_to_runq(KSTAT_IO_PTR((vd)->io_stats)); \ 582 } 583 584 #define VD_KSTAT_RUNQ_ENTER(vd) \ 585 if ((vd)->io_stats != NULL) { \ 586 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 587 kstat_runq_enter(KSTAT_IO_PTR((vd)->io_stats)); \ 588 } 589 590 #define VD_KSTAT_RUNQ_EXIT(vd) \ 591 if ((vd)->io_stats != NULL) { \ 592 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 593 kstat_runq_exit(KSTAT_IO_PTR((vd)->io_stats)); \ 594 } 595 596 /* 597 * Given a pointer to the instance private data of a vDisk driver (vd) and 598 * the name of the error stats entry we wish to update, increment that value 599 */ 600 #define VD_UPDATE_ERR_STATS(vd, stat_entry) \ 601 { \ 602 ASSERT((vd) != NULL); \ 603 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 604 if ((vd)->err_stats != NULL) { \ 605 vd_err_stats_t *stp; \ 606 stp = (vd_err_stats_t *)(vd)->err_stats->ks_data; \ 607 stp->stat_entry.value.ui32++; \ 608 } \ 609 } 610 611 /* Structure to record vDisk error statistics */ 612 typedef struct vd_err_stats { 613 struct kstat_named vd_softerrs; /* Softerrs */ 614 struct kstat_named vd_transerrs; /* Transport errs */ 615 struct kstat_named vd_protoerrs; /* VIO Protocol errs */ 616 struct kstat_named vd_vid; /* Vendor ID */ 617 struct kstat_named vd_pid; /* Product ID */ 618 struct kstat_named vd_capacity; /* Capacity of the disk */ 619 } vd_err_stats_t; 620 621 622 #ifdef __cplusplus 623 } 624 #endif 625 626 #endif /* _VDSK_COMMON_H */ 627