FreeBSD ZFS
The Zettabyte File System

vdev_disk.c

Go to the documentation of this file.
00001 /*
00002  * CDDL HEADER START
00003  *
00004  * The contents of this file are subject to the terms of the
00005  * Common Development and Distribution License (the "License").
00006  * You may not use this file except in compliance with the License.
00007  *
00008  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
00009  * or http://www.opensolaris.org/os/licensing.
00010  * See the License for the specific language governing permissions
00011  * and limitations under the License.
00012  *
00013  * When distributing Covered Code, include this CDDL HEADER in each
00014  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
00015  * If applicable, add the following below this CDDL HEADER, with the
00016  * fields enclosed by brackets "[]" replaced with your own identifying
00017  * information: Portions Copyright [yyyy] [name of copyright owner]
00018  *
00019  * CDDL HEADER END
00020  */
00021 /*
00022  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
00023  * Copyright (c) 2012 by Delphix. All rights reserved.
00024  */
00025 
00026 #include <sys/zfs_context.h>
00027 #include <sys/spa_impl.h>
00028 #include <sys/refcount.h>
00029 #include <sys/vdev_disk.h>
00030 #include <sys/vdev_impl.h>
00031 #include <sys/fs/zfs.h>
00032 #include <sys/zio.h>
00033 #include <sys/sunldi.h>
00034 #include <sys/efi_partition.h>
00035 #include <sys/fm/fs/zfs.h>
00036 
00042 extern ldi_ident_t zfs_li;
00043 
00044 typedef struct vdev_disk_buf {
00045         buf_t   vdb_buf;
00046         zio_t   *vdb_io;
00047 } vdev_disk_buf_t;
00048 
00049 static void
00050 vdev_disk_hold(vdev_t *vd)
00051 {
00052         ddi_devid_t devid;
00053         char *minor;
00054 
00055         ASSERT(spa_config_held(vd->vdev_spa, SCL_STATE, RW_WRITER));
00056 
00057         /*
00058          * We must have a pathname, and it must be absolute.
00059          */
00060         if (vd->vdev_path == NULL || vd->vdev_path[0] != '/')
00061                 return;
00062 
00063         /*
00064          * Only prefetch path and devid info if the device has
00065          * never been opened.
00066          */
00067         if (vd->vdev_tsd != NULL)
00068                 return;
00069 
00070         if (vd->vdev_wholedisk == -1ULL) {
00071                 size_t len = strlen(vd->vdev_path) + 3;
00072                 char *buf = kmem_alloc(len, KM_SLEEP);
00073 
00074                 (void) snprintf(buf, len, "%ss0", vd->vdev_path);
00075 
00076                 (void) ldi_vp_from_name(buf, &vd->vdev_name_vp);
00077                 kmem_free(buf, len);
00078         }
00079 
00080         if (vd->vdev_name_vp == NULL)
00081                 (void) ldi_vp_from_name(vd->vdev_path, &vd->vdev_name_vp);
00082 
00083         if (vd->vdev_devid != NULL &&
00084             ddi_devid_str_decode(vd->vdev_devid, &devid, &minor) == 0) {
00085                 (void) ldi_vp_from_devid(devid, minor, &vd->vdev_devid_vp);
00086                 ddi_devid_str_free(minor);
00087                 ddi_devid_free(devid);
00088         }
00089 }
00090 
00091 static void
00092 vdev_disk_rele(vdev_t *vd)
00093 {
00094         ASSERT(spa_config_held(vd->vdev_spa, SCL_STATE, RW_WRITER));
00095 
00096         if (vd->vdev_name_vp) {
00097                 VN_RELE_ASYNC(vd->vdev_name_vp,
00098                     dsl_pool_vnrele_taskq(vd->vdev_spa->spa_dsl_pool));
00099                 vd->vdev_name_vp = NULL;
00100         }
00101         if (vd->vdev_devid_vp) {
00102                 VN_RELE_ASYNC(vd->vdev_devid_vp,
00103                     dsl_pool_vnrele_taskq(vd->vdev_spa->spa_dsl_pool));
00104                 vd->vdev_devid_vp = NULL;
00105         }
00106 }
00107 
00108 static uint64_t
00109 vdev_disk_get_space(vdev_t *vd, uint64_t capacity, uint_t blksz)
00110 {
00111         ASSERT(vd->vdev_wholedisk);
00112 
00113         vdev_disk_t *dvd = vd->vdev_tsd;
00114         dk_efi_t dk_ioc;
00115         efi_gpt_t *efi;
00116         uint64_t avail_space = 0;
00117         int efisize = EFI_LABEL_SIZE * 2;
00118 
00119         dk_ioc.dki_data = kmem_alloc(efisize, KM_SLEEP);
00120         dk_ioc.dki_lba = 1;
00121         dk_ioc.dki_length = efisize;
00122         dk_ioc.dki_data_64 = (uint64_t)(uintptr_t)dk_ioc.dki_data;
00123         efi = dk_ioc.dki_data;
00124 
00125         if (ldi_ioctl(dvd->vd_lh, DKIOCGETEFI, (intptr_t)&dk_ioc,
00126             FKIOCTL, kcred, NULL) == 0) {
00127                 uint64_t efi_altern_lba = LE_64(efi->efi_gpt_AlternateLBA);
00128 
00129                 zfs_dbgmsg("vdev %s, capacity %llu, altern lba %llu",
00130                     vd->vdev_path, capacity, efi_altern_lba);
00131                 if (capacity > efi_altern_lba)
00132                         avail_space = (capacity - efi_altern_lba) * blksz;
00133         }
00134         kmem_free(dk_ioc.dki_data, efisize);
00135         return (avail_space);
00136 }
00137 
00138 static int
00139 vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
00140     uint64_t *ashift)
00141 {
00142         spa_t *spa = vd->vdev_spa;
00143         vdev_disk_t *dvd;
00144         struct dk_minfo_ext dkmext;
00145         int error;
00146         dev_t dev;
00147         int otyp;
00148 
00149         /*
00150          * We must have a pathname, and it must be absolute.
00151          */
00152         if (vd->vdev_path == NULL || vd->vdev_path[0] != '/') {
00153                 vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
00154                 return (EINVAL);
00155         }
00156 
00157         /*
00158          * Reopen the device if it's not currently open. Otherwise,
00159          * just update the physical size of the device.
00160          */
00161         if (vd->vdev_tsd != NULL) {
00162                 ASSERT(vd->vdev_reopening);
00163                 dvd = vd->vdev_tsd;
00164                 goto skip_open;
00165         }
00166 
00167         dvd = vd->vdev_tsd = kmem_zalloc(sizeof (vdev_disk_t), KM_SLEEP);
00168 
00169         /*
00170          * When opening a disk device, we want to preserve the user's original
00171          * intent.  We always want to open the device by the path the user gave
00172          * us, even if it is one of multiple paths to the save device.  But we
00173          * also want to be able to survive disks being removed/recabled.
00174          * Therefore the sequence of opening devices is:
00175          *
00176          * 1. Try opening the device by path.  For legacy pools without the
00177          *    'whole_disk' property, attempt to fix the path by appending 's0'.
00178          *
00179          * 2. If the devid of the device matches the stored value, return
00180          *    success.
00181          *
00182          * 3. Otherwise, the device may have moved.  Try opening the device
00183          *    by the devid instead.
00184          */
00185         if (vd->vdev_devid != NULL) {
00186                 if (ddi_devid_str_decode(vd->vdev_devid, &dvd->vd_devid,
00187                     &dvd->vd_minor) != 0) {
00188                         vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
00189                         return (EINVAL);
00190                 }
00191         }
00192 
00193         error = EINVAL;         /* presume failure */
00194 
00195         if (vd->vdev_path != NULL) {
00196                 ddi_devid_t devid;
00197 
00198                 if (vd->vdev_wholedisk == -1ULL) {
00199                         size_t len = strlen(vd->vdev_path) + 3;
00200                         char *buf = kmem_alloc(len, KM_SLEEP);
00201                         ldi_handle_t lh;
00202 
00203                         (void) snprintf(buf, len, "%ss0", vd->vdev_path);
00204 
00205                         if (ldi_open_by_name(buf, spa_mode(spa), kcred,
00206                             &lh, zfs_li) == 0) {
00207                                 spa_strfree(vd->vdev_path);
00208                                 vd->vdev_path = buf;
00209                                 vd->vdev_wholedisk = 1ULL;
00210                                 (void) ldi_close(lh, spa_mode(spa), kcred);
00211                         } else {
00212                                 kmem_free(buf, len);
00213                         }
00214                 }
00215 
00216                 error = ldi_open_by_name(vd->vdev_path, spa_mode(spa), kcred,
00217                     &dvd->vd_lh, zfs_li);
00218 
00219                 /*
00220                  * Compare the devid to the stored value.
00221                  */
00222                 if (error == 0 && vd->vdev_devid != NULL &&
00223                     ldi_get_devid(dvd->vd_lh, &devid) == 0) {
00224                         if (ddi_devid_compare(devid, dvd->vd_devid) != 0) {
00225                                 error = EINVAL;
00226                                 (void) ldi_close(dvd->vd_lh, spa_mode(spa),
00227                                     kcred);
00228                                 dvd->vd_lh = NULL;
00229                         }
00230                         ddi_devid_free(devid);
00231                 }
00232 
00233                 /*
00234                  * If we succeeded in opening the device, but 'vdev_wholedisk'
00235                  * is not yet set, then this must be a slice.
00236                  */
00237                 if (error == 0 && vd->vdev_wholedisk == -1ULL)
00238                         vd->vdev_wholedisk = 0;
00239         }
00240 
00241         /*
00242          * If we were unable to open by path, or the devid check fails, open by
00243          * devid instead.
00244          */
00245         if (error != 0 && vd->vdev_devid != NULL)
00246                 error = ldi_open_by_devid(dvd->vd_devid, dvd->vd_minor,
00247                     spa_mode(spa), kcred, &dvd->vd_lh, zfs_li);
00248 
00249         /*
00250          * If all else fails, then try opening by physical path (if available)
00251          * or the logical path (if we failed due to the devid check).  While not
00252          * as reliable as the devid, this will give us something, and the higher
00253          * level vdev validation will prevent us from opening the wrong device.
00254          */
00255         if (error) {
00256                 if (vd->vdev_physpath != NULL &&
00257                     (dev = ddi_pathname_to_dev_t(vd->vdev_physpath)) != NODEV)
00258                         error = ldi_open_by_dev(&dev, OTYP_BLK, spa_mode(spa),
00259                             kcred, &dvd->vd_lh, zfs_li);
00260 
00261                 /*
00262                  * Note that we don't support the legacy auto-wholedisk support
00263                  * as above.  This hasn't been used in a very long time and we
00264                  * don't need to propagate its oddities to this edge condition.
00265                  */
00266                 if (error && vd->vdev_path != NULL)
00267                         error = ldi_open_by_name(vd->vdev_path, spa_mode(spa),
00268                             kcred, &dvd->vd_lh, zfs_li);
00269         }
00270 
00271         if (error) {
00272                 vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
00273                 return (error);
00274         }
00275 
00276         /*
00277          * Once a device is opened, verify that the physical device path (if
00278          * available) is up to date.
00279          */
00280         if (ldi_get_dev(dvd->vd_lh, &dev) == 0 &&
00281             ldi_get_otyp(dvd->vd_lh, &otyp) == 0) {
00282                 char *physpath, *minorname;
00283 
00284                 physpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
00285                 minorname = NULL;
00286                 if (ddi_dev_pathname(dev, otyp, physpath) == 0 &&
00287                     ldi_get_minor_name(dvd->vd_lh, &minorname) == 0 &&
00288                     (vd->vdev_physpath == NULL ||
00289                     strcmp(vd->vdev_physpath, physpath) != 0)) {
00290                         if (vd->vdev_physpath)
00291                                 spa_strfree(vd->vdev_physpath);
00292                         (void) strlcat(physpath, ":", MAXPATHLEN);
00293                         (void) strlcat(physpath, minorname, MAXPATHLEN);
00294                         vd->vdev_physpath = spa_strdup(physpath);
00295                 }
00296                 if (minorname)
00297                         kmem_free(minorname, strlen(minorname) + 1);
00298                 kmem_free(physpath, MAXPATHLEN);
00299         }
00300 
00301 skip_open:
00302         /*
00303          * Determine the actual size of the device.
00304          */
00305         if (ldi_get_size(dvd->vd_lh, psize) != 0) {
00306                 vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
00307                 return (EINVAL);
00308         }
00309 
00310         /*
00311          * Determine the device's minimum transfer size.
00312          * If the ioctl isn't supported, assume DEV_BSIZE.
00313          */
00314         if (ldi_ioctl(dvd->vd_lh, DKIOCGMEDIAINFOEXT, (intptr_t)&dkmext,
00315             FKIOCTL, kcred, NULL) != 0)
00316                 dkmext.dki_pbsize = DEV_BSIZE;
00317 
00318         *ashift = highbit(MAX(dkmext.dki_pbsize, SPA_MINBLOCKSIZE)) - 1;
00319 
00320         if (vd->vdev_wholedisk == 1) {
00321                 uint64_t capacity = dkmext.dki_capacity - 1;
00322                 uint64_t blksz = dkmext.dki_lbsize;
00323                 int wce = 1;
00324 
00325                 /*
00326                  * If we own the whole disk, try to enable disk write caching.
00327                  * We ignore errors because it's OK if we can't do it.
00328                  */
00329                 (void) ldi_ioctl(dvd->vd_lh, DKIOCSETWCE, (intptr_t)&wce,
00330                     FKIOCTL, kcred, NULL);
00331 
00332                 *max_psize = *psize + vdev_disk_get_space(vd, capacity, blksz);
00333                 zfs_dbgmsg("capacity change: vdev %s, psize %llu, "
00334                     "max_psize %llu", vd->vdev_path, *psize, *max_psize);
00335         } else {
00336                 *max_psize = *psize;
00337         }
00338 
00339         /*
00340          * Clear the nowritecache bit, so that on a vdev_reopen() we will
00341          * try again.
00342          */
00343         vd->vdev_nowritecache = B_FALSE;
00344 
00345         return (0);
00346 }
00347 
00348 static void
00349 vdev_disk_close(vdev_t *vd)
00350 {
00351         vdev_disk_t *dvd = vd->vdev_tsd;
00352 
00353         if (vd->vdev_reopening || dvd == NULL)
00354                 return;
00355 
00356         if (dvd->vd_minor != NULL)
00357                 ddi_devid_str_free(dvd->vd_minor);
00358 
00359         if (dvd->vd_devid != NULL)
00360                 ddi_devid_free(dvd->vd_devid);
00361 
00362         if (dvd->vd_lh != NULL)
00363                 (void) ldi_close(dvd->vd_lh, spa_mode(vd->vdev_spa), kcred);
00364 
00365         vd->vdev_delayed_close = B_FALSE;
00366         kmem_free(dvd, sizeof (vdev_disk_t));
00367         vd->vdev_tsd = NULL;
00368 }
00369 
00370 int
00371 vdev_disk_physio(ldi_handle_t vd_lh, caddr_t data, size_t size,
00372     uint64_t offset, int flags)
00373 {
00374         buf_t *bp;
00375         int error = 0;
00376 
00377         if (vd_lh == NULL)
00378                 return (EINVAL);
00379 
00380         ASSERT(flags & B_READ || flags & B_WRITE);
00381 
00382         bp = getrbuf(KM_SLEEP);
00383         bp->b_flags = flags | B_BUSY | B_NOCACHE | B_FAILFAST;
00384         bp->b_bcount = size;
00385         bp->b_un.b_addr = (void *)data;
00386         bp->b_lblkno = lbtodb(offset);
00387         bp->b_bufsize = size;
00388 
00389         error = ldi_strategy(vd_lh, bp);
00390         ASSERT(error == 0);
00391         if ((error = biowait(bp)) == 0 && bp->b_resid != 0)
00392                 error = EIO;
00393         freerbuf(bp);
00394 
00395         return (error);
00396 }
00397 
00398 static void
00399 vdev_disk_io_intr(buf_t *bp)
00400 {
00401         vdev_disk_buf_t *vdb = (vdev_disk_buf_t *)bp;
00402         zio_t *zio = vdb->vdb_io;
00403 
00404         /*
00405          * The rest of the zio stack only deals with EIO, ECKSUM, and ENXIO.
00406          * Rather than teach the rest of the stack about other error
00407          * possibilities (EFAULT, etc), we normalize the error value here.
00408          */
00409         zio->io_error = (geterror(bp) != 0 ? EIO : 0);
00410 
00411         if (zio->io_error == 0 && bp->b_resid != 0)
00412                 zio->io_error = EIO;
00413 
00414         kmem_free(vdb, sizeof (vdev_disk_buf_t));
00415 
00416         zio_interrupt(zio);
00417 }
00418 
00419 static void
00420 vdev_disk_ioctl_free(zio_t *zio)
00421 {
00422         kmem_free(zio->io_vsd, sizeof (struct dk_callback));
00423 }
00424 
00425 static const zio_vsd_ops_t vdev_disk_vsd_ops = {
00426         vdev_disk_ioctl_free,
00427         zio_vsd_default_cksum_report
00428 };
00429 
00430 static void
00431 vdev_disk_ioctl_done(void *zio_arg, int error)
00432 {
00433         zio_t *zio = zio_arg;
00434 
00435         zio->io_error = error;
00436 
00437         zio_interrupt(zio);
00438 }
00439 
00440 static int
00441 vdev_disk_io_start(zio_t *zio)
00442 {
00443         vdev_t *vd = zio->io_vd;
00444         vdev_disk_t *dvd = vd->vdev_tsd;
00445         vdev_disk_buf_t *vdb;
00446         struct dk_callback *dkc;
00447         buf_t *bp;
00448         int error;
00449 
00450         if (zio->io_type == ZIO_TYPE_IOCTL) {
00451                 /* XXPOLICY */
00452                 if (!vdev_readable(vd)) {
00453                         zio->io_error = ENXIO;
00454                         return (ZIO_PIPELINE_CONTINUE);
00455                 }
00456 
00457                 switch (zio->io_cmd) {
00458 
00459                 case DKIOCFLUSHWRITECACHE:
00460 
00461                         if (zfs_nocacheflush)
00462                                 break;
00463 
00464                         if (vd->vdev_nowritecache) {
00465                                 zio->io_error = ENOTSUP;
00466                                 break;
00467                         }
00468 
00469                         zio->io_vsd = dkc = kmem_alloc(sizeof (*dkc), KM_SLEEP);
00470                         zio->io_vsd_ops = &vdev_disk_vsd_ops;
00471 
00472                         dkc->dkc_callback = vdev_disk_ioctl_done;
00473                         dkc->dkc_flag = FLUSH_VOLATILE;
00474                         dkc->dkc_cookie = zio;
00475 
00476                         error = ldi_ioctl(dvd->vd_lh, zio->io_cmd,
00477                             (uintptr_t)dkc, FKIOCTL, kcred, NULL);
00478 
00479                         if (error == 0) {
00480                                 /*
00481                                  * The ioctl will be done asychronously,
00482                                  * and will call vdev_disk_ioctl_done()
00483                                  * upon completion.
00484                                  */
00485                                 return (ZIO_PIPELINE_STOP);
00486                         }
00487 
00488                         if (error == ENOTSUP || error == ENOTTY) {
00489                                 /*
00490                                  * If we get ENOTSUP or ENOTTY, we know that
00491                                  * no future attempts will ever succeed.
00492                                  * In this case we set a persistent bit so
00493                                  * that we don't bother with the ioctl in the
00494                                  * future.
00495                                  */
00496                                 vd->vdev_nowritecache = B_TRUE;
00497                         }
00498                         zio->io_error = error;
00499 
00500                         break;
00501 
00502                 default:
00503                         zio->io_error = ENOTSUP;
00504                 }
00505 
00506                 return (ZIO_PIPELINE_CONTINUE);
00507         }
00508 
00509         vdb = kmem_alloc(sizeof (vdev_disk_buf_t), KM_SLEEP);
00510 
00511         vdb->vdb_io = zio;
00512         bp = &vdb->vdb_buf;
00513 
00514         bioinit(bp);
00515         bp->b_flags = B_BUSY | B_NOCACHE |
00516             (zio->io_type == ZIO_TYPE_READ ? B_READ : B_WRITE);
00517         if (!(zio->io_flags & (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD)))
00518                 bp->b_flags |= B_FAILFAST;
00519         bp->b_bcount = zio->io_size;
00520         bp->b_un.b_addr = zio->io_data;
00521         bp->b_lblkno = lbtodb(zio->io_offset);
00522         bp->b_bufsize = zio->io_size;
00523         bp->b_iodone = (int (*)())vdev_disk_io_intr;
00524 
00525         /* ldi_strategy() will return non-zero only on programming errors */
00526         VERIFY(ldi_strategy(dvd->vd_lh, bp) == 0);
00527 
00528         return (ZIO_PIPELINE_STOP);
00529 }
00530 
00531 static void
00532 vdev_disk_io_done(zio_t *zio)
00533 {
00534         vdev_t *vd = zio->io_vd;
00535 
00536         /*
00537          * If the device returned EIO, then attempt a DKIOCSTATE ioctl to see if
00538          * the device has been removed.  If this is the case, then we trigger an
00539          * asynchronous removal of the device. Otherwise, probe the device and
00540          * make sure it's still accessible.
00541          */
00542         if (zio->io_error == EIO && !vd->vdev_remove_wanted) {
00543                 vdev_disk_t *dvd = vd->vdev_tsd;
00544                 int state = DKIO_NONE;
00545 
00546                 if (ldi_ioctl(dvd->vd_lh, DKIOCSTATE, (intptr_t)&state,
00547                     FKIOCTL, kcred, NULL) == 0 && state != DKIO_INSERTED) {
00548                         /*
00549                          * We post the resource as soon as possible, instead of
00550                          * when the async removal actually happens, because the
00551                          * DE is using this information to discard previous I/O
00552                          * errors.
00553                          */
00554                         zfs_post_remove(zio->io_spa, vd);
00555                         vd->vdev_remove_wanted = B_TRUE;
00556                         spa_async_request(zio->io_spa, SPA_ASYNC_REMOVE);
00557                 } else if (!vd->vdev_delayed_close) {
00558                         vd->vdev_delayed_close = B_TRUE;
00559                 }
00560         }
00561 }
00562 
00563 vdev_ops_t vdev_disk_ops = {
00564         vdev_disk_open,
00565         vdev_disk_close,
00566         vdev_default_asize,
00567         vdev_disk_io_start,
00568         vdev_disk_io_done,
00569         NULL,
00570         vdev_disk_hold,
00571         vdev_disk_rele,
00572         VDEV_TYPE_DISK,         /* name of this vdev type */
00573         B_TRUE                  /* leaf vdev */
00574 };
00575 
00580 int
00581 vdev_disk_read_rootlabel(char *devpath, char *devid, nvlist_t **config)
00582 {
00583         ldi_handle_t vd_lh;
00584         vdev_label_t *label;
00585         uint64_t s, size;
00586         int l;
00587         ddi_devid_t tmpdevid;
00588         int error = -1;
00589         char *minor_name;
00590 
00591         /*
00592          * Read the device label and build the nvlist.
00593          */
00594         if (devid != NULL && ddi_devid_str_decode(devid, &tmpdevid,
00595             &minor_name) == 0) {
00596                 error = ldi_open_by_devid(tmpdevid, minor_name,
00597                     FREAD, kcred, &vd_lh, zfs_li);
00598                 ddi_devid_free(tmpdevid);
00599                 ddi_devid_str_free(minor_name);
00600         }
00601 
00602         if (error && (error = ldi_open_by_name(devpath, FREAD, kcred, &vd_lh,
00603             zfs_li)))
00604                 return (error);
00605 
00606         if (ldi_get_size(vd_lh, &s)) {
00607                 (void) ldi_close(vd_lh, FREAD, kcred);
00608                 return (EIO);
00609         }
00610 
00611         size = P2ALIGN_TYPED(s, sizeof (vdev_label_t), uint64_t);
00612         label = kmem_alloc(sizeof (vdev_label_t), KM_SLEEP);
00613 
00614         *config = NULL;
00615         for (l = 0; l < VDEV_LABELS; l++) {
00616                 uint64_t offset, state, txg = 0;
00617 
00618                 /* read vdev label */
00619                 offset = vdev_label_offset(size, l, 0);
00620                 if (vdev_disk_physio(vd_lh, (caddr_t)label,
00621                     VDEV_SKIP_SIZE + VDEV_PHYS_SIZE, offset, B_READ) != 0)
00622                         continue;
00623 
00624                 if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist,
00625                     sizeof (label->vl_vdev_phys.vp_nvlist), config, 0) != 0) {
00626                         *config = NULL;
00627                         continue;
00628                 }
00629 
00630                 if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_STATE,
00631                     &state) != 0 || state >= POOL_STATE_DESTROYED) {
00632                         nvlist_free(*config);
00633                         *config = NULL;
00634                         continue;
00635                 }
00636 
00637                 if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_TXG,
00638                     &txg) != 0 || txg == 0) {
00639                         nvlist_free(*config);
00640                         *config = NULL;
00641                         continue;
00642                 }
00643 
00644                 break;
00645         }
00646 
00647         kmem_free(label, sizeof (vdev_label_t));
00648         (void) ldi_close(vd_lh, FREAD, kcred);
00649         if (*config == NULL)
00650                 error = EIDRM;
00651 
00652         return (error);
00653 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines