summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McDonald <danmcd@mnx.io>2022-11-09 10:35:53 -0500
committerDan McDonald <danmcd@mnx.io>2022-11-09 10:35:53 -0500
commit992f4d7cf022e01498ab4493736eebf80367e8e1 (patch)
tree80c74f4bbab13568e80000236ef524e5c96c9f4c
parent54ba424d2c1a5e03a731822c8173ea9b1761ef66 (diff)
parentdb9597bf18e3b86bdb922182aa97f27a48f83858 (diff)
downloadillumos-joyent-992f4d7cf022e01498ab4493736eebf80367e8e1.tar.gz
[illumos-gate merge]
commit db9597bf18e3b86bdb922182aa97f27a48f83858 15152 ctfdump member output could be easider to decode commit b4fb003914e70b41d96dec8011864f6af1faf3ef 14978 ZFS autoexpand property should work for root pools commit 77c0a660417a046bfab6c8ef58d00c181c0264b3 15128 libnsl: variable is used uninitialized commit 1bf21c92db6af5f8263977d8b99706f8ab9b3a27 15136 want unit test for bhyve dirty page tracking
-rw-r--r--usr/src/cmd/ctfdump/ctfdump.c5
-rw-r--r--usr/src/cmd/syseventd/modules/zfs_mod/zfs_mod.c8
-rw-r--r--usr/src/lib/libnsl/ipsec/algs.c2
-rw-r--r--usr/src/lib/libnsl/rpc/clnt_generic.c88
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h2
-rw-r--r--usr/src/lib/libzfs/common/libzfs_pool.c115
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers1
-rw-r--r--usr/src/lib/libzpool/Makefile.com2
-rw-r--r--usr/src/man/man1/ctfdump.1196
-rw-r--r--usr/src/pkg/manifests/system-bhyve-tests.p5m1
-rw-r--r--usr/src/test/bhyve-tests/tests/inst_emul/Makefile3
-rw-r--r--usr/src/test/bhyve-tests/tests/inst_emul/page_dirty.c162
-rw-r--r--usr/src/test/bhyve-tests/tests/inst_emul/payload_page_dirty.s29
-rw-r--r--usr/src/uts/common/fs/zfs/spa.c16
-rw-r--r--usr/src/uts/common/fs/zfs/spa_misc.c42
-rw-r--r--usr/src/uts/common/fs/zfs/sys/spa.h1
-rw-r--r--usr/src/uts/common/fs/zfs/zvol.c10
17 files changed, 442 insertions, 241 deletions
diff --git a/usr/src/cmd/ctfdump/ctfdump.c b/usr/src/cmd/ctfdump/ctfdump.c
index d54b50c6e7..f739730188 100644
--- a/usr/src/cmd/ctfdump/ctfdump.c
+++ b/usr/src/cmd/ctfdump/ctfdump.c
@@ -11,6 +11,7 @@
/*
* Copyright 2020 Joyent, Inc.
+ * Copyright 2022 Oxide Computer Company
*/
/*
@@ -483,8 +484,8 @@ static int
ctfdump_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg)
{
int *count = arg;
- ctfdump_printf(CTFDUMP_TYPES, "\t%s type=%ld off=%lu\n", member, type,
- off);
+ ctfdump_printf(CTFDUMP_TYPES, "\t%s type=%ld off=%lu bits (%lu.%lu "
+ "bytes)\n", member, type, off, off / 8, off % 8);
*count = *count + 1;
return (0);
}
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 82c296a669..6a25af90f9 100644
--- a/usr/src/cmd/syseventd/modules/zfs_mod/zfs_mod.c
+++ b/usr/src/cmd/syseventd/modules/zfs_mod/zfs_mod.c
@@ -23,6 +23,7 @@
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
* Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2022 Oxide Computer Company
*/
/*
@@ -564,6 +565,13 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
char *path, fullpath[MAXPATHLEN];
uint64_t wholedisk = 0ULL;
+ /*
+ * If the /dev path of the device is invalid because the disk
+ * has been moved to a new location, we need to try to refresh
+ * that path before onlining the device.
+ */
+ zpool_vdev_refresh_path(g_zfshdl, zhp, tgt);
+
verify(nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH,
&path) == 0);
verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
diff --git a/usr/src/lib/libnsl/ipsec/algs.c b/usr/src/lib/libnsl/ipsec/algs.c
index 6620f02cae..a20473a6da 100644
--- a/usr/src/lib/libnsl/ipsec/algs.c
+++ b/usr/src/lib/libnsl/ipsec/algs.c
@@ -591,7 +591,7 @@ void
_build_internal_algs(ipsec_proto_t **alg_context, int *alg_nums)
{
FILE *f;
- int rc, trash_num;
+ int rc, trash_num = 0;
ipsec_proto_t *new_protos = NULL, *trash;
time_t filetime;
struct stat statbuf;
diff --git a/usr/src/lib/libnsl/rpc/clnt_generic.c b/usr/src/lib/libnsl/rpc/clnt_generic.c
index 34deeb1f2c..8801686a96 100644
--- a/usr/src/lib/libnsl/rpc/clnt_generic.c
+++ b/usr/src/lib/libnsl/rpc/clnt_generic.c
@@ -68,11 +68,11 @@ CLIENT *_clnt_tli_create_timed(int, const struct netconfig *, struct netbuf *,
*/
CLIENT *
clnt_create_vers(const char *hostname, const rpcprog_t prog,
- rpcvers_t *vers_out, const rpcvers_t vers_low,
- const rpcvers_t vers_high, const char *nettype)
+ rpcvers_t *vers_out, const rpcvers_t vers_low,
+ const rpcvers_t vers_high, const char *nettype)
{
return (clnt_create_vers_timed(hostname, prog, vers_out, vers_low,
- vers_high, nettype, NULL));
+ vers_high, nettype, NULL));
}
/*
@@ -102,7 +102,7 @@ clnt_create_vers_timed(const char *hostname, const rpcprog_t prog,
to = *tp;
rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
- NULL, (xdrproc_t)xdr_void, NULL, to);
+ NULL, (xdrproc_t)xdr_void, NULL, to);
if (rpc_stat == RPC_SUCCESS) {
*vers_out = vers_high;
return (clnt);
@@ -126,8 +126,7 @@ clnt_create_vers_timed(const char *hostname, const rpcprog_t prog,
}
CLNT_CONTROL(clnt, CLSET_VERS, (char *)&v_high);
rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
- NULL, (xdrproc_t)xdr_void,
- NULL, to);
+ NULL, (xdrproc_t)xdr_void, NULL, to);
if (rpc_stat == RPC_SUCCESS) {
*vers_out = v_high;
return (clnt);
@@ -250,7 +249,7 @@ clnt_create_timed(const char *hostname, const rpcprog_t prog,
*/
if (rpc_createerr.cf_stat == RPC_SYSTEMERROR) {
syslog(LOG_ERR, "clnt_create_timed: "
- "RPC_SYSTEMERROR.");
+ "RPC_SYSTEMERROR.");
break;
}
@@ -267,8 +266,8 @@ clnt_create_timed(const char *hostname, const rpcprog_t prog,
* translation failed'' or ``unknown host name''
*/
if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE ||
- rpc_createerr.cf_stat == RPC_UNKNOWNHOST) &&
- (save_cf_stat != RPC_SUCCESS)) {
+ rpc_createerr.cf_stat == RPC_UNKNOWNHOST) &&
+ (save_cf_stat != RPC_SUCCESS)) {
rpc_createerr.cf_stat = save_cf_stat;
rpc_createerr.cf_error = save_cf_error;
}
@@ -289,9 +288,9 @@ clnt_create_timed(const char *hostname, const rpcprog_t prog,
CLIENT *
clnt_create_service_timed(const char *host, const char *service,
- const rpcprog_t prog, const rpcvers_t vers,
- const ushort_t port, const char *netclass,
- const struct timeval *tmout)
+ const rpcprog_t prog, const rpcvers_t vers,
+ const ushort_t port, const char *netclass,
+ const struct timeval *tmout)
{
int fd;
void *handle;
@@ -399,7 +398,6 @@ clnt_create_service_timed(const char *host, const char *service,
__rpc_set_mac_options(fd, nconf, prog);
- /* LINTED pointer cast */
if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR))
== NULL) {
(void) t_close(fd);
@@ -423,18 +421,17 @@ clnt_create_service_timed(const char *host, const char *service,
netdir_free((void *)raddrs, ND_ADDRLIST);
if (port) {
- if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
- /* LINTED pointer alignment */
+ if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
((struct sockaddr_in *)
- tbind->addr.buf)->sin_port = htons(port);
- else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
- /* LINTED pointer alignment */
+ tbind->addr.buf)->sin_port = htons(port);
+ } else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) {
((struct sockaddr_in6 *)
- tbind->addr.buf)->sin6_port = htons(port);
+ tbind->addr.buf)->sin6_port = htons(port);
+ }
}
clnt = _clnt_tli_create_timed(fd, nconf, &tbind->addr,
- prog, vers, 0, 0, &to);
+ prog, vers, 0, 0, &to);
if (clnt == NULL) {
if (tbind)
@@ -453,7 +450,7 @@ clnt_create_service_timed(const char *host, const char *service,
*/
rpc_createerr.cf_stat = clnt_call(clnt, NULLPROC,
- xdr_void, 0, xdr_void, 0, to);
+ xdr_void, 0, xdr_void, 0, to);
rpc_createerr.cf_error.re_errno = rpc_callerr.re_status;
rpc_createerr.cf_error.re_terrno = 0;
@@ -464,8 +461,9 @@ clnt_create_service_timed(const char *host, const char *service,
if (tbind)
(void) t_free((char *)tbind, T_BIND);
continue;
- } else
+ } else {
break;
+ }
}
__rpc_endconf(handle);
@@ -520,15 +518,16 @@ clnt_tp_create_timed(const char *hostname, const rpcprog_t prog,
/*
* Get the address of the server
*/
- if ((svcaddr = __rpcb_findaddr_timed(prog, vers,
- (struct netconfig *)nconf, (char *)hostname,
- &cl, (struct timeval *)tp)) == NULL) {
+ svcaddr = __rpcb_findaddr_timed(prog, vers,
+ (struct netconfig *)nconf, (char *)hostname,
+ &cl, (struct timeval *)tp);
+ if (svcaddr == NULL) {
/* appropriate error number is set by rpcbind libraries */
return (NULL);
}
if (cl == NULL) {
cl = _clnt_tli_create_timed(RPC_ANYFD, nconf, svcaddr,
- prog, vers, 0, 0, tp);
+ prog, vers, 0, 0, tp);
} else {
/* Reuse the CLIENT handle and change the appropriate fields */
if (CLNT_CONTROL(cl, CLSET_SVC_ADDR, (void *)svcaddr) == TRUE) {
@@ -538,8 +537,8 @@ clnt_tp_create_timed(const char *hostname, const rpcprog_t prog,
netdir_free((char *)svcaddr, ND_ADDR);
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
syslog(LOG_ERR,
- "clnt_tp_create_timed: "
- "strdup failed.");
+ "clnt_tp_create_timed: "
+ "strdup failed.");
return (NULL);
}
}
@@ -551,8 +550,8 @@ clnt_tp_create_timed(const char *hostname, const rpcprog_t prog,
free(cl->cl_netid);
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
syslog(LOG_ERR,
- "clnt_tp_create_timed: "
- "strdup failed.");
+ "clnt_tp_create_timed: "
+ "strdup failed.");
return (NULL);
}
}
@@ -561,7 +560,7 @@ clnt_tp_create_timed(const char *hostname, const rpcprog_t prog,
} else {
CLNT_DESTROY(cl);
cl = _clnt_tli_create_timed(RPC_ANYFD, nconf, svcaddr,
- prog, vers, 0, 0, tp);
+ prog, vers, 0, 0, tp);
}
}
netdir_free((char *)svcaddr, ND_ADDR);
@@ -582,7 +581,7 @@ clnt_tli_create(const int fd, const struct netconfig *nconf,
const uint_t sendsz, const uint_t recvsz)
{
return (_clnt_tli_create_timed(fd, nconf, svcaddr, prog, vers, sendsz,
- recvsz, NULL));
+ recvsz, NULL));
}
/*
@@ -596,12 +595,12 @@ clnt_tli_create(const int fd, const struct netconfig *nconf,
*/
CLIENT *
_clnt_tli_create_timed(int fd, const struct netconfig *nconf,
- struct netbuf *svcaddr, rpcprog_t prog, rpcvers_t vers, uint_t sendsz,
- uint_t recvsz, const struct timeval *tp)
+ struct netbuf *svcaddr, rpcprog_t prog, rpcvers_t vers, uint_t sendsz,
+ uint_t recvsz, const struct timeval *tp)
{
CLIENT *cl; /* client handle */
struct t_info tinfo; /* transport info */
- bool_t madefd; /* whether fd opened here */
+ bool_t madefd = FALSE; /* whether fd opened here */
t_scalar_t servtype;
int retval;
@@ -647,13 +646,12 @@ _clnt_tli_create_timed(int fd, const struct netconfig *nconf,
(t_getinfo(fd, &tinfo) == -1))
goto err;
servtype = tinfo.servtype;
- madefd = FALSE;
}
switch (servtype) {
case T_COTS:
cl = _clnt_vc_create_timed(fd, svcaddr, prog, vers, sendsz,
- recvsz, tp);
+ recvsz, tp);
break;
case T_COTS_ORD:
if (nconf && ((strcmp(nconf->nc_protofmly, NC_INET) == 0) ||
@@ -663,7 +661,7 @@ _clnt_tli_create_timed(int fd, const struct netconfig *nconf,
goto err;
}
cl = _clnt_vc_create_timed(fd, svcaddr, prog, vers, sendsz,
- recvsz, tp);
+ recvsz, tp);
break;
case T_CLTS:
cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
@@ -681,7 +679,7 @@ _clnt_tli_create_timed(int fd, const struct netconfig *nconf,
rpc_createerr.cf_error.re_errno = errno;
rpc_createerr.cf_error.re_terrno = 0;
syslog(LOG_ERR,
- "clnt_tli_create: strdup failed");
+ "clnt_tli_create: strdup failed");
goto err1;
}
cl->cl_tp = strdup(nconf->nc_device);
@@ -692,7 +690,7 @@ _clnt_tli_create_timed(int fd, const struct netconfig *nconf,
rpc_createerr.cf_error.re_errno = errno;
rpc_createerr.cf_error.re_terrno = 0;
syslog(LOG_ERR,
- "clnt_tli_create: strdup failed");
+ "clnt_tli_create: strdup failed");
goto err1;
}
} else {
@@ -706,8 +704,8 @@ _clnt_tli_create_timed(int fd, const struct netconfig *nconf,
rpc_createerr.cf_error.re_errno = errno;
rpc_createerr.cf_error.re_terrno = 0;
syslog(LOG_ERR,
- "clnt_tli_create: "
- "strdup failed");
+ "clnt_tli_create: "
+ "strdup failed");
goto err1;
}
}
@@ -720,8 +718,8 @@ _clnt_tli_create_timed(int fd, const struct netconfig *nconf,
rpc_createerr.cf_error.re_errno = errno;
rpc_createerr.cf_error.re_terrno = 0;
syslog(LOG_ERR,
- "clnt_tli_create: "
- "strdup failed");
+ "clnt_tli_create: "
+ "strdup failed");
goto err1;
}
}
@@ -770,7 +768,7 @@ __rpc_raise_fd(int fd)
if (t_close(fd) == -1) {
/* this is okay, we will syslog an error, then use the new fd */
(void) syslog(LOG_ERR,
- "could not t_close() fd %d; mem & fd leak", fd);
+ "could not t_close() fd %d; mem & fd leak", fd);
}
return (nfd);
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index 5afdb2a0ba..9938b97dea 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -318,6 +318,8 @@ extern nvlist_t *zpool_find_vdev_by_physpath(zpool_handle_t *, const char *,
boolean_t *, boolean_t *, boolean_t *);
extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, const char *,
zpool_boot_label_t, uint64_t, int *);
+extern void zpool_vdev_refresh_path(libzfs_handle_t *, zpool_handle_t *,
+ nvlist_t *);
/*
* Functions to manage pool properties
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c
index bb04be87e1..d7060981fe 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -28,6 +28,7 @@
* Copyright (c) 2017 Datto Inc.
* Copyright (c) 2017, Intel Corporation.
* Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2022 Oxide Computer Company
*/
#include <ctype.h>
@@ -3964,17 +3965,70 @@ set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
}
/*
+ * This routine is responsible for identifying when disks have been
+ * reconfigured in a new location. The kernel will have opened the device by
+ * devid, but the path will still refer to the old location. To catch this, we
+ * first do a path -> devid translation (which is fast for the common case).
+ * If the devid matches, we're done. If not, we do a reverse devid -> path
+ * translation and issue the appropriate ioctl() to update the path of the
+ * vdev.
+ */
+void
+zpool_vdev_refresh_path(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv)
+{
+ char *path = NULL;
+ char *newpath = NULL;
+ char *physpath = NULL;
+ char *devid = NULL;
+
+ if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0) {
+ return;
+ }
+
+ if (nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
+ /*
+ * This vdev has a devid. We can use it to check the current
+ * path.
+ */
+ char *newdevid = path_to_devid(path);
+
+ if (newdevid == NULL || strcmp(devid, newdevid) != 0) {
+ newpath = devid_to_path(devid);
+ }
+
+ if (newdevid != NULL) {
+ devid_str_free(newdevid);
+ }
+
+ } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PHYS_PATH,
+ &physpath) == 0) {
+ /*
+ * This vdev does not have a devid, but it does have a physical
+ * path. Attempt to translate this to a /dev path.
+ */
+ newpath = path_from_physpath(hdl, path, physpath);
+ }
+
+ if (newpath == NULL) {
+ /*
+ * No path update is required.
+ */
+ return;
+ }
+
+ set_path(zhp, nv, newpath);
+ fnvlist_add_string(nv, ZPOOL_CONFIG_PATH, newpath);
+
+ free(newpath);
+}
+
+/*
* Given a vdev, return the name to display in iostat. If the vdev has a path,
* we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
- * We also check if this is a whole disk, in which case we strip off the
- * trailing 's0' slice name.
+ * We will confirm that the path and name of the vdev are current, and update
+ * them if not. We also check if this is a whole disk, in which case we strip
+ * off the trailing 's0' slice name.
*
- * This routine is also responsible for identifying when disks have been
- * reconfigured in a new location. The kernel will have opened the device by
- * devid, but the path will still refer to the old location. To catch this, we
- * first do a path -> devid translation (which is fast for the common case). If
- * the devid matches, we're done. If not, we do a reverse devid -> path
- * translation and issue the appropriate ioctl() to update the path of the vdev.
* If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
* of these checks.
*/
@@ -4017,9 +4071,6 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
} else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
vdev_stat_t *vs;
uint_t vsc;
- char *newpath = NULL;
- char *physpath = NULL;
- char *devid = NULL;
/*
* If the device is dead (faulted, offline, etc) then don't
@@ -4034,42 +4085,12 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
goto after_open;
}
- if (nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
- /*
- * This vdev has a devid. We can use it to check the
- * current path.
- */
- char *newdevid = path_to_devid(path);
-
- if (newdevid == NULL || strcmp(devid, newdevid) != 0) {
- newpath = devid_to_path(devid);
- }
-
- if (newdevid != NULL)
- devid_str_free(newdevid);
-
- } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PHYS_PATH,
- &physpath) == 0) {
- /*
- * This vdev does not have a devid, but it does have a
- * physical path. Attempt to translate this to a /dev
- * path.
- */
- newpath = path_from_physpath(hdl, path, physpath);
- }
-
- if (newpath != NULL) {
- /*
- * Update the path appropriately.
- */
- set_path(zhp, nv, newpath);
- if (nvlist_add_string(nv, ZPOOL_CONFIG_PATH,
- newpath) == 0) {
- verify(nvlist_lookup_string(nv,
- ZPOOL_CONFIG_PATH, &path) == 0);
- }
- free(newpath);
- }
+ /*
+ * Refresh the /dev path for this vdev if required, then ensure
+ * we're using the latest path value:
+ */
+ zpool_vdev_refresh_path(hdl, zhp, nv);
+ path = fnvlist_lookup_string(nv, ZPOOL_CONFIG_PATH);
if (name_flags & VDEV_NAME_FOLLOW_LINKS) {
char *rp = realpath(path, NULL);
diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers
index 456249d9ad..b437322adf 100644
--- a/usr/src/lib/libzfs/common/mapfile-vers
+++ b/usr/src/lib/libzfs/common/mapfile-vers
@@ -282,6 +282,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zpool_vdev_name;
zpool_vdev_offline;
zpool_vdev_online;
+ zpool_vdev_refresh_path;
zpool_vdev_remove;
zpool_vdev_remove_cancel;
zpool_vdev_split;
diff --git a/usr/src/lib/libzpool/Makefile.com b/usr/src/lib/libzpool/Makefile.com
index 31bd6aa5e2..ca5aeed189 100644
--- a/usr/src/lib/libzpool/Makefile.com
+++ b/usr/src/lib/libzpool/Makefile.com
@@ -68,7 +68,7 @@ CSTD= $(CSTD_GNU99)
CFLAGS += $(CCGDEBUG) $(CCVERBOSE) $(CNOGLOBAL)
CFLAGS64 += $(CCGDEBUG) $(CCVERBOSE) $(CNOGLOBAL)
-LDLIBS += -lcmdutils -lumem -lavl -lnvpair -lz -lc -lsysevent -lmd \
+LDLIBS += -lcmdutils -lumem -lavl -lnvpair -lz -lc -lmd \
-lfakekernel -lzutil
NATIVE_LIBS += libz.so
CPPFLAGS.first = -I$(SRC)/lib/libfakekernel/common
diff --git a/usr/src/man/man1/ctfdump.1 b/usr/src/man/man1/ctfdump.1
index 4a11726e3b..5c82baddb5 100644
--- a/usr/src/man/man1/ctfdump.1
+++ b/usr/src/man/man1/ctfdump.1
@@ -10,6 +10,7 @@
.\"
.\"
.\" Copyright 2018, Joyent, Inc.
+.\" Copyright 2022 Oxide Computer Company
.\"
.Dd September 20, 2021
.Dt CTFDUMP 1
@@ -33,48 +34,30 @@ data contained inside of
objects and raw
.Sy CTF
files.
-.Lp
+.Pp
.Nm
-can dump information about the
-.Sy CTF header ,
-the
-.Sy labels
-encoded in the
-.Sy CTF
-container,
-the types of
-.Sy data objects ,
-the internal
-.Sy string
-table,
-the types of the return function and the arguments for
-.Sy functions ,
-and of course, it displays information about the
-.Sy types
-defined in the
-.Sy CTF
-container.
-.Lp
+can dump information about the CTF header, the labels encoded in the
+CTF container, the types of data objects, the internal string table,
+the types of the return function and the arguments for functions,
+and of course, it displays information about the types defined in the
+CTF container.
+.Pp
.Nm
-can also be used to dump out the raw
-.Sy CTF
-data and send it to another file.
-When writing out data, it always ensures that the
-.Sy CTF
-data is decompressed.
-In this form, the
-.Sy CTF
-data can be inspected using
+can also be used to dump out the raw CTF data and send it to another
+file.
+When writing out data, it always ensures that the CTF data is
+decompressed.
+In this form, the CTF data can be inspected using
.Nm
and other tools such as
.Xr mdb 1 .
-.Lp
+.Pp
.Nm
in
.Fl c
mode will generate C-style output, which can be used for comparison.
Note that this output is not directly compilable.
-.Lp
+.Pp
When no options are specified,
.Nm
displays all information, except the C-style output.
@@ -84,99 +67,58 @@ option is used, then no information is displayed by default, unless
requested through the appropriate option.
.Sh OPTIONS
The following options are supported:
-.Bl -hang -width Ds
+.Bl -tag -width Ds
.It Fl c
-.Bd -filled -compact
Generate C-style output.
-.Ed
.It Fl d
-.Bd -filled -compact
Dump the types of symbols that correspond to objects.
-.Ed
.It Fl f
-.Bd -filled -compact
Dump the types of the return values and arguments of the functions.
-.Ed
.It Fl h
-.Bd -filled -compact
-Dump the
-.Sy CTF
-header
-.Ed
+Dump the CTF header
.It Fl l
-.Bd -filled -compact
-Dump all
-.Sy CTF
-labels associated with the file.
-.Ed
+Dump all CTF labels associated with the file.
.It Fl p Ar parent
-.Bd -filled -compact
Use the type information in
-.Em parent
+.Ar parent
to supplement output.
This is useful when a
-.Nm CTF
-container has been
-.Sy uniquified
-against
-.Em parent .
+.Nm
+CTF container has been uniquified against
+.Ar parent .
This allows
.Nm
to use the names of types when used with
.Fl t .
-.Ed
.It Fl s
-.Bd -filled -compact
-Dump the internal
-.Sy CTF
-string table
-.Ed
+Dump the internal CTF string table
.It Fl S
-.Bd -filled -compact
-Displays statistics about the
-.Sy CTF
-container.
-.Ed
+Displays statistics about the CTF container.
.It Fl t
-.Bd -filled -compact
-Dump the type information contained in the
-.Sy CTF
-container.
-.Ed
+Dump the type information contained in the CTF container.
.It Fl u Ar outfile
-.Bd -filled -compact
-Copies the uncompressed
-.Sy CTF
-data to the file specified by
-.Em outfile .
-This can be used to make it easier to inspect the raw
-.Sy CTF
-data.
-.Ed
+Copies the uncompressed CTF data to the file specified by
+.Ar outfile .
+This can be used to make it easier to inspect the raw CTF data.
.El
.Sh OUTPUT
When the
.Nm
utility is executed with its default options, it prints out a textual
-representation of the
-.Sy CTF
-information.
+representation of the CTF information.
Note, the output format of
.Nm
is subject to change at any time and should not be relied upon as a
stable format to be used for parsing.
.Ss CTF Header
-This section describes the values in the
-.Sy CTF
-header.
+This section describes the values in the CTF header.
Each line in the section describes the value of one of the
members of the header.
For more information on the meaning and interpretation of these members,
see
.Xr ctf 5 .
.Ss Label Table
-This section describes information about the labels present in the
-.Sy CTF
+This section describes information about the labels present in the CTF
information.
Each entry in this section, if present, starts with a
number and is followed by a string.
@@ -196,8 +138,7 @@ is the name of the label.
In this case, if there were no other labels,
it would indicate that the label applied to all types up to, and
including, the type number 2270.
-For more information on how labels are used with
-.Sy CTF
+For more information on how labels are used with CTF
information, see the section
.Em The Label Section
in
@@ -260,8 +201,7 @@ symbol table.
The following portions of this entry describe the return
type and then all of the arguments, in positional order.
.Ss Types
-The types section gives information about each type in the
-.Sy CTF
+The types section gives information about each type in the CTF
container.
Each entry begins with its type identifier.
The type identifier may either be in square brackets or in angle
@@ -303,40 +243,43 @@ Structures and unions will be preceded with the corresponding C keyword,
or
.Sy union .
After that, the size in bytes of the structure will be indicated.
-ON each subsequent line, a single member will be listed.
+On each subsequent line, a single member will be listed.
That line will contain the member's name, it's type identifier, and the
-offset into the structure that it can be found in, in bits.
+offset into the structure that the member starts at.
+The first values is in bits, which is what CTF encodes.
+It is then followed by bytes and the bit offset into the byte.
+That is the value
+.Sq 2.5
+indicates that it starts at the 5th bit in the 2nd byte
+.Pq i.e. bit 21 .
.Pp
The following show examples of type information for all of these
different types:
.Bd -literal
\&...
- [5] char [12] contents: 1, index: 2
- [6] short encoding=SIGNED offset=0 bits=16
- <7> struct exit_status (4 bytes)
- e_termination type=6 off=0
- e_exit type=6 off=16
+ [155] struct ctf_merge_handle (80 bytes)
+ cmh_inputs type=165 off=0 bits (0.0 bytes)
+ cmh_ninputs type=6 off=256 bits (32.0 bytes)
+ cmh_nthreads type=6 off=288 bits (36.0 bytes)
+ cmh_unique type=65 off=320 bits (40.0 bytes)
+ cmh_msyms type=115 off=384 bits (48.0 bytes)
+ cmh_ofd type=34 off=416 bits (52.0 bytes)
+ cmh_flags type=34 off=448 bits (56.0 bytes)
+ cmh_label type=94 off=512 bits (64.0 bytes)
+ cmh_pname type=94 off=576 bits (72.0 bytes)
- <8> typedef time_t refers to 2
- <9> struct utmp (36 bytes)
- ut_user type=3 off=0
- ut_id type=4 off=64
- ut_line type=5 off=96
- ut_pid type=6 off=192
- ut_type type=6 off=208
- ut_exit type=7 off=224
- ut_time type=8 off=256
+ <156> typedef ctf_merge_t refers to 155
+ [157] struct __va_list_tag (24 bytes)
+ gp_offset type=5 off=0 bits (0.0 bytes)
+ fp_offset type=5 off=32 bits (4.0 bytes)
+ overflow_arg_area type=41 off=64 bits (8.0 bytes)
+ reg_save_area type=41 off=128 bits (16.0 bytes)
- <10> struct utmp * refers to 9
- [11] const struct utmp refers to 9
- [12] const struct utmp * refers to 11
- <13> int encoding=SIGNED offset=0 bits=32
- <14> typedef int32_t refers to 13
+ [158] struct __va_list_tag [1] contents: 157, index: 9
\&...
.Ed
.Ss String Table
-This section describes all of the strings that are present in the
-.Sy CTF
+This section describes all of the strings that are present in the CTF
container.
Each line represents an entry in the string table.
First the byte offset into the string table is shown in brackets and
@@ -351,25 +294,24 @@ Note the following examples:
[35] short
.Ed
.Ss Statistics
-This section contains miscellaneous statistics about the
-.Sy CTF
-data present.
+This section contains miscellaneous statistics about the CTF data
+present.
Each line contains a single statistic.
A brief explanation of the statistic is placed first, followed by an
equals sign, and then finally the value.
.Sh EXIT STATUS
-.Bl -inset
+.Bl -tag -width Ds
.It Sy 0
-.Dl Execution completed successfully.
+Execution completed successfully.
.It Sy 1
-.Dl A fatal error occurred.
+A fatal error occurred.
.It Sy 2
-.Dl Invalid command line options were specified.
+Invalid command line options were specified.
.El
.Sh EXAMPLES
.Sy Example 1
Displaying the Type Section of a Single File
-.Lp
+.Pp
The following example dumps the type section of the file
.Sy /usr/lib/libc.so.1 .
.Bd -literal -offset 6n
@@ -385,10 +327,10 @@ $ ctfdump -t /usr/lib/libc.so.1
<7> typedef uintptr_t refers to 4
\&...
.Ed
-.Lp
+.Pp
.Sy Example 2
Dumping the CTF data to Another File
-.Lp
+.Pp
The following example dumps the entire CTF data from the file
.Sy /usr/lib/libc.so.1
and places it into the file
@@ -417,7 +359,7 @@ $ mdb ./ctf.out
cth_strlen = 0x7c9c
}
.Ed
-.Lp
+.Pp
.Sy Example 3
Dumping C-style output
.Bd -literal -offset 6n
diff --git a/usr/src/pkg/manifests/system-bhyve-tests.p5m b/usr/src/pkg/manifests/system-bhyve-tests.p5m
index e395e75a91..fe3225dd14 100644
--- a/usr/src/pkg/manifests/system-bhyve-tests.p5m
+++ b/usr/src/pkg/manifests/system-bhyve-tests.p5m
@@ -34,6 +34,7 @@ dir path=opt/bhyve-tests/tests/inst_emul
file path=opt/bhyve-tests/tests/inst_emul/cpuid mode=0555
file path=opt/bhyve-tests/tests/inst_emul/exit_paging mode=0555
file path=opt/bhyve-tests/tests/inst_emul/imul mode=0555
+file path=opt/bhyve-tests/tests/inst_emul/page_dirty mode=0555
file path=opt/bhyve-tests/tests/inst_emul/rdmsr mode=0555
file path=opt/bhyve-tests/tests/inst_emul/triple_fault mode=0555
file path=opt/bhyve-tests/tests/inst_emul/wrmsr mode=0555
diff --git a/usr/src/test/bhyve-tests/tests/inst_emul/Makefile b/usr/src/test/bhyve-tests/tests/inst_emul/Makefile
index 37a8b62b4f..f01a9c3bee 100644
--- a/usr/src/test/bhyve-tests/tests/inst_emul/Makefile
+++ b/usr/src/test/bhyve-tests/tests/inst_emul/Makefile
@@ -23,7 +23,8 @@ PROG = rdmsr \
# These should probably go in the `vmm` tests, but since they depend on
# in-guest payloads, it is easier to build them here.
PROG += triple_fault \
- exit_paging
+ exit_paging \
+ page_dirty
# C-based payloads need additional utils object
CPAYLOADS = cpuid
diff --git a/usr/src/test/bhyve-tests/tests/inst_emul/page_dirty.c b/usr/src/test/bhyve-tests/tests/inst_emul/page_dirty.c
new file mode 100644
index 0000000000..2e3a06bf47
--- /dev/null
+++ b/usr/src/test/bhyve-tests/tests/inst_emul/page_dirty.c
@@ -0,0 +1,162 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2022 Oxide Computer Company
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <libgen.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/debug.h>
+#include <sys/mman.h>
+#include <sys/vmm.h>
+#include <sys/vmm_dev.h>
+#include <vmmapi.h>
+
+#include "in_guest.h"
+
+#define PAGE_SZ 4096
+
+#define DIRTY_BITMAP_SZ (MEM_TOTAL_SZ / (PAGE_SZ * 8))
+
+static void
+read_dirty_bitmap(struct vmctx *ctx, uint8_t *bitmap)
+{
+ struct vmm_dirty_tracker track = {
+ .vdt_start_gpa = 0,
+ .vdt_len = MEM_TOTAL_SZ,
+ .vdt_pfns = (void *)bitmap,
+ };
+ int err = ioctl(vm_get_device_fd(ctx), VM_TRACK_DIRTY_PAGES, &track);
+ if (err != 0) {
+ test_fail_errno(errno, "Could not get dirty page bitmap");
+ }
+}
+
+static uint8_t
+popc8(uint8_t val)
+{
+ uint8_t cnt;
+
+ for (cnt = 0; val != 0; val &= (val - 1)) {
+ cnt++;
+ }
+ return (cnt);
+}
+
+static uint_t
+count_dirty_pages(const uint8_t *bitmap)
+{
+ uint_t count = 0;
+ for (uint_t i = 0; i < DIRTY_BITMAP_SZ; i++) {
+ count += popc8(bitmap[i]);
+ }
+ return (count);
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *test_suite_name = basename(argv[0]);
+ struct vmctx *ctx = NULL;
+ int err;
+
+ ctx = test_initialize(test_suite_name);
+
+ /* Until #14251 is fixed, warn the user of the test requirement */
+ (void) fprintf(stderr,
+ "Ensure that 'gpt_track_dirty' is set to 1 via mdb -kw\n"
+ "The reasoning is described in illumos #14251\n");
+
+ err = test_setup_vcpu(ctx, 0, MEM_LOC_PAYLOAD, MEM_LOC_STACK);
+ if (err != 0) {
+ test_fail_errno(err, "Could not initialize vcpu0");
+ }
+
+ uint8_t dirty_bitmap[DIRTY_BITMAP_SZ] = { 0 };
+
+ /* Clear pages which were dirtied as part of initialization */
+ read_dirty_bitmap(ctx, dirty_bitmap);
+ if (count_dirty_pages(dirty_bitmap) == 0) {
+ test_fail_msg("no pages dirtied during setup\n");
+ }
+
+ /*
+ * With nothing running, and the old dirty bits cleared, the NPT should
+ * now be devoid of pages marked dirty.
+ */
+ read_dirty_bitmap(ctx, dirty_bitmap);
+ if (count_dirty_pages(dirty_bitmap) != 0) {
+ test_fail_msg("pages still dirty after clear\n");
+ }
+
+ /* Dirty a page through the segvmm mapping. */
+ uint8_t *dptr = vm_map_gpa(ctx, MEM_LOC_STACK, 1);
+ *dptr = 1;
+
+ /* Check that it was marked as such */
+ read_dirty_bitmap(ctx, dirty_bitmap);
+ if (count_dirty_pages(dirty_bitmap) != 1) {
+ test_fail_msg("direct access did not dirty page\n");
+ }
+ if (dirty_bitmap[MEM_LOC_STACK / (PAGE_SZ * 8)] == 0) {
+ test_fail_msg("unexpected page dirtied\n");
+ }
+
+
+ /* Dirty it again to check shootdown logic */
+ *dptr = 2;
+ if (count_dirty_pages(dirty_bitmap) != 1) {
+ test_fail_msg("subsequent direct access did not dirty page\n");
+ }
+
+ struct vm_entry ventry = { 0 };
+ struct vm_exit vexit = { 0 };
+ do {
+ const enum vm_exit_kind kind =
+ test_run_vcpu(ctx, 0, &ventry, &vexit);
+ switch (kind) {
+ case VEK_REENTR:
+ break;
+ case VEK_TEST_PASS:
+ /*
+ * By now, the guest should have dirtied that page
+ * directly via hardware-accelerated path.
+ */
+ read_dirty_bitmap(ctx, dirty_bitmap);
+ /*
+ * The guest will dirty more than the page it is
+ * explicitly writing to: it must mark its own page
+ * tables with accessed/dirty bits too.
+ */
+ if (count_dirty_pages(dirty_bitmap) <= 1) {
+ test_fail_msg(
+ "in-guest access did not dirty page\n");
+ }
+ if (dirty_bitmap[MEM_LOC_STACK / (PAGE_SZ * 8)] == 0) {
+ test_fail_msg("expected page not dirtied\n");
+ }
+ test_pass();
+ break;
+ default:
+ test_fail_vmexit(&vexit);
+ break;
+ }
+ } while (true);
+}
diff --git a/usr/src/test/bhyve-tests/tests/inst_emul/payload_page_dirty.s b/usr/src/test/bhyve-tests/tests/inst_emul/payload_page_dirty.s
new file mode 100644
index 0000000000..4c1869ca9b
--- /dev/null
+++ b/usr/src/test/bhyve-tests/tests/inst_emul/payload_page_dirty.s
@@ -0,0 +1,29 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2022 Oxide Computer Company
+ */
+
+#include <sys/asm_linkage.h>
+#include "payload_common.h"
+
+
+ENTRY(start)
+ /* Dirty the stack page once again */
+ xorl %eax, %eax
+ movq %rax, MEM_LOC_STACK
+
+ movw $IOP_TEST_RESULT, %dx
+ movb $TEST_RESULT_PASS, %al
+ outb (%dx)
+ hlt
+SET_SIZE(start)
diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c
index 26cc3b0824..6364f19ed7 100644
--- a/usr/src/uts/common/fs/zfs/spa.c
+++ b/usr/src/uts/common/fs/zfs/spa.c
@@ -32,6 +32,7 @@
* Copyright (c) 2017, Intel Corporation.
* Copyright 2020 Joshua M. Clulow <josh@sysmgr.org>
* Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2022 Oxide Computer Company
*/
/*
@@ -5610,6 +5611,12 @@ spa_import_rootpool(char *devpath, char *devid, uint64_t pool_guid,
goto out;
}
+ /*
+ * The root disk may have been expanded while the system was offline.
+ * Kick off an async task to check for and handle expansion.
+ */
+ spa_async_request(spa, SPA_ASYNC_AUTOEXPAND);
+
error = 0;
out:
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
@@ -7534,8 +7541,6 @@ spa_async_probe(spa_t *spa, vdev_t *vd)
static void
spa_async_autoexpand(spa_t *spa, vdev_t *vd)
{
- sysevent_id_t eid;
- nvlist_t *attr;
char *physpath;
if (!spa->spa_autoexpand)
@@ -7552,13 +7557,8 @@ spa_async_autoexpand(spa_t *spa, vdev_t *vd)
physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
(void) snprintf(physpath, MAXPATHLEN, "/devices%s", vd->vdev_physpath);
- VERIFY(nvlist_alloc(&attr, NV_UNIQUE_NAME, KM_SLEEP) == 0);
- VERIFY(nvlist_add_string(attr, DEV_PHYS_PATH, physpath) == 0);
-
- (void) ddi_log_sysevent(zfs_dip, SUNW_VENDOR, EC_DEV_STATUS,
- ESC_DEV_DLE, attr, &eid, DDI_SLEEP);
+ zfs_post_dle_sysevent(physpath);
- nvlist_free(attr);
kmem_free(physpath, MAXPATHLEN);
}
diff --git a/usr/src/uts/common/fs/zfs/spa_misc.c b/usr/src/uts/common/fs/zfs/spa_misc.c
index cb59eef824..6e834005a1 100644
--- a/usr/src/uts/common/fs/zfs/spa_misc.c
+++ b/usr/src/uts/common/fs/zfs/spa_misc.c
@@ -29,6 +29,7 @@
* Copyright 2019 Joyent, Inc.
* Copyright (c) 2017, Intel Corporation.
* Copyright 2020 Joyent, Inc.
+ * Copyright 2022 Oxide Computer Company
*/
#include <sys/zfs_context.h>
@@ -2598,3 +2599,44 @@ spa_suspend_async_destroy(spa_t *spa)
return (B_FALSE);
}
+
+/*
+ * Generate a LUN expansion event. This routine does not use
+ * ddi_log_sysevent() because that would require a dev_info_t, and we may not
+ * have one available.
+ */
+void
+zfs_post_dle_sysevent(const char *physpath)
+{
+#ifdef _KERNEL
+ sysevent_t *ev = sysevent_alloc(EC_DEV_STATUS, ESC_DEV_DLE,
+ SUNW_KERN_PUB "zfs", SE_SLEEP);
+ sysevent_attr_list_t *attr = NULL;
+ sysevent_id_t eid;
+
+ VERIFY(ev != NULL);
+
+ /*
+ * The only attribute is the /devices path of the expanding device:
+ */
+ sysevent_value_t value = {
+ .value_type = SE_DATA_TYPE_STRING,
+ .value = {
+ .sv_string = (char *)physpath,
+ },
+ };
+ if (sysevent_add_attr(&attr, DEV_PHYS_PATH, &value, SE_SLEEP) != 0) {
+ sysevent_free(ev);
+ return;
+ }
+
+ if (sysevent_attach_attributes(ev, attr) != 0) {
+ sysevent_free_attr(attr);
+ sysevent_free(ev);
+ return;
+ }
+
+ (void) log_sysevent(ev, SE_SLEEP, &eid);
+ sysevent_free(ev);
+#endif
+}
diff --git a/usr/src/uts/common/fs/zfs/sys/spa.h b/usr/src/uts/common/fs/zfs/sys/spa.h
index af8057be8f..b896d51577 100644
--- a/usr/src/uts/common/fs/zfs/sys/spa.h
+++ b/usr/src/uts/common/fs/zfs/sys/spa.h
@@ -1104,6 +1104,7 @@ extern sysevent_t *spa_event_create(spa_t *spa, vdev_t *vd, nvlist_t *hist_nvl,
const char *name);
extern void spa_event_post(sysevent_t *ev);
extern void spa_event_discard(sysevent_t *ev);
+extern void zfs_post_dle_sysevent(const char *);
#ifdef ZFS_DEBUG
#define dprintf_bp(bp, fmt, ...) do { \
diff --git a/usr/src/uts/common/fs/zfs/zvol.c b/usr/src/uts/common/fs/zfs/zvol.c
index 1b3bc07600..3d2a42aa46 100644
--- a/usr/src/uts/common/fs/zfs/zvol.c
+++ b/usr/src/uts/common/fs/zfs/zvol.c
@@ -819,20 +819,12 @@ zvol_update_live_volsize(zvol_state_t *zv, uint64_t volsize)
* Generate a LUN expansion event.
*/
if (error == 0) {
- sysevent_id_t eid;
- nvlist_t *attr;
char *physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
(void) snprintf(physpath, MAXPATHLEN, "%s%u", ZVOL_PSEUDO_DEV,
zv->zv_minor);
- VERIFY(nvlist_alloc(&attr, NV_UNIQUE_NAME, KM_SLEEP) == 0);
- VERIFY(nvlist_add_string(attr, DEV_PHYS_PATH, physpath) == 0);
-
- (void) ddi_log_sysevent(zfs_dip, SUNW_VENDOR, EC_DEV_STATUS,
- ESC_DEV_DLE, attr, &eid, DDI_SLEEP);
-
- nvlist_free(attr);
+ zfs_post_dle_sysevent(physpath);
kmem_free(physpath, MAXPATHLEN);
}
return (error);