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