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