svn commit: r247580 - vendor-sys/illumos/dist/common/nvpair vendor-sys/illumos/dist/uts/common vendor-sys/illumos/dist/uts/common/fs/zfs vendor-sys/illumos/dist/uts/common/fs/zfs/sys vendor-sys/ill...
Martin Matuska
mm at FreeBSD.org
Fri Mar 1 21:01:47 UTC 2013
Author: mm
Date: Fri Mar 1 21:01:45 2013
New Revision: 247580
URL: http://svnweb.freebsd.org/changeset/base/247580
Log:
Update vendor/illumos/dist and vendor-sys/illumos/dist
to illumos-gate 13973:4972ab336f54
Illumos ZFS issues:
3464 zfs synctask code needs restructuring
Added:
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_destroy.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_userhold.c
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu_send.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_destroy.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_userhold.h
Modified:
vendor-sys/illumos/dist/common/nvpair/fnvpair.c
vendor-sys/illumos/dist/uts/common/Makefile.files
vendor-sys/illumos/dist/uts/common/fs/zfs/arc.c
vendor-sys/illumos/dist/uts/common/fs/zfs/bplist.c
vendor-sys/illumos/dist/uts/common/fs/zfs/bpobj.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dbuf.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_diff.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_send.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_traverse.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_tx.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dnode.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dnode_sync.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dataset.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_deleg.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dir.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_pool.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_prop.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_synctask.c
vendor-sys/illumos/dist/uts/common/fs/zfs/metaslab.c
vendor-sys/illumos/dist/uts/common/fs/zfs/refcount.c
vendor-sys/illumos/dist/uts/common/fs/zfs/rrwlock.c
vendor-sys/illumos/dist/uts/common/fs/zfs/sa.c
vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c
vendor-sys/illumos/dist/uts/common/fs/zfs/spa_history.c
vendor-sys/illumos/dist/uts/common/fs/zfs/spa_misc.c
vendor-sys/illumos/dist/uts/common/fs/zfs/space_map.c
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/arc.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dbuf.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu_objset.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu_tx.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_dataset.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_dir.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_pool.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_prop.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_synctask.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/metaslab.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/refcount.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/rrwlock.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/space_map.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/txg.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfeature.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_debug.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_ioctl.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_znode.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zil.h
vendor-sys/illumos/dist/uts/common/fs/zfs/txg.c
vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_ctldir.c
vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_ioctl.c
vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vfsops.c
vendor-sys/illumos/dist/uts/common/fs/zfs/zil.c
vendor-sys/illumos/dist/uts/common/fs/zfs/zio.c
vendor-sys/illumos/dist/uts/common/fs/zfs/zvol.c
vendor-sys/illumos/dist/uts/common/sys/nvpair.h
Changes in other areas also in this revision:
Modified:
vendor/illumos/dist/cmd/zdb/zdb.c
vendor/illumos/dist/cmd/zfs/zfs_main.c
vendor/illumos/dist/cmd/zhack/zhack.c
vendor/illumos/dist/cmd/ztest/ztest.c
vendor/illumos/dist/lib/libzfs/common/libzfs.h
vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c
vendor/illumos/dist/lib/libzfs/common/libzfs_sendrecv.c
vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.c
vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.h
vendor/illumos/dist/lib/libzpool/common/kernel.c
vendor/illumos/dist/lib/libzpool/common/sys/zfs_context.h
vendor/illumos/dist/man/man1m/zfs.1m
Modified: vendor-sys/illumos/dist/common/nvpair/fnvpair.c
==============================================================================
--- vendor-sys/illumos/dist/common/nvpair/fnvpair.c Fri Mar 1 20:51:53 2013 (r247579)
+++ vendor-sys/illumos/dist/common/nvpair/fnvpair.c Fri Mar 1 21:01:45 2013 (r247580)
@@ -26,6 +26,7 @@
#include <sys/nvpair.h>
#include <sys/kmem.h>
#include <sys/debug.h>
+#include <sys/param.h>
#ifndef _KERNEL
#include <stdlib.h>
#endif
@@ -114,6 +115,18 @@ fnvlist_merge(nvlist_t *dst, nvlist_t *s
VERIFY0(nvlist_merge(dst, src, KM_SLEEP));
}
+size_t
+fnvlist_num_pairs(nvlist_t *nvl)
+{
+ size_t count = 0;
+ nvpair_t *pair;
+
+ for (pair = nvlist_next_nvpair(nvl, 0); pair != NULL;
+ pair = nvlist_next_nvpair(nvl, pair))
+ count++;
+ return (count);
+}
+
void
fnvlist_add_boolean(nvlist_t *nvl, const char *name)
{
Modified: vendor-sys/illumos/dist/uts/common/Makefile.files
==============================================================================
--- vendor-sys/illumos/dist/uts/common/Makefile.files Fri Mar 1 20:51:53 2013 (r247579)
+++ vendor-sys/illumos/dist/uts/common/Makefile.files Fri Mar 1 21:01:45 2013 (r247580)
@@ -1346,8 +1346,10 @@ ZFS_COMMON_OBJS += \
dsl_dir.o \
dsl_dataset.o \
dsl_deadlist.o \
+ dsl_destroy.o \
dsl_pool.o \
dsl_synctask.o \
+ dsl_userhold.o \
dmu_zfetch.o \
dsl_deleg.o \
dsl_prop.o \
@@ -1358,6 +1360,7 @@ ZFS_COMMON_OBJS += \
lzjb.o \
metaslab.o \
refcount.o \
+ rrwlock.o \
sa.o \
sha256.o \
spa.o \
@@ -1417,7 +1420,6 @@ ZFS_OBJS += \
zfs_onexit.o \
zfs_replay.o \
zfs_rlock.o \
- rrwlock.o \
zfs_vfsops.o \
zfs_vnops.o \
zvol.o
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/arc.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/arc.c Fri Mar 1 20:51:53 2013 (r247579)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/arc.c Fri Mar 1 21:01:45 2013 (r247580)
@@ -1633,12 +1633,12 @@ arc_buf_free(arc_buf_t *buf, void *tag)
}
}
-int
+boolean_t
arc_buf_remove_ref(arc_buf_t *buf, void* tag)
{
arc_buf_hdr_t *hdr = buf->b_hdr;
kmutex_t *hash_lock = HDR_LOCK(hdr);
- int no_callback = (buf->b_efunc == NULL);
+ boolean_t no_callback = (buf->b_efunc == NULL);
if (hdr->b_state == arc_anon) {
ASSERT(hdr->b_datacnt == 1);
@@ -1843,7 +1843,7 @@ arc_evict(arc_state_t *state, uint64_t s
ARCSTAT_INCR(arcstat_mutex_miss, missed);
/*
- * We have just evicted some date into the ghost state, make
+ * We have just evicted some data into the ghost state, make
* sure we also adjust the ghost state size if necessary.
*/
if (arc_no_grow &&
@@ -2622,7 +2622,7 @@ arc_bcopy_func(zio_t *zio, arc_buf_t *bu
{
if (zio == NULL || zio->io_error == 0)
bcopy(buf->b_data, arg, buf->b_hdr->b_size);
- VERIFY(arc_buf_remove_ref(buf, arg) == 1);
+ VERIFY(arc_buf_remove_ref(buf, arg));
}
/* a generic arc_done_func_t */
@@ -2631,7 +2631,7 @@ arc_getbuf_func(zio_t *zio, arc_buf_t *b
{
arc_buf_t **bufp = arg;
if (zio && zio->io_error) {
- VERIFY(arc_buf_remove_ref(buf, arg) == 1);
+ VERIFY(arc_buf_remove_ref(buf, arg));
*bufp = NULL;
} else {
*bufp = buf;
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/bplist.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/bplist.c Fri Mar 1 20:51:53 2013 (r247579)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/bplist.c Fri Mar 1 21:01:45 2013 (r247580)
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <sys/bplist.h>
@@ -52,6 +53,12 @@ bplist_append(bplist_t *bpl, const blkpt
mutex_exit(&bpl->bpl_lock);
}
+/*
+ * To aid debugging, we keep the most recently removed entry. This way if
+ * we are in the callback, we can easily locate the entry.
+ */
+static bplist_entry_t *bplist_iterate_last_removed;
+
void
bplist_iterate(bplist_t *bpl, bplist_itor_t *func, void *arg, dmu_tx_t *tx)
{
@@ -59,6 +66,7 @@ bplist_iterate(bplist_t *bpl, bplist_ito
mutex_enter(&bpl->bpl_lock);
while (bpe = list_head(&bpl->bpl_list)) {
+ bplist_iterate_last_removed = bpe;
list_remove(&bpl->bpl_list, bpe);
mutex_exit(&bpl->bpl_lock);
func(arg, &bpe->bpe_blk, tx);
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/bpobj.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/bpobj.c Fri Mar 1 20:51:53 2013 (r247579)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/bpobj.c Fri Mar 1 21:01:45 2013 (r247580)
@@ -392,6 +392,10 @@ bpobj_enqueue_subobj(bpobj_t *bpo, uint6
DMU_OT_BPOBJ_SUBOBJ, SPA_MAXBLOCKSIZE, DMU_OT_NONE, 0, tx);
}
+ dmu_object_info_t doi;
+ ASSERT0(dmu_object_info(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs, &doi));
+ ASSERT3U(doi.doi_type, ==, DMU_OT_BPOBJ_SUBOBJ);
+
mutex_enter(&bpo->bpo_lock);
dmu_write(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs,
bpo->bpo_phys->bpo_num_subobjs * sizeof (subobj),
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dbuf.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dbuf.c Fri Mar 1 20:51:53 2013 (r247579)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dbuf.c Fri Mar 1 21:01:45 2013 (r247580)
@@ -39,7 +39,7 @@
#include <sys/sa_impl.h>
static void dbuf_destroy(dmu_buf_impl_t *db);
-static int dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
+static boolean_t dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
static void dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx);
/*
@@ -499,7 +499,7 @@ dbuf_read_done(zio_t *zio, arc_buf_t *bu
} else {
ASSERT(db->db_blkid != DMU_BONUS_BLKID);
ASSERT3P(db->db_buf, ==, NULL);
- VERIFY(arc_buf_remove_ref(buf, db) == 1);
+ VERIFY(arc_buf_remove_ref(buf, db));
db->db_state = DB_UNCACHED;
}
cv_broadcast(&db->db_changed);
@@ -828,10 +828,12 @@ dbuf_free_range(dnode_t *dn, uint64_t st
continue;
/* found a level 0 buffer in the range */
- if (dbuf_undirty(db, tx))
+ mutex_enter(&db->db_mtx);
+ if (dbuf_undirty(db, tx)) {
+ /* mutex has been dropped and dbuf destroyed */
continue;
+ }
- mutex_enter(&db->db_mtx);
if (db->db_state == DB_UNCACHED ||
db->db_state == DB_NOFILL ||
db->db_state == DB_EVICTING) {
@@ -958,7 +960,7 @@ dbuf_new_size(dmu_buf_impl_t *db, int si
mutex_enter(&db->db_mtx);
dbuf_set_data(db, buf);
- VERIFY(arc_buf_remove_ref(obuf, db) == 1);
+ VERIFY(arc_buf_remove_ref(obuf, db));
db->db.db_size = size;
if (db->db_level == 0) {
@@ -1258,7 +1260,10 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t
return (dr);
}
-static int
+/*
+ * Return TRUE if this evicted the dbuf.
+ */
+static boolean_t
dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
{
dnode_t *dn;
@@ -1267,18 +1272,17 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_
ASSERT(txg != 0);
ASSERT(db->db_blkid != DMU_BONUS_BLKID);
+ ASSERT0(db->db_level);
+ ASSERT(MUTEX_HELD(&db->db_mtx));
- mutex_enter(&db->db_mtx);
/*
* If this buffer is not dirty, we're done.
*/
for (drp = &db->db_last_dirty; (dr = *drp) != NULL; drp = &dr->dr_next)
if (dr->dr_txg <= txg)
break;
- if (dr == NULL || dr->dr_txg < txg) {
- mutex_exit(&db->db_mtx);
- return (0);
- }
+ if (dr == NULL || dr->dr_txg < txg)
+ return (B_FALSE);
ASSERT(dr->dr_txg == txg);
ASSERT(dr->dr_dbuf == db);
@@ -1286,24 +1290,12 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_
dn = DB_DNODE(db);
/*
- * If this buffer is currently held, we cannot undirty
- * it, since one of the current holders may be in the
- * middle of an update. Note that users of dbuf_undirty()
- * should not place a hold on the dbuf before the call.
- * Also note: we can get here with a spill block, so
- * test for that similar to how dbuf_dirty does.
+ * Note: This code will probably work even if there are concurrent
+ * holders, but it is untested in that scenerio, as the ZPL and
+ * ztest have additional locking (the range locks) that prevents
+ * that type of concurrent access.
*/
- if (refcount_count(&db->db_holds) > db->db_dirtycnt) {
- mutex_exit(&db->db_mtx);
- /* Make sure we don't toss this buffer at sync phase */
- if (db->db_blkid != DMU_SPILL_BLKID) {
- mutex_enter(&dn->dn_mtx);
- dnode_clear_range(dn, db->db_blkid, 1, tx);
- mutex_exit(&dn->dn_mtx);
- }
- DB_DNODE_EXIT(db);
- return (0);
- }
+ ASSERT3U(refcount_count(&db->db_holds), ==, db->db_dirtycnt);
dprintf_dbuf(db, "size=%llx\n", (u_longlong_t)db->db.db_size);
@@ -1332,21 +1324,13 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_
}
DB_DNODE_EXIT(db);
- if (db->db_level == 0) {
- if (db->db_state != DB_NOFILL) {
- dbuf_unoverride(dr);
+ if (db->db_state != DB_NOFILL) {
+ dbuf_unoverride(dr);
- ASSERT(db->db_buf != NULL);
- ASSERT(dr->dt.dl.dr_data != NULL);
- if (dr->dt.dl.dr_data != db->db_buf)
- VERIFY(arc_buf_remove_ref(dr->dt.dl.dr_data,
- db) == 1);
- }
- } else {
ASSERT(db->db_buf != NULL);
- ASSERT(list_head(&dr->dt.di.dr_children) == NULL);
- mutex_destroy(&dr->dt.di.dr_mtx);
- list_destroy(&dr->dt.di.dr_children);
+ ASSERT(dr->dt.dl.dr_data != NULL);
+ if (dr->dt.dl.dr_data != db->db_buf)
+ VERIFY(arc_buf_remove_ref(dr->dt.dl.dr_data, db));
}
kmem_free(dr, sizeof (dbuf_dirty_record_t));
@@ -1358,13 +1342,12 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_
ASSERT(db->db_state == DB_NOFILL || arc_released(buf));
dbuf_set_data(db, NULL);
- VERIFY(arc_buf_remove_ref(buf, db) == 1);
+ VERIFY(arc_buf_remove_ref(buf, db));
dbuf_evict(db);
- return (1);
+ return (B_TRUE);
}
- mutex_exit(&db->db_mtx);
- return (0);
+ return (B_FALSE);
}
#pragma weak dmu_buf_will_dirty = dbuf_will_dirty
@@ -1463,7 +1446,7 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, a
mutex_exit(&db->db_mtx);
(void) dbuf_dirty(db, tx);
bcopy(buf->b_data, db->db.db_data, db->db.db_size);
- VERIFY(arc_buf_remove_ref(buf, db) == 1);
+ VERIFY(arc_buf_remove_ref(buf, db));
xuio_stat_wbuf_copied();
return;
}
@@ -1481,10 +1464,10 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, a
arc_release(db->db_buf, db);
}
dr->dt.dl.dr_data = buf;
- VERIFY(arc_buf_remove_ref(db->db_buf, db) == 1);
+ VERIFY(arc_buf_remove_ref(db->db_buf, db));
} else if (dr == NULL || dr->dt.dl.dr_data != db->db_buf) {
arc_release(db->db_buf, db);
- VERIFY(arc_buf_remove_ref(db->db_buf, db) == 1);
+ VERIFY(arc_buf_remove_ref(db->db_buf, db));
}
db->db_buf = NULL;
}
@@ -2067,10 +2050,10 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db,
* This dbuf has anonymous data associated with it.
*/
dbuf_set_data(db, NULL);
- VERIFY(arc_buf_remove_ref(buf, db) == 1);
+ VERIFY(arc_buf_remove_ref(buf, db));
dbuf_evict(db);
} else {
- VERIFY(arc_buf_remove_ref(db->db_buf, db) == 0);
+ VERIFY(!arc_buf_remove_ref(db->db_buf, db));
/*
* A dbuf will be eligible for eviction if either the
@@ -2567,7 +2550,7 @@ dbuf_write_done(zio_t *zio, arc_buf_t *b
if (db->db_state != DB_NOFILL) {
if (dr->dt.dl.dr_data != db->db_buf)
VERIFY(arc_buf_remove_ref(dr->dt.dl.dr_data,
- db) == 1);
+ db));
else if (!arc_released(db->db_buf))
arc_set_callback(db->db_buf, dbuf_do_evict, db);
}
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c Fri Mar 1 20:51:53 2013 (r247579)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c Fri Mar 1 21:01:45 2013 (r247580)
@@ -1194,7 +1194,7 @@ void
dmu_return_arcbuf(arc_buf_t *buf)
{
arc_return_buf(buf, FTAG);
- VERIFY(arc_buf_remove_ref(buf, FTAG) == 1);
+ VERIFY(arc_buf_remove_ref(buf, FTAG));
}
/*
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_diff.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_diff.c Fri Mar 1 20:51:53 2013 (r247579)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_diff.c Fri Mar 1 21:01:45 2013 (r247580)
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <sys/dmu.h>
@@ -155,51 +156,49 @@ diff_cb(spa_t *spa, zilog_t *zilog, cons
}
int
-dmu_diff(objset_t *tosnap, objset_t *fromsnap, struct vnode *vp, offset_t *offp)
+dmu_diff(const char *tosnap_name, const char *fromsnap_name,
+ struct vnode *vp, offset_t *offp)
{
struct diffarg da;
- dsl_dataset_t *ds = tosnap->os_dsl_dataset;
- dsl_dataset_t *fromds = fromsnap->os_dsl_dataset;
- dsl_dataset_t *findds;
- dsl_dataset_t *relds;
- int err = 0;
+ dsl_dataset_t *fromsnap;
+ dsl_dataset_t *tosnap;
+ dsl_pool_t *dp;
+ int error;
+ uint64_t fromtxg;
- /* make certain we are looking at snapshots */
- if (!dsl_dataset_is_snapshot(ds) || !dsl_dataset_is_snapshot(fromds))
+ if (strchr(tosnap_name, '@') == NULL ||
+ strchr(fromsnap_name, '@') == NULL)
return (EINVAL);
- /* fromsnap must be earlier and from the same lineage as tosnap */
- if (fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg)
+ error = dsl_pool_hold(tosnap_name, FTAG, &dp);
+ if (error != 0)
+ return (error);
+
+ error = dsl_dataset_hold(dp, tosnap_name, FTAG, &tosnap);
+ if (error != 0) {
+ dsl_pool_rele(dp, FTAG);
+ return (error);
+ }
+
+ error = dsl_dataset_hold(dp, fromsnap_name, FTAG, &fromsnap);
+ if (error != 0) {
+ dsl_dataset_rele(tosnap, FTAG);
+ dsl_pool_rele(dp, FTAG);
+ return (error);
+ }
+
+ if (!dsl_dataset_is_before(tosnap, fromsnap)) {
+ dsl_dataset_rele(fromsnap, FTAG);
+ dsl_dataset_rele(tosnap, FTAG);
+ dsl_pool_rele(dp, FTAG);
return (EXDEV);
-
- relds = NULL;
- findds = ds;
-
- while (fromds->ds_dir != findds->ds_dir) {
- dsl_pool_t *dp = ds->ds_dir->dd_pool;
-
- if (!dsl_dir_is_clone(findds->ds_dir)) {
- if (relds)
- dsl_dataset_rele(relds, FTAG);
- return (EXDEV);
- }
-
- rw_enter(&dp->dp_config_rwlock, RW_READER);
- err = dsl_dataset_hold_obj(dp,
- findds->ds_dir->dd_phys->dd_origin_obj, FTAG, &findds);
- rw_exit(&dp->dp_config_rwlock);
-
- if (relds)
- dsl_dataset_rele(relds, FTAG);
-
- if (err)
- return (EXDEV);
-
- relds = findds;
}
- if (relds)
- dsl_dataset_rele(relds, FTAG);
+ fromtxg = fromsnap->ds_phys->ds_creation_txg;
+ dsl_dataset_rele(fromsnap, FTAG);
+
+ dsl_dataset_long_hold(tosnap, FTAG);
+ dsl_pool_rele(dp, FTAG);
da.da_vp = vp;
da.da_offp = offp;
@@ -207,15 +206,18 @@ dmu_diff(objset_t *tosnap, objset_t *fro
da.da_ddr.ddr_first = da.da_ddr.ddr_last = 0;
da.da_err = 0;
- err = traverse_dataset(ds, fromds->ds_phys->ds_creation_txg,
+ error = traverse_dataset(tosnap, fromtxg,
TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA, diff_cb, &da);
- if (err) {
- da.da_err = err;
+ if (error != 0) {
+ da.da_err = error;
} else {
/* we set the da.da_err we return as side-effect */
(void) write_record(&da);
}
+ dsl_dataset_long_rele(tosnap, FTAG);
+ dsl_dataset_rele(tosnap, FTAG);
+
return (da.da_err);
}
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c Fri Mar 1 20:51:53 2013 (r247579)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c Fri Mar 1 21:01:45 2013 (r247580)
@@ -44,6 +44,7 @@
#include <sys/zfs_ioctl.h>
#include <sys/sa.h>
#include <sys/zfs_onexit.h>
+#include <sys/dsl_destroy.h>
/*
* Needed to close a window in dnode_move() that allows the objset to be freed
@@ -280,7 +281,7 @@ dmu_objset_open_impl(spa_t *spa, dsl_dat
err = arc_read(NULL, spa, os->os_rootbp,
arc_getbuf_func, &os->os_phys_buf,
ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &aflags, &zb);
- if (err) {
+ if (err != 0) {
kmem_free(os, sizeof (objset_t));
/* convert checksum errors into IO errors */
if (err == ECKSUM)
@@ -320,34 +321,49 @@ dmu_objset_open_impl(spa_t *spa, dsl_dat
* checksum/compression/copies.
*/
if (ds) {
- err = dsl_prop_register(ds, "primarycache",
+ err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_PRIMARYCACHE),
primary_cache_changed_cb, os);
- if (err == 0)
- err = dsl_prop_register(ds, "secondarycache",
+ if (err == 0) {
+ err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_SECONDARYCACHE),
secondary_cache_changed_cb, os);
+ }
if (!dsl_dataset_is_snapshot(ds)) {
- if (err == 0)
- err = dsl_prop_register(ds, "checksum",
+ if (err == 0) {
+ err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_CHECKSUM),
checksum_changed_cb, os);
- if (err == 0)
- err = dsl_prop_register(ds, "compression",
+ }
+ if (err == 0) {
+ err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_COMPRESSION),
compression_changed_cb, os);
- if (err == 0)
- err = dsl_prop_register(ds, "copies",
+ }
+ if (err == 0) {
+ err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_COPIES),
copies_changed_cb, os);
- if (err == 0)
- err = dsl_prop_register(ds, "dedup",
+ }
+ if (err == 0) {
+ err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_DEDUP),
dedup_changed_cb, os);
- if (err == 0)
- err = dsl_prop_register(ds, "logbias",
+ }
+ if (err == 0) {
+ err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_LOGBIAS),
logbias_changed_cb, os);
- if (err == 0)
- err = dsl_prop_register(ds, "sync",
+ }
+ if (err == 0) {
+ err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_SYNC),
sync_changed_cb, os);
+ }
}
- if (err) {
+ if (err != 0) {
VERIFY(arc_buf_remove_ref(os->os_phys_buf,
- &os->os_phys_buf) == 1);
+ &os->os_phys_buf));
kmem_free(os, sizeof (objset_t));
return (err);
}
@@ -425,44 +441,66 @@ dmu_objset_from_ds(dsl_dataset_t *ds, ob
return (err);
}
-/* called from zpl */
+/*
+ * Holds the pool while the objset is held. Therefore only one objset
+ * can be held at a time.
+ */
int
dmu_objset_hold(const char *name, void *tag, objset_t **osp)
{
+ dsl_pool_t *dp;
dsl_dataset_t *ds;
int err;
- err = dsl_dataset_hold(name, tag, &ds);
- if (err)
+ err = dsl_pool_hold(name, tag, &dp);
+ if (err != 0)
return (err);
+ err = dsl_dataset_hold(dp, name, tag, &ds);
+ if (err != 0) {
+ dsl_pool_rele(dp, tag);
+ return (err);
+ }
err = dmu_objset_from_ds(ds, osp);
- if (err)
+ if (err != 0) {
dsl_dataset_rele(ds, tag);
+ dsl_pool_rele(dp, tag);
+ }
return (err);
}
-/* called from zpl */
+/*
+ * dsl_pool must not be held when this is called.
+ * Upon successful return, there will be a longhold on the dataset,
+ * and the dsl_pool will not be held.
+ */
int
dmu_objset_own(const char *name, dmu_objset_type_t type,
boolean_t readonly, void *tag, objset_t **osp)
{
+ dsl_pool_t *dp;
dsl_dataset_t *ds;
int err;
- err = dsl_dataset_own(name, B_FALSE, tag, &ds);
- if (err)
+ err = dsl_pool_hold(name, FTAG, &dp);
+ if (err != 0)
return (err);
+ err = dsl_dataset_own(dp, name, tag, &ds);
+ if (err != 0) {
+ dsl_pool_rele(dp, FTAG);
+ return (err);
+ }
err = dmu_objset_from_ds(ds, osp);
- if (err) {
+ dsl_pool_rele(dp, FTAG);
+ if (err != 0) {
dsl_dataset_disown(ds, tag);
} else if (type != DMU_OST_ANY && type != (*osp)->os_phys->os_type) {
- dmu_objset_disown(*osp, tag);
+ dsl_dataset_disown(ds, tag);
return (EINVAL);
} else if (!readonly && dsl_dataset_is_snapshot(ds)) {
- dmu_objset_disown(*osp, tag);
+ dsl_dataset_disown(ds, tag);
return (EROFS);
}
return (err);
@@ -471,7 +509,9 @@ dmu_objset_own(const char *name, dmu_obj
void
dmu_objset_rele(objset_t *os, void *tag)
{
+ dsl_pool_t *dp = dmu_objset_pool(os);
dsl_dataset_rele(os->os_dsl_dataset, tag);
+ dsl_pool_rele(dp, tag);
}
void
@@ -480,7 +520,7 @@ dmu_objset_disown(objset_t *os, void *ta
dsl_dataset_disown(os->os_dsl_dataset, tag);
}
-int
+void
dmu_objset_evict_dbufs(objset_t *os)
{
dnode_t *dn;
@@ -515,9 +555,7 @@ dmu_objset_evict_dbufs(objset_t *os)
mutex_enter(&os->os_lock);
dn = next_dn;
}
- dn = list_head(&os->os_dnodes);
mutex_exit(&os->os_lock);
- return (dn != DMU_META_DNODE(os));
}
void
@@ -530,33 +568,37 @@ dmu_objset_evict(objset_t *os)
if (ds) {
if (!dsl_dataset_is_snapshot(ds)) {
- VERIFY(0 == dsl_prop_unregister(ds, "checksum",
+ VERIFY0(dsl_prop_unregister(ds,
+ zfs_prop_to_name(ZFS_PROP_CHECKSUM),
checksum_changed_cb, os));
- VERIFY(0 == dsl_prop_unregister(ds, "compression",
+ VERIFY0(dsl_prop_unregister(ds,
+ zfs_prop_to_name(ZFS_PROP_COMPRESSION),
compression_changed_cb, os));
- VERIFY(0 == dsl_prop_unregister(ds, "copies",
+ VERIFY0(dsl_prop_unregister(ds,
+ zfs_prop_to_name(ZFS_PROP_COPIES),
copies_changed_cb, os));
- VERIFY(0 == dsl_prop_unregister(ds, "dedup",
+ VERIFY0(dsl_prop_unregister(ds,
+ zfs_prop_to_name(ZFS_PROP_DEDUP),
dedup_changed_cb, os));
- VERIFY(0 == dsl_prop_unregister(ds, "logbias",
+ VERIFY0(dsl_prop_unregister(ds,
+ zfs_prop_to_name(ZFS_PROP_LOGBIAS),
logbias_changed_cb, os));
- VERIFY(0 == dsl_prop_unregister(ds, "sync",
+ VERIFY0(dsl_prop_unregister(ds,
+ zfs_prop_to_name(ZFS_PROP_SYNC),
sync_changed_cb, os));
}
- VERIFY(0 == dsl_prop_unregister(ds, "primarycache",
+ VERIFY0(dsl_prop_unregister(ds,
+ zfs_prop_to_name(ZFS_PROP_PRIMARYCACHE),
primary_cache_changed_cb, os));
- VERIFY(0 == dsl_prop_unregister(ds, "secondarycache",
+ VERIFY0(dsl_prop_unregister(ds,
+ zfs_prop_to_name(ZFS_PROP_SECONDARYCACHE),
secondary_cache_changed_cb, os));
}
if (os->os_sa)
sa_tear_down(os);
- /*
- * We should need only a single pass over the dnode list, since
- * nothing can be added to the list at this point.
- */
- (void) dmu_objset_evict_dbufs(os);
+ dmu_objset_evict_dbufs(os);
dnode_special_close(&os->os_meta_dnode);
if (DMU_USERUSED_DNODE(os)) {
@@ -567,7 +609,7 @@ dmu_objset_evict(objset_t *os)
ASSERT3P(list_head(&os->os_dnodes), ==, NULL);
- VERIFY(arc_buf_remove_ref(os->os_phys_buf, &os->os_phys_buf) == 1);
+ VERIFY(arc_buf_remove_ref(os->os_phys_buf, &os->os_phys_buf));
/*
* This is a barrier to prevent the objset from going away in
@@ -599,10 +641,11 @@ dmu_objset_create_impl(spa_t *spa, dsl_d
dnode_t *mdn;
ASSERT(dmu_tx_is_syncing(tx));
+
if (ds != NULL)
- VERIFY(0 == dmu_objset_from_ds(ds, &os));
+ VERIFY0(dmu_objset_from_ds(ds, &os));
else
- VERIFY(0 == dmu_objset_open_impl(spa, NULL, bp, &os));
+ VERIFY0(dmu_objset_open_impl(spa, NULL, bp, &os));
mdn = DMU_META_DNODE(os);
@@ -650,359 +693,181 @@ dmu_objset_create_impl(spa_t *spa, dsl_d
return (os);
}
-struct oscarg {
- void (*userfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
- void *userarg;
- dsl_dataset_t *clone_origin;
- const char *lastname;
- dmu_objset_type_t type;
- uint64_t flags;
- cred_t *cr;
-};
+typedef struct dmu_objset_create_arg {
+ const char *doca_name;
+ cred_t *doca_cred;
+ void (*doca_userfunc)(objset_t *os, void *arg,
+ cred_t *cr, dmu_tx_t *tx);
+ void *doca_userarg;
+ dmu_objset_type_t doca_type;
+ uint64_t doca_flags;
+} dmu_objset_create_arg_t;
/*ARGSUSED*/
static int
-dmu_objset_create_check(void *arg1, void *arg2, dmu_tx_t *tx)
+dmu_objset_create_check(void *arg, dmu_tx_t *tx)
{
- dsl_dir_t *dd = arg1;
- struct oscarg *oa = arg2;
- objset_t *mos = dd->dd_pool->dp_meta_objset;
- int err;
- uint64_t ddobj;
+ dmu_objset_create_arg_t *doca = arg;
+ dsl_pool_t *dp = dmu_tx_pool(tx);
+ dsl_dir_t *pdd;
+ const char *tail;
+ int error;
+
+ if (strchr(doca->doca_name, '@') != NULL)
+ return (EINVAL);
- err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj,
- oa->lastname, sizeof (uint64_t), 1, &ddobj);
- if (err != ENOENT)
- return (err ? err : EEXIST);
-
- if (oa->clone_origin != NULL) {
- /* You can't clone across pools. */
- if (oa->clone_origin->ds_dir->dd_pool != dd->dd_pool)
- return (EXDEV);
-
- /* You can only clone snapshots, not the head datasets. */
- if (!dsl_dataset_is_snapshot(oa->clone_origin))
- return (EINVAL);
+ error = dsl_dir_hold(dp, doca->doca_name, FTAG, &pdd, &tail);
+ if (error != 0)
+ return (error);
+ if (tail == NULL) {
+ dsl_dir_rele(pdd, FTAG);
+ return (EEXIST);
}
+ dsl_dir_rele(pdd, FTAG);
return (0);
}
static void
-dmu_objset_create_sync(void *arg1, void *arg2, dmu_tx_t *tx)
+dmu_objset_create_sync(void *arg, dmu_tx_t *tx)
{
- dsl_dir_t *dd = arg1;
- spa_t *spa = dd->dd_pool->dp_spa;
- struct oscarg *oa = arg2;
- uint64_t obj;
+ dmu_objset_create_arg_t *doca = arg;
+ dsl_pool_t *dp = dmu_tx_pool(tx);
+ dsl_dir_t *pdd;
+ const char *tail;
dsl_dataset_t *ds;
+ uint64_t obj;
blkptr_t *bp;
+ objset_t *os;
- ASSERT(dmu_tx_is_syncing(tx));
+ VERIFY0(dsl_dir_hold(dp, doca->doca_name, FTAG, &pdd, &tail));
- obj = dsl_dataset_create_sync(dd, oa->lastname,
- oa->clone_origin, oa->flags, oa->cr, tx);
+ obj = dsl_dataset_create_sync(pdd, tail, NULL, doca->doca_flags,
+ doca->doca_cred, tx);
- VERIFY3U(0, ==, dsl_dataset_hold_obj(dd->dd_pool, obj, FTAG, &ds));
+ VERIFY0(dsl_dataset_hold_obj(pdd->dd_pool, obj, FTAG, &ds));
bp = dsl_dataset_get_blkptr(ds);
- if (BP_IS_HOLE(bp)) {
- objset_t *os =
- dmu_objset_create_impl(spa, ds, bp, oa->type, tx);
+ os = dmu_objset_create_impl(pdd->dd_pool->dp_spa,
+ ds, bp, doca->doca_type, tx);
- if (oa->userfunc)
- oa->userfunc(os, oa->userarg, oa->cr, tx);
+ if (doca->doca_userfunc != NULL) {
+ doca->doca_userfunc(os, doca->doca_userarg,
+ doca->doca_cred, tx);
}
- if (oa->clone_origin == NULL) {
- spa_history_log_internal_ds(ds, "create", tx, "");
- } else {
- char namebuf[MAXNAMELEN];
- dsl_dataset_name(oa->clone_origin, namebuf);
- spa_history_log_internal_ds(ds, "clone", tx,
- "origin=%s (%llu)", namebuf, oa->clone_origin->ds_object);
- }
+ spa_history_log_internal_ds(ds, "create", tx, "");
dsl_dataset_rele(ds, FTAG);
+ dsl_dir_rele(pdd, FTAG);
}
int
dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg)
{
- dsl_dir_t *pdd;
- const char *tail;
- int err = 0;
- struct oscarg oa = { 0 };
+ dmu_objset_create_arg_t doca;
- ASSERT(strchr(name, '@') == NULL);
- err = dsl_dir_open(name, FTAG, &pdd, &tail);
- if (err)
- return (err);
- if (tail == NULL) {
- dsl_dir_close(pdd, FTAG);
- return (EEXIST);
- }
+ doca.doca_name = name;
+ doca.doca_cred = CRED();
+ doca.doca_flags = flags;
+ doca.doca_userfunc = func;
+ doca.doca_userarg = arg;
+ doca.doca_type = type;
+
+ return (dsl_sync_task(name,
+ dmu_objset_create_check, dmu_objset_create_sync, &doca, 5));
+}
+
+typedef struct dmu_objset_clone_arg {
+ const char *doca_clone;
+ const char *doca_origin;
+ cred_t *doca_cred;
+} dmu_objset_clone_arg_t;
- oa.userfunc = func;
- oa.userarg = arg;
- oa.lastname = tail;
- oa.type = type;
- oa.flags = flags;
- oa.cr = CRED();
-
- err = dsl_sync_task_do(pdd->dd_pool, dmu_objset_create_check,
- dmu_objset_create_sync, pdd, &oa, 5);
- dsl_dir_close(pdd, FTAG);
- return (err);
-}
-
-int
-dmu_objset_clone(const char *name, dsl_dataset_t *clone_origin, uint64_t flags)
+/*ARGSUSED*/
+static int
+dmu_objset_clone_check(void *arg, dmu_tx_t *tx)
{
+ dmu_objset_clone_arg_t *doca = arg;
dsl_dir_t *pdd;
const char *tail;
- int err = 0;
- struct oscarg oa = { 0 };
+ int error;
+ dsl_dataset_t *origin;
+ dsl_pool_t *dp = dmu_tx_pool(tx);
- ASSERT(strchr(name, '@') == NULL);
- err = dsl_dir_open(name, FTAG, &pdd, &tail);
- if (err)
- return (err);
+ if (strchr(doca->doca_clone, '@') != NULL)
+ return (EINVAL);
+
+ error = dsl_dir_hold(dp, doca->doca_clone, FTAG, &pdd, &tail);
+ if (error != 0)
+ return (error);
if (tail == NULL) {
- dsl_dir_close(pdd, FTAG);
+ dsl_dir_rele(pdd, FTAG);
return (EEXIST);
}
-
- oa.lastname = tail;
- oa.clone_origin = clone_origin;
- oa.flags = flags;
- oa.cr = CRED();
-
- err = dsl_sync_task_do(pdd->dd_pool, dmu_objset_create_check,
- dmu_objset_create_sync, pdd, &oa, 5);
- dsl_dir_close(pdd, FTAG);
- return (err);
-}
-
-int
-dmu_objset_destroy(const char *name, boolean_t defer)
-{
- dsl_dataset_t *ds;
- int error;
-
- error = dsl_dataset_own(name, B_TRUE, FTAG, &ds);
- if (error == 0) {
- error = dsl_dataset_destroy(ds, FTAG, defer);
- /* dsl_dataset_destroy() closes the ds. */
+ /* You can't clone across pools. */
+ if (pdd->dd_pool != dp) {
+ dsl_dir_rele(pdd, FTAG);
+ return (EXDEV);
}
+ dsl_dir_rele(pdd, FTAG);
- return (error);
-}
-
-typedef struct snapallarg {
- dsl_sync_task_group_t *saa_dstg;
- boolean_t saa_needsuspend;
- nvlist_t *saa_props;
-
- /* the following are used only if 'temporary' is set: */
- boolean_t saa_temporary;
- const char *saa_htag;
- struct dsl_ds_holdarg *saa_ha;
- dsl_dataset_t *saa_newds;
-} snapallarg_t;
-
-typedef struct snaponearg {
- const char *soa_longname; /* long snap name */
- const char *soa_snapname; /* short snap name */
- snapallarg_t *soa_saa;
-} snaponearg_t;
-
-static int
-snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
-{
- objset_t *os = arg1;
- snaponearg_t *soa = arg2;
- snapallarg_t *saa = soa->soa_saa;
- int error;
-
- /* The props have already been checked by zfs_check_userprops(). */
-
- error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
- soa->soa_snapname, tx);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list