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