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