summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2016-05-16 11:33:05 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2016-05-16 11:33:05 +0000
commit1b61f1b86caf956a46c4dc4c8e36312f0b489fd7 (patch)
tree56f2914895345df8fd35c18a3e91726d8180a74e
parent49c1eac6be431a9eff055d8757270b3c9fb1678a (diff)
parent8df0bcf0df7622a075cc6e52f659d2fcfdd08cdc (diff)
downloadillumos-joyent-1b61f1b86caf956a46c4dc4c8e36312f0b489fd7.tar.gz
[illumos-gate merge]
commit 8df0bcf0df7622a075cc6e52f659d2fcfdd08cdc 6513 partially filled holes lose birth time commit 0d8fa8f8eba3ea46bc79d73445009505d1dd5d7d 6902 speed up listing of snapshots if requesting name only and sorting by name Conflicts: usr/src/lib/libzfs/common/libzfs_iter.c usr/src/lib/libzfs/common/libzfs_impl.h
-rw-r--r--usr/src/cmd/ndmpd/ndmp/ndmpd_chkpnt.c3
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_vss.c9
-rw-r--r--usr/src/cmd/zfs/zfs_iter.c28
-rw-r--r--usr/src/cmd/zfs/zfs_iter.h5
-rw-r--r--usr/src/cmd/zfs/zfs_main.c17
-rw-r--r--usr/src/cmd/zoneadm/zfs.c15
-rw-r--r--usr/src/lib/libbe/common/be_create.c11
-rw-r--r--usr/src/lib/libbe/common/be_list.c4
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h3
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c19
-rw-r--r--usr/src/lib/libzfs/common/libzfs_impl.h3
-rw-r--r--usr/src/lib/libzfs/common/libzfs_iter.c25
-rw-r--r--usr/src/lib/libzfs/common/libzfs_sendrecv.c3
-rw-r--r--usr/src/uts/common/fs/zfs/arc.c20
-rw-r--r--usr/src/uts/common/fs/zfs/dbuf.c123
-rw-r--r--usr/src/uts/common/fs/zfs/dmu.c15
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_objset.c8
-rw-r--r--usr/src/uts/common/fs/zfs/dnode_sync.c24
-rw-r--r--usr/src/uts/common/fs/zfs/sys/arc.h10
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h2
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zio.h10
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ioctl.c4
-rw-r--r--usr/src/uts/common/fs/zfs/zio.c31
23 files changed, 305 insertions, 87 deletions
diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd_chkpnt.c b/usr/src/cmd/ndmpd/ndmp/ndmpd_chkpnt.c
index de84284c68..ea391590db 100644
--- a/usr/src/cmd/ndmpd/ndmp/ndmpd_chkpnt.c
+++ b/usr/src/cmd/ndmpd/ndmp/ndmpd_chkpnt.c
@@ -2,6 +2,7 @@
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
+ * Copyright (c) 2016 Martin Matuska. All rights reserved.
*/
/*
@@ -115,7 +116,7 @@ ndmp_has_backup_snapshot(char *volname, char *jobname)
(void) snprintf(chname, ZFS_MAXNAMELEN, "@%s", jobname);
snp.snp_name = chname;
- (void) zfs_iter_snapshots(zhp, ndmp_has_backup, &snp);
+ (void) zfs_iter_snapshots(zhp, B_FALSE, ndmp_has_backup, &snp);
zfs_close(zhp);
(void) mutex_unlock(&zlib_mtx);
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_vss.c b/usr/src/cmd/smbsrv/smbd/smbd_vss.c
index be78fc1ccc..759c696513 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_vss.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_vss.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Martin Matuska. All rights reserved.
*/
#include <synch.h>
@@ -120,7 +121,7 @@ smbd_vss_get_count(const char *path, uint32_t *count)
return (-1);
}
- (void) zfs_iter_snapshots(zfshd, smbd_vss_iterate_count,
+ (void) zfs_iter_snapshots(zfshd, B_FALSE, smbd_vss_iterate_count,
(void *)&vss_count);
if (vss_count.vc_count > SMBD_VSS_SNAPSHOT_MAX)
@@ -183,8 +184,8 @@ smbd_vss_get_snapshots(const char *path, uint32_t count,
return;
}
- (void) zfs_iter_snapshots(zfshd, smbd_vss_iterate_get_uint64_date,
- (void *)&vss_uint64_date);
+ (void) zfs_iter_snapshots(zfshd, B_FALSE,
+ smbd_vss_iterate_get_uint64_date, (void *)&vss_uint64_date);
*num_gmttokens = vss_uint64_date.gd_return_count;
*return_count = vss_uint64_date.gd_return_count;
@@ -261,7 +262,7 @@ smbd_vss_map_gmttoken(const char *path, char *gmttoken, time_t toktime,
return (-1);
}
- (void) zfs_iter_snapshots(zfshd, smbd_vss_iterate_map_gmttoken,
+ (void) zfs_iter_snapshots(zfshd, B_FALSE, smbd_vss_iterate_map_gmttoken,
(void *)&vss_map_gmttoken);
/* compare the zfs snapshot name and the local snap name */
diff --git a/usr/src/cmd/zfs/zfs_iter.c b/usr/src/cmd/zfs/zfs_iter.c
index 3581a4715e..e32748d290 100644
--- a/usr/src/cmd/zfs/zfs_iter.c
+++ b/usr/src/cmd/zfs/zfs_iter.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -136,7 +137,9 @@ zfs_callback(zfs_handle_t *zhp, void *data)
(void) zfs_iter_filesystems(zhp, zfs_callback, data);
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
ZFS_TYPE_BOOKMARK)) == 0) && include_snaps)
- (void) zfs_iter_snapshots(zhp, zfs_callback, data);
+ (void) zfs_iter_snapshots(zhp,
+ (cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
+ data);
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks)
(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
@@ -193,6 +196,14 @@ zfs_free_sort_columns(zfs_sort_column_t *sc)
}
}
+boolean_t
+zfs_sort_only_by_name(const zfs_sort_column_t *sc)
+{
+
+ return (sc != NULL && sc->sc_next == NULL &&
+ sc->sc_prop == ZFS_PROP_NAME);
+}
+
/* ARGSUSED */
static int
zfs_compare(const void *larg, const void *rarg, void *unused)
@@ -233,7 +244,13 @@ zfs_compare(const void *larg, const void *rarg, void *unused)
lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG);
rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG);
- if (lcreate < rcreate)
+ /*
+ * Both lcreate and rcreate being 0 means we don't have
+ * properties and we should compare full name.
+ */
+ if (lcreate == 0 && rcreate == 0)
+ ret = strcmp(lat + 1, rat + 1);
+ else if (lcreate < rcreate)
ret = -1;
else if (lcreate > rcreate)
ret = 1;
@@ -299,7 +316,14 @@ zfs_sort(const void *larg, const void *rarg, void *data)
if (rvalid)
verify(nvlist_lookup_string(rval,
ZPROP_VALUE, &rstr) == 0);
+ } else if (psc->sc_prop == ZFS_PROP_NAME) {
+ lvalid = rvalid = B_TRUE;
+
+ (void) strlcpy(lbuf, zfs_get_name(l), sizeof (lbuf));
+ (void) strlcpy(rbuf, zfs_get_name(r), sizeof (rbuf));
+ lstr = lbuf;
+ rstr = rbuf;
} else if (zfs_prop_is_string(psc->sc_prop)) {
lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf,
sizeof (lbuf), NULL, NULL, 0, B_TRUE) == 0);
diff --git a/usr/src/cmd/zfs/zfs_iter.h b/usr/src/cmd/zfs/zfs_iter.h
index d896d7cf57..b89b466ce6 100644
--- a/usr/src/cmd/zfs/zfs_iter.h
+++ b/usr/src/cmd/zfs/zfs_iter.h
@@ -22,6 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
@@ -45,12 +46,14 @@ typedef struct zfs_sort_column {
#define ZFS_ITER_PROP_LISTSNAPS (1 << 2)
#define ZFS_ITER_DEPTH_LIMIT (1 << 3)
#define ZFS_ITER_RECVD_PROPS (1 << 4)
-#define ZFS_ITER_LITERAL_PROPS (1 << 5)
+#define ZFS_ITER_SIMPLE (1 << 5)
+#define ZFS_ITER_LITERAL_PROPS (1 << 6)
int zfs_for_each(int, char **, int options, zfs_type_t,
zfs_sort_column_t *, zprop_list_t **, int, zfs_iter_f, void *);
int zfs_add_sort_column(zfs_sort_column_t **, const char *, boolean_t);
void zfs_free_sort_columns(zfs_sort_column_t *);
+boolean_t zfs_sort_only_by_name(const zfs_sort_column_t *);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index 53630b21b9..ff21aede8a 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -24,6 +24,7 @@
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
@@ -3035,7 +3036,12 @@ print_dataset(zfs_handle_t *zhp, list_cbdata_t *cb)
first = B_FALSE;
}
- if (pl->pl_prop != ZPROP_INVAL) {
+ if (pl->pl_prop == ZFS_PROP_NAME) {
+ (void) strlcpy(property, zfs_get_name(zhp),
+ sizeof (property));
+ propstr = property;
+ right_justify = zfs_prop_align_right(pl->pl_prop);
+ } else if (pl->pl_prop != ZPROP_INVAL) {
if (zfs_prop_get(zhp, pl->pl_prop, property,
sizeof (property), NULL, NULL, 0,
cb->cb_literal) != 0)
@@ -3209,6 +3215,13 @@ zfs_do_list(int argc, char **argv)
fields = default_fields;
/*
+ * If we are only going to list snapshot names and sort by name,
+ * then we can use faster version.
+ */
+ if (strcmp(fields, "name") == 0 && zfs_sort_only_by_name(sortcol))
+ flags |= ZFS_ITER_SIMPLE;
+
+ /*
* If "-o space" and no types were specified, don't display snapshots.
*/
if (strcmp(fields, "space") == 0 && types_specified == B_FALSE)
@@ -3529,7 +3542,7 @@ zfs_do_rollback(int argc, char **argv)
cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
cb.cb_first = B_TRUE;
cb.cb_error = 0;
- if ((ret = zfs_iter_snapshots(zhp, rollback_check, &cb)) != 0)
+ if ((ret = zfs_iter_snapshots(zhp, B_FALSE, rollback_check, &cb)) != 0)
goto out;
if ((ret = zfs_iter_bookmarks(zhp, rollback_check, &cb)) != 0)
goto out;
diff --git a/usr/src/cmd/zoneadm/zfs.c b/usr/src/cmd/zoneadm/zfs.c
index 327daec20c..a318a06dfb 100644
--- a/usr/src/cmd/zoneadm/zfs.c
+++ b/usr/src/cmd/zoneadm/zfs.c
@@ -23,6 +23,7 @@
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2016 Martin Matuska. All rights reserved.
*/
/*
@@ -247,7 +248,7 @@ get_snap_max(zfs_handle_t *zhp, void *data)
cbp->max = num;
}
- res = zfs_iter_snapshots(zhp, get_snap_max, data);
+ res = zfs_iter_snapshots(zhp, B_FALSE, get_snap_max, data);
zfs_close(zhp);
return (res);
}
@@ -276,7 +277,7 @@ take_snapshot(zfs_handle_t *zhp, char *snapshot_name, int snap_size,
cb.len = strlen(template);
cb.max = 0;
- if (zfs_iter_snapshots(zhp, get_snap_max, &cb) != 0)
+ if (zfs_iter_snapshots(zhp, B_FALSE, get_snap_max, &cb) != 0)
return (Z_ERR);
cb.max++;
@@ -736,7 +737,7 @@ promote_clone(zfs_handle_t *src_zhp, zfs_handle_t *cln_zhp)
sd.len = strlen(template);
sd.max = 0;
- if (zfs_iter_snapshots(cln_zhp, get_snap_max, &sd) != 0)
+ if (zfs_iter_snapshots(cln_zhp, B_FALSE, get_snap_max, &sd) != 0)
return (Z_ERR);
/*
@@ -749,7 +750,7 @@ promote_clone(zfs_handle_t *src_zhp, zfs_handle_t *cln_zhp)
sd.len = strlen(template);
sd.num = 0;
- if (zfs_iter_snapshots(src_zhp, get_snap_max, &sd) != 0)
+ if (zfs_iter_snapshots(src_zhp, B_FALSE, get_snap_max, &sd) != 0)
return (Z_ERR);
/*
@@ -758,7 +759,7 @@ promote_clone(zfs_handle_t *src_zhp, zfs_handle_t *cln_zhp)
*/
sd.max++;
sd.cntr = 0;
- if (zfs_iter_snapshots(src_zhp, rename_snap, &sd) != 0)
+ if (zfs_iter_snapshots(src_zhp, B_FALSE, rename_snap, &sd) != 0)
return (Z_ERR);
/* close and reopen the clone dataset to get the latest info */
@@ -790,7 +791,7 @@ promote_all_clones(zfs_handle_t *zhp)
cd.origin_creation = 0;
cd.snapshot = NULL;
- if (zfs_iter_snapshots(zhp, find_clone, &cd) != 0) {
+ if (zfs_iter_snapshots(zhp, B_FALSE, find_clone, &cd) != 0) {
zfs_close(zhp);
return (Z_ERR);
}
@@ -1053,7 +1054,7 @@ destroy_zfs(char *zonepath)
return (Z_ERR);
/* Now cleanup any snapshots remaining. */
- if (zfs_iter_snapshots(zhp, rm_snap, NULL) != 0) {
+ if (zfs_iter_snapshots(zhp, B_FALSE, rm_snap, NULL) != 0) {
zfs_close(zhp);
return (Z_ERR);
}
diff --git a/usr/src/lib/libbe/common/be_create.c b/usr/src/lib/libbe/common/be_create.c
index d06c9b02da..6ea2324200 100644
--- a/usr/src/lib/libbe/common/be_create.c
+++ b/usr/src/lib/libbe/common/be_create.c
@@ -23,6 +23,7 @@
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2016 Martin Matuska. All rights reserved.
*/
/*
@@ -483,7 +484,8 @@ be_destroy(nvlist_t *be_attrs)
* Check if BE has snapshots and BE_DESTROY_FLAG_SNAPSHOTS
* is not set.
*/
- (void) zfs_iter_snapshots(zhp, be_has_snapshot_callback, &bs_found);
+ (void) zfs_iter_snapshots(zhp, B_FALSE, be_has_snapshot_callback,
+ &bs_found);
if (!dd.destroy_snaps && bs_found) {
ZFS_CLOSE(zhp);
return (BE_ERR_SS_EXISTS);
@@ -2552,7 +2554,8 @@ be_destroy_callback(zfs_handle_t *zhp, void *data)
* Iterate through this file system's snapshots and
* destroy them before destroying the file system itself.
*/
- if ((ret = zfs_iter_snapshots(zhp, be_destroy_callback, dd))
+ if ((ret = zfs_iter_snapshots(zhp, B_FALSE, be_destroy_callback,
+ dd))
!= 0) {
ZFS_CLOSE(zhp);
return (ret);
@@ -2627,8 +2630,8 @@ be_demote_callback(zfs_handle_t *zhp, void *data)
for (i = 0; i < 2; i++) {
- if (zfs_iter_snapshots(zhp, be_demote_find_clone_callback, &dd)
- != 0) {
+ if (zfs_iter_snapshots(zhp, B_FALSE,
+ be_demote_find_clone_callback, &dd) != 0) {
be_print_err(gettext("be_demote_callback: "
"failed to iterate snapshots for %s: %s\n"),
zfs_get_name(zhp), libzfs_error_description(g_zfs));
diff --git a/usr/src/lib/libbe/common/be_list.c b/usr/src/lib/libbe/common/be_list.c
index ddf3f652dd..2534b7c32c 100644
--- a/usr/src/lib/libbe/common/be_list.c
+++ b/usr/src/lib/libbe/common/be_list.c
@@ -28,6 +28,7 @@
* Copyright 2011 Joyent, Inc. All rights reserved.
* Copyright 2015 Toomas Soome <tsoome@me.com>
* Copyright 2015 Gary Mills
+ * Copyright (c) 2016 Martin Matuska. All rights reserved.
*/
#include <assert.h>
@@ -506,7 +507,8 @@ be_get_list_callback(zpool_handle_t *zlp, void *data)
zpool_close(zlp);
return (ret);
}
- ret = zfs_iter_snapshots(zhp, be_add_children_callback, cb);
+ ret = zfs_iter_snapshots(zhp, B_FALSE, be_add_children_callback,
+ cb);
}
if (ret == 0)
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index 795b4e2ed8..29edae5109 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
@@ -538,7 +539,7 @@ extern int zfs_iter_root(libzfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_children(zfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_dependents(zfs_handle_t *, boolean_t, zfs_iter_f, void *);
extern int zfs_iter_filesystems(zfs_handle_t *, zfs_iter_f, void *);
-extern int zfs_iter_snapshots(zfs_handle_t *, zfs_iter_f, void *);
+extern int zfs_iter_snapshots(zfs_handle_t *, boolean_t, zfs_iter_f, void *);
extern int zfs_iter_snapshots_sorted(zfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_snapspec(zfs_handle_t *, const char *, zfs_iter_f, void *);
extern int zfs_iter_bookmarks(zfs_handle_t *, zfs_iter_f, void *);
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index 2b613c04f0..566130dd81 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -24,6 +24,7 @@
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
* Copyright (c) 2013 Martin Matuska. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -523,6 +524,22 @@ make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
}
zfs_handle_t *
+make_dataset_simple_handle_zc(zfs_handle_t *pzhp, zfs_cmd_t *zc)
+{
+ zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
+
+ if (zhp == NULL)
+ return (NULL);
+
+ zhp->zfs_hdl = pzhp->zfs_hdl;
+ (void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
+ zhp->zfs_head_type = pzhp->zfs_type;
+ zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
+ zhp->zpool_hdl = zpool_handle(zhp);
+ return (zhp);
+}
+
+zfs_handle_t *
zfs_handle_dup(zfs_handle_t *zhp_orig)
{
zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
@@ -3814,7 +3831,7 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
cb.cb_force = force;
cb.cb_target = snap->zfs_name;
cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
- (void) zfs_iter_snapshots(zhp, rollback_destroy, &cb);
+ (void) zfs_iter_snapshots(zhp, B_FALSE, rollback_destroy, &cb);
(void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
if (cb.cb_error)
diff --git a/usr/src/lib/libzfs/common/libzfs_impl.h b/usr/src/lib/libzfs/common/libzfs_impl.h
index 9d98718dcb..4d34e68492 100644
--- a/usr/src/lib/libzfs/common/libzfs_impl.h
+++ b/usr/src/lib/libzfs/common/libzfs_impl.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -151,9 +152,9 @@ int zpool_standard_error_fmt(libzfs_handle_t *, int, const char *, ...);
int get_dependents(libzfs_handle_t *, boolean_t, const char *, char ***,
size_t *);
zfs_handle_t *make_dataset_handle_zc(libzfs_handle_t *, zfs_cmd_t *);
+zfs_handle_t *make_dataset_simple_handle_zc(zfs_handle_t *, zfs_cmd_t *);
int libzfs_cmd_set_cachedprops(libzfs_handle_t *, zfs_cmd_t *);
-
int zprop_parse_value(libzfs_handle_t *, nvpair_t *, int, zfs_type_t,
nvlist_t *, char **, uint64_t *, const char *);
int zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp,
diff --git a/usr/src/lib/libzfs/common/libzfs_iter.c b/usr/src/lib/libzfs/common/libzfs_iter.c
index 54a177e5ed..155161d661 100644
--- a/usr/src/lib/libzfs/common/libzfs_iter.c
+++ b/usr/src/lib/libzfs/common/libzfs_iter.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
@@ -141,7 +142,8 @@ zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
* Iterate over all snapshots
*/
int
-zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
+zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
+ void *data)
{
zfs_cmd_t zc = { 0 };
zfs_handle_t *nzhp;
@@ -151,18 +153,25 @@ zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
zhp->zfs_type == ZFS_TYPE_BOOKMARK)
return (0);
+
if (zhp->zfs_hdl->libzfs_cachedprops &&
libzfs_cmd_set_cachedprops(zhp->zfs_hdl, &zc) != 0)
return (-1);
+ zc.zc_simple = simple;
+
+
if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT,
&zc)) == 0) {
- if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
- &zc)) == NULL)
+ if (simple)
+ nzhp = make_dataset_simple_handle_zc(zhp, &zc);
+ else
+ nzhp = make_dataset_handle_zc(zhp->zfs_hdl, &zc);
+ if (nzhp == NULL)
continue;
if ((ret = func(nzhp, data)) != 0) {
@@ -293,7 +302,7 @@ zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data)
avl_create(&avl, zfs_snapshot_compare,
sizeof (zfs_node_t), offsetof(zfs_node_t, zn_avlnode));
- ret = zfs_iter_snapshots(zhp, zfs_sort_snaps, &avl);
+ ret = zfs_iter_snapshots(zhp, B_FALSE, zfs_sort_snaps, &avl);
for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node))
ret |= callback(node->zn_handle, data);
@@ -438,7 +447,7 @@ zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0)
return (ret);
- return (zfs_iter_snapshots(zhp, func, data));
+ return (zfs_iter_snapshots(zhp, B_FALSE, func, data));
}
@@ -499,8 +508,10 @@ iter_dependents_cb(zfs_handle_t *zhp, void *arg)
isf.next = ida->stack;
ida->stack = &isf;
err = zfs_iter_filesystems(zhp, iter_dependents_cb, ida);
- if (err == 0)
- err = zfs_iter_snapshots(zhp, iter_dependents_cb, ida);
+ if (err == 0) {
+ err = zfs_iter_snapshots(zhp, B_FALSE,
+ iter_dependents_cb, ida);
+ }
ida->stack = isf.next;
}
diff --git a/usr/src/lib/libzfs/common/libzfs_sendrecv.c b/usr/src/lib/libzfs/common/libzfs_sendrecv.c
index 81d79d8976..adc5f68414 100644
--- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c
+++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c
@@ -23,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -841,7 +842,7 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
sd->parent_fromsnap_guid = 0;
VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0));
VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0));
- (void) zfs_iter_snapshots(zhp, send_iterate_snap, sd);
+ (void) zfs_iter_snapshots(zhp, B_FALSE, send_iterate_snap, sd);
VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
nvlist_free(sd->parent_snaps);
diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c
index 7cd1a6d7a8..96e8411251 100644
--- a/usr/src/uts/common/fs/zfs/arc.c
+++ b/usr/src/uts/common/fs/zfs/arc.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2014 by Saso Kiselkov. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
@@ -674,6 +674,7 @@ typedef struct arc_write_callback arc_write_callback_t;
struct arc_write_callback {
void *awcb_private;
arc_done_func_t *awcb_ready;
+ arc_done_func_t *awcb_children_ready;
arc_done_func_t *awcb_physdone;
arc_done_func_t *awcb_done;
arc_buf_t *awcb_buf;
@@ -4683,6 +4684,15 @@ arc_write_ready(zio_t *zio)
hdr->b_flags |= ARC_FLAG_IO_IN_PROGRESS;
}
+static void
+arc_write_children_ready(zio_t *zio)
+{
+ arc_write_callback_t *callback = zio->io_private;
+ arc_buf_t *buf = callback->awcb_buf;
+
+ callback->awcb_children_ready(zio, buf, callback->awcb_private);
+}
+
/*
* The SPA calls this callback for each physical write that happens on behalf
* of a logical write. See the comment in dbuf_write_physdone() for details.
@@ -4779,7 +4789,8 @@ arc_write_done(zio_t *zio)
zio_t *
arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
blkptr_t *bp, arc_buf_t *buf, boolean_t l2arc, boolean_t l2arc_compress,
- const zio_prop_t *zp, arc_done_func_t *ready, arc_done_func_t *physdone,
+ const zio_prop_t *zp, arc_done_func_t *ready,
+ arc_done_func_t *children_ready, arc_done_func_t *physdone,
arc_done_func_t *done, void *private, zio_priority_t priority,
int zio_flags, const zbookmark_phys_t *zb)
{
@@ -4799,13 +4810,16 @@ arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
hdr->b_flags |= ARC_FLAG_L2COMPRESS;
callback = kmem_zalloc(sizeof (arc_write_callback_t), KM_SLEEP);
callback->awcb_ready = ready;
+ callback->awcb_children_ready = children_ready;
callback->awcb_physdone = physdone;
callback->awcb_done = done;
callback->awcb_private = private;
callback->awcb_buf = buf;
zio = zio_write(pio, spa, txg, bp, buf->b_data, hdr->b_size, zp,
- arc_write_ready, arc_write_physdone, arc_write_done, callback,
+ arc_write_ready,
+ (children_ready != NULL) ? arc_write_children_ready : NULL,
+ arc_write_physdone, arc_write_done, callback,
priority, zio_flags, zb);
return (zio);
diff --git a/usr/src/uts/common/fs/zfs/dbuf.c b/usr/src/uts/common/fs/zfs/dbuf.c
index 47abc99dae..64a4cb74d0 100644
--- a/usr/src/uts/common/fs/zfs/dbuf.c
+++ b/usr/src/uts/common/fs/zfs/dbuf.c
@@ -486,13 +486,49 @@ dbuf_verify(dmu_buf_impl_t *db)
* If the blkptr isn't set but they have nonzero data,
* it had better be dirty, otherwise we'll lose that
* data when we evict this buffer.
+ *
+ * There is an exception to this rule for indirect blocks; in
+ * this case, if the indirect block is a hole, we fill in a few
+ * fields on each of the child blocks (importantly, birth time)
+ * to prevent hole birth times from being lost when you
+ * partially fill in a hole.
*/
if (db->db_dirtycnt == 0) {
- uint64_t *buf = db->db.db_data;
- int i;
+ if (db->db_level == 0) {
+ uint64_t *buf = db->db.db_data;
+ int i;
- for (i = 0; i < db->db.db_size >> 3; i++) {
- ASSERT(buf[i] == 0);
+ for (i = 0; i < db->db.db_size >> 3; i++) {
+ ASSERT(buf[i] == 0);
+ }
+ } else {
+ blkptr_t *bps = db->db.db_data;
+ ASSERT3U(1 << DB_DNODE(db)->dn_indblkshift, ==,
+ db->db.db_size);
+ /*
+ * We want to verify that all the blkptrs in the
+ * indirect block are holes, but we may have
+ * automatically set up a few fields for them.
+ * We iterate through each blkptr and verify
+ * they only have those fields set.
+ */
+ for (int i = 0;
+ i < db->db.db_size / sizeof (blkptr_t);
+ i++) {
+ blkptr_t *bp = &bps[i];
+ ASSERT(ZIO_CHECKSUM_IS_ZERO(
+ &bp->blk_cksum));
+ ASSERT(
+ DVA_IS_EMPTY(&bp->blk_dva[0]) &&
+ DVA_IS_EMPTY(&bp->blk_dva[1]) &&
+ DVA_IS_EMPTY(&bp->blk_dva[2]));
+ ASSERT0(bp->blk_fill);
+ ASSERT0(bp->blk_pad[0]);
+ ASSERT0(bp->blk_pad[1]);
+ ASSERT(!BP_IS_EMBEDDED(bp));
+ ASSERT(BP_IS_HOLE(bp));
+ ASSERT0(bp->blk_phys_birth);
+ }
}
}
}
@@ -671,10 +707,31 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
BP_IS_HOLE(db->db_blkptr)))) {
arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db);
- DB_DNODE_EXIT(db);
dbuf_set_data(db, arc_buf_alloc(db->db_objset->os_spa,
db->db.db_size, db, type));
bzero(db->db.db_data, db->db.db_size);
+
+ if (db->db_blkptr != NULL && db->db_level > 0 &&
+ BP_IS_HOLE(db->db_blkptr) &&
+ db->db_blkptr->blk_birth != 0) {
+ blkptr_t *bps = db->db.db_data;
+ for (int i = 0; i < ((1 <<
+ DB_DNODE(db)->dn_indblkshift) / sizeof (blkptr_t));
+ i++) {
+ blkptr_t *bp = &bps[i];
+ ASSERT3U(BP_GET_LSIZE(db->db_blkptr), ==,
+ 1 << dn->dn_indblkshift);
+ BP_SET_LSIZE(bp,
+ BP_GET_LEVEL(db->db_blkptr) == 1 ?
+ dn->dn_datablksz :
+ BP_GET_LSIZE(db->db_blkptr));
+ BP_SET_TYPE(bp, BP_GET_TYPE(db->db_blkptr));
+ BP_SET_LEVEL(bp,
+ BP_GET_LEVEL(db->db_blkptr) - 1);
+ BP_SET_BIRTH(bp, db->db_blkptr->blk_birth, 0);
+ }
+ }
+ DB_DNODE_EXIT(db);
db->db_state = DB_CACHED;
mutex_exit(&db->db_mtx);
return;
@@ -2960,6 +3017,45 @@ dbuf_write_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
rw_exit(&dn->dn_struct_rwlock);
}
+/* ARGSUSED */
+/*
+ * This function gets called just prior to running through the compression
+ * stage of the zio pipeline. If we're an indirect block comprised of only
+ * holes, then we want this indirect to be compressed away to a hole. In
+ * order to do that we must zero out any information about the holes that
+ * this indirect points to prior to before we try to compress it.
+ */
+static void
+dbuf_write_children_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
+{
+ dmu_buf_impl_t *db = vdb;
+ dnode_t *dn;
+ blkptr_t *bp;
+ uint64_t i;
+ int epbs;
+
+ ASSERT3U(db->db_level, >, 0);
+ DB_DNODE_ENTER(db);
+ dn = DB_DNODE(db);
+ epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
+
+ /* Determine if all our children are holes */
+ for (i = 0, bp = db->db.db_data; i < 1 << epbs; i++, bp++) {
+ if (!BP_IS_HOLE(bp))
+ break;
+ }
+
+ /*
+ * If all the children are holes, then zero them all out so that
+ * we may get compressed away.
+ */
+ if (i == 1 << epbs) {
+ /* didn't find any non-holes */
+ bzero(db->db.db_data, db->db.db_size);
+ }
+ DB_DNODE_EXIT(db);
+}
+
/*
* The SPA will call this callback several times for each zio - once
* for every physical child i/o (zio->io_phys_children times). This
@@ -3214,7 +3310,8 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
dr->dr_zio = zio_write(zio, os->os_spa, txg,
&dr->dr_bp_copy, contents, db->db.db_size, &zp,
- dbuf_write_override_ready, NULL, dbuf_write_override_done,
+ dbuf_write_override_ready, NULL, NULL,
+ dbuf_write_override_done,
dr, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
mutex_enter(&db->db_mtx);
dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
@@ -3226,14 +3323,26 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
zp.zp_checksum == ZIO_CHECKSUM_NOPARITY);
dr->dr_zio = zio_write(zio, os->os_spa, txg,
&dr->dr_bp_copy, NULL, db->db.db_size, &zp,
- dbuf_write_nofill_ready, NULL, dbuf_write_nofill_done, db,
+ dbuf_write_nofill_ready, NULL, NULL,
+ dbuf_write_nofill_done, db,
ZIO_PRIORITY_ASYNC_WRITE,
ZIO_FLAG_MUSTSUCCEED | ZIO_FLAG_NODATA, &zb);
} else {
ASSERT(arc_released(data));
+
+ /*
+ * For indirect blocks, we want to setup the children
+ * ready callback so that we can properly handle an indirect
+ * block that only contains holes.
+ */
+ arc_done_func_t *children_ready_cb = NULL;
+ if (db->db_level != 0)
+ children_ready_cb = dbuf_write_children_ready;
+
dr->dr_zio = arc_write(zio, os->os_spa, txg,
&dr->dr_bp_copy, data, DBUF_IS_L2CACHEABLE(db),
DBUF_IS_L2COMPRESSIBLE(db), &zp, dbuf_write_ready,
+ children_ready_cb,
dbuf_write_physdone, dbuf_write_done, db,
ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
}
diff --git a/usr/src/uts/common/fs/zfs/dmu.c b/usr/src/uts/common/fs/zfs/dmu.c
index 48c2fbf0c0..8ce9178ad2 100644
--- a/usr/src/uts/common/fs/zfs/dmu.c
+++ b/usr/src/uts/common/fs/zfs/dmu.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
*/
/* Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */
/* Copyright (c) 2013, Joyent, Inc. All rights reserved. */
@@ -1507,10 +1507,11 @@ dmu_sync_late_arrival(zio_t *pio, objset_t *os, dmu_sync_cb_t *done, zgd_t *zgd,
dsa->dsa_zgd = zgd;
dsa->dsa_tx = tx;
- zio_nowait(zio_write(pio, os->os_spa, dmu_tx_get_txg(tx), zgd->zgd_bp,
- zgd->zgd_db->db_data, zgd->zgd_db->db_size, zp,
- dmu_sync_late_arrival_ready, NULL, dmu_sync_late_arrival_done, dsa,
- ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, zb));
+ zio_nowait(zio_write(pio, os->os_spa, dmu_tx_get_txg(tx),
+ zgd->zgd_bp, zgd->zgd_db->db_data, zgd->zgd_db->db_size,
+ zp, dmu_sync_late_arrival_ready, NULL,
+ NULL, dmu_sync_late_arrival_done, dsa, ZIO_PRIORITY_SYNC_WRITE,
+ ZIO_FLAG_CANFAIL, zb));
return (0);
}
@@ -1663,8 +1664,8 @@ dmu_sync(zio_t *pio, uint64_t txg, dmu_sync_cb_t *done, zgd_t *zgd)
zio_nowait(arc_write(pio, os->os_spa, txg,
bp, dr->dt.dl.dr_data, DBUF_IS_L2CACHEABLE(db),
DBUF_IS_L2COMPRESSIBLE(db), &zp, dmu_sync_ready,
- NULL, dmu_sync_done, dsa, ZIO_PRIORITY_SYNC_WRITE,
- ZIO_FLAG_CANFAIL, &zb));
+ NULL, NULL, dmu_sync_done, dsa,
+ ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, &zb));
return (0);
}
diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c
index 367dbcb9c2..82c585487e 100644
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.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, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
@@ -1116,9 +1116,9 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
zio = arc_write(pio, os->os_spa, tx->tx_txg,
os->os_rootbp, os->os_phys_buf, DMU_OS_IS_L2CACHEABLE(os),
- DMU_OS_IS_L2COMPRESSIBLE(os), &zp, dmu_objset_write_ready,
- NULL, dmu_objset_write_done, os, ZIO_PRIORITY_ASYNC_WRITE,
- ZIO_FLAG_MUSTSUCCEED, &zb);
+ DMU_OS_IS_L2COMPRESSIBLE(os),
+ &zp, dmu_objset_write_ready, NULL, NULL, dmu_objset_write_done,
+ os, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
/*
* Sync special dnodes - the parent IO for the sync is the root block
diff --git a/usr/src/uts/common/fs/zfs/dnode_sync.c b/usr/src/uts/common/fs/zfs/dnode_sync.c
index 9aee513818..7179c41cbf 100644
--- a/usr/src/uts/common/fs/zfs/dnode_sync.c
+++ b/usr/src/uts/common/fs/zfs/dnode_sync.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
*/
@@ -60,20 +60,14 @@ dnode_increase_indirection(dnode_t *dn, dmu_tx_t *tx)
dprintf("os=%p obj=%llu, increase to %d\n", dn->dn_objset,
dn->dn_object, dn->dn_phys->dn_nlevels);
- /* check for existing blkptrs in the dnode */
- for (i = 0; i < nblkptr; i++)
- if (!BP_IS_HOLE(&dn->dn_phys->dn_blkptr[i]))
- break;
- if (i != nblkptr) {
- /* transfer dnode's block pointers to new indirect block */
- (void) dbuf_read(db, NULL, DB_RF_MUST_SUCCEED|DB_RF_HAVESTRUCT);
- ASSERT(db->db.db_data);
- ASSERT(arc_released(db->db_buf));
- ASSERT3U(sizeof (blkptr_t) * nblkptr, <=, db->db.db_size);
- bcopy(dn->dn_phys->dn_blkptr, db->db.db_data,
- sizeof (blkptr_t) * nblkptr);
- arc_buf_freeze(db->db_buf);
- }
+ /* transfer dnode's block pointers to new indirect block */
+ (void) dbuf_read(db, NULL, DB_RF_MUST_SUCCEED|DB_RF_HAVESTRUCT);
+ ASSERT(db->db.db_data);
+ ASSERT(arc_released(db->db_buf));
+ ASSERT3U(sizeof (blkptr_t) * nblkptr, <=, db->db.db_size);
+ bcopy(dn->dn_phys->dn_blkptr, db->db.db_data,
+ sizeof (blkptr_t) * nblkptr);
+ arc_buf_freeze(db->db_buf);
/* set dbuf's parent pointers to new indirect buf */
for (i = 0; i < nblkptr; i++) {
diff --git a/usr/src/uts/common/fs/zfs/sys/arc.h b/usr/src/uts/common/fs/zfs/sys/arc.h
index 899b72114b..f886a2ae3a 100644
--- a/usr/src/uts/common/fs/zfs/sys/arc.h
+++ b/usr/src/uts/common/fs/zfs/sys/arc.h
@@ -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, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
@@ -141,9 +141,11 @@ int arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
arc_flags_t *arc_flags, const zbookmark_phys_t *zb);
zio_t *arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
blkptr_t *bp, arc_buf_t *buf, boolean_t l2arc, boolean_t l2arc_compress,
- const zio_prop_t *zp, arc_done_func_t *ready, arc_done_func_t *physdone,
- arc_done_func_t *done, void *private, zio_priority_t priority,
- int zio_flags, const zbookmark_phys_t *zb);
+ const zio_prop_t *zp,
+ arc_done_func_t *ready, arc_done_func_t *child_ready,
+ arc_done_func_t *physdone, arc_done_func_t *done,
+ void *private, zio_priority_t priority, int zio_flags,
+ const zbookmark_phys_t *zb);
void arc_freed(spa_t *spa, const blkptr_t *bp);
void arc_set_callback(arc_buf_t *buf, arc_evict_func_t *func, void *private);
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h b/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h
index 3bc1a90322..9d17cda9c1 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h
+++ b/usr/src/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]
@@ -370,6 +371,7 @@ typedef struct zfs_cmd {
uint32_t zc_flags;
uint64_t zc_action_handle;
int zc_cleanup_fd;
+ uint8_t zc_simple;
boolean_t zc_resumable;
uint64_t zc_sendobj;
uint64_t zc_fromobj;
diff --git a/usr/src/uts/common/fs/zfs/sys/zio.h b/usr/src/uts/common/fs/zfs/sys/zio.h
index c783a8a31e..6d02c95b22 100644
--- a/usr/src/uts/common/fs/zfs/sys/zio.h
+++ b/usr/src/uts/common/fs/zfs/sys/zio.h
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
@@ -400,6 +400,7 @@ struct zio {
/* Callback info */
zio_done_func_t *io_ready;
+ zio_done_func_t *io_children_ready;
zio_done_func_t *io_physdone;
zio_done_func_t *io_done;
void *io_private;
@@ -466,9 +467,10 @@ extern zio_t *zio_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, void *data,
extern zio_t *zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
void *data, uint64_t size, const zio_prop_t *zp,
- zio_done_func_t *ready, zio_done_func_t *physdone, zio_done_func_t *done,
- void *private,
- zio_priority_t priority, enum zio_flag flags, const zbookmark_phys_t *zb);
+ zio_done_func_t *ready, zio_done_func_t *children_ready,
+ zio_done_func_t *physdone, zio_done_func_t *done,
+ void *private, zio_priority_t priority, enum zio_flag flags,
+ const zbookmark_phys_t *zb);
extern zio_t *zio_rewrite(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
void *data, uint64_t size, zio_done_func_t *done, void *private,
diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
index 886c4a05f6..7d9947b870 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
* Portions Copyright 2011 Martin Matuska
* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
@@ -2287,6 +2288,7 @@ top:
* zc_name name of filesystem
* zc_cookie zap cursor
* zc_nvlist_dst_size size of buffer for property nvlist
+ * zc_simple when set, only name is requested
*
* outputs:
* zc_name name of next snapshot
@@ -2332,7 +2334,7 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
zc->zc_name + strlen(zc->zc_name), &zc->zc_obj, &zc->zc_cookie,
NULL);
- if (error == 0) {
+ if (error == 0 && !zc->zc_simple) {
dsl_dataset_t *ds;
dsl_pool_t *dp = os->os_dsl_dataset->ds_dir->dd_pool;
diff --git a/usr/src/uts/common/fs/zfs/zio.c b/usr/src/uts/common/fs/zfs/zio.c
index 0bbeba3483..bfbcdfb511 100644
--- a/usr/src/uts/common/fs/zfs/zio.c
+++ b/usr/src/uts/common/fs/zfs/zio.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -708,9 +708,10 @@ zio_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
zio_t *
zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
void *data, uint64_t size, const zio_prop_t *zp,
- zio_done_func_t *ready, zio_done_func_t *physdone, zio_done_func_t *done,
- void *private,
- zio_priority_t priority, enum zio_flag flags, const zbookmark_phys_t *zb)
+ zio_done_func_t *ready, zio_done_func_t *children_ready,
+ zio_done_func_t *physdone, zio_done_func_t *done,
+ void *private, zio_priority_t priority, enum zio_flag flags,
+ const zbookmark_phys_t *zb)
{
zio_t *zio;
@@ -729,6 +730,7 @@ zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
ZIO_DDT_CHILD_WRITE_PIPELINE : ZIO_WRITE_PIPELINE);
zio->io_ready = ready;
+ zio->io_children_ready = children_ready;
zio->io_physdone = physdone;
zio->io_prop = *zp;
@@ -1103,6 +1105,16 @@ zio_write_bp_init(zio_t *zio)
if (!IO_IS_ALLOCATING(zio))
return (ZIO_PIPELINE_CONTINUE);
+ if (zio->io_children_ready != NULL) {
+ /*
+ * Now that all our children are ready, run the callback
+ * associated with this zio in case it wants to modify the
+ * data to be written.
+ */
+ ASSERT3U(zp->zp_level, >, 0);
+ zio->io_children_ready(zio);
+ }
+
ASSERT(zio->io_child_type != ZIO_CHILD_DDT);
if (zio->io_bp_override) {
@@ -2025,9 +2037,9 @@ zio_write_gang_block(zio_t *pio)
zio_nowait(zio_write(zio, spa, txg, &gbh->zg_blkptr[g],
(char *)pio->io_data + (pio->io_size - resid), lsize, &zp,
- zio_write_gang_member_ready, NULL, NULL, &gn->gn_child[g],
- pio->io_priority, ZIO_GANG_CHILD_FLAGS(pio),
- &pio->io_bookmark));
+ zio_write_gang_member_ready, NULL, NULL, NULL,
+ &gn->gn_child[g], pio->io_priority,
+ ZIO_GANG_CHILD_FLAGS(pio), &pio->io_bookmark));
}
/*
@@ -2416,7 +2428,7 @@ zio_ddt_write(zio_t *zio)
dio = zio_write(zio, spa, txg, bp, zio->io_orig_data,
zio->io_orig_size, &czp, NULL, NULL,
- zio_ddt_ditto_write_done, dde, zio->io_priority,
+ NULL, zio_ddt_ditto_write_done, dde, zio->io_priority,
ZIO_DDT_CHILD_FLAGS(zio), &zio->io_bookmark);
zio_push_transform(dio, zio->io_data, zio->io_size, 0, NULL);
@@ -2437,7 +2449,8 @@ zio_ddt_write(zio_t *zio)
ddt_phys_addref(ddp);
} else {
cio = zio_write(zio, spa, txg, bp, zio->io_orig_data,
- zio->io_orig_size, zp, zio_ddt_child_write_ready, NULL,
+ zio->io_orig_size, zp,
+ zio_ddt_child_write_ready, NULL, NULL,
zio_ddt_child_write_done, dde, zio->io_priority,
ZIO_DDT_CHILD_FLAGS(zio), &zio->io_bookmark);