diff options
author | Eric Schrock <Eric.Schrock@Sun.COM> | 2009-10-21 16:03:06 -0700 |
---|---|---|
committer | Eric Schrock <Eric.Schrock@Sun.COM> | 2009-10-21 16:03:06 -0700 |
commit | 096d22d43da2758693a6df66ce7d9ab54c9d464c (patch) | |
tree | b8425c2c1973621ead490969138ea2a8ebc6513f | |
parent | 807e8f10a5bd74064a2c6ed98b73c845df2f834e (diff) | |
download | illumos-joyent-096d22d43da2758693a6df66ce7d9ab54c9d464c.tar.gz |
6893087 removing and inserting a faulted vdev clears faulted state
6893088 new ereports need to be generated when clearing a vdev
6893090 clearing a vdev should automatically detach spare
6893099 zpool_clear_label() would be useful
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs.h | 3 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_import.c | 30 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/mapfile-vers | 1 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev.c | 32 |
4 files changed, 65 insertions, 1 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h index 3df4e5ccaa..d4200f270e 100644 --- a/usr/src/lib/libzfs/common/libzfs.h +++ b/usr/src/lib/libzfs/common/libzfs.h @@ -581,9 +581,10 @@ extern int zpool_in_use(libzfs_handle_t *, int, pool_state_t *, char **, boolean_t *); /* - * ftyp special. Read the label from a given device. + * Label manipulation. */ extern int zpool_read_label(int, nvlist_t **); +extern int zpool_clear_label(int); /* is this zvol valid for use as a dump device? */ extern int zvol_check_dump_config(char *); diff --git a/usr/src/lib/libzfs/common/libzfs_import.c b/usr/src/lib/libzfs/common/libzfs_import.c index f5793390ea..8705361b6c 100644 --- a/usr/src/lib/libzfs/common/libzfs_import.c +++ b/usr/src/lib/libzfs/common/libzfs_import.c @@ -898,6 +898,36 @@ zpool_read_label(int fd, nvlist_t **config) } /* + * Given a file descriptor, clear (zero) the label information. This function + * is currently only used in the appliance stack as part of the ZFS sysevent + * module. + */ +int +zpool_clear_label(int fd) +{ + struct stat64 statbuf; + int l; + vdev_label_t *label; + uint64_t size; + + if (fstat64(fd, &statbuf) == -1) + return (0); + size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t); + + if ((label = calloc(sizeof (vdev_label_t), 1)) == NULL) + return (-1); + + for (l = 0; l < VDEV_LABELS; l++) { + if (pwrite64(fd, label, sizeof (vdev_label_t), + label_offset(size, l)) != sizeof (vdev_label_t)) + return (-1); + } + + free(label); + return (0); +} + +/* * Given a list of directories to search, find all pools stored on disk. This * includes partial pools which are not available to import. If no args are * given (argc is 0), then the default directory (/dev/dsk) is searched. diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers index 17a07d40a9..72b2b3da69 100644 --- a/usr/src/lib/libzfs/common/mapfile-vers +++ b/usr/src/lib/libzfs/common/mapfile-vers @@ -151,6 +151,7 @@ SUNWprivate_1.1 { zfs_userquota_prop_prefixes; zpool_add; zpool_clear; + zpool_clear_label; zpool_close; zpool_create; zpool_destroy; diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c index bc1d3dbea2..b50dddabe4 100644 --- a/usr/src/uts/common/fs/zfs/vdev.c +++ b/usr/src/uts/common/fs/zfs/vdev.c @@ -1132,6 +1132,19 @@ vdev_open(vdev_t *vd) vd->vdev_removed = B_FALSE; + /* + * Recheck the faulted flag now that we have confirmed that + * the vdev is accessible. If we're faulted, bail. + */ + if (vd->vdev_faulted) { + ASSERT(vd->vdev_children == 0); + ASSERT(vd->vdev_label_aux == VDEV_AUX_ERR_EXCEEDED || + vd->vdev_label_aux == VDEV_AUX_EXTERNAL); + vdev_set_state(vd, B_TRUE, VDEV_STATE_FAULTED, + vd->vdev_label_aux); + return (ENXIO); + } + if (vd->vdev_degraded) { ASSERT(vd->vdev_children == 0); vdev_set_state(vd, B_TRUE, VDEV_STATE_DEGRADED, @@ -2231,12 +2244,21 @@ vdev_clear(spa_t *spa, vdev_t *vd) if (vd->vdev_faulted || vd->vdev_degraded || !vdev_readable(vd) || !vdev_writeable(vd)) { + /* + * When reopening in reponse to a clear event, it may be due to + * a fmadm repair request. In this case, if the device is + * still broken, we want to still post the ereport again. + */ + vd->vdev_forcefault = B_TRUE; + vd->vdev_faulted = vd->vdev_degraded = 0; vd->vdev_cant_read = B_FALSE; vd->vdev_cant_write = B_FALSE; vdev_reopen(vd); + vd->vdev_forcefault = B_FALSE; + if (vd != rvd) vdev_state_dirty(vd->vdev_top); @@ -2245,6 +2267,16 @@ vdev_clear(spa_t *spa, vdev_t *vd) spa_event_notify(spa, vd, ESC_ZFS_VDEV_CLEAR); } + + /* + * When clearing a FMA-diagnosed fault, we always want to + * unspare the device, as we assume that the original spare was + * done in response to the FMA fault. + */ + if (!vdev_is_dead(vd) && vd->vdev_parent != NULL && + vd->vdev_parent->vdev_ops == &vdev_spare_ops && + vd->vdev_parent->vdev_child[0] == vd) + vd->vdev_unspare = B_TRUE; } boolean_t |