Home | History | Annotate | Download | only in zfs
      1   2926  ek110237 /*
      2   2926  ek110237  * CDDL HEADER START
      3   2926  ek110237  *
      4   2926  ek110237  * The contents of this file are subject to the terms of the
      5   2926  ek110237  * Common Development and Distribution License (the "License").
      6   2926  ek110237  * You may not use this file except in compliance with the License.
      7   2926  ek110237  *
      8   2926  ek110237  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9   2926  ek110237  * or http://www.opensolaris.org/os/licensing.
     10   2926  ek110237  * See the License for the specific language governing permissions
     11   2926  ek110237  * and limitations under the License.
     12   2926  ek110237  *
     13   2926  ek110237  * When distributing Covered Code, include this CDDL HEADER in each
     14   2926  ek110237  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15   2926  ek110237  * If applicable, add the following below this CDDL HEADER, with the
     16   2926  ek110237  * fields enclosed by brackets "[]" replaced with your own identifying
     17   2926  ek110237  * information: Portions Copyright [yyyy] [name of copyright owner]
     18   2926  ek110237  *
     19   2926  ek110237  * CDDL HEADER END
     20   2926  ek110237  */
     21   2926  ek110237 
     22   2926  ek110237 /*
     23   9512      Neil  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24   2926  ek110237  * Use is subject to license terms.
     25   2926  ek110237  */
     26   2926  ek110237 
     27   4543     marks #include <sys/spa.h>
     28   2926  ek110237 #include <sys/spa_impl.h>
     29   2926  ek110237 #include <sys/zap.h>
     30   2926  ek110237 #include <sys/dsl_synctask.h>
     31   4543     marks #include <sys/dmu_tx.h>
     32   4543     marks #include <sys/dmu_objset.h>
     33   4543     marks #include <sys/utsname.h>
     34   4543     marks #include <sys/cmn_err.h>
     35   4543     marks #include <sys/sunddi.h>
     36   4543     marks #ifdef _KERNEL
     37   4543     marks #include <sys/zone.h>
     38   4543     marks #endif
     39   2926  ek110237 
     40   2926  ek110237 /*
     41   2926  ek110237  * Routines to manage the on-disk history log.
     42   2926  ek110237  *
     43   2926  ek110237  * The history log is stored as a dmu object containing
     44   2926  ek110237  * <packed record length, record nvlist> tuples.
     45   2926  ek110237  *
     46   2926  ek110237  * Where "record nvlist" is a nvlist containing uint64_ts and strings, and
     47   2926  ek110237  * "packed record length" is the packed length of the "record nvlist" stored
     48   2926  ek110237  * as a little endian uint64_t.
     49   2926  ek110237  *
     50   2926  ek110237  * The log is implemented as a ring buffer, though the original creation
     51   2926  ek110237  * of the pool ('zpool create') is never overwritten.
     52   2926  ek110237  *
     53   2926  ek110237  * The history log is tracked as object 'spa_t::spa_history'.  The bonus buffer
     54   2926  ek110237  * of 'spa_history' stores the offsets for logging/retrieving history as
     55   2926  ek110237  * 'spa_history_phys_t'.  'sh_pool_create_len' is the ending offset in bytes of
     56   2926  ek110237  * where the 'zpool create' record is stored.  This allows us to never
     57   2926  ek110237  * overwrite the original creation of the pool.  'sh_phys_max_off' is the
     58   2926  ek110237  * physical ending offset in bytes of the log.  This tells you the length of
     59   2926  ek110237  * the buffer. 'sh_eof' is the logical EOF (in bytes).  Whenever a record
     60   2926  ek110237  * is added, 'sh_eof' is incremented by the the size of the record.
     61   2926  ek110237  * 'sh_eof' is never decremented.  'sh_bof' is the logical BOF (in bytes).
     62   2926  ek110237  * This is where the consumer should start reading from after reading in
     63   2926  ek110237  * the 'zpool create' portion of the log.
     64   2926  ek110237  *
     65   2926  ek110237  * 'sh_records_lost' keeps track of how many records have been overwritten
     66   2926  ek110237  * and permanently lost.
     67   2926  ek110237  */
     68   2926  ek110237 
     69   2926  ek110237 /* convert a logical offset to physical */
     70   2926  ek110237 static uint64_t
     71   2926  ek110237 spa_history_log_to_phys(uint64_t log_off, spa_history_phys_t *shpp)
     72   2926  ek110237 {
     73   2926  ek110237 	uint64_t phys_len;
     74   2926  ek110237 
     75   2926  ek110237 	phys_len = shpp->sh_phys_max_off - shpp->sh_pool_create_len;
     76   2926  ek110237 	return ((log_off - shpp->sh_pool_create_len) % phys_len
     77   2926  ek110237 	    + shpp->sh_pool_create_len);
     78   2926  ek110237 }
     79   2926  ek110237 
     80   2926  ek110237 void
     81   2926  ek110237 spa_history_create_obj(spa_t *spa, dmu_tx_t *tx)
     82   2926  ek110237 {
     83   2926  ek110237 	dmu_buf_t *dbp;
     84   2926  ek110237 	spa_history_phys_t *shpp;
     85   2926  ek110237 	objset_t *mos = spa->spa_meta_objset;
     86   2926  ek110237 
     87   2926  ek110237 	ASSERT(spa->spa_history == 0);
     88   2926  ek110237 	spa->spa_history = dmu_object_alloc(mos, DMU_OT_SPA_HISTORY,
     89   2926  ek110237 	    SPA_MAXBLOCKSIZE, DMU_OT_SPA_HISTORY_OFFSETS,
     90   2926  ek110237 	    sizeof (spa_history_phys_t), tx);
     91   2926  ek110237 
     92   2926  ek110237 	VERIFY(zap_add(mos, DMU_POOL_DIRECTORY_OBJECT,
     93   2926  ek110237 	    DMU_POOL_HISTORY, sizeof (uint64_t), 1,
     94   2926  ek110237 	    &spa->spa_history, tx) == 0);
     95   2926  ek110237 
     96   2926  ek110237 	VERIFY(0 == dmu_bonus_hold(mos, spa->spa_history, FTAG, &dbp));
     97   2926  ek110237 	ASSERT(dbp->db_size >= sizeof (spa_history_phys_t));
     98   2926  ek110237 
     99   2926  ek110237 	shpp = dbp->db_data;
    100   2926  ek110237 	dmu_buf_will_dirty(dbp, tx);
    101   2926  ek110237 
    102   2926  ek110237 	/*
    103   2926  ek110237 	 * Figure out maximum size of history log.  We set it at
    104   2926  ek110237 	 * 1% of pool size, with a max of 32MB and min of 128KB.
    105   2926  ek110237 	 */
    106  10922      Jeff 	shpp->sh_phys_max_off =
    107  10922      Jeff 	    metaslab_class_get_dspace(spa_normal_class(spa)) / 100;
    108   2926  ek110237 	shpp->sh_phys_max_off = MIN(shpp->sh_phys_max_off, 32<<20);
    109   2926  ek110237 	shpp->sh_phys_max_off = MAX(shpp->sh_phys_max_off, 128<<10);
    110   2926  ek110237 
    111   2926  ek110237 	dmu_buf_rele(dbp, FTAG);
    112   2926  ek110237 }
    113   2926  ek110237 
    114   2926  ek110237 /*
    115   2926  ek110237  * Change 'sh_bof' to the beginning of the next record.
    116   2926  ek110237  */
    117   2926  ek110237 static int
    118   2926  ek110237 spa_history_advance_bof(spa_t *spa, spa_history_phys_t *shpp)
    119   2926  ek110237 {
    120   2926  ek110237 	objset_t *mos = spa->spa_meta_objset;
    121   2926  ek110237 	uint64_t firstread, reclen, phys_bof;
    122   2926  ek110237 	char buf[sizeof (reclen)];
    123   2926  ek110237 	int err;
    124   2926  ek110237 
    125   2926  ek110237 	phys_bof = spa_history_log_to_phys(shpp->sh_bof, shpp);
    126   2926  ek110237 	firstread = MIN(sizeof (reclen), shpp->sh_phys_max_off - phys_bof);
    127   2926  ek110237 
    128   2926  ek110237 	if ((err = dmu_read(mos, spa->spa_history, phys_bof, firstread,
    129   9512      Neil 	    buf, DMU_READ_PREFETCH)) != 0)
    130   2926  ek110237 		return (err);
    131   2926  ek110237 	if (firstread != sizeof (reclen)) {
    132   2926  ek110237 		if ((err = dmu_read(mos, spa->spa_history,
    133   2926  ek110237 		    shpp->sh_pool_create_len, sizeof (reclen) - firstread,
    134   9512      Neil 		    buf + firstread, DMU_READ_PREFETCH)) != 0)
    135   2926  ek110237 			return (err);
    136   2926  ek110237 	}
    137   2926  ek110237 
    138   2926  ek110237 	reclen = LE_64(*((uint64_t *)buf));
    139   2926  ek110237 	shpp->sh_bof += reclen + sizeof (reclen);
    140   2926  ek110237 	shpp->sh_records_lost++;
    141   2926  ek110237 	return (0);
    142   2926  ek110237 }
    143   2926  ek110237 
    144   2926  ek110237 static int
    145   2926  ek110237 spa_history_write(spa_t *spa, void *buf, uint64_t len, spa_history_phys_t *shpp,
    146   2926  ek110237     dmu_tx_t *tx)
    147   2926  ek110237 {
    148   2926  ek110237 	uint64_t firstwrite, phys_eof;
    149   2926  ek110237 	objset_t *mos = spa->spa_meta_objset;
    150   2926  ek110237 	int err;
    151   2926  ek110237 
    152   2926  ek110237 	ASSERT(MUTEX_HELD(&spa->spa_history_lock));
    153   2926  ek110237 
    154   2926  ek110237 	/* see if we need to reset logical BOF */
    155   2926  ek110237 	while (shpp->sh_phys_max_off - shpp->sh_pool_create_len -
    156   2926  ek110237 	    (shpp->sh_eof - shpp->sh_bof) <= len) {
    157   4543     marks 		if ((err = spa_history_advance_bof(spa, shpp)) != 0) {
    158   2926  ek110237 			return (err);
    159   4543     marks 		}
    160   2926  ek110237 	}
    161   2926  ek110237 
    162   2926  ek110237 	phys_eof = spa_history_log_to_phys(shpp->sh_eof, shpp);
    163   2926  ek110237 	firstwrite = MIN(len, shpp->sh_phys_max_off - phys_eof);
    164   2926  ek110237 	shpp->sh_eof += len;
    165   2926  ek110237 	dmu_write(mos, spa->spa_history, phys_eof, firstwrite, buf, tx);
    166   2926  ek110237 
    167   2926  ek110237 	len -= firstwrite;
    168   2926  ek110237 	if (len > 0) {
    169   2926  ek110237 		/* write out the rest at the beginning of physical file */
    170   2926  ek110237 		dmu_write(mos, spa->spa_history, shpp->sh_pool_create_len,
    171   2926  ek110237 		    len, (char *)buf + firstwrite, tx);
    172   2926  ek110237 	}
    173   2926  ek110237 
    174   2926  ek110237 	return (0);
    175   2926  ek110237 }
    176   2926  ek110237 
    177   4543     marks static char *
    178   4543     marks spa_history_zone()
    179   4543     marks {
    180   4543     marks #ifdef _KERNEL
    181   4543     marks 	return (curproc->p_zone->zone_name);
    182   4543     marks #else
    183   4543     marks 	return ("global");
    184   4543     marks #endif
    185   4543     marks }
    186   4543     marks 
    187   2926  ek110237 /*
    188   2926  ek110237  * Write out a history event.
    189   2926  ek110237  */
    190   4577    ahrens static void
    191   4543     marks spa_history_log_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
    192   2926  ek110237 {
    193   2926  ek110237 	spa_t		*spa = arg1;
    194   2926  ek110237 	history_arg_t	*hap = arg2;
    195   2926  ek110237 	const char	*history_str = hap->ha_history_str;
    196   2926  ek110237 	objset_t	*mos = spa->spa_meta_objset;
    197   2926  ek110237 	dmu_buf_t	*dbp;
    198   2926  ek110237 	spa_history_phys_t *shpp;
    199   2926  ek110237 	size_t		reclen;
    200   2926  ek110237 	uint64_t	le_len;
    201   2926  ek110237 	nvlist_t	*nvrecord;
    202   2926  ek110237 	char		*record_packed = NULL;
    203   2926  ek110237 	int		ret;
    204   2926  ek110237 
    205   2926  ek110237 	/*
    206   2926  ek110237 	 * If we have an older pool that doesn't have a command
    207   2926  ek110237 	 * history object, create it now.
    208   2926  ek110237 	 */
    209   2926  ek110237 	mutex_enter(&spa->spa_history_lock);
    210   2926  ek110237 	if (!spa->spa_history)
    211   2926  ek110237 		spa_history_create_obj(spa, tx);
    212   2926  ek110237 	mutex_exit(&spa->spa_history_lock);
    213   2926  ek110237 
    214   2926  ek110237 	/*
    215   2926  ek110237 	 * Get the offset of where we need to write via the bonus buffer.
    216   2926  ek110237 	 * Update the offset when the write completes.
    217   2926  ek110237 	 */
    218   2926  ek110237 	VERIFY(0 == dmu_bonus_hold(mos, spa->spa_history, FTAG, &dbp));
    219   2926  ek110237 	shpp = dbp->db_data;
    220   2926  ek110237 
    221   2926  ek110237 	dmu_buf_will_dirty(dbp, tx);
    222   2926  ek110237 
    223   2926  ek110237 #ifdef ZFS_DEBUG
    224   2926  ek110237 	{
    225   2926  ek110237 		dmu_object_info_t doi;
    226   2926  ek110237 		dmu_object_info_from_db(dbp, &doi);
    227   2926  ek110237 		ASSERT3U(doi.doi_bonus_type, ==, DMU_OT_SPA_HISTORY_OFFSETS);
    228   2926  ek110237 	}
    229   2926  ek110237 #endif
    230   2926  ek110237 
    231   2926  ek110237 	VERIFY(nvlist_alloc(&nvrecord, NV_UNIQUE_NAME, KM_SLEEP) == 0);
    232   2926  ek110237 	VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_TIME,
    233   2926  ek110237 	    gethrestime_sec()) == 0);
    234   4543     marks 	VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_WHO,
    235   4543     marks 	    (uint64_t)crgetuid(cr)) == 0);
    236   4543     marks 	if (hap->ha_zone[0] != '\0')
    237   4543     marks 		VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_ZONE,
    238   4543     marks 		    hap->ha_zone) == 0);
    239   4543     marks #ifdef _KERNEL
    240   4543     marks 	VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_HOST,
    241   4543     marks 	    utsname.nodename) == 0);
    242   4543     marks #endif
    243   4543     marks 	if (hap->ha_log_type == LOG_CMD_POOL_CREATE ||
    244   4543     marks 	    hap->ha_log_type == LOG_CMD_NORMAL) {
    245   4543     marks 		VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_CMD,
    246   4543     marks 		    history_str) == 0);
    247   4543     marks 	} else {
    248   4543     marks 		VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_INT_EVENT,
    249   4543     marks 		    hap->ha_event) == 0);
    250   4543     marks 		VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_TXG,
    251   4543     marks 		    tx->tx_txg) == 0);
    252   4543     marks 		VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_INT_STR,
    253   4543     marks 		    history_str) == 0);
    254   4543     marks 	}
    255   4543     marks 
    256   4611     marks 	VERIFY(nvlist_size(nvrecord, &reclen, NV_ENCODE_XDR) == 0);
    257   4611     marks 	record_packed = kmem_alloc(reclen, KM_SLEEP);
    258   4611     marks 
    259   2926  ek110237 	VERIFY(nvlist_pack(nvrecord, &record_packed, &reclen,
    260   2926  ek110237 	    NV_ENCODE_XDR, KM_SLEEP) == 0);
    261   2926  ek110237 
    262   2926  ek110237 	mutex_enter(&spa->spa_history_lock);
    263   4543     marks 	if (hap->ha_log_type == LOG_CMD_POOL_CREATE)
    264   2926  ek110237 		VERIFY(shpp->sh_eof == shpp->sh_pool_create_len);
    265   2926  ek110237 
    266   2926  ek110237 	/* write out the packed length as little endian */
    267   3444  ek110237 	le_len = LE_64((uint64_t)reclen);
    268   2926  ek110237 	ret = spa_history_write(spa, &le_len, sizeof (le_len), shpp, tx);
    269   2926  ek110237 	if (!ret)
    270   2926  ek110237 		ret = spa_history_write(spa, record_packed, reclen, shpp, tx);
    271   2926  ek110237 
    272   4543     marks 	if (!ret && hap->ha_log_type == LOG_CMD_POOL_CREATE) {
    273   2926  ek110237 		shpp->sh_pool_create_len += sizeof (le_len) + reclen;
    274   2926  ek110237 		shpp->sh_bof = shpp->sh_pool_create_len;
    275   2926  ek110237 	}
    276   2926  ek110237 
    277   2926  ek110237 	mutex_exit(&spa->spa_history_lock);
    278   2926  ek110237 	nvlist_free(nvrecord);
    279   2926  ek110237 	kmem_free(record_packed, reclen);
    280   2926  ek110237 	dmu_buf_rele(dbp, FTAG);
    281   4577    ahrens 
    282   4577    ahrens 	if (hap->ha_log_type == LOG_INTERNAL) {
    283   4577    ahrens 		kmem_free((void*)hap->ha_history_str, HIS_MAX_RECORD_LEN);
    284   4577    ahrens 		kmem_free(hap, sizeof (history_arg_t));
    285   4577    ahrens 	}
    286   2926  ek110237 }
    287   2926  ek110237 
    288   2926  ek110237 /*
    289   2926  ek110237  * Write out a history event.
    290   2926  ek110237  */
    291   2926  ek110237 int
    292   4543     marks spa_history_log(spa_t *spa, const char *history_str, history_log_type_t what)
    293   2926  ek110237 {
    294   2926  ek110237 	history_arg_t ha;
    295   4577    ahrens 
    296   4577    ahrens 	ASSERT(what != LOG_INTERNAL);
    297   2926  ek110237 
    298   2926  ek110237 	ha.ha_history_str = history_str;
    299   4543     marks 	ha.ha_log_type = what;
    300   4543     marks 	(void) strlcpy(ha.ha_zone, spa_history_zone(), sizeof (ha.ha_zone));
    301   2926  ek110237 	return (dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_history_log_sync,
    302   2926  ek110237 	    spa, &ha, 0));
    303   2926  ek110237 }
    304   2926  ek110237 
    305   2926  ek110237 /*
    306   2926  ek110237  * Read out the command history.
    307   2926  ek110237  */
    308   2926  ek110237 int
    309   2926  ek110237 spa_history_get(spa_t *spa, uint64_t *offp, uint64_t *len, char *buf)
    310   2926  ek110237 {
    311   2926  ek110237 	objset_t *mos = spa->spa_meta_objset;
    312   2926  ek110237 	dmu_buf_t *dbp;
    313   2926  ek110237 	uint64_t read_len, phys_read_off, phys_eof;
    314   2926  ek110237 	uint64_t leftover = 0;
    315   2926  ek110237 	spa_history_phys_t *shpp;
    316   2926  ek110237 	int err;
    317   2926  ek110237 
    318   2926  ek110237 	/*
    319   2926  ek110237 	 * If the command history  doesn't exist (older pool),
    320   2926  ek110237 	 * that's ok, just return ENOENT.
    321   2926  ek110237 	 */
    322   2926  ek110237 	if (!spa->spa_history)
    323   2926  ek110237 		return (ENOENT);
    324   2926  ek110237 
    325   2926  ek110237 	if ((err = dmu_bonus_hold(mos, spa->spa_history, FTAG, &dbp)) != 0)
    326   2926  ek110237 		return (err);
    327   2926  ek110237 	shpp = dbp->db_data;
    328   2926  ek110237 
    329   2926  ek110237 #ifdef ZFS_DEBUG
    330   2926  ek110237 	{
    331   2926  ek110237 		dmu_object_info_t doi;
    332   2926  ek110237 		dmu_object_info_from_db(dbp, &doi);
    333   2926  ek110237 		ASSERT3U(doi.doi_bonus_type, ==, DMU_OT_SPA_HISTORY_OFFSETS);
    334   2926  ek110237 	}
    335   2926  ek110237 #endif
    336   2926  ek110237 
    337   2926  ek110237 	mutex_enter(&spa->spa_history_lock);
    338   2926  ek110237 	phys_eof = spa_history_log_to_phys(shpp->sh_eof, shpp);
    339   2926  ek110237 
    340   2926  ek110237 	if (*offp < shpp->sh_pool_create_len) {
    341   2926  ek110237 		/* read in just the zpool create history */
    342   2926  ek110237 		phys_read_off = *offp;
    343   2926  ek110237 		read_len = MIN(*len, shpp->sh_pool_create_len -
    344   2926  ek110237 		    phys_read_off);
    345   2926  ek110237 	} else {
    346   2926  ek110237 		/*
    347   2926  ek110237 		 * Need to reset passed in offset to BOF if the passed in
    348   2926  ek110237 		 * offset has since been overwritten.
    349   2926  ek110237 		 */
    350   2926  ek110237 		*offp = MAX(*offp, shpp->sh_bof);
    351   2926  ek110237 		phys_read_off = spa_history_log_to_phys(*offp, shpp);
    352   2926  ek110237 
    353   2926  ek110237 		/*
    354   2926  ek110237 		 * Read up to the minimum of what the user passed down or
    355   2926  ek110237 		 * the EOF (physical or logical).  If we hit physical EOF,
    356   2926  ek110237 		 * use 'leftover' to read from the physical BOF.
    357   2926  ek110237 		 */
    358   2926  ek110237 		if (phys_read_off <= phys_eof) {
    359   2926  ek110237 			read_len = MIN(*len, phys_eof - phys_read_off);
    360   2926  ek110237 		} else {
    361   2926  ek110237 			read_len = MIN(*len,
    362   2926  ek110237 			    shpp->sh_phys_max_off - phys_read_off);
    363   2926  ek110237 			if (phys_read_off + *len > shpp->sh_phys_max_off) {
    364   2926  ek110237 				leftover = MIN(*len - read_len,
    365   2926  ek110237 				    phys_eof - shpp->sh_pool_create_len);
    366   2926  ek110237 			}
    367   2926  ek110237 		}
    368   2926  ek110237 	}
    369   2926  ek110237 
    370   2926  ek110237 	/* offset for consumer to use next */
    371   2926  ek110237 	*offp += read_len + leftover;
    372   2926  ek110237 
    373   2926  ek110237 	/* tell the consumer how much you actually read */
    374   2926  ek110237 	*len = read_len + leftover;
    375   2926  ek110237 
    376   2926  ek110237 	if (read_len == 0) {
    377   2926  ek110237 		mutex_exit(&spa->spa_history_lock);
    378   2926  ek110237 		dmu_buf_rele(dbp, FTAG);
    379   2926  ek110237 		return (0);
    380   2926  ek110237 	}
    381   2926  ek110237 
    382   9512      Neil 	err = dmu_read(mos, spa->spa_history, phys_read_off, read_len, buf,
    383   9512      Neil 	    DMU_READ_PREFETCH);
    384   2926  ek110237 	if (leftover && err == 0) {
    385   2926  ek110237 		err = dmu_read(mos, spa->spa_history, shpp->sh_pool_create_len,
    386   9512      Neil 		    leftover, buf + read_len, DMU_READ_PREFETCH);
    387   2926  ek110237 	}
    388   2926  ek110237 	mutex_exit(&spa->spa_history_lock);
    389   2926  ek110237 
    390   2926  ek110237 	dmu_buf_rele(dbp, FTAG);
    391   2926  ek110237 	return (err);
    392   2926  ek110237 }
    393   4543     marks 
    394   9946      Mark static void
    395   9946      Mark log_internal(history_internal_events_t event, spa_t *spa,
    396   9946      Mark     dmu_tx_t *tx, cred_t *cr, const char *fmt, va_list adx)
    397   4543     marks {
    398   4577    ahrens 	history_arg_t *hap;
    399   4543     marks 	char *str;
    400   4543     marks 
    401   7046    ahrens 	/*
    402   7046    ahrens 	 * If this is part of creating a pool, not everything is
    403   7046    ahrens 	 * initialized yet, so don't bother logging the internal events.
    404   7046    ahrens 	 */
    405   7046    ahrens 	if (tx->tx_txg == TXG_INITIAL)
    406   7046    ahrens 		return;
    407   7046    ahrens 
    408   4577    ahrens 	hap = kmem_alloc(sizeof (history_arg_t), KM_SLEEP);
    409   4543     marks 	str = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP);
    410   4543     marks 
    411   4543     marks 	(void) vsnprintf(str, HIS_MAX_RECORD_LEN, fmt, adx);
    412   4543     marks 
    413   4577    ahrens 	hap->ha_log_type = LOG_INTERNAL;
    414   4577    ahrens 	hap->ha_history_str = str;
    415   4577    ahrens 	hap->ha_event = event;
    416   4577    ahrens 	hap->ha_zone[0] = '\0';
    417   4577    ahrens 
    418   4577    ahrens 	if (dmu_tx_is_syncing(tx)) {
    419   4577    ahrens 		spa_history_log_sync(spa, hap, cr, tx);
    420   4577    ahrens 	} else {
    421   4577    ahrens 		dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
    422   4577    ahrens 		    spa_history_log_sync, spa, hap, 0, tx);
    423   4577    ahrens 	}
    424   4577    ahrens 	/* spa_history_log_sync() will free hap and str */
    425   4543     marks }
    426   9946      Mark 
    427   9946      Mark void
    428   9946      Mark spa_history_internal_log(history_internal_events_t event, spa_t *spa,
    429   9946      Mark     dmu_tx_t *tx, cred_t *cr, const char *fmt, ...)
    430   9946      Mark {
    431   9946      Mark 	dmu_tx_t *htx = tx;
    432   9946      Mark 	va_list adx;
    433   9946      Mark 
    434   9946      Mark 	/* create a tx if we didn't get one */
    435   9946      Mark 	if (tx == NULL) {
    436   9946      Mark 		htx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
    437   9946      Mark 		if (dmu_tx_assign(htx, TXG_WAIT) != 0) {
    438   9946      Mark 			dmu_tx_abort(htx);
    439   9946      Mark 			return;
    440   9946      Mark 		}
    441   9946      Mark 	}
    442   9946      Mark 
    443   9946      Mark 	va_start(adx, fmt);
    444   9946      Mark 	log_internal(event, spa, htx, cr, fmt, adx);
    445   9946      Mark 	va_end(adx);
    446   9946      Mark 
    447   9946      Mark 	/* if we didn't get a tx from the caller, commit the one we made */
    448   9946      Mark 	if (tx == NULL)
    449   9946      Mark 		dmu_tx_commit(htx);
    450   9946      Mark }
    451   9946      Mark 
    452   9946      Mark void
    453   9946      Mark spa_history_log_version(spa_t *spa, history_internal_events_t event)
    454   9946      Mark {
    455   9946      Mark #ifdef _KERNEL
    456   9946      Mark 	uint64_t current_vers = spa_version(spa);
    457   9946      Mark 
    458   9946      Mark 	if (current_vers >= SPA_VERSION_ZPOOL_HISTORY) {
    459   9946      Mark 		spa_history_internal_log(event, spa, NULL, CRED(),
    460   9946      Mark 		    "pool spa %llu; zfs spa %llu; zpl %d; uts %s %s %s %s",
    461   9946      Mark 		    (u_longlong_t)current_vers, SPA_VERSION, ZPL_VERSION,
    462   9946      Mark 		    utsname.nodename, utsname.release, utsname.version,
    463   9946      Mark 		    utsname.machine);
    464   9946      Mark 	}
    465   9946      Mark 	cmn_err(CE_CONT, "!%s version %llu pool %s using %llu",
    466   9946      Mark 	    event == LOG_POOL_IMPORT ? "imported" :
    467   9946      Mark 	    event == LOG_POOL_CREATE ? "created" : "accessed",
    468   9946      Mark 	    (u_longlong_t)current_vers, spa_name(spa), SPA_VERSION);
    469   9946      Mark #endif
    470   9946      Mark }
    471