summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2013-03-05 08:09:53 +0000
committermm <mm@FreeBSD.org>2013-03-05 08:09:53 +0000
commit99f883783c89d10b9d02e77393eb9d0a307f3ca0 (patch)
tree669ea5740806cbf29b6e064275d3f5a62478bd47 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c
parent712512f2cc075f7890eaf59c6aa392f330857ff9 (diff)
parentd5063724619a16bd1592c39395c787e97be18693 (diff)
downloadFreeBSD-src-99f883783c89d10b9d02e77393eb9d0a307f3ca0.zip
FreeBSD-src-99f883783c89d10b9d02e77393eb9d0a307f3ca0.tar.gz
WiP merge of libzfs_core (MFV r238590, r238592)
not yet working, ioctl handling needs to be changed
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c214
1 files changed, 125 insertions, 89 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c
index 5cd5a9d..6ac8a93 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <sys/spa.h>
@@ -30,8 +30,11 @@
#include <sys/dsl_synctask.h>
#include <sys/dmu_tx.h>
#include <sys/dmu_objset.h>
+#include <sys/dsl_dataset.h>
+#include <sys/dsl_dir.h>
#include <sys/utsname.h>
#include <sys/sunddi.h>
+#include <sys/cred.h>
#include "zfs_comutil.h"
#ifdef _KERNEL
#include <sys/cmn_err.h>
@@ -176,14 +179,14 @@ spa_history_write(spa_t *spa, void *buf, uint64_t len, spa_history_phys_t *shpp,
}
static char *
-spa_history_zone()
+spa_history_zone(void)
{
#ifdef _KERNEL
/* XXX: pr_hostname can be changed by default from within a jail! */
if (jailed(curthread->td_ucred))
return (curthread->td_ucred->cr_prison->pr_hostname);
#endif
- return ("global");
+ return (NULL);
}
/*
@@ -194,14 +197,12 @@ static void
spa_history_log_sync(void *arg1, void *arg2, dmu_tx_t *tx)
{
spa_t *spa = arg1;
- history_arg_t *hap = arg2;
- const char *history_str = hap->ha_history_str;
+ nvlist_t *nvl = arg2;
objset_t *mos = spa->spa_meta_objset;
dmu_buf_t *dbp;
spa_history_phys_t *shpp;
size_t reclen;
uint64_t le_len;
- nvlist_t *nvrecord;
char *record_packed = NULL;
int ret;
@@ -231,46 +232,35 @@ spa_history_log_sync(void *arg1, void *arg2, dmu_tx_t *tx)
}
#endif
- VERIFY(nvlist_alloc(&nvrecord, NV_UNIQUE_NAME, KM_SLEEP) == 0);
- VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_TIME,
- gethrestime_sec()) == 0);
- VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_WHO, hap->ha_uid) == 0);
- if (hap->ha_zone != NULL)
- VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_ZONE,
- hap->ha_zone) == 0);
+ fnvlist_add_uint64(nvl, ZPOOL_HIST_TIME, gethrestime_sec());
#ifdef _KERNEL
- VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_HOST,
- utsname.nodename) == 0);
+ fnvlist_add_string(nvl, ZPOOL_HIST_HOST, utsname.nodename);
#endif
- if (hap->ha_log_type == LOG_CMD_POOL_CREATE ||
- hap->ha_log_type == LOG_CMD_NORMAL) {
- VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_CMD,
- history_str) == 0);
-
- zfs_dbgmsg("command: %s", history_str);
- } else {
- VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_INT_EVENT,
- hap->ha_event) == 0);
- VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_TXG,
- tx->tx_txg) == 0);
- VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_INT_STR,
- history_str) == 0);
-
- zfs_dbgmsg("internal %s pool:%s txg:%llu %s",
- zfs_history_event_names[hap->ha_event], spa_name(spa),
- (longlong_t)tx->tx_txg, history_str);
-
+ if (nvlist_exists(nvl, ZPOOL_HIST_CMD)) {
+ zfs_dbgmsg("command: %s",
+ fnvlist_lookup_string(nvl, ZPOOL_HIST_CMD));
+ } else if (nvlist_exists(nvl, ZPOOL_HIST_INT_NAME)) {
+ if (nvlist_exists(nvl, ZPOOL_HIST_DSNAME)) {
+ zfs_dbgmsg("txg %lld %s %s (id %llu) %s",
+ fnvlist_lookup_uint64(nvl, ZPOOL_HIST_TXG),
+ fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_NAME),
+ fnvlist_lookup_string(nvl, ZPOOL_HIST_DSNAME),
+ fnvlist_lookup_uint64(nvl, ZPOOL_HIST_DSID),
+ fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_STR));
+ } else {
+ zfs_dbgmsg("txg %lld %s %s",
+ fnvlist_lookup_uint64(nvl, ZPOOL_HIST_TXG),
+ fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_NAME),
+ fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_STR));
+ }
+ } else if (nvlist_exists(nvl, ZPOOL_HIST_IOCTL)) {
+ zfs_dbgmsg("ioctl %s",
+ fnvlist_lookup_string(nvl, ZPOOL_HIST_IOCTL));
}
- VERIFY(nvlist_size(nvrecord, &reclen, NV_ENCODE_XDR) == 0);
- record_packed = kmem_alloc(reclen, KM_SLEEP);
-
- VERIFY(nvlist_pack(nvrecord, &record_packed, &reclen,
- NV_ENCODE_XDR, KM_SLEEP) == 0);
+ record_packed = fnvlist_pack(nvl, &reclen);
mutex_enter(&spa->spa_history_lock);
- if (hap->ha_log_type == LOG_CMD_POOL_CREATE)
- VERIFY(shpp->sh_eof == shpp->sh_pool_create_len);
/* write out the packed length as little endian */
le_len = LE_64((uint64_t)reclen);
@@ -278,33 +268,42 @@ spa_history_log_sync(void *arg1, void *arg2, dmu_tx_t *tx)
if (!ret)
ret = spa_history_write(spa, record_packed, reclen, shpp, tx);
- if (!ret && hap->ha_log_type == LOG_CMD_POOL_CREATE) {
- shpp->sh_pool_create_len += sizeof (le_len) + reclen;
- shpp->sh_bof = shpp->sh_pool_create_len;
+ /* The first command is the create, which we keep forever */
+ if (ret == 0 && shpp->sh_pool_create_len == 0 &&
+ nvlist_exists(nvl, ZPOOL_HIST_CMD)) {
+ shpp->sh_pool_create_len = shpp->sh_bof = shpp->sh_eof;
}
mutex_exit(&spa->spa_history_lock);
- nvlist_free(nvrecord);
- kmem_free(record_packed, reclen);
+ fnvlist_pack_free(record_packed, reclen);
dmu_buf_rele(dbp, FTAG);
-
- strfree(hap->ha_history_str);
- if (hap->ha_zone != NULL)
- strfree(hap->ha_zone);
- kmem_free(hap, sizeof (history_arg_t));
+ fnvlist_free(nvl);
}
/*
* Write out a history event.
*/
int
-spa_history_log(spa_t *spa, const char *history_str, history_log_type_t what)
+spa_history_log(spa_t *spa, const char *msg)
+{
+ int err;
+ nvlist_t *nvl = fnvlist_alloc();
+
+ fnvlist_add_string(nvl, ZPOOL_HIST_CMD, msg);
+ err = spa_history_log_nvl(spa, nvl);
+ fnvlist_free(nvl);
+ return (err);
+}
+
+int
+spa_history_log_nvl(spa_t *spa, nvlist_t *nvl)
{
- history_arg_t *ha;
int err = 0;
dmu_tx_t *tx;
+ nvlist_t *nvarg;
- ASSERT(what != LOG_INTERNAL);
+ if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY)
+ return (EINVAL);
if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY || !spa_writeable(spa))
return (EINVAL);
@@ -316,19 +315,21 @@ spa_history_log(spa_t *spa, const char *history_str, history_log_type_t what)
return (err);
}
- ha = kmem_alloc(sizeof (history_arg_t), KM_SLEEP);
- ha->ha_history_str = strdup(history_str);
- ha->ha_zone = strdup(spa_history_zone());
- ha->ha_log_type = what;
- ha->ha_uid = crgetuid(CRED());
+ nvarg = fnvlist_dup(nvl);
+ if (spa_history_zone() != NULL) {
+ fnvlist_add_string(nvarg, ZPOOL_HIST_ZONE,
+ spa_history_zone());
+ }
+ fnvlist_add_uint64(nvarg, ZPOOL_HIST_WHO, crgetruid(CRED()));
/* Kick this off asynchronously; errors are ignored. */
dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
- spa_history_log_sync, spa, ha, 0, tx);
+ spa_history_log_sync, spa, nvarg, 0, tx);
dmu_tx_commit(tx);
- /* spa_history_log_sync will free ha and strings */
+ /* spa_history_log_sync will free nvl */
return (err);
+
}
/*
@@ -345,7 +346,7 @@ spa_history_get(spa_t *spa, uint64_t *offp, uint64_t *len, char *buf)
int err;
/*
- * If the command history doesn't exist (older pool),
+ * If the command history doesn't exist (older pool),
* that's ok, just return ENOENT.
*/
if (!spa->spa_history)
@@ -428,11 +429,14 @@ spa_history_get(spa_t *spa, uint64_t *offp, uint64_t *len, char *buf)
return (err);
}
+/*
+ * The nvlist will be consumed by this call.
+ */
static void
-log_internal(history_internal_events_t event, spa_t *spa,
+log_internal(nvlist_t *nvl, const char *operation, spa_t *spa,
dmu_tx_t *tx, const char *fmt, va_list adx)
{
- history_arg_t *ha;
+ char *msg;
va_list adx2;
/*
@@ -445,30 +449,27 @@ log_internal(history_internal_events_t event, spa_t *spa,
va_copy(adx2, adx);
- ha = kmem_alloc(sizeof (history_arg_t), KM_SLEEP);
- ha->ha_history_str = kmem_alloc(vsnprintf(NULL, 0, fmt, adx2) + 1,
- KM_SLEEP);
+ msg = kmem_alloc(vsnprintf(NULL, 0, fmt, adx) + 1, KM_SLEEP);
+ (void) vsprintf(msg, fmt, adx);
+ fnvlist_add_string(nvl, ZPOOL_HIST_INT_STR, msg);
+ strfree(msg);
va_end(adx2);
- (void) vsprintf(ha->ha_history_str, fmt, adx);
-
- ha->ha_log_type = LOG_INTERNAL;
- ha->ha_event = event;
- ha->ha_zone = NULL;
- ha->ha_uid = 0;
+ fnvlist_add_string(nvl, ZPOOL_HIST_INT_NAME, operation);
+ fnvlist_add_uint64(nvl, ZPOOL_HIST_TXG, tx->tx_txg);
if (dmu_tx_is_syncing(tx)) {
- spa_history_log_sync(spa, ha, tx);
+ spa_history_log_sync(spa, nvl, tx);
} else {
dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
- spa_history_log_sync, spa, ha, 0, tx);
+ spa_history_log_sync, spa, nvl, 0, tx);
}
- /* spa_history_log_sync() will free ha and strings */
+ /* spa_history_log_sync() will free nvl */
}
void
-spa_history_log_internal(history_internal_events_t event, spa_t *spa,
+spa_history_log_internal(spa_t *spa, const char *operation,
dmu_tx_t *tx, const char *fmt, ...)
{
dmu_tx_t *htx = tx;
@@ -484,7 +485,7 @@ spa_history_log_internal(history_internal_events_t event, spa_t *spa,
}
va_start(adx, fmt);
- log_internal(event, spa, htx, fmt, adx);
+ log_internal(fnvlist_alloc(), operation, spa, htx, fmt, adx);
va_end(adx);
/* if we didn't get a tx from the caller, commit the one we made */
@@ -493,22 +494,57 @@ spa_history_log_internal(history_internal_events_t event, spa_t *spa,
}
void
-spa_history_log_version(spa_t *spa, history_internal_events_t event)
+spa_history_log_internal_ds(dsl_dataset_t *ds, const char *operation,
+ dmu_tx_t *tx, const char *fmt, ...)
+{
+ va_list adx;
+ char namebuf[MAXNAMELEN];
+ nvlist_t *nvl = fnvlist_alloc();
+
+ ASSERT(tx != NULL);
+
+ dsl_dataset_name(ds, namebuf);
+ fnvlist_add_string(nvl, ZPOOL_HIST_DSNAME, namebuf);
+ fnvlist_add_uint64(nvl, ZPOOL_HIST_DSID, ds->ds_object);
+
+ va_start(adx, fmt);
+ log_internal(nvl, operation, dsl_dataset_get_spa(ds), tx, fmt, adx);
+ va_end(adx);
+}
+
+void
+spa_history_log_internal_dd(dsl_dir_t *dd, const char *operation,
+ dmu_tx_t *tx, const char *fmt, ...)
+{
+ va_list adx;
+ char namebuf[MAXNAMELEN];
+ nvlist_t *nvl = fnvlist_alloc();
+
+ ASSERT(tx != NULL);
+
+ dsl_dir_name(dd, namebuf);
+ fnvlist_add_string(nvl, ZPOOL_HIST_DSNAME, namebuf);
+ fnvlist_add_uint64(nvl, ZPOOL_HIST_DSID,
+ dd->dd_phys->dd_head_dataset_obj);
+
+ va_start(adx, fmt);
+ log_internal(nvl, operation, dd->dd_pool->dp_spa, tx, fmt, adx);
+ va_end(adx);
+}
+
+void
+spa_history_log_version(spa_t *spa, const char *operation)
{
#ifdef _KERNEL
uint64_t current_vers = spa_version(spa);
- if (current_vers >= SPA_VERSION_ZPOOL_HISTORY) {
- spa_history_log_internal(event, spa, NULL,
- "pool spa %llu; zfs spa %llu; zpl %d; uts %s %s %s %s",
- (u_longlong_t)current_vers, SPA_VERSION, ZPL_VERSION,
- utsname.nodename, utsname.release, utsname.version,
- utsname.machine);
- }
-#if 0
- cmn_err(CE_CONT, "!%s version %llu pool %s using %llu",
- event == LOG_POOL_IMPORT ? "imported" :
- event == LOG_POOL_CREATE ? "created" : "accessed",
+ spa_history_log_internal(spa, operation, NULL,
+ "pool version %llu; software version %llu/%d; uts %s %s %s %s",
+ (u_longlong_t)current_vers, SPA_VERSION, ZPL_VERSION,
+ utsname.nodename, utsname.release, utsname.version,
+ utsname.machine);
+#ifdef illumos
+ cmn_err(CE_CONT, "!%s version %llu pool %s using %llu", operation,
(u_longlong_t)current_vers, spa_name(spa), SPA_VERSION);
#endif
#endif
OpenPOWER on IntegriCloud