diff options
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts')
33 files changed, 464 insertions, 264 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c index a69fcc3..c74d072 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c @@ -20,7 +20,7 @@ */ /* - * Copyright (c) 2011, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -220,9 +220,10 @@ bptree_iterate(objset_t *os, uint64_t obj, boolean_t free, bptree_itor_t func, if (zfs_free_leak_on_eio) flags |= TRAVERSE_HARD; - zfs_dbgmsg("bptree index %d: traversing from min_txg=%lld " + zfs_dbgmsg("bptree index %lld: traversing from min_txg=%lld " "bookmark %lld/%lld/%lld/%lld", - i, (longlong_t)bte.be_birth_txg, + (longlong_t)i, + (longlong_t)bte.be_birth_txg, (longlong_t)bte.be_zb.zb_objset, (longlong_t)bte.be_zb.zb_object, (longlong_t)bte.be_zb.zb_level, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c index 82c5854..fe0c0db 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c @@ -621,7 +621,7 @@ dmu_objset_refresh_ownership(objset_t *os, void *tag) { dsl_pool_t *dp; dsl_dataset_t *ds, *newds; - char name[MAXNAMELEN]; + char name[ZFS_MAX_DATASET_NAME_LEN]; ds = os->os_dsl_dataset; VERIFY3P(ds, !=, NULL); @@ -791,11 +791,17 @@ dmu_objset_create_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, /* * Determine the number of levels necessary for the meta-dnode - * to contain DN_MAX_OBJECT dnodes. + * to contain DN_MAX_OBJECT dnodes. Note that in order to + * ensure that we do not overflow 64 bits, there has to be + * a nlevels that gives us a number of blocks > DN_MAX_OBJECT + * but < 2^64. Therefore, + * (mdn->dn_indblkshift - SPA_BLKPTRSHIFT) (10) must be + * less than (64 - log2(DN_MAX_OBJECT)) (16). */ - while ((uint64_t)mdn->dn_nblkptr << (mdn->dn_datablkshift + + while ((uint64_t)mdn->dn_nblkptr << + (mdn->dn_datablkshift - DNODE_SHIFT + (levels - 1) * (mdn->dn_indblkshift - SPA_BLKPTRSHIFT)) < - DN_MAX_OBJECT * sizeof (dnode_phys_t)) + DN_MAX_OBJECT) levels++; mdn->dn_next_nlevels[tx->tx_txg & TXG_MASK] = @@ -839,6 +845,9 @@ dmu_objset_create_check(void *arg, dmu_tx_t *tx) if (strchr(doca->doca_name, '@') != NULL) return (SET_ERROR(EINVAL)); + if (strlen(doca->doca_name) >= ZFS_MAX_DATASET_NAME_LEN) + return (SET_ERROR(ENAMETOOLONG)); + error = dsl_dir_hold(dp, doca->doca_name, FTAG, &pdd, &tail); if (error != 0) return (error); @@ -923,6 +932,9 @@ dmu_objset_clone_check(void *arg, dmu_tx_t *tx) if (strchr(doca->doca_clone, '@') != NULL) return (SET_ERROR(EINVAL)); + if (strlen(doca->doca_clone) >= ZFS_MAX_DATASET_NAME_LEN) + return (SET_ERROR(ENAMETOOLONG)); + error = dsl_dir_hold(dp, doca->doca_clone, FTAG, &pdd, &tail); if (error != 0) return (error); @@ -962,7 +974,7 @@ dmu_objset_clone_sync(void *arg, dmu_tx_t *tx) const char *tail; dsl_dataset_t *origin, *ds; uint64_t obj; - char namebuf[MAXNAMELEN]; + char namebuf[ZFS_MAX_DATASET_NAME_LEN]; VERIFY0(dsl_dir_hold(dp, doca->doca_clone, FTAG, &pdd, &tail)); VERIFY0(dsl_dataset_hold(dp, doca->doca_origin, FTAG, &origin)); @@ -1973,7 +1985,7 @@ dmu_objset_get_user(objset_t *os) /* * Determine name of filesystem, given name of snapshot. - * buf must be at least MAXNAMELEN bytes + * buf must be at least ZFS_MAX_DATASET_NAME_LEN bytes */ int dmu_fsname(const char *snapname, char *buf) @@ -1981,7 +1993,7 @@ dmu_fsname(const char *snapname, char *buf) char *atp = strchr(snapname, '@'); if (atp == NULL) return (SET_ERROR(EINVAL)); - if (atp - snapname >= MAXNAMELEN) + if (atp - snapname >= ZFS_MAX_DATASET_NAME_LEN) return (SET_ERROR(ENAMETOOLONG)); (void) strlcpy(buf, snapname, atp - snapname + 1); return (0); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c index 9e8d86e..874a1ca 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c @@ -1347,7 +1347,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx) dsl_dataset_rele(ds, FTAG); } else if (error == ENOENT) { /* target fs does not exist; must be a full backup or clone */ - char buf[MAXNAMELEN]; + char buf[ZFS_MAX_DATASET_NAME_LEN]; /* * If it's a non-clone incremental, we are missing the @@ -1367,7 +1367,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx) return (SET_ERROR(EINVAL)); /* Open the parent of tofs */ - ASSERT3U(strlen(tofs), <, MAXNAMELEN); + ASSERT3U(strlen(tofs), <, sizeof (buf)); (void) strlcpy(buf, tofs, strrchr(tofs, '/') - tofs + 1); error = dsl_dataset_hold(dp, buf, FTAG, &ds); if (error != 0) @@ -1551,7 +1551,8 @@ dmu_recv_resume_begin_check(void *arg, dmu_tx_t *tx) !spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LZ4_COMPRESS)) return (SET_ERROR(ENOTSUP)); - char recvname[ZFS_MAXNAMELEN]; + /* 6 extra bytes for /%recv */ + char recvname[ZFS_MAX_DATASET_NAME_LEN + 6]; (void) snprintf(recvname, sizeof (recvname), "%s/%s", tofs, recv_clone_name); @@ -1624,7 +1625,8 @@ dmu_recv_resume_begin_sync(void *arg, dmu_tx_t *tx) const char *tofs = drba->drba_cookie->drc_tofs; dsl_dataset_t *ds; uint64_t dsobj; - char recvname[ZFS_MAXNAMELEN]; + /* 6 extra bytes for /%recv */ + char recvname[ZFS_MAX_DATASET_NAME_LEN + 6]; (void) snprintf(recvname, sizeof (recvname), "%s/%s", tofs, recv_clone_name); @@ -2364,7 +2366,7 @@ dmu_recv_cleanup_ds(dmu_recv_cookie_t *drc) txg_wait_synced(drc->drc_ds->ds_dir->dd_pool, 0); dsl_dataset_disown(drc->drc_ds, dmu_recv_tag); } else { - char name[MAXNAMELEN]; + char name[ZFS_MAX_DATASET_NAME_LEN]; dsl_dataset_name(drc->drc_ds, name); dsl_dataset_disown(drc->drc_ds, dmu_recv_tag); (void) dsl_destroy_head(name); @@ -3183,13 +3185,13 @@ static int dmu_recv_existing_end(dmu_recv_cookie_t *drc) { int error; - char name[MAXNAMELEN]; #ifdef _KERNEL /* * We will be destroying the ds; make sure its origin is unmounted if * necessary. */ + char name[ZFS_MAX_DATASET_NAME_LEN]; dsl_dataset_name(drc->drc_ds, name); zfs_destroy_unmount_origin(name); #endif diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c index bea484f..63af9e3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c @@ -129,6 +129,12 @@ dmu_tx_hold_object_impl(dmu_tx_t *tx, objset_t *os, uint64_t object, txh = kmem_zalloc(sizeof (dmu_tx_hold_t), KM_SLEEP); txh->txh_tx = tx; txh->txh_dnode = dn; + refcount_create(&txh->txh_space_towrite); + refcount_create(&txh->txh_space_tofree); + refcount_create(&txh->txh_space_tooverwrite); + refcount_create(&txh->txh_space_tounref); + refcount_create(&txh->txh_memory_tohold); + refcount_create(&txh->txh_fudge); #ifdef ZFS_DEBUG txh->txh_type = type; txh->txh_arg1 = arg1; @@ -201,12 +207,18 @@ dmu_tx_count_twig(dmu_tx_hold_t *txh, dnode_t *dn, dmu_buf_impl_t *db, freeable = (bp && (freeable || dsl_dataset_block_freeable(ds, bp, bp->blk_birth))); - if (freeable) - txh->txh_space_tooverwrite += space; - else - txh->txh_space_towrite += space; - if (bp) - txh->txh_space_tounref += bp_get_dsize(os->os_spa, bp); + if (freeable) { + (void) refcount_add_many(&txh->txh_space_tooverwrite, + space, FTAG); + } else { + (void) refcount_add_many(&txh->txh_space_towrite, + space, FTAG); + } + + if (bp) { + (void) refcount_add_many(&txh->txh_space_tounref, + bp_get_dsize(os->os_spa, bp), FTAG); + } dmu_tx_count_twig(txh, dn, parent, level + 1, blkid >> epbs, freeable, history); @@ -336,8 +348,11 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len) bits = 64 - min_bs; epbs = min_ibs - SPA_BLKPTRSHIFT; for (bits -= epbs * (nlvls - 1); - bits >= 0; bits -= epbs) - txh->txh_fudge += 1ULL << max_ibs; + bits >= 0; bits -= epbs) { + (void) refcount_add_many( + &txh->txh_fudge, + 1ULL << max_ibs, FTAG); + } goto out; } off += delta; @@ -353,7 +368,8 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len) */ start = P2ALIGN(off, 1ULL << max_bs); end = P2ROUNDUP(off + len, 1ULL << max_bs) - 1; - txh->txh_space_towrite += end - start + 1; + (void) refcount_add_many(&txh->txh_space_towrite, + end - start + 1, FTAG); start >>= min_bs; end >>= min_bs; @@ -368,18 +384,21 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len) start >>= epbs; end >>= epbs; ASSERT3U(end, >=, start); - txh->txh_space_towrite += (end - start + 1) << max_ibs; + (void) refcount_add_many(&txh->txh_space_towrite, + (end - start + 1) << max_ibs, FTAG); if (start != 0) { /* * We also need a new blkid=0 indirect block * to reference any existing file data. */ - txh->txh_space_towrite += 1ULL << max_ibs; + (void) refcount_add_many(&txh->txh_space_towrite, + 1ULL << max_ibs, FTAG); } } out: - if (txh->txh_space_towrite + txh->txh_space_tooverwrite > + if (refcount_count(&txh->txh_space_towrite) + + refcount_count(&txh->txh_space_tooverwrite) > 2 * DMU_MAX_ACCESS) err = SET_ERROR(EFBIG); @@ -398,12 +417,15 @@ dmu_tx_count_dnode(dmu_tx_hold_t *txh) if (dn && dn->dn_dbuf->db_blkptr && dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset, dn->dn_dbuf->db_blkptr, dn->dn_dbuf->db_blkptr->blk_birth)) { - txh->txh_space_tooverwrite += space; - txh->txh_space_tounref += space; + (void) refcount_add_many(&txh->txh_space_tooverwrite, + space, FTAG); + (void) refcount_add_many(&txh->txh_space_tounref, space, FTAG); } else { - txh->txh_space_towrite += space; - if (dn && dn->dn_dbuf->db_blkptr) - txh->txh_space_tounref += space; + (void) refcount_add_many(&txh->txh_space_towrite, space, FTAG); + if (dn && dn->dn_dbuf->db_blkptr) { + (void) refcount_add_many(&txh->txh_space_tounref, + space, FTAG); + } } } @@ -525,7 +547,8 @@ dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len) break; } - txh->txh_memory_tohold += dbuf->db.db_size; + (void) refcount_add_many(&txh->txh_memory_tohold, + dbuf->db.db_size, FTAG); /* * We don't check memory_tohold against DMU_MAX_ACCESS because @@ -578,20 +601,23 @@ dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len) (dn->dn_indblkshift - SPA_BLKPTRSHIFT); while (level++ < maxlevel) { - txh->txh_memory_tohold += MAX(MIN(blkcnt, nl1blks), 1) - << dn->dn_indblkshift; + (void) refcount_add_many(&txh->txh_memory_tohold, + MAX(MIN(blkcnt, nl1blks), 1) << dn->dn_indblkshift, + FTAG); blkcnt = 1 + (blkcnt >> epbs); } } /* account for new level 1 indirect blocks that might show up */ if (skipped > 0) { - txh->txh_fudge += skipped << dn->dn_indblkshift; + (void) refcount_add_many(&txh->txh_fudge, + skipped << dn->dn_indblkshift, FTAG); skipped = MIN(skipped, DMU_MAX_DELETEBLKCNT >> epbs); - txh->txh_memory_tohold += skipped << dn->dn_indblkshift; + (void) refcount_add_many(&txh->txh_memory_tohold, + skipped << dn->dn_indblkshift, FTAG); } - txh->txh_space_tofree += space; - txh->txh_space_tounref += unref; + (void) refcount_add_many(&txh->txh_space_tofree, space, FTAG); + (void) refcount_add_many(&txh->txh_space_tounref, unref, FTAG); } /* @@ -617,7 +643,10 @@ dmu_tx_mark_netfree(dmu_tx_t *tx) * cause overflows when doing math with these values (e.g. in * dmu_tx_try_assign()). */ - txh->txh_space_tofree = txh->txh_space_tounref = 1024 * 1024 * 1024; + (void) refcount_add_many(&txh->txh_space_tofree, + 1024 * 1024 * 1024, FTAG); + (void) refcount_add_many(&txh->txh_space_tounref, + 1024 * 1024 * 1024, FTAG); } void @@ -717,9 +746,7 @@ dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, const char *name) { dmu_tx_hold_t *txh; dnode_t *dn; - dsl_dataset_phys_t *ds_phys; - uint64_t nblocks; - int epbs, err; + int err; ASSERT(tx->tx_txg == 0); @@ -762,12 +789,17 @@ dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, const char *name) */ bp = &dn->dn_phys->dn_blkptr[0]; if (dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset, - bp, bp->blk_birth)) - txh->txh_space_tooverwrite += MZAP_MAX_BLKSZ; - else - txh->txh_space_towrite += MZAP_MAX_BLKSZ; - if (!BP_IS_HOLE(bp)) - txh->txh_space_tounref += MZAP_MAX_BLKSZ; + bp, bp->blk_birth)) { + (void) refcount_add_many(&txh->txh_space_tooverwrite, + MZAP_MAX_BLKSZ, FTAG); + } else { + (void) refcount_add_many(&txh->txh_space_towrite, + MZAP_MAX_BLKSZ, FTAG); + } + if (!BP_IS_HOLE(bp)) { + (void) refcount_add_many(&txh->txh_space_tounref, + MZAP_MAX_BLKSZ, FTAG); + } return; } @@ -789,15 +821,29 @@ dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, const char *name) /* * If the modified blocks are scattered to the four winds, - * we'll have to modify an indirect twig for each. + * we'll have to modify an indirect twig for each. We can make + * modifications at up to 3 locations: + * - header block at the beginning of the object + * - target leaf block + * - end of the object, where we might need to write: + * - a new leaf block if the target block needs to be split + * - the new pointer table, if it is growing + * - the new cookie table, if it is growing */ - epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT; - ds_phys = dsl_dataset_phys(dn->dn_objset->os_dsl_dataset); - for (nblocks = dn->dn_maxblkid >> epbs; nblocks != 0; nblocks >>= epbs) - if (ds_phys->ds_prev_snap_obj) - txh->txh_space_towrite += 3 << dn->dn_indblkshift; - else - txh->txh_space_tooverwrite += 3 << dn->dn_indblkshift; + int epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT; + dsl_dataset_phys_t *ds_phys = + dsl_dataset_phys(dn->dn_objset->os_dsl_dataset); + for (int lvl = 1; lvl < dn->dn_nlevels; lvl++) { + uint64_t num_indirects = 1 + (dn->dn_maxblkid >> (epbs * lvl)); + uint64_t spc = MIN(3, num_indirects) << dn->dn_indblkshift; + if (ds_phys->ds_prev_snap_obj != 0) { + (void) refcount_add_many(&txh->txh_space_towrite, + spc, FTAG); + } else { + (void) refcount_add_many(&txh->txh_space_tooverwrite, + spc, FTAG); + } + } } void @@ -822,7 +868,7 @@ dmu_tx_hold_space(dmu_tx_t *tx, uint64_t space) txh = dmu_tx_hold_object_impl(tx, tx->tx_objset, DMU_NEW_OBJECT, THT_SPACE, space, 0); - txh->txh_space_towrite += space; + (void) refcount_add_many(&txh->txh_space_towrite, space, FTAG); } int @@ -1175,12 +1221,12 @@ dmu_tx_try_assign(dmu_tx_t *tx, txg_how_t txg_how) (void) refcount_add(&dn->dn_tx_holds, tx); mutex_exit(&dn->dn_mtx); } - towrite += txh->txh_space_towrite; - tofree += txh->txh_space_tofree; - tooverwrite += txh->txh_space_tooverwrite; - tounref += txh->txh_space_tounref; - tohold += txh->txh_memory_tohold; - fudge += txh->txh_fudge; + towrite += refcount_count(&txh->txh_space_towrite); + tofree += refcount_count(&txh->txh_space_tofree); + tooverwrite += refcount_count(&txh->txh_space_tooverwrite); + tounref += refcount_count(&txh->txh_space_tounref); + tohold += refcount_count(&txh->txh_memory_tohold); + fudge += refcount_count(&txh->txh_fudge); } /* @@ -1383,24 +1429,59 @@ dmu_tx_willuse_space(dmu_tx_t *tx, int64_t delta) #endif } -void -dmu_tx_commit(dmu_tx_t *tx) +static void +dmu_tx_destroy(dmu_tx_t *tx) { dmu_tx_hold_t *txh; + while ((txh = list_head(&tx->tx_holds)) != NULL) { + dnode_t *dn = txh->txh_dnode; + + list_remove(&tx->tx_holds, txh); + refcount_destroy_many(&txh->txh_space_towrite, + refcount_count(&txh->txh_space_towrite)); + refcount_destroy_many(&txh->txh_space_tofree, + refcount_count(&txh->txh_space_tofree)); + refcount_destroy_many(&txh->txh_space_tooverwrite, + refcount_count(&txh->txh_space_tooverwrite)); + refcount_destroy_many(&txh->txh_space_tounref, + refcount_count(&txh->txh_space_tounref)); + refcount_destroy_many(&txh->txh_memory_tohold, + refcount_count(&txh->txh_memory_tohold)); + refcount_destroy_many(&txh->txh_fudge, + refcount_count(&txh->txh_fudge)); + kmem_free(txh, sizeof (dmu_tx_hold_t)); + if (dn != NULL) + dnode_rele(dn, tx); + } + + list_destroy(&tx->tx_callbacks); + list_destroy(&tx->tx_holds); +#ifdef ZFS_DEBUG + refcount_destroy_many(&tx->tx_space_written, + refcount_count(&tx->tx_space_written)); + refcount_destroy_many(&tx->tx_space_freed, + refcount_count(&tx->tx_space_freed)); +#endif + kmem_free(tx, sizeof (dmu_tx_t)); +} + +void +dmu_tx_commit(dmu_tx_t *tx) +{ ASSERT(tx->tx_txg != 0); /* * Go through the transaction's hold list and remove holds on * associated dnodes, notifying waiters if no holds remain. */ - while (txh = list_head(&tx->tx_holds)) { + for (dmu_tx_hold_t *txh = list_head(&tx->tx_holds); txh != NULL; + txh = list_next(&tx->tx_holds, txh)) { dnode_t *dn = txh->txh_dnode; - list_remove(&tx->tx_holds, txh); - kmem_free(txh, sizeof (dmu_tx_hold_t)); if (dn == NULL) continue; + mutex_enter(&dn->dn_mtx); ASSERT3U(dn->dn_assigned_txg, ==, tx->tx_txg); @@ -1409,7 +1490,6 @@ dmu_tx_commit(dmu_tx_t *tx) cv_broadcast(&dn->dn_notxholds); } mutex_exit(&dn->dn_mtx); - dnode_rele(dn, tx); } if (tx->tx_tempreserve_cookie) @@ -1421,51 +1501,26 @@ dmu_tx_commit(dmu_tx_t *tx) if (tx->tx_anyobj == FALSE) txg_rele_to_sync(&tx->tx_txgh); - list_destroy(&tx->tx_callbacks); - list_destroy(&tx->tx_holds); #ifdef ZFS_DEBUG dprintf("towrite=%llu written=%llu tofree=%llu freed=%llu\n", tx->tx_space_towrite, refcount_count(&tx->tx_space_written), tx->tx_space_tofree, refcount_count(&tx->tx_space_freed)); - refcount_destroy_many(&tx->tx_space_written, - refcount_count(&tx->tx_space_written)); - refcount_destroy_many(&tx->tx_space_freed, - refcount_count(&tx->tx_space_freed)); #endif - kmem_free(tx, sizeof (dmu_tx_t)); + dmu_tx_destroy(tx); } void dmu_tx_abort(dmu_tx_t *tx) { - dmu_tx_hold_t *txh; - ASSERT(tx->tx_txg == 0); - while (txh = list_head(&tx->tx_holds)) { - dnode_t *dn = txh->txh_dnode; - - list_remove(&tx->tx_holds, txh); - kmem_free(txh, sizeof (dmu_tx_hold_t)); - if (dn != NULL) - dnode_rele(dn, tx); - } - /* * Call any registered callbacks with an error code. */ if (!list_is_empty(&tx->tx_callbacks)) dmu_tx_do_callbacks(&tx->tx_callbacks, ECANCELED); - list_destroy(&tx->tx_callbacks); - list_destroy(&tx->tx_holds); -#ifdef ZFS_DEBUG - refcount_destroy_many(&tx->tx_space_written, - refcount_count(&tx->tx_space_written)); - refcount_destroy_many(&tx->tx_space_freed, - refcount_count(&tx->tx_space_freed)); -#endif - kmem_free(tx, sizeof (dmu_tx_t)); + dmu_tx_destroy(tx); } uint64_t @@ -1504,7 +1559,7 @@ dmu_tx_do_callbacks(list_t *cb_list, int error) { dmu_tx_callback_t *dcb; - while (dcb = list_head(cb_list)) { + while ((dcb = list_head(cb_list)) != NULL) { list_remove(cb_list, dcb); dcb->dcb_func(dcb->dcb_data, error); kmem_free(dcb, sizeof (dmu_tx_callback_t)); @@ -1562,18 +1617,24 @@ dmu_tx_hold_spill(dmu_tx_t *tx, uint64_t object) /* If blkptr doesn't exist then add space to towrite */ if (!(dn->dn_phys->dn_flags & DNODE_FLAG_SPILL_BLKPTR)) { - txh->txh_space_towrite += SPA_OLD_MAXBLOCKSIZE; + (void) refcount_add_many(&txh->txh_space_towrite, + SPA_OLD_MAXBLOCKSIZE, FTAG); } else { blkptr_t *bp; bp = &dn->dn_phys->dn_spill; if (dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset, - bp, bp->blk_birth)) - txh->txh_space_tooverwrite += SPA_OLD_MAXBLOCKSIZE; - else - txh->txh_space_towrite += SPA_OLD_MAXBLOCKSIZE; - if (!BP_IS_HOLE(bp)) - txh->txh_space_tounref += SPA_OLD_MAXBLOCKSIZE; + bp, bp->blk_birth)) { + (void) refcount_add_many(&txh->txh_space_tooverwrite, + SPA_OLD_MAXBLOCKSIZE, FTAG); + } else { + (void) refcount_add_many(&txh->txh_space_towrite, + SPA_OLD_MAXBLOCKSIZE, FTAG); + } + if (!BP_IS_HOLE(bp)) { + (void) refcount_add_many(&txh->txh_space_tounref, + SPA_OLD_MAXBLOCKSIZE, FTAG); + } } } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c index bc08d1c..39d572c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c @@ -34,10 +34,10 @@ static int dsl_bookmark_hold_ds(dsl_pool_t *dp, const char *fullname, dsl_dataset_t **dsp, void *tag, char **shortnamep) { - char buf[MAXNAMELEN]; + char buf[ZFS_MAX_DATASET_NAME_LEN]; char *hashp; - if (strlen(fullname) >= MAXNAMELEN) + if (strlen(fullname) >= ZFS_MAX_DATASET_NAME_LEN) return (SET_ERROR(ENAMETOOLONG)); hashp = strchr(fullname, '#'); if (hashp == NULL) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c index 00b9c7e..8d97789 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c @@ -676,22 +676,37 @@ dsl_dataset_name(dsl_dataset_t *ds, char *name) dsl_dir_name(ds->ds_dir, name); VERIFY0(dsl_dataset_get_snapname(ds)); if (ds->ds_snapname[0]) { - (void) strcat(name, "@"); + VERIFY3U(strlcat(name, "@", ZFS_MAX_DATASET_NAME_LEN), + <, ZFS_MAX_DATASET_NAME_LEN); /* * We use a "recursive" mutex so that we * can call dprintf_ds() with ds_lock held. */ if (!MUTEX_HELD(&ds->ds_lock)) { mutex_enter(&ds->ds_lock); - (void) strcat(name, ds->ds_snapname); + VERIFY3U(strlcat(name, ds->ds_snapname, + ZFS_MAX_DATASET_NAME_LEN), <, + ZFS_MAX_DATASET_NAME_LEN); mutex_exit(&ds->ds_lock); } else { - (void) strcat(name, ds->ds_snapname); + VERIFY3U(strlcat(name, ds->ds_snapname, + ZFS_MAX_DATASET_NAME_LEN), <, + ZFS_MAX_DATASET_NAME_LEN); } } } } +int +dsl_dataset_namelen(dsl_dataset_t *ds) +{ + VERIFY0(dsl_dataset_get_snapname(ds)); + mutex_enter(&ds->ds_lock); + int len = dsl_dir_namelen(ds->ds_dir) + 1 + strlen(ds->ds_snapname); + mutex_exit(&ds->ds_lock); + return (len); +} + void dsl_dataset_rele(dsl_dataset_t *ds, void *tag) { @@ -1296,10 +1311,10 @@ dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx) int error = 0; dsl_dataset_t *ds; char *name, *atp; - char dsname[MAXNAMELEN]; + char dsname[ZFS_MAX_DATASET_NAME_LEN]; name = nvpair_name(pair); - if (strlen(name) >= MAXNAMELEN) + if (strlen(name) >= ZFS_MAX_DATASET_NAME_LEN) error = SET_ERROR(ENAMETOOLONG); if (error == 0) { atp = strchr(name, '@'); @@ -1474,7 +1489,7 @@ dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx) pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) { dsl_dataset_t *ds; char *name, *atp; - char dsname[MAXNAMELEN]; + char dsname[ZFS_MAX_DATASET_NAME_LEN]; name = nvpair_name(pair); atp = strchr(name, '@'); @@ -1520,7 +1535,7 @@ dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors) suspended = fnvlist_alloc(); for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL; pair = nvlist_next_nvpair(snaps, pair)) { - char fsname[MAXNAMELEN]; + char fsname[ZFS_MAX_DATASET_NAME_LEN]; char *snapname = nvpair_name(pair); char *atp; void *cookie; @@ -1738,7 +1753,7 @@ get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv) zap_cursor_retrieve(&zc, &za) == 0; zap_cursor_advance(&zc)) { dsl_dataset_t *clone; - char buf[ZFS_MAXNAMELEN]; + char buf[ZFS_MAX_DATASET_NAME_LEN]; VERIFY0(dsl_dataset_hold_obj(ds->ds_dir->dd_pool, za.za_first_integer, FTAG, &clone)); dsl_dir_name(clone->ds_dir, buf); @@ -1846,7 +1861,7 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv) get_clones_stat(ds, nv); } else { if (ds->ds_prev != NULL && ds->ds_prev != dp->dp_origin_snap) { - char buf[MAXNAMELEN]; + char buf[ZFS_MAX_DATASET_NAME_LEN]; dsl_dataset_name(ds->ds_prev, buf); dsl_prop_nvlist_add_string(nv, ZFS_PROP_PREV_SNAP, buf); } @@ -1907,12 +1922,15 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv) * stats set on our child named "%recv". Check the child * for the prop. */ - char recvname[ZFS_MAXNAMELEN]; + /* 6 extra bytes for /%recv */ + char recvname[ZFS_MAX_DATASET_NAME_LEN + 6]; dsl_dataset_t *recv_ds; dsl_dataset_name(ds, recvname); - (void) strcat(recvname, "/"); - (void) strcat(recvname, recv_clone_name); - if (dsl_dataset_hold(dp, recvname, FTAG, &recv_ds) == 0) { + if (strlcat(recvname, "/", sizeof (recvname)) < + sizeof (recvname) && + strlcat(recvname, recv_clone_name, sizeof (recvname)) < + sizeof (recvname) && + dsl_dataset_hold(dp, recvname, FTAG, &recv_ds) == 0) { get_receive_resume_stats(recv_ds, nv); dsl_dataset_rele(recv_ds, FTAG); } @@ -2039,7 +2057,7 @@ dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp, /* dataset name + 1 for the "@" + the new snapshot name must fit */ if (dsl_dir_namelen(hds->ds_dir) + 1 + - strlen(ddrsa->ddrsa_newsnapname) >= MAXNAMELEN) + strlen(ddrsa->ddrsa_newsnapname) >= ZFS_MAX_DATASET_NAME_LEN) error = SET_ERROR(ENAMETOOLONG); return (error); @@ -2287,7 +2305,7 @@ dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx) dsl_pool_t *dp = dmu_tx_pool(tx); dsl_dataset_t *ds, *clone; uint64_t cloneobj; - char namebuf[ZFS_MAXNAMELEN]; + char namebuf[ZFS_MAX_DATASET_NAME_LEN]; VERIFY0(dsl_dataset_hold(dp, ddra->ddra_fsname, FTAG, &ds)); @@ -2863,7 +2881,7 @@ promote_rele(dsl_dataset_promote_arg_t *ddpa, void *tag) * Promote a clone. * * If it fails due to a conflicting snapshot name, "conflsnap" will be filled - * in with the name. (It must be at least MAXNAMELEN bytes long.) + * in with the name. (It must be at least ZFS_MAX_DATASET_NAME_LEN bytes long.) */ int dsl_dataset_promote(const char *name, char *conflsnap) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c index 9e9c19d..7870b49 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2015 by Delphix. All rights reserved. */ /* @@ -330,7 +330,7 @@ dsl_deleg_get(const char *ddname, nvlist_t **nvp) zap_attribute_t baseza; nvlist_t *sp_nvp; uint64_t n; - char source[MAXNAMELEN]; + char source[ZFS_MAX_DATASET_NAME_LEN]; if (dsl_dir_phys(dd)->dd_deleg_zapobj == 0 || zap_count(mos, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c index 00341ad..224575e 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c @@ -303,13 +303,14 @@ dsl_dir_async_rele(dsl_dir_t *dd, void *tag) dmu_buf_rele(dd->dd_dbuf, tag); } -/* buf must be long enough (MAXNAMELEN + strlen(MOS_DIR_NAME) + 1 should do) */ +/* buf must be at least ZFS_MAX_DATASET_NAME_LEN bytes */ void dsl_dir_name(dsl_dir_t *dd, char *buf) { if (dd->dd_parent) { dsl_dir_name(dd->dd_parent, buf); - (void) strcat(buf, "/"); + VERIFY3U(strlcat(buf, "/", ZFS_MAX_DATASET_NAME_LEN), <, + ZFS_MAX_DATASET_NAME_LEN); } else { buf[0] = '\0'; } @@ -319,10 +320,12 @@ dsl_dir_name(dsl_dir_t *dd, char *buf) * dprintf_dd() with dd_lock held */ mutex_enter(&dd->dd_lock); - (void) strcat(buf, dd->dd_myname); + VERIFY3U(strlcat(buf, dd->dd_myname, ZFS_MAX_DATASET_NAME_LEN), + <, ZFS_MAX_DATASET_NAME_LEN); mutex_exit(&dd->dd_lock); } else { - (void) strcat(buf, dd->dd_myname); + VERIFY3U(strlcat(buf, dd->dd_myname, ZFS_MAX_DATASET_NAME_LEN), + <, ZFS_MAX_DATASET_NAME_LEN); } } @@ -371,12 +374,12 @@ getcomponent(const char *path, char *component, const char **nextp) if (p != NULL && (p[0] != '@' || strpbrk(path+1, "/@") || p[1] == '\0')) return (SET_ERROR(EINVAL)); - if (strlen(path) >= MAXNAMELEN) + if (strlen(path) >= ZFS_MAX_DATASET_NAME_LEN) return (SET_ERROR(ENAMETOOLONG)); (void) strcpy(component, path); p = NULL; } else if (p[0] == '/') { - if (p - path >= MAXNAMELEN) + if (p - path >= ZFS_MAX_DATASET_NAME_LEN) return (SET_ERROR(ENAMETOOLONG)); (void) strncpy(component, path, p - path); component[p - path] = '\0'; @@ -388,7 +391,7 @@ getcomponent(const char *path, char *component, const char **nextp) */ if (strchr(path, '/')) return (SET_ERROR(EINVAL)); - if (p - path >= MAXNAMELEN) + if (p - path >= ZFS_MAX_DATASET_NAME_LEN) return (SET_ERROR(ENAMETOOLONG)); (void) strncpy(component, path, p - path); component[p - path] = '\0'; @@ -410,7 +413,7 @@ int dsl_dir_hold(dsl_pool_t *dp, const char *name, void *tag, dsl_dir_t **ddp, const char **tailp) { - char buf[MAXNAMELEN]; + char buf[ZFS_MAX_DATASET_NAME_LEN]; const char *spaname, *next, *nextnext = NULL; int err; dsl_dir_t *dd; @@ -977,7 +980,7 @@ dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv) if (dsl_dir_is_clone(dd)) { dsl_dataset_t *ds; - char buf[MAXNAMELEN]; + char buf[ZFS_MAX_DATASET_NAME_LEN]; VERIFY0(dsl_dataset_hold_obj(dd->dd_pool, dsl_dir_phys(dd)->dd_origin_obj, FTAG, &ds)); @@ -1685,11 +1688,11 @@ static int dsl_valid_rename(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg) { int *deltap = arg; - char namebuf[MAXNAMELEN]; + char namebuf[ZFS_MAX_DATASET_NAME_LEN]; dsl_dataset_name(ds, namebuf); - if (strlen(namebuf) + *deltap >= MAXNAMELEN) + if (strlen(namebuf) + *deltap >= ZFS_MAX_DATASET_NAME_LEN) return (SET_ERROR(ENAMETOOLONG)); return (0); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c index 25a7d96..f57a511 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright 2015, Joyent, Inc. */ @@ -1059,7 +1059,7 @@ dsl_prop_get_all_ds(dsl_dataset_t *ds, nvlist_t **nvp, dsl_pool_t *dp = dd->dd_pool; objset_t *mos = dp->dp_meta_objset; int err = 0; - char setpoint[MAXNAMELEN]; + char setpoint[ZFS_MAX_DATASET_NAME_LEN]; VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c index f6408c8..89c8eba 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c @@ -1115,7 +1115,7 @@ dsl_scan_visitds(dsl_scan_t *scn, uint64_t dsobj, dmu_tx_t *tx) dmu_buf_will_dirty(ds->ds_dbuf, tx); dsl_scan_visit_rootbp(scn, ds, &dsl_dataset_phys(ds)->ds_bp, tx); - char *dsname = kmem_alloc(ZFS_MAXNAMELEN, KM_SLEEP); + char *dsname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP); dsl_dataset_name(ds, dsname); zfs_dbgmsg("scanned dataset %llu (%s) with min=%llu max=%llu; " "pausing=%u", @@ -1123,7 +1123,7 @@ dsl_scan_visitds(dsl_scan_t *scn, uint64_t dsobj, dmu_tx_t *tx) (longlong_t)scn->scn_phys.scn_cur_min_txg, (longlong_t)scn->scn_phys.scn_cur_max_txg, (int)scn->scn_pausing); - kmem_free(dsname, ZFS_MAXNAMELEN); + kmem_free(dsname, ZFS_MAX_DATASET_NAME_LEN); if (scn->scn_pausing) goto out; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c index a67db5f..54a15e1 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright (c) 2013 Steven Hartland. All rights reserved. */ @@ -180,7 +180,7 @@ dsl_dataset_user_hold_sync_one_impl(nvlist_t *tmpholds, dsl_dataset_t *ds, } typedef struct zfs_hold_cleanup_arg { - char zhca_spaname[MAXNAMELEN]; + char zhca_spaname[ZFS_MAX_DATASET_NAME_LEN]; uint64_t zhca_spa_load_guid; nvlist_t *zhca_holds; } zfs_hold_cleanup_arg_t; @@ -574,7 +574,7 @@ dsl_dataset_user_release_impl(nvlist_t *holds, nvlist_t *errlist, error = dsl_dataset_hold_obj_string(tmpdp, nvpair_name(pair), FTAG, &ds); if (error == 0) { - char name[MAXNAMELEN]; + char name[ZFS_MAX_DATASET_NAME_LEN]; dsl_dataset_name(ds, name); dsl_pool_config_exit(tmpdp, FTAG); dsl_dataset_rele(ds, FTAG); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c index 173c949..0258747 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -151,6 +151,8 @@ const zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = { { ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* IOCTL */ }; +static sysevent_t *spa_event_create(spa_t *spa, vdev_t *vd, const char *name); +static void spa_event_post(sysevent_t *ev); static void spa_sync_version(void *arg, dmu_tx_t *tx); static void spa_sync_props(void *arg, dmu_tx_t *tx); static boolean_t spa_has_active_shared_spare(spa_t *spa); @@ -370,8 +372,7 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp) break; } - strval = kmem_alloc( - MAXNAMELEN + strlen(MOS_DIR_NAME) + 1, + strval = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP); dsl_dataset_name(ds, strval); dsl_dataset_rele(ds, FTAG); @@ -384,8 +385,7 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp) spa_prop_add_list(*nvp, prop, strval, intval, src); if (strval != NULL) - kmem_free(strval, - MAXNAMELEN + strlen(MOS_DIR_NAME) + 1); + kmem_free(strval, ZFS_MAX_DATASET_NAME_LEN); break; @@ -1996,6 +1996,16 @@ spa_load_verify_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, return (0); } +/* ARGSUSED */ +int +verify_dataset_name_len(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg) +{ + if (dsl_dataset_namelen(ds) >= ZFS_MAX_DATASET_NAME_LEN) + return (SET_ERROR(ENAMETOOLONG)); + + return (0); +} + static int spa_load_verify(spa_t *spa) { @@ -2010,6 +2020,14 @@ spa_load_verify(spa_t *spa) if (policy.zrp_request & ZPOOL_NEVER_REWIND) return (0); + dsl_pool_config_enter(spa->spa_dsl_pool, FTAG); + error = dmu_objset_find_dp(spa->spa_dsl_pool, + spa->spa_dsl_pool->dp_root_dir_obj, verify_dataset_name_len, NULL, + DS_FIND_CHILDREN); + dsl_pool_config_exit(spa->spa_dsl_pool, FTAG); + if (error != 0) + return (error); + rio = zio_root(spa, NULL, &sle, ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE); @@ -5722,6 +5740,7 @@ int spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) { vdev_t *vd; + sysevent_t *ev = NULL; metaslab_group_t *mg; nvlist_t **spares, **l2cache, *nv; uint64_t txg = 0; @@ -5745,6 +5764,9 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) * in this pool. */ if (vd == NULL || unspare) { + if (vd == NULL) + vd = spa_lookup_by_guid(spa, guid, B_TRUE); + ev = spa_event_create(spa, vd, ESC_ZFS_VDEV_REMOVE_AUX); spa_vdev_remove_aux(spa->spa_spares.sav_config, ZPOOL_CONFIG_SPARES, spares, nspares, nv); spa_load_spares(spa); @@ -5759,6 +5781,8 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) /* * Cache devices can always be removed. */ + vd = spa_lookup_by_guid(spa, guid, B_TRUE); + ev = spa_event_create(spa, vd, ESC_ZFS_VDEV_REMOVE_AUX); spa_vdev_remove_aux(spa->spa_l2cache.sav_config, ZPOOL_CONFIG_L2CACHE, l2cache, nl2cache, nv); spa_load_l2cache(spa); @@ -5799,6 +5823,7 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) /* * Clean up the vdev namespace. */ + ev = spa_event_create(spa, vd, ESC_ZFS_VDEV_REMOVE_DEV); spa_vdev_remove_from_namespace(spa, vd); } else if (vd != NULL) { @@ -5814,7 +5839,10 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) } if (!locked) - return (spa_vdev_exit(spa, NULL, txg, error)); + error = spa_vdev_exit(spa, NULL, txg, error); + + if (ev) + spa_event_post(ev); return (error); } @@ -7210,24 +7238,17 @@ spa_has_active_shared_spare(spa_t *spa) return (B_FALSE); } -/* - * Post a sysevent corresponding to the given event. The 'name' must be one of - * the event definitions in sys/sysevent/eventdefs.h. The payload will be - * filled in from the spa and (optionally) the vdev. This doesn't do anything - * in the userland libzpool, as we don't want consumers to misinterpret ztest - * or zdb as real changes. - */ -void -spa_event_notify(spa_t *spa, vdev_t *vd, const char *name) +static sysevent_t * +spa_event_create(spa_t *spa, vdev_t *vd, const char *name) { + sysevent_t *ev = NULL; #ifdef _KERNEL - sysevent_t *ev; sysevent_attr_list_t *attr = NULL; sysevent_value_t value; - sysevent_id_t eid; ev = sysevent_alloc(EC_ZFS, (char *)name, SUNW_KERN_PUB "zfs", SE_SLEEP); + ASSERT(ev != NULL); value.value_type = SE_DATA_TYPE_STRING; value.value.sv_string = spa_name(spa); @@ -7259,11 +7280,34 @@ spa_event_notify(spa_t *spa, vdev_t *vd, const char *name) goto done; attr = NULL; - (void) log_sysevent(ev, SE_SLEEP, &eid); - done: if (attr) sysevent_free_attr(attr); + +#endif + return (ev); +} + +static void +spa_event_post(sysevent_t *ev) +{ +#ifdef _KERNEL + sysevent_id_t eid; + + (void) log_sysevent(ev, SE_SLEEP, &eid); sysevent_free(ev); #endif } + +/* + * Post a sysevent corresponding to the given event. The 'name' must be one of + * the event definitions in sys/sysevent/eventdefs.h. The payload will be + * filled in from the spa and (optionally) the vdev. This doesn't do anything + * in the userland libzpool, as we don't want consumers to misinterpret ztest + * or zdb as real changes. + */ +void +spa_event_notify(spa_t *spa, vdev_t *vd, const char *name) +{ + spa_event_post(spa_event_create(spa, vd, name)); +} 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 8965686..02147b4 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, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -501,7 +501,7 @@ 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]; + char namebuf[ZFS_MAX_DATASET_NAME_LEN]; nvlist_t *nvl = fnvlist_alloc(); ASSERT(tx != NULL); @@ -520,7 +520,7 @@ 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]; + char namebuf[ZFS_MAX_DATASET_NAME_LEN]; nvlist_t *nvl = fnvlist_alloc(); ASSERT(tx != NULL); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c index 63350b3..3d00c9f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c @@ -411,12 +411,20 @@ zfs_deadman_init() * it is possible to run the pool completely out of space, causing it to * be permanently read-only. * + * Note that on very small pools, the slop space will be larger than + * 3.2%, in an effort to have it be at least spa_min_slop (128MB), + * but we never allow it to be more than half the pool size. + * * See also the comments in zfs_space_check_t. */ int spa_slop_shift = 5; SYSCTL_INT(_vfs_zfs, OID_AUTO, spa_slop_shift, CTLFLAG_RWTUN, &spa_slop_shift, 0, "Shift value of reserved space (1/(2^spa_slop_shift))."); +uint64_t spa_min_slop = 128 * 1024 * 1024; +SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, spa_min_slop, CTLFLAG_RWTUN, + &spa_min_slop, 0, + "Minimal value of reserved space"); /* * ========================================================================== @@ -1723,14 +1731,16 @@ spa_get_asize(spa_t *spa, uint64_t lsize) /* * Return the amount of slop space in bytes. It is 1/32 of the pool (3.2%), - * or at least 32MB. + * or at least 128MB, unless that would cause it to be more than half the + * pool size. * * See the comment above spa_slop_shift for details. */ uint64_t -spa_get_slop_space(spa_t *spa) { +spa_get_slop_space(spa_t *spa) +{ uint64_t space = spa_get_dspace(spa); - return (MAX(space >> spa_slop_shift, SPA_MINDEVSIZE >> 1)); + return (MAX(space >> spa_slop_shift, MIN(space >> 1, spa_min_slop))); } uint64_t diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h index 8a8f29c..6452828 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h @@ -816,7 +816,7 @@ typedef struct dmu_objset_stats { dmu_objset_type_t dds_type; uint8_t dds_is_snapshot; uint8_t dds_inconsistent; - char dds_origin[MAXNAMELEN]; + char dds_origin[ZFS_MAX_DATASET_NAME_LEN]; } dmu_objset_stats_t; /* diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_tx.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_tx.h index fa99f98..0954e02 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_tx.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_tx.h @@ -23,7 +23,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. */ #ifndef _SYS_DMU_TX_H @@ -101,12 +101,12 @@ typedef struct dmu_tx_hold { dmu_tx_t *txh_tx; list_node_t txh_node; struct dnode *txh_dnode; - uint64_t txh_space_towrite; - uint64_t txh_space_tofree; - uint64_t txh_space_tooverwrite; - uint64_t txh_space_tounref; - uint64_t txh_memory_tohold; - uint64_t txh_fudge; + refcount_t txh_space_towrite; + refcount_t txh_space_tofree; + refcount_t txh_space_tooverwrite; + refcount_t txh_space_tounref; + refcount_t txh_memory_tohold; + refcount_t txh_fudge; #ifdef ZFS_DEBUG enum dmu_tx_hold_type txh_type; uint64_t txh_arg1; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h index dfa3e57..98780b2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h @@ -58,7 +58,7 @@ extern "C" { */ #define DNODE_SHIFT 9 /* 512 bytes */ #define DN_MIN_INDBLKSHIFT 12 /* 4k */ -#define DN_MAX_INDBLKSHIFT 14 /* 16k */ +#define DN_MAX_INDBLKSHIFT 17 /* 128k */ #define DNODE_BLOCK_SHIFT 14 /* 16k */ #define DNODE_CORE_SIZE 64 /* 64 bytes for dnode sans blkptrs */ #define DN_MAX_OBJECT_SHIFT 48 /* 256 trillion (zfs_fid_t limit) */ @@ -88,6 +88,11 @@ extern "C" { #define DNODES_PER_BLOCK_SHIFT (DNODE_BLOCK_SHIFT - DNODE_SHIFT) #define DNODES_PER_BLOCK (1ULL << DNODES_PER_BLOCK_SHIFT) + +/* + * This is inaccurate if the indblkshift of the particular object is not the + * max. But it's only used by userland to calculate the zvol reservation. + */ #define DNODES_PER_LEVEL_SHIFT (DN_MAX_INDBLKSHIFT - SPA_BLKPTRSHIFT) #define DNODES_PER_LEVEL (1ULL << DNODES_PER_LEVEL_SHIFT) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h index 766ae3c..17d15d7 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h @@ -221,7 +221,7 @@ typedef struct dsl_dataset { uint8_t ds_feature_activation_needed[SPA_FEATURES]; /* Protected by ds_lock; keep at end of struct for better locality */ - char ds_snapname[MAXNAMELEN]; + char ds_snapname[ZFS_MAX_DATASET_NAME_LEN]; } dsl_dataset_t; inline dsl_dataset_phys_t * @@ -256,6 +256,7 @@ int dsl_dataset_own_obj(struct dsl_pool *dp, uint64_t dsobj, void dsl_dataset_disown(dsl_dataset_t *ds, void *tag); void dsl_dataset_name(dsl_dataset_t *ds, char *name); boolean_t dsl_dataset_tryown(dsl_dataset_t *ds, void *tag); +int dsl_dataset_namelen(dsl_dataset_t *ds); boolean_t dsl_dataset_has_owner(dsl_dataset_t *ds); uint64_t dsl_dataset_create_sync(dsl_dir_t *pds, const char *lastname, dsl_dataset_t *origin, uint64_t flags, cred_t *, dmu_tx_t *); @@ -347,10 +348,10 @@ void dsl_dataset_deactivate_feature(uint64_t dsobj, #ifdef ZFS_DEBUG #define dprintf_ds(ds, fmt, ...) do { \ if (zfs_flags & ZFS_DEBUG_DPRINTF) { \ - char *__ds_name = kmem_alloc(MAXNAMELEN, KM_SLEEP); \ + char *__ds_name = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP); \ dsl_dataset_name(ds, __ds_name); \ dprintf("ds=%s " fmt, __ds_name, __VA_ARGS__); \ - kmem_free(__ds_name, MAXNAMELEN); \ + kmem_free(__ds_name, ZFS_MAX_DATASET_NAME_LEN); \ } \ _NOTE(CONSTCOND) } while (0) #else diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h index 93fb73f..ab2d740 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h @@ -112,7 +112,7 @@ struct dsl_dir { int64_t dd_space_towrite[TXG_SIZE]; /* protected by dd_lock; keep at end of struct for better locality */ - char dd_myname[MAXNAMELEN]; + char dd_myname[ZFS_MAX_DATASET_NAME_LEN]; }; inline dsl_dir_phys_t * @@ -176,11 +176,10 @@ boolean_t dsl_dir_is_zapified(dsl_dir_t *dd); #ifdef ZFS_DEBUG #define dprintf_dd(dd, fmt, ...) do { \ if (zfs_flags & ZFS_DEBUG_DPRINTF) { \ - char *__ds_name = kmem_alloc(MAXNAMELEN + strlen(MOS_DIR_NAME) + 1, \ - KM_SLEEP); \ + char *__ds_name = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP); \ dsl_dir_name(dd, __ds_name); \ dprintf("dd=%s " fmt, __ds_name, __VA_ARGS__); \ - kmem_free(__ds_name, MAXNAMELEN + strlen(MOS_DIR_NAME) + 1); \ + kmem_free(__ds_name, ZFS_MAX_DATASET_NAME_LEN); \ } \ _NOTE(CONSTCOND) } while (0) #else diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h index 0a25b6c..0e24c56 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h @@ -127,7 +127,7 @@ struct spa { /* * Fields protected by spa_namespace_lock. */ - char spa_name[MAXNAMELEN]; /* pool name */ + char spa_name[ZFS_MAX_DATASET_NAME_LEN]; /* pool name */ char *spa_comment; /* comment */ avl_node_t spa_avl; /* node in spa_namespace_avl */ nvlist_t *spa_config; /* last synced config */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h index fbd5130..2f5ce88 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. */ #ifndef _SYS_ZAP_H @@ -80,6 +80,7 @@ */ #include <sys/dmu.h> +#include <sys/refcount.h> #ifdef __cplusplus extern "C" { @@ -217,7 +218,7 @@ int zap_prefetch_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, int key_numints); int zap_count_write(objset_t *os, uint64_t zapobj, const char *name, - int add, uint64_t *towrite, uint64_t *tooverwrite); + int add, refcount_t *towrite, refcount_t *tooverwrite); /* * Create an attribute with the given name and value. @@ -343,7 +344,7 @@ typedef struct { boolean_t za_normalization_conflict; uint64_t za_num_integers; uint64_t za_first_integer; /* no sign extension for <8byte ints */ - char za_name[MAXNAMELEN]; + char za_name[ZAP_MAXNAMELEN]; } zap_attribute_t; /* diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_impl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_impl.h index 6af259f..99123a6 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_impl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_impl.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015 by Delphix. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -213,8 +214,8 @@ int fzap_lookup(zap_name_t *zn, uint64_t integer_size, uint64_t num_integers, void *buf, char *realname, int rn_len, boolean_t *normalization_conflictp); void fzap_prefetch(zap_name_t *zn); -int fzap_count_write(zap_name_t *zn, int add, uint64_t *towrite, - uint64_t *tooverwrite); +int fzap_count_write(zap_name_t *zn, int add, refcount_t *towrite, + refcount_t *tooverwrite); int fzap_add(zap_name_t *zn, uint64_t integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx); int fzap_update(zap_name_t *zn, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h index f42df17..0cbef1d 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved. * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright 2016 RackTop Systems. * Copyright (c) 2014 Integros [integros.com] @@ -352,6 +353,12 @@ typedef enum zfs_case { ZFS_CASE_MIXED } zfs_case_t; +/* + * Note: this struct must have the same layout in 32-bit and 64-bit, so + * that 32-bit processes (like /sbin/zfs) can pass it to the 64-bit + * kernel. Therefore, we add padding to it so that no "hidden" padding + * is automatically added on 64-bit (but not on 32-bit). + */ typedef struct zfs_cmd { char zc_name[MAXPATHLEN]; /* name of pool or dataset */ uint64_t zc_nvlist_src; /* really (char *) */ @@ -388,7 +395,9 @@ typedef struct zfs_cmd { uint64_t zc_action_handle; int zc_cleanup_fd; uint8_t zc_simple; + uint8_t zc_pad3[3]; boolean_t zc_resumable; + uint32_t zc_pad4; uint64_t zc_sendobj; uint64_t zc_fromobj; uint64_t zc_createtxg; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h index 7649295..79728c1 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -135,17 +135,6 @@ extern "C" { #define ZFS_SA_ATTRS "SA_ATTRS" /* - * Path component length - * - * The generic fs code uses MAXNAMELEN to represent - * what the largest component length is. Unfortunately, - * this length includes the terminating NULL. ZFS needs - * to tell the users via pathconf() and statvfs() what the - * true maximum length of a component is, excluding the NULL. - */ -#define ZFS_MAXNAMELEN (MAXNAMELEN - 1) - -/* * Convert mode bits (zp_mode) to BSD-style DT_* values for storing in * the directory entries. */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c index 717368c..f36b191 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c @@ -1342,8 +1342,8 @@ fzap_get_stats(zap_t *zap, zap_stats_t *zs) } int -fzap_count_write(zap_name_t *zn, int add, uint64_t *towrite, - uint64_t *tooverwrite) +fzap_count_write(zap_name_t *zn, int add, refcount_t *towrite, + refcount_t *tooverwrite) { zap_t *zap = zn->zn_zap; zap_leaf_t *l; @@ -1353,9 +1353,11 @@ fzap_count_write(zap_name_t *zn, int add, uint64_t *towrite, * Account for the header block of the fatzap. */ if (!add && dmu_buf_freeable(zap->zap_dbuf)) { - *tooverwrite += zap->zap_dbuf->db_size; + (void) refcount_add_many(tooverwrite, + zap->zap_dbuf->db_size, FTAG); } else { - *towrite += zap->zap_dbuf->db_size; + (void) refcount_add_many(towrite, + zap->zap_dbuf->db_size, FTAG); } /* @@ -1367,10 +1369,13 @@ fzap_count_write(zap_name_t *zn, int add, uint64_t *towrite, * could extend the table. */ if (add) { - if (zap_f_phys(zap)->zap_ptrtbl.zt_blk == 0) - *towrite += zap->zap_dbuf->db_size; - else - *towrite += (zap->zap_dbuf->db_size * 3); + if (zap_f_phys(zap)->zap_ptrtbl.zt_blk == 0) { + (void) refcount_add_many(towrite, + zap->zap_dbuf->db_size, FTAG); + } else { + (void) refcount_add_many(towrite, + zap->zap_dbuf->db_size * 3, FTAG); + } } /* @@ -1383,13 +1388,14 @@ fzap_count_write(zap_name_t *zn, int add, uint64_t *towrite, } if (!add && dmu_buf_freeable(l->l_dbuf)) { - *tooverwrite += l->l_dbuf->db_size; + (void) refcount_add_many(tooverwrite, l->l_dbuf->db_size, FTAG); } else { /* * If this an add operation, the leaf block could split. * Hence, we need to account for an additional leaf block. */ - *towrite += (add ? 2 : 1) * l->l_dbuf->db_size; + (void) refcount_add_many(towrite, + (add ? 2 : 1) * l->l_dbuf->db_size, FTAG); } zap_put_leaf(l); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c index 8461b2a..b8a04be 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -1414,7 +1414,7 @@ zap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs) int zap_count_write(objset_t *os, uint64_t zapobj, const char *name, int add, - uint64_t *towrite, uint64_t *tooverwrite) + refcount_t *towrite, refcount_t *tooverwrite) { zap_t *zap; int err = 0; @@ -1424,14 +1424,15 @@ zap_count_write(objset_t *os, uint64_t zapobj, const char *name, int add, * be affected in this operation. So, account for the worst case : * - 3 blocks overwritten: target leaf, ptrtbl block, header block * - 4 new blocks written if adding: - * - 2 blocks for possibly split leaves, - * - 2 grown ptrtbl blocks + * - 2 blocks for possibly split leaves, + * - 2 grown ptrtbl blocks * * This also accomodates the case where an add operation to a fairly * large microzap results in a promotion to fatzap. */ if (name == NULL) { - *towrite += (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE; + (void) refcount_add_many(towrite, + (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE, FTAG); return (err); } @@ -1455,7 +1456,8 @@ zap_count_write(objset_t *os, uint64_t zapobj, const char *name, int add, /* * We treat this case as similar to (name == NULL) */ - *towrite += (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE; + (void) refcount_add_many(towrite, + (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE, FTAG); } } else { /* @@ -1473,13 +1475,17 @@ zap_count_write(objset_t *os, uint64_t zapobj, const char *name, int add, * 4 new blocks written : 2 new split leaf, 2 grown * ptrtbl blocks */ - if (dmu_buf_freeable(zap->zap_dbuf)) - *tooverwrite += MZAP_MAX_BLKSZ; - else - *towrite += MZAP_MAX_BLKSZ; + if (dmu_buf_freeable(zap->zap_dbuf)) { + (void) refcount_add_many(tooverwrite, + MZAP_MAX_BLKSZ, FTAG); + } else { + (void) refcount_add_many(towrite, + MZAP_MAX_BLKSZ, FTAG); + } if (add) { - *towrite += 4 * MZAP_MAX_BLKSZ; + (void) refcount_add_many(towrite, + 4 * MZAP_MAX_BLKSZ, FTAG); } } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c index cbafa03..9eaa7d2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. */ @@ -787,8 +787,8 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, zfs_snapentry_t search, *sep; zfsvfs_t *zfsvfs; avl_index_t where; - char from[MAXNAMELEN], to[MAXNAMELEN]; - char real[MAXNAMELEN], fsname[MAXNAMELEN]; + char from[ZFS_MAX_DATASET_NAME_LEN], to[ZFS_MAX_DATASET_NAME_LEN]; + char real[ZFS_MAX_DATASET_NAME_LEN], fsname[ZFS_MAX_DATASET_NAME_LEN]; int err; zfsvfs = sdvp->v_vfsp->vfs_data; @@ -796,7 +796,7 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, if ((flags & FIGNORECASE) || zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { err = dmu_snapshot_realname(zfsvfs->z_os, snm, real, - MAXNAMELEN, NULL); + sizeof (real), NULL); if (err == 0) { snm = real; } else if (err != ENOTSUP) { @@ -809,9 +809,9 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, dmu_objset_name(zfsvfs->z_os, fsname); - err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from); + err = zfsctl_snapshot_zname(sdvp, snm, sizeof (from), from); if (err == 0) - err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to); + err = zfsctl_snapshot_zname(tdvp, tnm, sizeof (to), to); if (err == 0) err = zfs_secpolicy_rename_perms(from, to, cr); if (err != 0) @@ -854,8 +854,8 @@ zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr, zfs_snapentry_t *sep; zfs_snapentry_t search; zfsvfs_t *zfsvfs; - char snapname[MAXNAMELEN]; - char real[MAXNAMELEN]; + char snapname[ZFS_MAX_DATASET_NAME_LEN]; + char real[ZFS_MAX_DATASET_NAME_LEN]; int err; zfsvfs = dvp->v_vfsp->vfs_data; @@ -864,7 +864,7 @@ zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr, if ((flags & FIGNORECASE) || zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { err = dmu_snapshot_realname(zfsvfs->z_os, name, real, - MAXNAMELEN, NULL); + sizeof (real), NULL); if (err == 0) { name = real; } else if (err != ENOTSUP) { @@ -875,7 +875,7 @@ zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr, ZFS_EXIT(zfsvfs); - err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname); + err = zfsctl_snapshot_zname(dvp, name, sizeof (snapname), snapname); if (err == 0) err = zfs_secpolicy_destroy_perms(snapname, cr); if (err != 0) @@ -911,7 +911,7 @@ zfsctl_snapdir_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr, caller_context_t *cc, int flags, vsecattr_t *vsecp) { zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; - char name[MAXNAMELEN]; + char name[ZFS_MAX_DATASET_NAME_LEN]; int err; static enum symfollow follow = NO_FOLLOW; static enum uio_seg seg = UIO_SYSSPACE; @@ -973,8 +973,8 @@ zfsctl_snapdir_lookup(ap) char nm[NAME_MAX + 1]; zfsctl_snapdir_t *sdp = dvp->v_data; objset_t *snap; - char snapname[MAXNAMELEN]; - char real[MAXNAMELEN]; + char snapname[ZFS_MAX_DATASET_NAME_LEN]; + char real[ZFS_MAX_DATASET_NAME_LEN]; char *mountpoint; zfs_snapentry_t *sep, search; size_t mountpoint_len; @@ -1019,7 +1019,7 @@ zfsctl_snapdir_lookup(ap) boolean_t conflict = B_FALSE; err = dmu_snapshot_realname(zfsvfs->z_os, nm, real, - MAXNAMELEN, &conflict); + sizeof (real), &conflict); if (err == 0) { strlcpy(nm, real, sizeof(nm)); } else if (err != ENOTSUP) { @@ -1060,7 +1060,7 @@ relookup: /* * The requested snapshot is not currently mounted, look it up. */ - err = zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname); + err = zfsctl_snapshot_zname(dvp, nm, sizeof (snapname), snapname); if (err != 0) { mutex_exit(&sdp->sd_lock); ZFS_EXIT(zfsvfs); @@ -1197,7 +1197,7 @@ zfsctl_snapdir_readdir_cb(vnode_t *vp, void *dp, int *eofp, offset_t *offp, offset_t *nextp, void *data, int flags) { zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; - char snapname[MAXNAMELEN]; + char snapname[ZFS_MAX_DATASET_NAME_LEN]; uint64_t id, cookie; boolean_t case_conflict; int error; @@ -1206,8 +1206,8 @@ zfsctl_snapdir_readdir_cb(vnode_t *vp, void *dp, int *eofp, cookie = *offp; dsl_pool_config_enter(dmu_objset_pool(zfsvfs->z_os), FTAG); - error = dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN, snapname, &id, - &cookie, &case_conflict); + error = dmu_snapshot_list_next(zfsvfs->z_os, + sizeof (snapname), snapname, &id, &cookie, &case_conflict); dsl_pool_config_exit(dmu_objset_pool(zfsvfs->z_os), FTAG); if (error) { ZFS_EXIT(zfsvfs); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index aa5ab2e..d76ba07 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -21,13 +21,12 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>. - * All rights reserved. + * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved. * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. * Copyright 2014 Xin Li <delphij@FreeBSD.org>. All rights reserved. * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. * Copyright 2015 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2014, Joyent, Inc. All rights reserved. + * Copyright (c) 2014, 2016 Joyent, Inc. All rights reserved. * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2013 Steven Hartland. All rights reserved. @@ -501,6 +500,14 @@ zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) dsl_dataset_t *ds; dsl_pool_t *dp; + /* + * First do a quick check for root in the global zone, which + * is allowed to do all write_perms. This ensures that zfs_ioc_* + * will get to handle nonexistent datasets. + */ + if (INGLOBALZONE(curthread) && secpolicy_zfs(cr) == 0) + return (0); + error = dsl_pool_hold(name, FTAG, &dp); if (error != 0) return (error); @@ -640,7 +647,7 @@ zfs_secpolicy_setprop(const char *dsname, zfs_prop_t prop, nvpair_t *propval, case ZFS_PROP_SNAPSHOT_LIMIT: if (!INGLOBALZONE(curthread)) { uint64_t zoned; - char setpoint[MAXNAMELEN]; + char setpoint[ZFS_MAX_DATASET_NAME_LEN]; /* * Unprivileged users are allowed to modify the * limit on things *under* (ie. contained by) @@ -876,7 +883,7 @@ zfs_secpolicy_destroy_snaps(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) int zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) { - char parentname[MAXNAMELEN]; + char parentname[ZFS_MAX_DATASET_NAME_LEN]; int error; if ((error = zfs_secpolicy_write_perms(from, @@ -948,7 +955,7 @@ zfs_secpolicy_promote(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) error = dsl_dataset_hold(dp, zc->zc_name, FTAG, &clone); if (error == 0) { - char parentname[MAXNAMELEN]; + char parentname[ZFS_MAX_DATASET_NAME_LEN]; dsl_dataset_t *origin = NULL; dsl_dir_t *dd; dd = clone->ds_dir; @@ -1117,7 +1124,7 @@ zfs_secpolicy_log_history(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) static int zfs_secpolicy_create_clone(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) { - char parentname[MAXNAMELEN]; + char parentname[ZFS_MAX_DATASET_NAME_LEN]; int error; char *origin; @@ -1260,7 +1267,7 @@ zfs_secpolicy_hold(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL; pair = nvlist_next_nvpair(holds, pair)) { - char fsname[MAXNAMELEN]; + char fsname[ZFS_MAX_DATASET_NAME_LEN]; error = dmu_fsname(nvpair_name(pair), fsname); if (error != 0) return (error); @@ -1281,7 +1288,7 @@ zfs_secpolicy_release(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) for (pair = nvlist_next_nvpair(innvl, NULL); pair != NULL; pair = nvlist_next_nvpair(innvl, pair)) { - char fsname[MAXNAMELEN]; + char fsname[ZFS_MAX_DATASET_NAME_LEN]; error = dmu_fsname(nvpair_name(pair), fsname); if (error != 0) return (error); @@ -2353,7 +2360,8 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) * A dataset name of maximum length cannot have any snapshots, * so exit immediately. */ - if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { + if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= + ZFS_MAX_DATASET_NAME_LEN) { dmu_objset_rele(os, FTAG); return (SET_ERROR(ESRCH)); } @@ -3157,7 +3165,7 @@ zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, boolean_t fuids_ok, sa_ok; uint64_t zplver = ZPL_VERSION; objset_t *os = NULL; - char parentname[MAXNAMELEN]; + char parentname[ZFS_MAX_DATASET_NAME_LEN]; char *cp; spa_t *spa; uint64_t spa_vers; @@ -3536,7 +3544,7 @@ zfs_destroy_unmount_origin(const char *fsname) return; ds = dmu_objset_ds(os); if (dsl_dir_is_clone(ds->ds_dir) && DS_IS_DEFER_DESTROY(ds->ds_prev)) { - char originname[MAXNAMELEN]; + char originname[ZFS_MAX_DATASET_NAME_LEN]; dsl_dataset_name(ds->ds_prev, originname); dmu_objset_rele(os, FTAG); (void) zfs_unmount_snap(originname); @@ -3756,7 +3764,7 @@ static int recursive_unmount(const char *fsname, void *arg) { const char *snapname = arg; - char fullname[MAXNAMELEN]; + char fullname[ZFS_MAX_DATASET_NAME_LEN]; (void) snprintf(fullname, sizeof (fullname), "%s@%s", fsname, snapname); return (zfs_unmount_snap(fullname)); @@ -4291,7 +4299,7 @@ zfs_ioc_recv(zfs_cmd_t *zc) nvlist_t *delayprops = NULL; /* sent properties applied post-receive */ char *origin = NULL; char *tosnap; - char tofs[ZFS_MAXNAMELEN]; + char tofs[ZFS_MAX_DATASET_NAME_LEN]; cap_rights_t rights; boolean_t first_recvd_props = B_FALSE; @@ -6253,6 +6261,14 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, goto out; } break; + case ZFS_IOCVER_INLANES: + if (zc_iocparm->zfs_cmd_size != sizeof(zfs_cmd_inlanes_t)) { + error = SET_ERROR(EFAULT); + goto out; + } + compat = B_TRUE; + cflag = ZFS_CMD_COMPAT_INLANES; + break; case ZFS_IOCVER_RESUME: if (zc_iocparm->zfs_cmd_size != sizeof(zfs_cmd_resume_t)) { error = SET_ERROR(EFAULT); @@ -6360,7 +6376,7 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, break; } - if (error == 0 && !(flag & FKIOCTL)) + if (error == 0) error = vec->zvec_secpolicy(zc, innvl, cr); if (error != 0) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c index a9da14c..fbaa324 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -1790,7 +1790,7 @@ zfs_statfs(vfs_t *vfsp, struct statfs *statp) strlcpy(statp->f_mntonname, vfsp->mnt_stat.f_mntonname, sizeof(statp->f_mntonname)); - statp->f_namemax = ZFS_MAXNAMELEN; + statp->f_namemax = MAXNAMELEN - 1; ZFS_EXIT(zfsvfs); return (0); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 4693542..a700a5e 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -1454,7 +1454,8 @@ zfs_lookup_lock(vnode_t *dvp, vnode_t *vp, const char *name, int lkflags) ASSERT_VOP_LOCKED(dvp, __func__); #ifdef DIAGNOSTIC - ASSERT(!RRM_LOCK_HELD(&zfsvfs->z_teardown_lock)); + if ((zdp->z_pflags & ZFS_XATTR) == 0) + VERIFY(!RRM_LOCK_HELD(&zfsvfs->z_teardown_lock)); #endif if (name[0] == 0 || (name[0] == '.' && name[1] == 0)) { @@ -3197,6 +3198,11 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, if (err == 0 && xattr_obj) { err = zfs_zget(zp->z_zfsvfs, xattr_obj, &attrzp); + if (err == 0) { + err = vn_lock(ZTOV(attrzp), LK_EXCLUSIVE); + if (err != 0) + vrele(ZTOV(attrzp)); + } if (err) goto out2; } @@ -3206,7 +3212,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, if (new_uid != zp->z_uid && zfs_fuid_overquota(zfsvfs, B_FALSE, new_uid)) { if (attrzp) - vrele(ZTOV(attrzp)); + vput(ZTOV(attrzp)); err = SET_ERROR(EDQUOT); goto out2; } @@ -3218,7 +3224,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, if (new_gid != zp->z_gid && zfs_fuid_overquota(zfsvfs, B_TRUE, new_gid)) { if (attrzp) - vrele(ZTOV(attrzp)); + vput(ZTOV(attrzp)); err = SET_ERROR(EDQUOT); goto out2; } @@ -3449,7 +3455,7 @@ out: } if (attrzp) - vrele(ZTOV(attrzp)); + vput(ZTOV(attrzp)); if (aclp) zfs_acl_free(aclp); @@ -5968,13 +5974,15 @@ zfs_lock(ap) vp = ap->a_vp; flags = ap->a_flags; if ((flags & LK_INTERLOCK) == 0 && (flags & LK_NOWAIT) == 0 && - (vp->v_iflag & VI_DOOMED) == 0 && (zp = vp->v_data) != NULL) { + (vp->v_iflag & VI_DOOMED) == 0 && (zp = vp->v_data) != NULL && + (zp->z_pflags & ZFS_XATTR) == 0) { zfsvfs = zp->z_zfsvfs; VERIFY(!RRM_LOCK_HELD(&zfsvfs->z_teardown_lock)); } err = vop_stdlock(ap); if ((flags & LK_INTERLOCK) != 0 && (flags & LK_NOWAIT) == 0 && - (vp->v_iflag & VI_DOOMED) == 0 && (zp = vp->v_data) != NULL) { + (vp->v_iflag & VI_DOOMED) == 0 && (zp = vp->v_data) != NULL && + (zp->z_pflags & ZFS_XATTR) == 0) { zfsvfs = zp->z_zfsvfs; VERIFY(!RRM_LOCK_HELD(&zfsvfs->z_teardown_lock)); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c index 993a468..31ff734 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c @@ -1970,7 +1970,7 @@ typedef struct zil_replay_arg { static int zil_replay_error(zilog_t *zilog, lr_t *lr, int error) { - char name[MAXNAMELEN]; + char name[ZFS_MAX_DATASET_NAME_LEN]; zilog->zl_replaying_seq--; /* didn't actually replay this one */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h index ef24fc3..444707c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h @@ -74,9 +74,13 @@ typedef enum dmu_objset_type { #define ZFS_TYPE_DATASET \ (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME | ZFS_TYPE_SNAPSHOT) +/* + * All of these include the terminating NUL byte. + */ #define ZAP_MAXNAMELEN 256 #define ZAP_MAXVALUELEN (1024 * 8) #define ZAP_OLDMAXVALUELEN 1024 +#define ZFS_MAX_DATASET_NAME_LEN 256 /* * Dataset properties are identified by these constants and must be added to @@ -606,6 +610,8 @@ typedef struct zpool_rewind_policy { /* * This is needed in userland to report the minimum necessary device size. + * + * Note that the zfs test suite uses 64MB vdevs. */ #define SPA_MINDEVSIZE (64ULL << 20) diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/sysevent/eventdefs.h b/sys/cddl/contrib/opensolaris/uts/common/sys/sysevent/eventdefs.h index 5760a85..7357fec 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/sysevent/eventdefs.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/sysevent/eventdefs.h @@ -249,6 +249,8 @@ extern "C" { #define ESC_ZFS_RESILVER_START "ESC_ZFS_resilver_start" #define ESC_ZFS_RESILVER_FINISH "ESC_ZFS_resilver_finish" #define ESC_ZFS_VDEV_REMOVE "ESC_ZFS_vdev_remove" +#define ESC_ZFS_VDEV_REMOVE_AUX "ESC_ZFS_vdev_remove_aux" +#define ESC_ZFS_VDEV_REMOVE_DEV "ESC_ZFS_vdev_remove_dev" #define ESC_ZFS_POOL_CREATE "ESC_ZFS_pool_create" #define ESC_ZFS_POOL_DESTROY "ESC_ZFS_pool_destroy" #define ESC_ZFS_POOL_IMPORT "ESC_ZFS_pool_import" |