1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22168404Spjd * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 23168404Spjd * All rights reserved. 24236155Smm * 25236155Smm * Portions Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org> 26168404Spjd */ 27168404Spjd 28168404Spjd#include <sys/zfs_context.h> 29168404Spjd#include <sys/param.h> 30168404Spjd#include <sys/kernel.h> 31168404Spjd#include <sys/bio.h> 32169303Spjd#include <sys/disk.h> 33168404Spjd#include <sys/spa.h> 34205346Spjd#include <sys/spa_impl.h> 35168404Spjd#include <sys/vdev_impl.h> 36168404Spjd#include <sys/fs/zfs.h> 37168404Spjd#include <sys/zio.h> 38168404Spjd#include <geom/geom.h> 39169303Spjd#include <geom/geom_int.h> 40168404Spjd 41168404Spjd/* 42168404Spjd * Virtual device vector for GEOM. 43168404Spjd */ 44168404Spjd 45256956Ssmhstatic g_attrchanged_t vdev_geom_attrchanged; 46168404Spjdstruct g_class zfs_vdev_class = { 47168404Spjd .name = "ZFS::VDEV", 48168404Spjd .version = G_VERSION, 49256956Ssmh .attrchanged = vdev_geom_attrchanged, 50168404Spjd}; 51168404Spjd 52168404SpjdDECLARE_GEOM_CLASS(zfs_vdev_class, zfs_vdev); 53168404Spjd 54240868SpjdSYSCTL_DECL(_vfs_zfs_vdev); 55240868Spjd/* Don't send BIO_FLUSH. */ 56267992Shselaskystatic int vdev_geom_bio_flush_disable; 57267992ShselaskySYSCTL_INT(_vfs_zfs_vdev, OID_AUTO, bio_flush_disable, CTLFLAG_RWTUN, 58219089Spjd &vdev_geom_bio_flush_disable, 0, "Disable BIO_FLUSH"); 59240868Spjd/* Don't send BIO_DELETE. */ 60267992Shselaskystatic int vdev_geom_bio_delete_disable; 61267992ShselaskySYSCTL_INT(_vfs_zfs_vdev, OID_AUTO, bio_delete_disable, CTLFLAG_RWTUN, 62240868Spjd &vdev_geom_bio_delete_disable, 0, "Disable BIO_DELETE"); 63219089Spjd 64298786Sasomers/* Declare local functions */ 65298786Sasomersstatic void vdev_geom_detach(struct g_consumer *cp, boolean_t open_for_read); 66298786Sasomers 67294329Sasomers/* 68294329Sasomers * Thread local storage used to indicate when a thread is probing geoms 69294329Sasomers * for their guids. If NULL, this thread is not tasting geoms. If non NULL, 70294329Sasomers * it is looking for a replacement for the vdev_t* that is its value. 71294329Sasomers */ 72294329Sasomersuint_t zfs_geom_probe_vdev_key; 73294329Sasomers 74168404Spjdstatic void 75256956Ssmhvdev_geom_set_rotation_rate(vdev_t *vd, struct g_consumer *cp) 76256956Ssmh{ 77256956Ssmh int error; 78256956Ssmh uint16_t rate; 79256956Ssmh 80256956Ssmh error = g_getattr("GEOM::rotation_rate", cp, &rate); 81256956Ssmh if (error == 0) 82256956Ssmh vd->vdev_rotation_rate = rate; 83256956Ssmh else 84256956Ssmh vd->vdev_rotation_rate = VDEV_RATE_UNKNOWN; 85256956Ssmh} 86256956Ssmh 87256956Ssmhstatic void 88300881Sasomersvdev_geom_set_physpath(struct g_consumer *cp, boolean_t do_null_update) 89256956Ssmh{ 90302058Sasomers boolean_t needs_update = B_FALSE; 91256956Ssmh vdev_t *vd; 92293677Sasomers char *physpath; 93293677Sasomers int error, physpath_len; 94256956Ssmh 95293677Sasomers if (g_access(cp, 1, 0, 0) != 0) 96293677Sasomers return; 97293677Sasomers 98300881Sasomers vd = cp->private; 99293677Sasomers physpath_len = MAXPATHLEN; 100293677Sasomers physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO); 101293677Sasomers error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath); 102293677Sasomers g_access(cp, -1, 0, 0); 103293677Sasomers if (error == 0) { 104293677Sasomers char *old_physpath; 105293677Sasomers 106297868Sasomers /* g_topology lock ensures that vdev has not been closed */ 107297868Sasomers g_topology_assert(); 108293677Sasomers old_physpath = vd->vdev_physpath; 109293677Sasomers vd->vdev_physpath = spa_strdup(physpath); 110293677Sasomers 111300881Sasomers if (old_physpath != NULL) { 112300881Sasomers needs_update = (strcmp(old_physpath, 113300881Sasomers vd->vdev_physpath) != 0); 114293677Sasomers spa_strfree(old_physpath); 115300881Sasomers } else 116300881Sasomers needs_update = do_null_update; 117293677Sasomers } 118293677Sasomers g_free(physpath); 119300881Sasomers 120300881Sasomers /* 121300881Sasomers * If the physical path changed, update the config. 122300881Sasomers * Only request an update for previously unset physpaths if 123300881Sasomers * requested by the caller. 124300881Sasomers */ 125300881Sasomers if (needs_update) 126300881Sasomers spa_async_request(vd->vdev_spa, SPA_ASYNC_CONFIG_UPDATE); 127300881Sasomers 128256956Ssmh} 129256956Ssmh 130256956Ssmhstatic void 131300881Sasomersvdev_geom_attrchanged(struct g_consumer *cp, const char *attr) 132300881Sasomers{ 133300881Sasomers vdev_t *vd; 134300881Sasomers char *old_physpath; 135300881Sasomers int error; 136300881Sasomers 137300881Sasomers vd = cp->private; 138300881Sasomers if (vd == NULL) 139300881Sasomers return; 140300881Sasomers 141300881Sasomers if (strcmp(attr, "GEOM::rotation_rate") == 0) { 142300881Sasomers vdev_geom_set_rotation_rate(vd, cp); 143300881Sasomers return; 144300881Sasomers } 145300881Sasomers 146300881Sasomers if (strcmp(attr, "GEOM::physpath") == 0) { 147300881Sasomers vdev_geom_set_physpath(cp, /*do_null_update*/B_TRUE); 148300881Sasomers return; 149300881Sasomers } 150300881Sasomers} 151300881Sasomers 152300881Sasomersstatic void 153168404Spjdvdev_geom_orphan(struct g_consumer *cp) 154168404Spjd{ 155168404Spjd vdev_t *vd; 156168404Spjd 157168404Spjd g_topology_assert(); 158168404Spjd 159168404Spjd vd = cp->private; 160293677Sasomers if (vd == NULL) { 161293677Sasomers /* Vdev close in progress. Ignore the event. */ 162253754Smav return; 163293677Sasomers } 164168404Spjd 165219089Spjd /* 166219089Spjd * Orphan callbacks occur from the GEOM event thread. 167219089Spjd * Concurrent with this call, new I/O requests may be 168219089Spjd * working their way through GEOM about to find out 169219089Spjd * (only once executed by the g_down thread) that we've 170219089Spjd * been orphaned from our disk provider. These I/Os 171219089Spjd * must be retired before we can detach our consumer. 172219089Spjd * This is most easily achieved by acquiring the 173219089Spjd * SPA ZIO configuration lock as a writer, but doing 174219089Spjd * so with the GEOM topology lock held would cause 175219089Spjd * a lock order reversal. Instead, rely on the SPA's 176219089Spjd * async removal support to invoke a close on this 177219089Spjd * vdev once it is safe to do so. 178219089Spjd */ 179185029Spjd vd->vdev_remove_wanted = B_TRUE; 180185029Spjd spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE); 181168404Spjd} 182168404Spjd 183168404Spjdstatic struct g_consumer * 184293677Sasomersvdev_geom_attach(struct g_provider *pp, vdev_t *vd) 185168404Spjd{ 186168404Spjd struct g_geom *gp; 187168404Spjd struct g_consumer *cp; 188298017Sasomers int error; 189168404Spjd 190168404Spjd g_topology_assert(); 191168404Spjd 192168404Spjd ZFS_LOG(1, "Attaching to %s.", pp->name); 193298786Sasomers 194298786Sasomers if (pp->sectorsize > VDEV_PAD_SIZE || !ISP2(pp->sectorsize)) { 195298786Sasomers ZFS_LOG(1, "Failing attach of %s. Incompatible sectorsize %d\n", 196298786Sasomers pp->name, pp->sectorsize); 197298786Sasomers return (NULL); 198298786Sasomers } else if (pp->mediasize < SPA_MINDEVSIZE) { 199298786Sasomers ZFS_LOG(1, "Failing attach of %s. Incompatible mediasize %ju\n", 200298786Sasomers pp->name, pp->mediasize); 201298786Sasomers return (NULL); 202298786Sasomers } 203298786Sasomers 204168404Spjd /* Do we have geom already? No? Create one. */ 205168404Spjd LIST_FOREACH(gp, &zfs_vdev_class.geom, geom) { 206169303Spjd if (gp->flags & G_GEOM_WITHER) 207169303Spjd continue; 208169303Spjd if (strcmp(gp->name, "zfs::vdev") != 0) 209169303Spjd continue; 210169303Spjd break; 211168404Spjd } 212168404Spjd if (gp == NULL) { 213168404Spjd gp = g_new_geomf(&zfs_vdev_class, "zfs::vdev"); 214168404Spjd gp->orphan = vdev_geom_orphan; 215293677Sasomers gp->attrchanged = vdev_geom_attrchanged; 216168404Spjd cp = g_new_consumer(gp); 217298017Sasomers error = g_attach(cp, pp); 218298017Sasomers if (error != 0) { 219298017Sasomers ZFS_LOG(1, "%s(%d): g_attach failed: %d\n", __func__, 220298017Sasomers __LINE__, error); 221298786Sasomers vdev_geom_detach(cp, B_FALSE); 222168404Spjd return (NULL); 223168404Spjd } 224298017Sasomers error = g_access(cp, 1, 0, 1); 225298017Sasomers if (error != 0) { 226298017Sasomers ZFS_LOG(1, "%s(%d): g_access failed: %d\n", __func__, 227298017Sasomers __LINE__, error); 228298786Sasomers vdev_geom_detach(cp, B_FALSE); 229168404Spjd return (NULL); 230168404Spjd } 231168404Spjd ZFS_LOG(1, "Created geom and consumer for %s.", pp->name); 232168404Spjd } else { 233168404Spjd /* Check if we are already connected to this provider. */ 234168404Spjd LIST_FOREACH(cp, &gp->consumer, consumer) { 235168404Spjd if (cp->provider == pp) { 236168404Spjd ZFS_LOG(1, "Found consumer for %s.", pp->name); 237168404Spjd break; 238168404Spjd } 239168404Spjd } 240168404Spjd if (cp == NULL) { 241168404Spjd cp = g_new_consumer(gp); 242298017Sasomers error = g_attach(cp, pp); 243298017Sasomers if (error != 0) { 244298017Sasomers ZFS_LOG(1, "%s(%d): g_attach failed: %d\n", 245298017Sasomers __func__, __LINE__, error); 246298786Sasomers vdev_geom_detach(cp, B_FALSE); 247168404Spjd return (NULL); 248168404Spjd } 249298017Sasomers error = g_access(cp, 1, 0, 1); 250298017Sasomers if (error != 0) { 251298017Sasomers ZFS_LOG(1, "%s(%d): g_access failed: %d\n", 252298017Sasomers __func__, __LINE__, error); 253298786Sasomers vdev_geom_detach(cp, B_FALSE); 254168404Spjd return (NULL); 255168404Spjd } 256168404Spjd ZFS_LOG(1, "Created consumer for %s.", pp->name); 257168404Spjd } else { 258298017Sasomers error = g_access(cp, 1, 0, 1); 259298017Sasomers if (error != 0) { 260298017Sasomers ZFS_LOG(1, "%s(%d): g_access failed: %d\n", 261298017Sasomers __func__, __LINE__, error); 262168404Spjd return (NULL); 263298017Sasomers } 264168404Spjd ZFS_LOG(1, "Used existing consumer for %s.", pp->name); 265168404Spjd } 266168404Spjd } 267293677Sasomers 268293677Sasomers /* 269293677Sasomers * BUG: cp may already belong to a vdev. This could happen if: 270293677Sasomers * 1) That vdev is a shared spare, or 271293677Sasomers * 2) We are trying to reopen a missing vdev and we are scanning by 272293677Sasomers * guid. In that case, we'll ultimately fail to open this consumer, 273293677Sasomers * but not until after setting the private field. 274293677Sasomers * The solution is to: 275293677Sasomers * 1) Don't set the private field until after the open succeeds, and 276293677Sasomers * 2) Set it to a linked list of vdevs, not just a single vdev 277293677Sasomers */ 278293677Sasomers cp->private = vd; 279300881Sasomers if (vd != NULL) { 280298786Sasomers vd->vdev_tsd = cp; 281300881Sasomers vdev_geom_set_physpath(cp, /*do_null_update*/B_FALSE); 282300881Sasomers } 283293677Sasomers 284256880Smav cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; 285168404Spjd return (cp); 286168404Spjd} 287168404Spjd 288168404Spjdstatic void 289298786Sasomersvdev_geom_detach(struct g_consumer *cp, boolean_t open_for_read) 290168404Spjd{ 291168404Spjd struct g_geom *gp; 292298786Sasomers vdev_t *vd; 293168404Spjd 294168404Spjd g_topology_assert(); 295168404Spjd 296298786Sasomers ZFS_LOG(1, "Detaching consumer. Provider %s.", 297298786Sasomers cp->provider && cp->provider->name ? cp->provider->name : "NULL"); 298293677Sasomers 299298786Sasomers vd = cp->private; 300293677Sasomers cp->private = NULL; 301293677Sasomers 302293677Sasomers gp = cp->geom; 303298786Sasomers if (open_for_read) 304298786Sasomers g_access(cp, -1, 0, -1); 305168404Spjd /* Destroy consumer on last close. */ 306168404Spjd if (cp->acr == 0 && cp->ace == 0) { 307168404Spjd if (cp->acw > 0) 308168404Spjd g_access(cp, 0, -cp->acw, 0); 309293677Sasomers if (cp->provider != NULL) { 310298786Sasomers ZFS_LOG(1, "Destroying consumer to %s.", 311298786Sasomers cp->provider->name ? cp->provider->name : "NULL"); 312293677Sasomers g_detach(cp); 313293677Sasomers } 314168404Spjd g_destroy_consumer(cp); 315168404Spjd } 316168404Spjd /* Destroy geom if there are no consumers left. */ 317168404Spjd if (LIST_EMPTY(&gp->consumer)) { 318168404Spjd ZFS_LOG(1, "Destroyed geom %s.", gp->name); 319168404Spjd g_wither_geom(gp, ENXIO); 320168404Spjd } 321168404Spjd} 322168404Spjd 323292066Sasomersstatic void 324298786Sasomersvdev_geom_close_locked(vdev_t *vd) 325298786Sasomers{ 326298786Sasomers struct g_consumer *cp; 327298786Sasomers 328298786Sasomers g_topology_assert(); 329298786Sasomers 330298786Sasomers cp = vd->vdev_tsd; 331298814Sasomers vd->vdev_tsd = NULL; 332298814Sasomers vd->vdev_delayed_close = B_FALSE; 333298786Sasomers if (cp == NULL) 334298786Sasomers return; 335298786Sasomers 336298786Sasomers ZFS_LOG(1, "Closing access to %s.", cp->provider->name); 337298786Sasomers 338298786Sasomers vdev_geom_detach(cp, B_TRUE); 339298786Sasomers} 340298786Sasomers 341298786Sasomersstatic void 342292066Sasomersnvlist_get_guids(nvlist_t *list, uint64_t *pguid, uint64_t *vguid) 343185029Spjd{ 344185029Spjd 345294358Sasomers (void) nvlist_lookup_uint64(list, ZPOOL_CONFIG_GUID, vguid); 346294358Sasomers (void) nvlist_lookup_uint64(list, ZPOOL_CONFIG_POOL_GUID, pguid); 347185029Spjd} 348185029Spjd 349300059Sasomers/* 350300059Sasomers * Issue one or more bios to the vdev in parallel 351300059Sasomers * cmds, datas, offsets, errors, and sizes are arrays of length ncmds. Each IO 352300059Sasomers * operation is described by parallel entries from each array. There may be 353300059Sasomers * more bios actually issued than entries in the array 354300059Sasomers */ 355300059Sasomersstatic void 356300059Sasomersvdev_geom_io(struct g_consumer *cp, int *cmds, void **datas, off_t *offsets, 357300059Sasomers off_t *sizes, int *errors, int ncmds) 358185029Spjd{ 359300059Sasomers struct bio **bios; 360185029Spjd u_char *p; 361300059Sasomers off_t off, maxio, s, end; 362300059Sasomers int i, n_bios, j; 363300059Sasomers size_t bios_size; 364185029Spjd 365208682Spjd maxio = MAXPHYS - (MAXPHYS % cp->provider->sectorsize); 366300059Sasomers n_bios = 0; 367185029Spjd 368300059Sasomers /* How many bios are required for all commands ? */ 369300059Sasomers for (i = 0; i < ncmds; i++) 370300059Sasomers n_bios += (sizes[i] + maxio - 1) / maxio; 371300059Sasomers 372300059Sasomers /* Allocate memory for the bios */ 373300059Sasomers bios_size = n_bios * sizeof(struct bio*); 374300059Sasomers bios = kmem_zalloc(bios_size, KM_SLEEP); 375300059Sasomers 376300059Sasomers /* Prepare and issue all of the bios */ 377300059Sasomers for (i = j = 0; i < ncmds; i++) { 378300059Sasomers off = offsets[i]; 379300059Sasomers p = datas[i]; 380300059Sasomers s = sizes[i]; 381300059Sasomers end = off + s; 382300059Sasomers ASSERT((off % cp->provider->sectorsize) == 0); 383300059Sasomers ASSERT((s % cp->provider->sectorsize) == 0); 384300059Sasomers 385300059Sasomers for (; off < end; off += maxio, p += maxio, s -= maxio, j++) { 386300059Sasomers bios[j] = g_alloc_bio(); 387300059Sasomers bios[j]->bio_cmd = cmds[i]; 388300059Sasomers bios[j]->bio_done = NULL; 389300059Sasomers bios[j]->bio_offset = off; 390300059Sasomers bios[j]->bio_length = MIN(s, maxio); 391300059Sasomers bios[j]->bio_data = p; 392300059Sasomers g_io_request(bios[j], cp); 393300059Sasomers } 394185029Spjd } 395300059Sasomers ASSERT(j == n_bios); 396185029Spjd 397300059Sasomers /* Wait for all of the bios to complete, and clean them up */ 398300059Sasomers for (i = j = 0; i < ncmds; i++) { 399300059Sasomers off = offsets[i]; 400300059Sasomers s = sizes[i]; 401300059Sasomers end = off + s; 402300059Sasomers 403300059Sasomers for (; off < end; off += maxio, s -= maxio, j++) { 404300059Sasomers errors[i] = biowait(bios[j], "vdev_geom_io") || errors[i]; 405300059Sasomers g_destroy_bio(bios[j]); 406300059Sasomers } 407300059Sasomers } 408300059Sasomers kmem_free(bios, bios_size); 409185029Spjd} 410185029Spjd 411241286Savgstatic int 412241286Savgvdev_geom_read_config(struct g_consumer *cp, nvlist_t **config) 413241286Savg{ 414185029Spjd struct g_provider *pp; 415300059Sasomers vdev_phys_t *vdev_lists[VDEV_LABELS]; 416185029Spjd char *p, *buf; 417185029Spjd size_t buflen; 418300059Sasomers uint64_t psize, state, txg; 419300059Sasomers off_t offsets[VDEV_LABELS]; 420300059Sasomers off_t size; 421300059Sasomers off_t sizes[VDEV_LABELS]; 422300059Sasomers int cmds[VDEV_LABELS]; 423300059Sasomers int errors[VDEV_LABELS]; 424300059Sasomers int l, len; 425185029Spjd 426185029Spjd g_topology_assert_not(); 427185029Spjd 428185029Spjd pp = cp->provider; 429241286Savg ZFS_LOG(1, "Reading config from %s...", pp->name); 430185029Spjd 431185029Spjd psize = pp->mediasize; 432185029Spjd psize = P2ALIGN(psize, (uint64_t)sizeof(vdev_label_t)); 433185029Spjd 434300059Sasomers size = sizeof(*vdev_lists[0]) + pp->sectorsize - 435300059Sasomers ((sizeof(*vdev_lists[0]) - 1) % pp->sectorsize) - 1; 436185029Spjd 437300059Sasomers buflen = sizeof(vdev_lists[0]->vp_nvlist); 438185029Spjd 439241286Savg *config = NULL; 440300059Sasomers /* Create all of the IO requests */ 441185174Spjd for (l = 0; l < VDEV_LABELS; l++) { 442300059Sasomers cmds[l] = BIO_READ; 443300059Sasomers vdev_lists[l] = kmem_alloc(size, KM_SLEEP); 444300059Sasomers offsets[l] = vdev_label_offset(psize, l, 0) + VDEV_SKIP_SIZE; 445300059Sasomers sizes[l] = size; 446300059Sasomers errors[l] = 0; 447300059Sasomers ASSERT(offsets[l] % pp->sectorsize == 0); 448300059Sasomers } 449185029Spjd 450300059Sasomers /* Issue the IO requests */ 451300059Sasomers vdev_geom_io(cp, cmds, (void**)vdev_lists, offsets, sizes, errors, 452300059Sasomers VDEV_LABELS); 453185029Spjd 454300059Sasomers /* Parse the labels */ 455300059Sasomers for (l = 0; l < VDEV_LABELS; l++) { 456300059Sasomers if (errors[l] != 0) 457185029Spjd continue; 458185029Spjd 459300059Sasomers buf = vdev_lists[l]->vp_nvlist; 460300059Sasomers 461241286Savg if (nvlist_unpack(buf, buflen, config, 0) != 0) 462185029Spjd continue; 463185029Spjd 464241286Savg if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_STATE, 465252056Ssmh &state) != 0 || state > POOL_STATE_L2CACHE) { 466241286Savg nvlist_free(*config); 467241286Savg *config = NULL; 468241286Savg continue; 469241286Savg } 470241286Savg 471300059Sasomers if (state != POOL_STATE_SPARE && 472300059Sasomers state != POOL_STATE_L2CACHE && 473242135Savg (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_TXG, 474242135Savg &txg) != 0 || txg == 0)) { 475241286Savg nvlist_free(*config); 476241286Savg *config = NULL; 477241286Savg continue; 478241286Savg } 479241286Savg 480241286Savg break; 481185029Spjd } 482185029Spjd 483300059Sasomers /* Free the label storage */ 484300059Sasomers for (l = 0; l < VDEV_LABELS; l++) 485300059Sasomers kmem_free(vdev_lists[l], size); 486300059Sasomers 487241286Savg return (*config == NULL ? ENOENT : 0); 488185029Spjd} 489185029Spjd 490243502Savgstatic void 491243502Savgresize_configs(nvlist_t ***configs, uint64_t *count, uint64_t id) 492241286Savg{ 493243502Savg nvlist_t **new_configs; 494243502Savg uint64_t i; 495243502Savg 496243502Savg if (id < *count) 497243502Savg return; 498244635Savg new_configs = kmem_zalloc((id + 1) * sizeof(nvlist_t *), 499244635Savg KM_SLEEP); 500243502Savg for (i = 0; i < *count; i++) 501243502Savg new_configs[i] = (*configs)[i]; 502243502Savg if (*configs != NULL) 503243502Savg kmem_free(*configs, *count * sizeof(void *)); 504243502Savg *configs = new_configs; 505243502Savg *count = id + 1; 506243502Savg} 507243502Savg 508243502Savgstatic void 509243502Savgprocess_vdev_config(nvlist_t ***configs, uint64_t *count, nvlist_t *cfg, 510243502Savg const char *name, uint64_t* known_pool_guid) 511243502Savg{ 512243502Savg nvlist_t *vdev_tree; 513243502Savg uint64_t pool_guid; 514243502Savg uint64_t vdev_guid, known_guid; 515243502Savg uint64_t id, txg, known_txg; 516241286Savg char *pname; 517243502Savg int i; 518241286Savg 519243502Savg if (nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &pname) != 0 || 520241286Savg strcmp(pname, name) != 0) 521243502Savg goto ignore; 522241286Savg 523243502Savg if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_GUID, &pool_guid) != 0) 524243502Savg goto ignore; 525241286Savg 526243502Savg if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_TOP_GUID, &vdev_guid) != 0) 527243502Savg goto ignore; 528241286Savg 529243502Savg if (nvlist_lookup_nvlist(cfg, ZPOOL_CONFIG_VDEV_TREE, &vdev_tree) != 0) 530243502Savg goto ignore; 531243502Savg 532243502Savg if (nvlist_lookup_uint64(vdev_tree, ZPOOL_CONFIG_ID, &id) != 0) 533243502Savg goto ignore; 534243502Savg 535243502Savg VERIFY(nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_TXG, &txg) == 0); 536243502Savg 537243502Savg if (*known_pool_guid != 0) { 538243502Savg if (pool_guid != *known_pool_guid) 539243502Savg goto ignore; 540243502Savg } else 541243502Savg *known_pool_guid = pool_guid; 542243502Savg 543243502Savg resize_configs(configs, count, id); 544243502Savg 545243502Savg if ((*configs)[id] != NULL) { 546243502Savg VERIFY(nvlist_lookup_uint64((*configs)[id], 547243502Savg ZPOOL_CONFIG_POOL_TXG, &known_txg) == 0); 548243502Savg if (txg <= known_txg) 549243502Savg goto ignore; 550243502Savg nvlist_free((*configs)[id]); 551243502Savg } 552243502Savg 553243502Savg (*configs)[id] = cfg; 554243502Savg return; 555243502Savg 556243502Savgignore: 557243502Savg nvlist_free(cfg); 558241286Savg} 559241286Savg 560241286Savgint 561243502Savgvdev_geom_read_pool_label(const char *name, 562243502Savg nvlist_t ***configs, uint64_t *count) 563241286Savg{ 564241286Savg struct g_class *mp; 565298786Sasomers struct g_geom *gp; 566241286Savg struct g_provider *pp; 567241286Savg struct g_consumer *zcp; 568241286Savg nvlist_t *vdev_cfg; 569243502Savg uint64_t pool_guid; 570241286Savg int error; 571241286Savg 572241286Savg DROP_GIANT(); 573241286Savg g_topology_lock(); 574241286Savg 575243502Savg *configs = NULL; 576243502Savg *count = 0; 577243502Savg pool_guid = 0; 578241286Savg LIST_FOREACH(mp, &g_classes, class) { 579241286Savg if (mp == &zfs_vdev_class) 580241286Savg continue; 581241286Savg LIST_FOREACH(gp, &mp->geom, geom) { 582241286Savg if (gp->flags & G_GEOM_WITHER) 583241286Savg continue; 584241286Savg LIST_FOREACH(pp, &gp->provider, provider) { 585241286Savg if (pp->flags & G_PF_WITHER) 586241286Savg continue; 587298786Sasomers zcp = vdev_geom_attach(pp, NULL); 588298786Sasomers if (zcp == NULL) 589241286Savg continue; 590241286Savg g_topology_unlock(); 591241286Savg error = vdev_geom_read_config(zcp, &vdev_cfg); 592241286Savg g_topology_lock(); 593298786Sasomers vdev_geom_detach(zcp, B_TRUE); 594241286Savg if (error) 595241286Savg continue; 596241286Savg ZFS_LOG(1, "successfully read vdev config"); 597241286Savg 598243502Savg process_vdev_config(configs, count, 599243502Savg vdev_cfg, name, &pool_guid); 600241286Savg } 601241286Savg } 602241286Savg } 603241286Savg g_topology_unlock(); 604241286Savg PICKUP_GIANT(); 605243502Savg 606243502Savg return (*count > 0 ? 0 : ENOENT); 607169303Spjd} 608169303Spjd 609292066Sasomersstatic void 610292066Sasomersvdev_geom_read_guids(struct g_consumer *cp, uint64_t *pguid, uint64_t *vguid) 611241286Savg{ 612241286Savg nvlist_t *config; 613241286Savg 614241286Savg g_topology_assert_not(); 615241286Savg 616292066Sasomers *pguid = 0; 617292066Sasomers *vguid = 0; 618241286Savg if (vdev_geom_read_config(cp, &config) == 0) { 619292066Sasomers nvlist_get_guids(config, pguid, vguid); 620241286Savg nvlist_free(config); 621241286Savg } 622241286Savg} 623241286Savg 624298786Sasomersstatic boolean_t 625298786Sasomersvdev_attach_ok(vdev_t *vd, struct g_provider *pp) 626298786Sasomers{ 627298786Sasomers uint64_t pool_guid; 628298786Sasomers uint64_t vdev_guid; 629298786Sasomers struct g_consumer *zcp; 630298786Sasomers boolean_t pool_ok; 631298786Sasomers boolean_t vdev_ok; 632298786Sasomers 633298786Sasomers zcp = vdev_geom_attach(pp, NULL); 634298786Sasomers if (zcp == NULL) { 635298786Sasomers ZFS_LOG(1, "Unable to attach tasting instance to %s.", 636298786Sasomers pp->name); 637298786Sasomers return (B_FALSE); 638298786Sasomers } 639298786Sasomers g_topology_unlock(); 640298786Sasomers vdev_geom_read_guids(zcp, &pool_guid, &vdev_guid); 641298786Sasomers g_topology_lock(); 642298786Sasomers vdev_geom_detach(zcp, B_TRUE); 643298786Sasomers 644298786Sasomers /* 645298786Sasomers * Check that the label's vdev guid matches the desired guid. If the 646298786Sasomers * label has a pool guid, check that it matches too. (Inactive spares 647298786Sasomers * and L2ARCs do not have any pool guid in the label.) 648298786Sasomers */ 649298786Sasomers if ((pool_guid == 0 || pool_guid == spa_guid(vd->vdev_spa)) && 650298786Sasomers vdev_guid == vd->vdev_guid) { 651298786Sasomers ZFS_LOG(1, "guids match for provider %s.", vd->vdev_path); 652298786Sasomers return (B_TRUE); 653298786Sasomers } else { 654298786Sasomers ZFS_LOG(1, "guid mismatch for provider %s: " 655298786Sasomers "%ju:%ju != %ju:%ju.", vd->vdev_path, 656298786Sasomers (uintmax_t)spa_guid(vd->vdev_spa), 657298786Sasomers (uintmax_t)vd->vdev_guid, 658298786Sasomers (uintmax_t)pool_guid, (uintmax_t)vdev_guid); 659298786Sasomers return (B_FALSE); 660298786Sasomers } 661298786Sasomers} 662298786Sasomers 663219089Spjdstatic struct g_consumer * 664293677Sasomersvdev_geom_attach_by_guids(vdev_t *vd) 665169303Spjd{ 666169303Spjd struct g_class *mp; 667298786Sasomers struct g_geom *gp; 668169303Spjd struct g_provider *pp; 669298786Sasomers struct g_consumer *cp; 670169303Spjd 671169303Spjd g_topology_assert(); 672169303Spjd 673219089Spjd cp = NULL; 674169303Spjd LIST_FOREACH(mp, &g_classes, class) { 675169303Spjd if (mp == &zfs_vdev_class) 676169303Spjd continue; 677169303Spjd LIST_FOREACH(gp, &mp->geom, geom) { 678169303Spjd if (gp->flags & G_GEOM_WITHER) 679169303Spjd continue; 680169303Spjd LIST_FOREACH(pp, &gp->provider, provider) { 681298786Sasomers if (!vdev_attach_ok(vd, pp)) 682169303Spjd continue; 683293677Sasomers cp = vdev_geom_attach(pp, vd); 684219089Spjd if (cp == NULL) { 685292069Sasomers printf("ZFS WARNING: Unable to " 686292066Sasomers "attach to %s.\n", pp->name); 687169303Spjd continue; 688169303Spjd } 689219089Spjd break; 690169303Spjd } 691219089Spjd if (cp != NULL) 692219089Spjd break; 693169303Spjd } 694219089Spjd if (cp != NULL) 695219089Spjd break; 696169303Spjd } 697169303Spjdend: 698169303Spjd return (cp); 699169303Spjd} 700169303Spjd 701185029Spjdstatic struct g_consumer * 702292066Sasomersvdev_geom_open_by_guids(vdev_t *vd) 703168404Spjd{ 704185174Spjd struct g_consumer *cp; 705185174Spjd char *buf; 706185174Spjd size_t len; 707185174Spjd 708219089Spjd g_topology_assert(); 709219089Spjd 710297986Sasomers ZFS_LOG(1, "Searching by guids [%ju:%ju].", 711297986Sasomers (uintmax_t)spa_guid(vd->vdev_spa), (uintmax_t)vd->vdev_guid); 712293677Sasomers cp = vdev_geom_attach_by_guids(vd); 713185174Spjd if (cp != NULL) { 714185174Spjd len = strlen(cp->provider->name) + strlen("/dev/") + 1; 715185174Spjd buf = kmem_alloc(len, KM_SLEEP); 716197842Spjd 717185174Spjd snprintf(buf, len, "/dev/%s", cp->provider->name); 718185174Spjd spa_strfree(vd->vdev_path); 719185174Spjd vd->vdev_path = buf; 720185174Spjd 721292066Sasomers ZFS_LOG(1, "Attach by guid [%ju:%ju] succeeded, provider %s.", 722292066Sasomers (uintmax_t)spa_guid(vd->vdev_spa), 723185174Spjd (uintmax_t)vd->vdev_guid, vd->vdev_path); 724185174Spjd } else { 725292066Sasomers ZFS_LOG(1, "Search by guid [%ju:%ju] failed.", 726292066Sasomers (uintmax_t)spa_guid(vd->vdev_spa), 727185174Spjd (uintmax_t)vd->vdev_guid); 728185174Spjd } 729185174Spjd 730185174Spjd return (cp); 731185174Spjd} 732185174Spjd 733185174Spjdstatic struct g_consumer * 734200158Spjdvdev_geom_open_by_path(vdev_t *vd, int check_guid) 735185174Spjd{ 736168404Spjd struct g_provider *pp; 737168404Spjd struct g_consumer *cp; 738168404Spjd 739219089Spjd g_topology_assert(); 740219089Spjd 741169303Spjd cp = NULL; 742168404Spjd pp = g_provider_by_name(vd->vdev_path + sizeof("/dev/") - 1); 743169303Spjd if (pp != NULL) { 744169303Spjd ZFS_LOG(1, "Found provider by name %s.", vd->vdev_path); 745298786Sasomers if (!check_guid || vdev_attach_ok(vd, pp)) 746298786Sasomers cp = vdev_geom_attach(pp, vd); 747168404Spjd } 748169303Spjd 749185029Spjd return (cp); 750185029Spjd} 751169303Spjd 752185029Spjdstatic int 753236155Smmvdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, 754254591Sgibbs uint64_t *logical_ashift, uint64_t *physical_ashift) 755185029Spjd{ 756185029Spjd struct g_provider *pp; 757185029Spjd struct g_consumer *cp; 758219089Spjd size_t bufsize; 759224791Spjd int error; 760185029Spjd 761294329Sasomers /* Set the TLS to indicate downstack that we should not access zvols*/ 762294329Sasomers VERIFY(tsd_set(zfs_geom_probe_vdev_key, vd) == 0); 763294329Sasomers 764185029Spjd /* 765185029Spjd * We must have a pathname, and it must be absolute. 766185029Spjd */ 767185029Spjd if (vd->vdev_path == NULL || vd->vdev_path[0] != '/') { 768185029Spjd vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL; 769185029Spjd return (EINVAL); 770185029Spjd } 771185029Spjd 772185029Spjd vd->vdev_tsd = NULL; 773185029Spjd 774219089Spjd DROP_GIANT(); 775219089Spjd g_topology_lock(); 776203504Spjd error = 0; 777205346Spjd 778292066Sasomers if (vd->vdev_spa->spa_splitting_newspa || 779292066Sasomers (vd->vdev_prevstate == VDEV_STATE_UNKNOWN && 780292066Sasomers vd->vdev_spa->spa_load_state == SPA_LOAD_NONE)) { 781292066Sasomers /* 782292066Sasomers * We are dealing with a vdev that hasn't been previously 783292066Sasomers * opened (since boot), and we are not loading an 784292066Sasomers * existing pool configuration. This looks like a 785292066Sasomers * vdev add operation to a new or existing pool. 786292066Sasomers * Assume the user knows what he/she is doing and find 787292066Sasomers * GEOM provider by its name, ignoring GUID mismatches. 788292066Sasomers * 789292066Sasomers * XXPOLICY: It would be safer to only allow a device 790292066Sasomers * that is unlabeled or labeled but missing 791292066Sasomers * GUID information to be opened in this fashion, 792292066Sasomers * unless we are doing a split, in which case we 793292066Sasomers * should allow any guid. 794292066Sasomers */ 795205346Spjd cp = vdev_geom_open_by_path(vd, 0); 796292066Sasomers } else { 797292066Sasomers /* 798292066Sasomers * Try using the recorded path for this device, but only 799292066Sasomers * accept it if its label data contains the expected GUIDs. 800292066Sasomers */ 801205346Spjd cp = vdev_geom_open_by_path(vd, 1); 802205346Spjd if (cp == NULL) { 803205346Spjd /* 804205346Spjd * The device at vd->vdev_path doesn't have the 805292066Sasomers * expected GUIDs. The disks might have merely 806205346Spjd * moved around so try all other GEOM providers 807292066Sasomers * to find one with the right GUIDs. 808205346Spjd */ 809292066Sasomers cp = vdev_geom_open_by_guids(vd); 810205346Spjd } 811169303Spjd } 812205346Spjd 813294329Sasomers /* Clear the TLS now that tasting is done */ 814294329Sasomers VERIFY(tsd_set(zfs_geom_probe_vdev_key, NULL) == 0); 815294329Sasomers 816185174Spjd if (cp == NULL) { 817185174Spjd ZFS_LOG(1, "Provider %s not found.", vd->vdev_path); 818203504Spjd error = ENOENT; 819218278Sae } else if (cp->provider->sectorsize > VDEV_PAD_SIZE || 820218278Sae !ISP2(cp->provider->sectorsize)) { 821218278Sae ZFS_LOG(1, "Provider %s has unsupported sectorsize.", 822218278Sae vd->vdev_path); 823293677Sasomers 824293677Sasomers vdev_geom_close_locked(vd); 825218278Sae error = EINVAL; 826218278Sae cp = NULL; 827209962Smm } else if (cp->acw == 0 && (spa_mode(vd->vdev_spa) & FWRITE) != 0) { 828207936Spjd int i; 829207936Spjd 830207936Spjd for (i = 0; i < 5; i++) { 831207936Spjd error = g_access(cp, 0, 1, 0); 832207936Spjd if (error == 0) 833207936Spjd break; 834207936Spjd g_topology_unlock(); 835207936Spjd tsleep(vd, 0, "vdev", hz / 2); 836207936Spjd g_topology_lock(); 837207936Spjd } 838203504Spjd if (error != 0) { 839207934Spjd printf("ZFS WARNING: Unable to open %s for writing (error=%d).\n", 840203504Spjd vd->vdev_path, error); 841293677Sasomers vdev_geom_close_locked(vd); 842203504Spjd cp = NULL; 843203504Spjd } 844185174Spjd } 845293677Sasomers 846298072Sasomers /* Fetch initial physical path information for this device. */ 847298072Sasomers if (cp != NULL) 848298072Sasomers vdev_geom_attrchanged(cp, "GEOM::physpath"); 849298072Sasomers 850219089Spjd g_topology_unlock(); 851219089Spjd PICKUP_GIANT(); 852203504Spjd if (cp == NULL) { 853203504Spjd vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 854203504Spjd return (error); 855203504Spjd } 856169303Spjd pp = cp->provider; 857168404Spjd 858168404Spjd /* 859168404Spjd * Determine the actual size of the device. 860168404Spjd */ 861236155Smm *max_psize = *psize = pp->mediasize; 862168404Spjd 863168404Spjd /* 864254591Sgibbs * Determine the device's minimum transfer size and preferred 865254591Sgibbs * transfer size. 866168404Spjd */ 867254591Sgibbs *logical_ashift = highbit(MAX(pp->sectorsize, SPA_MINBLOCKSIZE)) - 1; 868254591Sgibbs *physical_ashift = 0; 869296613Smav if (pp->stripesize > (1 << *logical_ashift) && ISP2(pp->stripesize) && 870296615Smav pp->stripesize <= (1 << SPA_MAXASHIFT) && pp->stripeoffset == 0) 871254591Sgibbs *physical_ashift = highbit(pp->stripesize) - 1; 872168404Spjd 873168404Spjd /* 874240868Spjd * Clear the nowritecache settings, so that on a vdev_reopen() 875240868Spjd * we will try again. 876168404Spjd */ 877168404Spjd vd->vdev_nowritecache = B_FALSE; 878168404Spjd 879256956Ssmh /* 880256956Ssmh * Determine the device's rotation rate. 881256956Ssmh */ 882256956Ssmh vdev_geom_set_rotation_rate(vd, cp); 883256956Ssmh 884168404Spjd return (0); 885168404Spjd} 886168404Spjd 887168404Spjdstatic void 888168404Spjdvdev_geom_close(vdev_t *vd) 889168404Spjd{ 890168404Spjd 891293677Sasomers DROP_GIANT(); 892293677Sasomers g_topology_lock(); 893293677Sasomers vdev_geom_close_locked(vd); 894293677Sasomers g_topology_unlock(); 895293677Sasomers PICKUP_GIANT(); 896168404Spjd} 897168404Spjd 898168404Spjdstatic void 899168404Spjdvdev_geom_io_intr(struct bio *bp) 900168404Spjd{ 901219089Spjd vdev_t *vd; 902168404Spjd zio_t *zio; 903168404Spjd 904168404Spjd zio = bp->bio_caller1; 905219089Spjd vd = zio->io_vd; 906208142Spjd zio->io_error = bp->bio_error; 907208142Spjd if (zio->io_error == 0 && bp->bio_resid != 0) 908269407Ssmh zio->io_error = SET_ERROR(EIO); 909264885Ssmh 910264885Ssmh switch(zio->io_error) { 911264885Ssmh case ENOTSUP: 912208142Spjd /* 913264885Ssmh * If we get ENOTSUP for BIO_FLUSH or BIO_DELETE we know 914264885Ssmh * that future attempts will never succeed. In this case 915264885Ssmh * we set a persistent flag so that we don't bother with 916264885Ssmh * requests in the future. 917208142Spjd */ 918264885Ssmh switch(bp->bio_cmd) { 919264885Ssmh case BIO_FLUSH: 920264885Ssmh vd->vdev_nowritecache = B_TRUE; 921264885Ssmh break; 922264885Ssmh case BIO_DELETE: 923264885Ssmh vd->vdev_notrim = B_TRUE; 924264885Ssmh break; 925219089Spjd } 926264885Ssmh break; 927264885Ssmh case ENXIO: 928264885Ssmh if (!vd->vdev_remove_wanted) { 929264885Ssmh /* 930264885Ssmh * If provider's error is set we assume it is being 931264885Ssmh * removed. 932264885Ssmh */ 933264885Ssmh if (bp->bio_to->error != 0) { 934264885Ssmh vd->vdev_remove_wanted = B_TRUE; 935264885Ssmh spa_async_request(zio->io_spa, 936264885Ssmh SPA_ASYNC_REMOVE); 937264885Ssmh } else if (!vd->vdev_delayed_close) { 938264885Ssmh vd->vdev_delayed_close = B_TRUE; 939264885Ssmh } 940264885Ssmh } 941264885Ssmh break; 942219089Spjd } 943208142Spjd g_destroy_bio(bp); 944296510Smav zio_delay_interrupt(zio); 945168404Spjd} 946168404Spjd 947274304Sdelphijstatic void 948168404Spjdvdev_geom_io_start(zio_t *zio) 949168404Spjd{ 950168404Spjd vdev_t *vd; 951168404Spjd struct g_consumer *cp; 952168404Spjd struct bio *bp; 953168404Spjd int error; 954168404Spjd 955168404Spjd vd = zio->io_vd; 956168404Spjd 957265152Ssmh switch (zio->io_type) { 958265152Ssmh case ZIO_TYPE_IOCTL: 959168404Spjd /* XXPOLICY */ 960185029Spjd if (!vdev_readable(vd)) { 961265152Ssmh zio->io_error = SET_ERROR(ENXIO); 962274304Sdelphij zio_interrupt(zio); 963274304Sdelphij return; 964269407Ssmh } else { 965269407Ssmh switch (zio->io_cmd) { 966269407Ssmh case DKIOCFLUSHWRITECACHE: 967269407Ssmh if (zfs_nocacheflush || vdev_geom_bio_flush_disable) 968269407Ssmh break; 969269407Ssmh if (vd->vdev_nowritecache) { 970269407Ssmh zio->io_error = SET_ERROR(ENOTSUP); 971269407Ssmh break; 972269407Ssmh } 973269407Ssmh goto sendreq; 974269407Ssmh default: 975265152Ssmh zio->io_error = SET_ERROR(ENOTSUP); 976168404Spjd } 977168404Spjd } 978168404Spjd 979274304Sdelphij zio_execute(zio); 980274304Sdelphij return; 981265152Ssmh case ZIO_TYPE_FREE: 982265152Ssmh if (vd->vdev_notrim) { 983265152Ssmh zio->io_error = SET_ERROR(ENOTSUP); 984269407Ssmh } else if (!vdev_geom_bio_delete_disable) { 985269407Ssmh goto sendreq; 986265152Ssmh } 987274304Sdelphij zio_execute(zio); 988274304Sdelphij return; 989168404Spjd } 990168404Spjdsendreq: 991274619Ssmh ASSERT(zio->io_type == ZIO_TYPE_READ || 992274619Ssmh zio->io_type == ZIO_TYPE_WRITE || 993274619Ssmh zio->io_type == ZIO_TYPE_FREE || 994274619Ssmh zio->io_type == ZIO_TYPE_IOCTL); 995274619Ssmh 996208142Spjd cp = vd->vdev_tsd; 997185029Spjd if (cp == NULL) { 998265152Ssmh zio->io_error = SET_ERROR(ENXIO); 999269407Ssmh zio_interrupt(zio); 1000274304Sdelphij return; 1001168404Spjd } 1002168404Spjd bp = g_alloc_bio(); 1003168404Spjd bp->bio_caller1 = zio; 1004168404Spjd switch (zio->io_type) { 1005168404Spjd case ZIO_TYPE_READ: 1006168404Spjd case ZIO_TYPE_WRITE: 1007296510Smav zio->io_target_timestamp = zio_handle_io_delay(zio); 1008168404Spjd bp->bio_cmd = zio->io_type == ZIO_TYPE_READ ? BIO_READ : BIO_WRITE; 1009168404Spjd bp->bio_data = zio->io_data; 1010168404Spjd bp->bio_offset = zio->io_offset; 1011168404Spjd bp->bio_length = zio->io_size; 1012168404Spjd break; 1013265152Ssmh case ZIO_TYPE_FREE: 1014265152Ssmh bp->bio_cmd = BIO_DELETE; 1015265152Ssmh bp->bio_data = NULL; 1016265152Ssmh bp->bio_offset = zio->io_offset; 1017265152Ssmh bp->bio_length = zio->io_size; 1018265152Ssmh break; 1019168404Spjd case ZIO_TYPE_IOCTL: 1020269407Ssmh bp->bio_cmd = BIO_FLUSH; 1021269407Ssmh bp->bio_flags |= BIO_ORDERED; 1022269407Ssmh bp->bio_data = NULL; 1023269407Ssmh bp->bio_offset = cp->provider->mediasize; 1024269407Ssmh bp->bio_length = 0; 1025168404Spjd break; 1026168404Spjd } 1027168404Spjd bp->bio_done = vdev_geom_io_intr; 1028168404Spjd 1029168404Spjd g_io_request(bp, cp); 1030168404Spjd} 1031168404Spjd 1032168404Spjdstatic void 1033168404Spjdvdev_geom_io_done(zio_t *zio) 1034168404Spjd{ 1035168404Spjd} 1036168404Spjd 1037219089Spjdstatic void 1038219089Spjdvdev_geom_hold(vdev_t *vd) 1039219089Spjd{ 1040219089Spjd} 1041219089Spjd 1042219089Spjdstatic void 1043219089Spjdvdev_geom_rele(vdev_t *vd) 1044219089Spjd{ 1045219089Spjd} 1046219089Spjd 1047168404Spjdvdev_ops_t vdev_geom_ops = { 1048168404Spjd vdev_geom_open, 1049168404Spjd vdev_geom_close, 1050168404Spjd vdev_default_asize, 1051168404Spjd vdev_geom_io_start, 1052168404Spjd vdev_geom_io_done, 1053168404Spjd NULL, 1054219089Spjd vdev_geom_hold, 1055219089Spjd vdev_geom_rele, 1056168404Spjd VDEV_TYPE_DISK, /* name of this vdev type */ 1057168404Spjd B_TRUE /* leaf vdev */ 1058168404Spjd}; 1059