diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/syseventd/modules/zfs_mod/zfs_mod.c | 140 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/modules/common/ses/ses.c | 4 | ||||
-rw-r--r-- | usr/src/man/man5/fnmatch.5 | 14 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/dmu_objset.c | 10 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/dsl_pool.c | 7 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/rrwlock.c | 25 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/spa.c | 10 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/dsl_pool.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/rrwlock.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev.c | 9 | ||||
-rw-r--r-- | usr/src/uts/common/sys/sysevent/eventdefs.h | 5 |
11 files changed, 201 insertions, 25 deletions
diff --git a/usr/src/cmd/syseventd/modules/zfs_mod/zfs_mod.c b/usr/src/cmd/syseventd/modules/zfs_mod/zfs_mod.c index 8fff5c748a..f165b3c502 100644 --- a/usr/src/cmd/syseventd/modules/zfs_mod/zfs_mod.c +++ b/usr/src/cmd/syseventd/modules/zfs_mod/zfs_mod.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ /* @@ -297,7 +297,7 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data) if (nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &guid) != 0 || guid != dp->dd_vdev_guid) return; - } else { + } else if (dp->dd_compare != NULL) { len = strlen(dp->dd_compare); if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 || @@ -585,6 +585,109 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data) return (0); } +/* + * This function is called for each vdev of a pool for which any of the + * following events was recieved: + * - ESC_ZFS_vdev_add + * - ESC_ZFS_vdev_attach + * - ESC_ZFS_vdev_clear + * - ESC_ZFS_vdev_online + * - ESC_ZFS_pool_create + * - ESC_ZFS_pool_import + * It will update the vdevs FRU property if it is out of date. + */ +/*ARGSUSED2*/ +static void +zfs_sync_vdev_fru(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t isdisk) +{ + char *devpath, *cptr, *oldfru = NULL; + const char *newfru; + uint64_t vdev_guid; + + (void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &vdev_guid); + (void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_PHYS_PATH, &devpath); + (void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_FRU, &oldfru); + + /* remove :<slice> from devpath */ + cptr = strrchr(devpath, ':'); + if (cptr != NULL) + *cptr = '\0'; + + newfru = libzfs_fru_lookup(g_zfshdl, devpath); + if (newfru == NULL) { + syseventd_print(9, "zfs_sync_vdev_fru: no FRU for %s\n", + devpath); + return; + } + + /* do nothing if the FRU hasn't changed */ + if (oldfru != NULL && libzfs_fru_compare(g_zfshdl, oldfru, newfru)) { + syseventd_print(9, "zfs_sync_vdev_fru: FRU unchanged\n"); + return; + } + + syseventd_print(9, "zfs_sync_vdev_fru: devpath = %s\n", devpath); + syseventd_print(9, "zfs_sync_vdev_fru: FRU = %s\n", newfru); + + (void) zpool_fru_set(zhp, vdev_guid, newfru); +} + +/* + * This function handles the following events: + * - ESC_ZFS_vdev_add + * - ESC_ZFS_vdev_attach + * - ESC_ZFS_vdev_clear + * - ESC_ZFS_vdev_online + * - ESC_ZFS_pool_create + * - ESC_ZFS_pool_import + * It will iterate over the pool vdevs to update the FRU property. + */ +int +zfs_deliver_sync(nvlist_t *nvl) +{ + dev_data_t dd = { 0 }; + char *pname; + zpool_handle_t *zhp; + nvlist_t *config, *vdev; + + if (nvlist_lookup_string(nvl, "pool_name", &pname) != 0) { + syseventd_print(9, "zfs_deliver_sync: no pool name\n"); + return (-1); + } + + /* + * If this event was triggered by a pool export or destroy we cannot + * open the pool. This is not an error, just return 0 as we don't care + * about these events. + */ + zhp = zpool_open_canfail(g_zfshdl, pname); + if (zhp == NULL) + return (0); + + config = zpool_get_config(zhp, NULL); + if (config == NULL) { + syseventd_print(9, "zfs_deliver_sync: " + "failed to get pool config for %s\n", pname); + zpool_close(zhp); + return (-1); + } + + if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &vdev) != 0) { + syseventd_print(0, "zfs_deliver_sync: " + "failed to get vdev tree for %s\n", pname); + zpool_close(zhp); + return (-1); + } + + libzfs_fru_refresh(g_zfshdl); + + dd.dd_func = zfs_sync_vdev_fru; + zfs_iter_vdev(zhp, vdev, &dd); + + zpool_close(zhp); + return (0); +} + int zfs_deliver_dle(nvlist_t *nvl) { @@ -622,7 +725,8 @@ zfs_deliver_event(sysevent_t *ev, int unused) const char *subclass = sysevent_get_subclass_name(ev); nvlist_t *nvl; int ret; - boolean_t is_lofi, is_check, is_dle = B_FALSE; + boolean_t is_lofi = B_FALSE, is_check = B_FALSE; + boolean_t is_dle = B_FALSE, is_sync = B_FALSE; if (strcmp(class, EC_DEV_ADD) == 0) { /* @@ -637,14 +741,26 @@ zfs_deliver_event(sysevent_t *ev, int unused) return (0); is_check = B_FALSE; - } else if (strcmp(class, EC_ZFS) == 0 && - strcmp(subclass, ESC_ZFS_VDEV_CHECK) == 0) { - /* - * This event signifies that a device failed to open during pool - * load, but the 'autoreplace' property was set, so we should - * pretend it's just been added. - */ - is_check = B_TRUE; + } else if (strcmp(class, EC_ZFS) == 0) { + if (strcmp(subclass, ESC_ZFS_VDEV_CHECK) == 0) { + /* + * This event signifies that a device failed to open + * during pool load, but the 'autoreplace' property was + * set, so we should pretend it's just been added. + */ + is_check = B_TRUE; + } else if ((strcmp(subclass, ESC_ZFS_VDEV_ADD) == 0) || + (strcmp(subclass, ESC_ZFS_VDEV_ATTACH) == 0) || + (strcmp(subclass, ESC_ZFS_VDEV_CLEAR) == 0) || + (strcmp(subclass, ESC_ZFS_VDEV_ONLINE) == 0) || + (strcmp(subclass, ESC_ZFS_POOL_CREATE) == 0) || + (strcmp(subclass, ESC_ZFS_POOL_IMPORT) == 0)) { + /* + * When we receive these events we check the pool + * configuration and update the vdev FRUs if necessary. + */ + is_sync = B_TRUE; + } } else if (strcmp(class, EC_DEV_STATUS) == 0 && strcmp(subclass, ESC_DEV_DLE) == 0) { is_dle = B_TRUE; @@ -657,6 +773,8 @@ zfs_deliver_event(sysevent_t *ev, int unused) if (is_dle) ret = zfs_deliver_dle(nvl); + else if (is_sync) + ret = zfs_deliver_sync(nvl); else if (is_check) ret = zfs_deliver_check(nvl); else diff --git a/usr/src/lib/fm/topo/modules/common/ses/ses.c b/usr/src/lib/fm/topo/modules/common/ses/ses.c index d8d7b5e24b..835c6e7b9a 100644 --- a/usr/src/lib/fm/topo/modules/common/ses/ses.c +++ b/usr/src/lib/fm/topo/modules/common/ses/ses.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Milan Jurik. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ #include <alloca.h> @@ -452,12 +453,15 @@ ses_contract_thread(void *arg) ctid_t ctid; struct pollfd fds; int pollret; + sigset_t sigset; ses_ct_print("start contract event thread"); efd = open64(CTFS_ROOT "/device/pbundle", O_RDONLY); fds.fd = efd; fds.events = POLLIN; fds.revents = 0; + sigaddset(&sigset, sesthread.thr_sig); + pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); for (;;) { /* check if we've been asked to exit */ (void) pthread_mutex_lock(&sesthread.mt); diff --git a/usr/src/man/man5/fnmatch.5 b/usr/src/man/man5/fnmatch.5 index f4c0ec71dc..a0bd5d4cec 100644 --- a/usr/src/man/man5/fnmatch.5 +++ b/usr/src/man/man5/fnmatch.5 @@ -9,11 +9,10 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH FNMATCH 5 "Mar 28, 1995" +.TH FNMATCH 5 "Jun 14, 2015" .SH NAME fnmatch \- file name pattern matching .SH DESCRIPTION -.sp .LP The pattern matching notation described below is used to specify patterns for matching strings in the shell. Historically, pattern matching notation is @@ -22,12 +21,10 @@ this reason, the description of the rules for this pattern matching notation is based on the description of regular expression notation described on the \fBregex\fR(5) manual page. .SS "Patterns Matching a Single Character" -.sp .LP -The following \fIpatterns matching a single character\fR match a single -character: \fIordinary characters\fR, \fIspecial pattern characters\fR and -\fIpattern bracket expressions\fR. The pattern bracket expression will also -match a single collating element. +The following patterns match a single character: \fIordinary characters\fR, +\fIspecial pattern characters\fR and \fIpattern bracket expressions\fR. The pattern +bracket expression will also match a single collating element. .sp .LP An ordinary character is a pattern that matches itself. It can be any character @@ -162,7 +159,6 @@ syntax errors can result or implementation extensions can be triggered. For example, the KornShell supports a series of extensions based on parentheses in patterns; see \fBksh\fR(1) .SS "Patterns Matching Multiple Characters" -.sp .LP The following rules are used to construct \fIpatterns matching multiple characters\fR from \fIpatterns matching a single character\fR: @@ -238,7 +234,6 @@ matches the strings \fBad\fR, \fBabcd\fR, \fBefabcd\fR, \fBaaaad\fR and .RE .SS "Patterns Used for Filename Expansion" -.sp .LP The rules described so far in \fBPatterns\fR \fBMatching\fR \fBMultiple\fR \fBCharacters\fR and \fBPatterns\fR \fBMatching\fR \fBa\fR \fBSingle\fR @@ -305,6 +300,5 @@ bracket expression or does not match any existing filenames or pathnames, the pattern string is left unchanged. .RE .SH SEE ALSO -.sp .LP \fBfind\fR(1), \fBksh\fR(1), \fBfnmatch\fR(3C), \fBregex\fR(5) diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c index 646968ece9..9ad18f0d11 100644 --- a/usr/src/uts/common/fs/zfs/dmu_objset.c +++ b/usr/src/uts/common/fs/zfs/dmu_objset.c @@ -1746,7 +1746,15 @@ dmu_objset_find_dp_cb(void *arg) dmu_objset_find_ctx_t *dcp = arg; dsl_pool_t *dp = dcp->dc_dp; - dsl_pool_config_enter(dp, FTAG); + /* + * We need to get a pool_config_lock here, as there are several + * asssert(pool_config_held) down the stack. Getting a lock via + * dsl_pool_config_enter is risky, as it might be stalled by a + * pending writer. This would deadlock, as the write lock can + * only be granted when our parent thread gives up the lock. + * The _prio interface gives us priority over a pending writer. + */ + dsl_pool_config_enter_prio(dp, FTAG); dmu_objset_find_dp_impl(dcp); diff --git a/usr/src/uts/common/fs/zfs/dsl_pool.c b/usr/src/uts/common/fs/zfs/dsl_pool.c index 8ad7c789d3..2ba96d6323 100644 --- a/usr/src/uts/common/fs/zfs/dsl_pool.c +++ b/usr/src/uts/common/fs/zfs/dsl_pool.c @@ -1047,6 +1047,13 @@ dsl_pool_config_enter(dsl_pool_t *dp, void *tag) } void +dsl_pool_config_enter_prio(dsl_pool_t *dp, void *tag) +{ + ASSERT(!rrw_held(&dp->dp_config_rwlock, RW_READER)); + rrw_enter_read_prio(&dp->dp_config_rwlock, tag); +} + +void dsl_pool_config_exit(dsl_pool_t *dp, void *tag) { rrw_exit(&dp->dp_config_rwlock, tag); diff --git a/usr/src/uts/common/fs/zfs/rrwlock.c b/usr/src/uts/common/fs/zfs/rrwlock.c index e3aa01a31c..51394c01c4 100644 --- a/usr/src/uts/common/fs/zfs/rrwlock.c +++ b/usr/src/uts/common/fs/zfs/rrwlock.c @@ -159,8 +159,8 @@ rrw_destroy(rrwlock_t *rrl) refcount_destroy(&rrl->rr_linked_rcount); } -void -rrw_enter_read(rrwlock_t *rrl, void *tag) +static void +rrw_enter_read_impl(rrwlock_t *rrl, boolean_t prio, void *tag) { mutex_enter(&rrl->rr_lock); #if !defined(DEBUG) && defined(_KERNEL) @@ -176,7 +176,7 @@ rrw_enter_read(rrwlock_t *rrl, void *tag) ASSERT(refcount_count(&rrl->rr_anon_rcount) >= 0); while (rrl->rr_writer != NULL || (rrl->rr_writer_wanted && - refcount_is_zero(&rrl->rr_anon_rcount) && + refcount_is_zero(&rrl->rr_anon_rcount) && !prio && rrn_find(rrl) == NULL)) cv_wait(&rrl->rr_cv, &rrl->rr_lock); @@ -192,6 +192,25 @@ rrw_enter_read(rrwlock_t *rrl, void *tag) } void +rrw_enter_read(rrwlock_t *rrl, void *tag) +{ + rrw_enter_read_impl(rrl, B_FALSE, tag); +} + +/* + * take a read lock even if there are pending write lock requests. if we want + * to take a lock reentrantly, but from different threads (that have a + * relationship to each other), the normal detection mechanism to overrule + * the pending writer does not work, so we have to give an explicit hint here. + */ +void +rrw_enter_read_prio(rrwlock_t *rrl, void *tag) +{ + rrw_enter_read_impl(rrl, B_TRUE, tag); +} + + +void rrw_enter_write(rrwlock_t *rrl) { mutex_enter(&rrl->rr_lock); diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c index e9d2432a81..7a7c1b7d8f 100644 --- a/usr/src/uts/common/fs/zfs/spa.c +++ b/usr/src/uts/common/fs/zfs/spa.c @@ -3689,6 +3689,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props, txg_wait_synced(spa->spa_dsl_pool, txg); spa_config_sync(spa, B_FALSE, B_TRUE); + spa_event_notify(spa, NULL, ESC_ZFS_POOL_CREATE); spa_history_log_version(spa, "create"); @@ -3956,6 +3957,9 @@ spa_import(const char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags) spa_config_sync(spa, B_FALSE, B_TRUE); mutex_exit(&spa_namespace_lock); + + spa_event_notify(spa, NULL, ESC_ZFS_POOL_IMPORT); + return (0); } @@ -4087,6 +4091,8 @@ spa_import(const char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags) mutex_exit(&spa_namespace_lock); spa_history_log_version(spa, "import"); + spa_event_notify(spa, NULL, ESC_ZFS_POOL_IMPORT); + return (0); } @@ -4429,6 +4435,8 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot) spa_config_update(spa, SPA_CONFIG_UPDATE_POOL); mutex_exit(&spa_namespace_lock); + spa_event_notify(spa, vd, ESC_ZFS_VDEV_ADD); + return (0); } @@ -4638,6 +4646,8 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing) if (spa->spa_bootfs) spa_event_notify(spa, newvd, ESC_ZFS_BOOTFS_VDEV_ATTACH); + spa_event_notify(spa, newvd, ESC_ZFS_VDEV_ATTACH); + return (0); } diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_pool.h b/usr/src/uts/common/fs/zfs/sys/dsl_pool.h index 0f6d17514e..0e27a53820 100644 --- a/usr/src/uts/common/fs/zfs/sys/dsl_pool.h +++ b/usr/src/uts/common/fs/zfs/sys/dsl_pool.h @@ -152,6 +152,7 @@ void dsl_pool_upgrade_dir_clones(dsl_pool_t *dp, dmu_tx_t *tx); void dsl_pool_mos_diduse_space(dsl_pool_t *dp, int64_t used, int64_t comp, int64_t uncomp); void dsl_pool_config_enter(dsl_pool_t *dp, void *tag); +void dsl_pool_config_enter_prio(dsl_pool_t *dp, void *tag); void dsl_pool_config_exit(dsl_pool_t *dp, void *tag); boolean_t dsl_pool_config_held(dsl_pool_t *dp); boolean_t dsl_pool_config_held_writer(dsl_pool_t *dp); diff --git a/usr/src/uts/common/fs/zfs/sys/rrwlock.h b/usr/src/uts/common/fs/zfs/sys/rrwlock.h index bddf0768ae..947b51f872 100644 --- a/usr/src/uts/common/fs/zfs/sys/rrwlock.h +++ b/usr/src/uts/common/fs/zfs/sys/rrwlock.h @@ -70,6 +70,7 @@ void rrw_init(rrwlock_t *rrl, boolean_t track_all); void rrw_destroy(rrwlock_t *rrl); void rrw_enter(rrwlock_t *rrl, krw_t rw, void *tag); void rrw_enter_read(rrwlock_t *rrl, void *tag); +void rrw_enter_read_prio(rrwlock_t *rrl, void *tag); void rrw_enter_write(rrwlock_t *rrl); void rrw_exit(rrwlock_t *rrl, void *tag); boolean_t rrw_held(rrwlock_t *rrl, krw_t rw); diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c index 9e27578f8e..1c57fce4dc 100644 --- a/usr/src/uts/common/fs/zfs/vdev.c +++ b/usr/src/uts/common/fs/zfs/vdev.c @@ -2357,6 +2357,7 @@ int vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate) { vdev_t *vd, *tvd, *pvd, *rvd = spa->spa_root_vdev; + boolean_t postevent = B_FALSE; spa_vdev_state_enter(spa, SCL_NONE); @@ -2366,6 +2367,10 @@ vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate) if (!vd->vdev_ops->vdev_op_leaf) return (spa_vdev_state_exit(spa, NULL, ENOTSUP)); + postevent = + (vd->vdev_offline == B_TRUE || vd->vdev_tmpoffline == B_TRUE) ? + B_TRUE : B_FALSE; + tvd = vd->vdev_top; vd->vdev_offline = B_FALSE; vd->vdev_tmpoffline = B_FALSE; @@ -2401,6 +2406,10 @@ vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate) return (spa_vdev_state_exit(spa, vd, ENOTSUP)); spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE); } + + if (postevent) + spa_event_notify(spa, vd, ESC_ZFS_VDEV_ONLINE); + return (spa_vdev_state_exit(spa, vd, 0)); } diff --git a/usr/src/uts/common/sys/sysevent/eventdefs.h b/usr/src/uts/common/sys/sysevent/eventdefs.h index 5a75c5d844..424d95b7a0 100644 --- a/usr/src/uts/common/sys/sysevent/eventdefs.h +++ b/usr/src/uts/common/sys/sysevent/eventdefs.h @@ -249,9 +249,14 @@ extern "C" { #define ESC_ZFS_RESILVER_START "ESC_ZFS_resilver_start" #define ESC_ZFS_RESILVER_FINISH "ESC_ZFS_resilver_finish" #define ESC_ZFS_VDEV_REMOVE "ESC_ZFS_vdev_remove" +#define ESC_ZFS_POOL_CREATE "ESC_ZFS_pool_create" #define ESC_ZFS_POOL_DESTROY "ESC_ZFS_pool_destroy" +#define ESC_ZFS_POOL_IMPORT "ESC_ZFS_pool_import" +#define ESC_ZFS_VDEV_ADD "ESC_ZFS_vdev_add" +#define ESC_ZFS_VDEV_ATTACH "ESC_ZFS_vdev_attach" #define ESC_ZFS_VDEV_CLEAR "ESC_ZFS_vdev_clear" #define ESC_ZFS_VDEV_CHECK "ESC_ZFS_vdev_check" +#define ESC_ZFS_VDEV_ONLINE "ESC_ZFS_vdev_online" #define ESC_ZFS_CONFIG_SYNC "ESC_ZFS_config_sync" #define ESC_ZFS_SCRUB_START "ESC_ZFS_scrub_start" #define ESC_ZFS_SCRUB_FINISH "ESC_ZFS_scrub_finish" |