summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libctf/common/ctf_lib.c6
-rw-r--r--lib/libdtrace/common/dt_aggregate.c89
-rw-r--r--lib/libdtrace/common/dt_cc.c302
-rw-r--r--lib/libdtrace/common/dt_consume.c186
-rw-r--r--lib/libdtrace/common/dt_dof.c14
-rw-r--r--lib/libdtrace/common/dt_errtags.h30
-rw-r--r--lib/libdtrace/common/dt_impl.h13
-rw-r--r--lib/libdtrace/common/dt_map.c172
-rw-r--r--lib/libdtrace/common/dt_open.c32
-rw-r--r--lib/libdtrace/common/dt_options.c27
-rw-r--r--lib/libdtrace/common/dt_parser.c8
-rw-r--r--lib/libdtrace/common/dt_pragma.c41
-rw-r--r--lib/libdtrace/common/dt_print.c648
-rw-r--r--lib/libdtrace/common/dt_printf.c12
-rw-r--r--lib/libdtrace/common/dt_program.c2
-rw-r--r--lib/libdtrace/common/dtrace.h19
-rw-r--r--lib/libdtrace/i386/regs.d.in151
-rw-r--r--lib/libnvpair/libnvpair.c5
-rw-r--r--lib/libuutil/common/uu_list.c7
-rw-r--r--lib/libzfs/common/libzfs.h111
-rw-r--r--lib/libzfs/common/libzfs_config.c83
-rw-r--r--lib/libzfs/common/libzfs_dataset.c918
-rw-r--r--lib/libzfs/common/libzfs_graph.c653
-rw-r--r--lib/libzfs/common/libzfs_impl.h12
-rw-r--r--lib/libzfs/common/libzfs_import.c18
-rw-r--r--lib/libzfs/common/libzfs_iter.c462
-rw-r--r--lib/libzfs/common/libzfs_pool.c363
-rw-r--r--lib/libzfs/common/libzfs_sendrecv.c642
-rw-r--r--lib/libzfs/common/libzfs_status.c18
-rw-r--r--lib/libzfs/common/libzfs_util.c42
-rw-r--r--lib/libzfs_core/common/libzfs_core.c477
-rw-r--r--lib/libzfs_core/common/libzfs_core.h62
-rw-r--r--lib/libzpool/common/kernel.c12
-rw-r--r--lib/libzpool/common/sys/zfs_context.h21
-rw-r--r--lib/libzpool/common/taskq.c103
35 files changed, 1454 insertions, 4307 deletions
diff --git a/lib/libctf/common/ctf_lib.c b/lib/libctf/common/ctf_lib.c
index 1c5c3f1d5f7e..6e599540a4f6 100644
--- a/lib/libctf/common/ctf_lib.c
+++ b/lib/libctf/common/ctf_lib.c
@@ -24,6 +24,8 @@
* Use is subject to license terms.
*/
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
@@ -35,9 +37,9 @@
#include <gelf.h>
#ifdef _LP64
-static const char *_libctf_zlib = "/usr/lib/64/libz.so.1";
+static const char *_libctf_zlib = "/usr/lib/64/libz.so";
#else
-static const char *_libctf_zlib = "/usr/lib/libz.so.1";
+static const char *_libctf_zlib = "/usr/lib/libz.so";
#endif
static struct {
diff --git a/lib/libdtrace/common/dt_aggregate.c b/lib/libdtrace/common/dt_aggregate.c
index bb766f71c466..2e66250b88d7 100644
--- a/lib/libdtrace/common/dt_aggregate.c
+++ b/lib/libdtrace/common/dt_aggregate.c
@@ -24,9 +24,7 @@
* Use is subject to license terms.
*/
-/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- */
+#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <strings.h>
@@ -206,83 +204,6 @@ dt_aggregate_lquantizedcmp(int64_t *lhs, int64_t *rhs)
return (0);
}
-static void
-dt_aggregate_llquantize(int64_t *existing, int64_t *new, size_t size)
-{
- int i;
-
- for (i = 1; i < size / sizeof (int64_t); i++)
- existing[i] = existing[i] + new[i];
-}
-
-static long double
-dt_aggregate_llquantizedsum(int64_t *llquanta)
-{
- int64_t arg = *llquanta++;
- uint16_t factor = DTRACE_LLQUANTIZE_FACTOR(arg);
- uint16_t low = DTRACE_LLQUANTIZE_LOW(arg);
- uint16_t high = DTRACE_LLQUANTIZE_HIGH(arg);
- uint16_t nsteps = DTRACE_LLQUANTIZE_NSTEP(arg);
- int bin = 0, order;
- int64_t value = 1, next, step;
- long double total;
-
- assert(nsteps >= factor);
- assert(nsteps % factor == 0);
-
- for (order = 0; order < low; order++)
- value *= factor;
-
- total = (long double)llquanta[bin++] * (long double)(value - 1);
-
- next = value * factor;
- step = next > nsteps ? next / nsteps : 1;
-
- while (order <= high) {
- assert(value < next);
- total += (long double)llquanta[bin++] * (long double)(value);
-
- if ((value += step) != next)
- continue;
-
- next = value * factor;
- step = next > nsteps ? next / nsteps : 1;
- order++;
- }
-
- return (total + (long double)llquanta[bin] * (long double)value);
-}
-
-static int
-dt_aggregate_llquantizedcmp(int64_t *lhs, int64_t *rhs)
-{
- long double lsum = dt_aggregate_llquantizedsum(lhs);
- long double rsum = dt_aggregate_llquantizedsum(rhs);
- int64_t lzero, rzero;
-
- if (lsum < rsum)
- return (DT_LESSTHAN);
-
- if (lsum > rsum)
- return (DT_GREATERTHAN);
-
- /*
- * If they're both equal, then we will compare based on the weights at
- * zero. If the weights at zero are equal, then this will be judged a
- * tie and will be resolved based on the key comparison.
- */
- lzero = lhs[1];
- rzero = rhs[1];
-
- if (lzero < rzero)
- return (DT_LESSTHAN);
-
- if (lzero > rzero)
- return (DT_GREATERTHAN);
-
- return (0);
-}
-
static int
dt_aggregate_quantizedcmp(int64_t *lhs, int64_t *rhs)
{
@@ -661,10 +582,6 @@ hashnext:
h->dtahe_aggregate = dt_aggregate_lquantize;
break;
- case DTRACEAGG_LLQUANTIZE:
- h->dtahe_aggregate = dt_aggregate_llquantize;
- break;
-
case DTRACEAGG_COUNT:
case DTRACEAGG_SUM:
case DTRACEAGG_AVG:
@@ -932,10 +849,6 @@ dt_aggregate_valcmp(const void *lhs, const void *rhs)
rval = dt_aggregate_lquantizedcmp(laddr, raddr);
break;
- case DTRACEAGG_LLQUANTIZE:
- rval = dt_aggregate_llquantizedcmp(laddr, raddr);
- break;
-
case DTRACEAGG_COUNT:
case DTRACEAGG_SUM:
case DTRACEAGG_MIN:
diff --git a/lib/libdtrace/common/dt_cc.c b/lib/libdtrace/common/dt_cc.c
index 8b8bcf475cba..24a386bbde95 100644
--- a/lib/libdtrace/common/dt_cc.c
+++ b/lib/libdtrace/common/dt_cc.c
@@ -21,8 +21,6 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
*/
/*
@@ -84,7 +82,6 @@
#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/sysmacros.h>
#include <assert.h>
#include <strings.h>
@@ -679,59 +676,13 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
ap->dtad_kind = DTRACEACT_DIFEXPR;
}
-/*
- * The print() action behaves identically to trace(), except that it stores the
- * CTF type of the argument (if present) within the DOF for the DIFEXPR action.
- * To do this, we set the 'dtsd_strdata' to point to the fully-qualified CTF
- * type ID for the result of the DIF action. We use the ID instead of the name
- * to handles complex types like arrays and function pointers that can't be
- * resolved by ctf_type_lookup(). This is later processed by
- * dtrace_dof_create() and turned into a reference into the string table so
- * that we can get the type information when we process the data after the
- * fact.
- */
-static void
-dt_action_print(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
-{
- dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
- dt_node_t *dret;
- size_t len;
- dt_module_t *dmp;
-
- if (dt_node_is_void(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_PRINT_VOID,
- "print( ) may not be applied to a void expression\n");
- }
-
- if (dt_node_is_dynamic(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_PRINT_DYN,
- "print( ) may not be applied to a dynamic expression\n");
- }
-
- dt_cg(yypcb, dnp->dn_args);
-
- dret = yypcb->pcb_dret;
- dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
-
- len = snprintf(NULL, 0, "%s`%d", dmp->dm_name, dret->dn_type) + 1;
- sdp->dtsd_strdata = dt_alloc(dtp, len);
- if (sdp->dtsd_strdata == NULL)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
- (void) snprintf(sdp->dtsd_strdata, len, "%s`%d", dmp->dm_name,
- dret->dn_type);
-
- ap->dtad_difo = dt_as(yypcb);
- ap->dtad_kind = DTRACEACT_DIFEXPR;
-}
-
static void
dt_action_tracemem(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
{
dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
dt_node_t *addr = dnp->dn_args;
- dt_node_t *max = dnp->dn_args->dn_list;
- dt_node_t *size;
+ dt_node_t *size = dnp->dn_args->dn_list;
char n[DT_TYPE_NAMELEN];
@@ -743,37 +694,17 @@ dt_action_tracemem(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
dt_node_type_name(addr, n, sizeof (n)));
}
- if (dt_node_is_posconst(max) == 0) {
- dnerror(max, D_TRACEMEM_SIZE, "tracemem( ) argument #2 must "
+ if (dt_node_is_posconst(size) == 0) {
+ dnerror(size, D_TRACEMEM_SIZE, "tracemem( ) argument #2 must "
"be a non-zero positive integral constant expression\n");
}
- if ((size = max->dn_list) != NULL) {
- if (size->dn_list != NULL) {
- dnerror(size, D_TRACEMEM_ARGS, "tracemem ( ) prototype "
- "mismatch: expected at most 3 args\n");
- }
-
- if (!dt_node_is_scalar(size)) {
- dnerror(size, D_TRACEMEM_DYNSIZE, "tracemem ( ) "
- "dynamic size (argument #3) must be of "
- "scalar type\n");
- }
-
- dt_cg(yypcb, size);
- ap->dtad_difo = dt_as(yypcb);
- ap->dtad_difo->dtdo_rtype = dt_int_rtype;
- ap->dtad_kind = DTRACEACT_TRACEMEM_DYNSIZE;
-
- ap = dt_stmt_action(dtp, sdp);
- }
-
dt_cg(yypcb, addr);
ap->dtad_difo = dt_as(yypcb);
- ap->dtad_kind = DTRACEACT_TRACEMEM;
+ ap->dtad_kind = DTRACEACT_DIFEXPR;
ap->dtad_difo->dtdo_rtype.dtdt_flags |= DIF_TF_BYREF;
- ap->dtad_difo->dtdo_rtype.dtdt_size = max->dn_value;
+ ap->dtad_difo->dtdo_rtype.dtdt_size = size->dn_value;
}
static void
@@ -1103,9 +1034,6 @@ dt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
case DT_ACT_TRACE:
dt_action_trace(dtp, dnp->dn_expr, sdp);
break;
- case DT_ACT_PRINT:
- dt_action_print(dtp, dnp->dn_expr, sdp);
- break;
case DT_ACT_TRACEMEM:
dt_action_tracemem(dtp, dnp->dn_expr, sdp);
break;
@@ -1363,145 +1291,6 @@ dt_compile_agg(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
argmax = 5;
}
- if (fid->di_id == DTRACEAGG_LLQUANTIZE) {
- /*
- * For log/linear quantizations, we have between one and five
- * arguments in addition to the expression:
- *
- * arg1 => Factor
- * arg2 => Low magnitude
- * arg3 => High magnitude
- * arg4 => Number of steps per magnitude
- * arg5 => Quantization increment value (defaults to 1)
- */
- dt_node_t *llarg = dnp->dn_aggfun->dn_args->dn_list;
- uint64_t oarg, order, v;
- dt_idsig_t *isp;
- int i;
-
- struct {
- char *str; /* string identifier */
- int badtype; /* error on bad type */
- int badval; /* error on bad value */
- int mismatch; /* error on bad match */
- int shift; /* shift value */
- uint16_t value; /* value itself */
- } args[] = {
- { "factor", D_LLQUANT_FACTORTYPE,
- D_LLQUANT_FACTORVAL, D_LLQUANT_FACTORMATCH,
- DTRACE_LLQUANTIZE_FACTORSHIFT },
- { "low magnitude", D_LLQUANT_LOWTYPE,
- D_LLQUANT_LOWVAL, D_LLQUANT_LOWMATCH,
- DTRACE_LLQUANTIZE_LOWSHIFT },
- { "high magnitude", D_LLQUANT_HIGHTYPE,
- D_LLQUANT_HIGHVAL, D_LLQUANT_HIGHMATCH,
- DTRACE_LLQUANTIZE_HIGHSHIFT },
- { "linear steps per magnitude", D_LLQUANT_NSTEPTYPE,
- D_LLQUANT_NSTEPVAL, D_LLQUANT_NSTEPMATCH,
- DTRACE_LLQUANTIZE_NSTEPSHIFT },
- { NULL }
- };
-
- assert(arg == 0);
-
- for (i = 0; args[i].str != NULL; i++) {
- if (llarg->dn_kind != DT_NODE_INT) {
- dnerror(llarg, args[i].badtype, "llquantize( ) "
- "argument #%d (%s) must be an "
- "integer constant\n", i + 1, args[i].str);
- }
-
- if ((uint64_t)llarg->dn_value > UINT16_MAX) {
- dnerror(llarg, args[i].badval, "llquantize( ) "
- "argument #%d (%s) must be an unsigned "
- "16-bit quantity\n", i + 1, args[i].str);
- }
-
- args[i].value = (uint16_t)llarg->dn_value;
-
- assert(!(arg & (UINT16_MAX << args[i].shift)));
- arg |= ((uint64_t)args[i].value << args[i].shift);
- llarg = llarg->dn_list;
- }
-
- assert(arg != 0);
-
- if (args[0].value < 2) {
- dnerror(dnp, D_LLQUANT_FACTORSMALL, "llquantize( ) "
- "factor (argument #1) must be two or more\n");
- }
-
- if (args[1].value >= args[2].value) {
- dnerror(dnp, D_LLQUANT_MAGRANGE, "llquantize( ) "
- "high magnitude (argument #3) must be greater "
- "than low magnitude (argument #2)\n");
- }
-
- if (args[3].value < args[0].value) {
- dnerror(dnp, D_LLQUANT_FACTORNSTEPS, "llquantize( ) "
- "factor (argument #1) must be less than or "
- "equal to the number of linear steps per "
- "magnitude (argument #4)\n");
- }
-
- for (v = args[0].value; v < args[3].value; v *= args[0].value)
- continue;
-
- if ((args[3].value % args[0].value) || (v % args[3].value)) {
- dnerror(dnp, D_LLQUANT_FACTOREVEN, "llquantize( ) "
- "factor (argument #1) must evenly divide the "
- "number of steps per magnitude (argument #4), "
- "and the number of steps per magnitude must evenly "
- "divide a power of the factor\n");
- }
-
- for (i = 0, order = 1; i < args[2].value; i++) {
- if (order * args[0].value > order) {
- order *= args[0].value;
- continue;
- }
-
- dnerror(dnp, D_LLQUANT_MAGTOOBIG, "llquantize( ) "
- "factor (%d) raised to power of high magnitude "
- "(%d) overflows 64-bits\n", args[0].value,
- args[2].value);
- }
-
- isp = (dt_idsig_t *)aid->di_data;
-
- if (isp->dis_auxinfo == 0) {
- /*
- * This is the first time we've seen an llquantize()
- * for this aggregation; we'll store our argument
- * as the auxiliary signature information.
- */
- isp->dis_auxinfo = arg;
- } else if ((oarg = isp->dis_auxinfo) != arg) {
- /*
- * If we have seen this llquantize() before and the
- * argument doesn't match the original argument, pick
- * the original argument apart to concisely report the
- * mismatch.
- */
- int expected = 0, found = 0;
-
- for (i = 0; expected == found; i++) {
- assert(args[i].str != NULL);
-
- expected = (oarg >> args[i].shift) & UINT16_MAX;
- found = (arg >> args[i].shift) & UINT16_MAX;
- }
-
- dnerror(dnp, args[i - 1].mismatch, "llquantize( ) "
- "%s (argument #%d) doesn't match previous "
- "declaration: expected %d, found %d\n",
- args[i - 1].str, i, expected, found);
- }
-
- incr = llarg;
- argmax = 6;
- }
-
if (fid->di_id == DTRACEAGG_QUANTIZE) {
incr = dnp->dn_aggfun->dn_args->dn_list;
argmax = 2;
@@ -2124,23 +1913,25 @@ dt_lib_depend_free(dtrace_hdl_t *dtp)
}
}
+
/*
- * Open all the .d library files found in the specified directory and
- * compile each one of them. We silently ignore any missing directories and
- * other files found therein. We only fail (and thereby fail dt_load_libs()) if
- * we fail to compile a library and the error is something other than #pragma D
- * depends_on. Dependency errors are silently ignored to permit a library
- * directory to contain libraries which may not be accessible depending on our
- * privileges.
+ * Open all of the .d library files found in the specified directory and
+ * compile each one in topological order to cache its inlines and translators,
+ * etc. We silently ignore any missing directories and other files found
+ * therein. We only fail (and thereby fail dt_load_libs()) if we fail to
+ * compile a library and the error is something other than #pragma D depends_on.
+ * Dependency errors are silently ignored to permit a library directory to
+ * contain libraries which may not be accessible depending on our privileges.
*/
static int
dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
{
struct dirent *dp;
- const char *p, *end;
+ const char *p;
DIR *dirp;
char fname[PATH_MAX];
+ dtrace_prog_t *pgp;
FILE *fp;
void *rv;
dt_lib_depend_t *dld;
@@ -2164,28 +1955,9 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
continue;
}
- /*
- * Skip files whose name match an already processed library
- */
- for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
- dld = dt_list_next(dld)) {
- end = strrchr(dld->dtld_library, '/');
- /* dt_lib_depend_add ensures this */
- assert(end != NULL);
- if (strcmp(end + 1, dp->d_name) == 0)
- break;
- }
-
- if (dld != NULL) {
- dt_dprintf("skipping library %s, already processed "
- "library with the same name: %s", dp->d_name,
- dld->dtld_library);
- continue;
- }
-
dtp->dt_filetag = fname;
if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0)
- return (-1); /* preserve dt_errno */
+ goto err;
rv = dt_compile(dtp, DT_CTX_DPROG,
DTRACE_PROBESPEC_NAME, NULL,
@@ -2194,7 +1966,7 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
if (rv != NULL && dtp->dt_errno &&
(dtp->dt_errno != EDT_COMPILER ||
dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND)))
- return (-1); /* preserve dt_errno */
+ goto err;
if (dtp->dt_errno)
dt_dprintf("error parsing library %s: %s\n",
@@ -2205,27 +1977,6 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
}
(void) closedir(dirp);
-
- return (0);
-}
-
-/*
- * Perform a topological sorting of all the libraries found across the entire
- * dt_lib_path. Once sorted, compile each one in topological order to cache its
- * inlines and translators, etc. We silently ignore any missing directories and
- * other files found therein. We only fail (and thereby fail dt_load_libs()) if
- * we fail to compile a library and the error is something other than #pragma D
- * depends_on. Dependency errors are silently ignored to permit a library
- * directory to contain libraries which may not be accessible depending on our
- * privileges.
- */
-static int
-dt_load_libs_sort(dtrace_hdl_t *dtp)
-{
- dtrace_prog_t *pgp;
- FILE *fp;
- dt_lib_depend_t *dld;
-
/*
* Finish building the graph containing the library dependencies
* and perform a topological sort to generate an ordered list
@@ -2286,14 +2037,7 @@ dt_load_libs(dtrace_hdl_t *dtp)
dtp->dt_cflags |= DTRACE_C_NOLIBS;
- /*
- * /usr/lib/dtrace is always at the head of the list. The rest of the
- * list is specified in the precedence order the user requested. Process
- * everything other than the head first. DTRACE_C_NOLIBS has already
- * been spcified so dt_vopen will ensure that there is always one entry
- * in dt_lib_path.
- */
- for (dirp = dt_list_next(dt_list_next(&dtp->dt_lib_path));
+ for (dirp = dt_list_next(&dtp->dt_lib_path);
dirp != NULL; dirp = dt_list_next(dirp)) {
if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) {
dtp->dt_cflags &= ~DTRACE_C_NOLIBS;
@@ -2301,16 +2045,6 @@ dt_load_libs(dtrace_hdl_t *dtp)
}
}
- /* Handle /usr/lib/dtrace */
- dirp = dt_list_next(&dtp->dt_lib_path);
- if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) {
- dtp->dt_cflags &= ~DTRACE_C_NOLIBS;
- return (-1); /* errno is set for us */
- }
-
- if (dt_load_libs_sort(dtp) < 0)
- return (-1); /* errno is set for us */
-
return (0);
}
diff --git a/lib/libdtrace/common/dt_consume.c b/lib/libdtrace/common/dt_consume.c
index d3a554c1c6b7..564189a000ad 100644
--- a/lib/libdtrace/common/dt_consume.c
+++ b/lib/libdtrace/common/dt_consume.c
@@ -23,11 +23,6 @@
* Use is subject to license terms.
*/
-/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
- */
-
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
@@ -686,121 +681,6 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
return (0);
}
-int
-dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
- size_t size, uint64_t normal)
-{
- int i, first_bin, last_bin, bin = 1, order, levels;
- uint16_t factor, low, high, nsteps;
- const int64_t *data = addr;
- int64_t value = 1, next, step;
- char positives = 0, negatives = 0;
- long double total = 0;
- uint64_t arg;
- char c[32];
-
- if (size < sizeof (uint64_t))
- return (dt_set_errno(dtp, EDT_DMISMATCH));
-
- arg = *data++;
- size -= sizeof (uint64_t);
-
- factor = DTRACE_LLQUANTIZE_FACTOR(arg);
- low = DTRACE_LLQUANTIZE_LOW(arg);
- high = DTRACE_LLQUANTIZE_HIGH(arg);
- nsteps = DTRACE_LLQUANTIZE_NSTEP(arg);
-
- /*
- * We don't expect to be handed invalid llquantize() parameters here,
- * but sanity check them (to a degree) nonetheless.
- */
- if (size > INT32_MAX || factor < 2 || low >= high ||
- nsteps == 0 || factor > nsteps)
- return (dt_set_errno(dtp, EDT_DMISMATCH));
-
- levels = (int)size / sizeof (uint64_t);
-
- first_bin = 0;
- last_bin = levels - 1;
-
- while (first_bin < levels && data[first_bin] == 0)
- first_bin++;
-
- if (first_bin == levels) {
- first_bin = 0;
- last_bin = 1;
- } else {
- if (first_bin > 0)
- first_bin--;
-
- while (last_bin > 0 && data[last_bin] == 0)
- last_bin--;
-
- if (last_bin < levels - 1)
- last_bin++;
- }
-
- for (i = first_bin; i <= last_bin; i++) {
- positives |= (data[i] > 0);
- negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
- }
-
- if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
- "------------- Distribution -------------", "count") < 0)
- return (-1);
-
- for (order = 0; order < low; order++)
- value *= factor;
-
- next = value * factor;
- step = next > nsteps ? next / nsteps : 1;
-
- if (first_bin == 0) {
- (void) snprintf(c, sizeof (c), "< %lld", value);
-
- if (dt_printf(dtp, fp, "%16s ", c) < 0)
- return (-1);
-
- if (dt_print_quantline(dtp, fp, data[0], normal,
- total, positives, negatives) < 0)
- return (-1);
- }
-
- while (order <= high) {
- if (bin >= first_bin && bin <= last_bin) {
- if (dt_printf(dtp, fp, "%16lld ", (long long)value) < 0)
- return (-1);
-
- if (dt_print_quantline(dtp, fp, data[bin],
- normal, total, positives, negatives) < 0)
- return (-1);
- }
-
- assert(value < next);
- bin++;
-
- if ((value += step) != next)
- continue;
-
- next = value * factor;
- step = next > nsteps ? next / nsteps : 1;
- order++;
- }
-
- if (last_bin < bin)
- return (0);
-
- assert(last_bin == bin);
- (void) snprintf(c, sizeof (c), ">= %lld", value);
-
- if (dt_printf(dtp, fp, "%16s ", c) < 0)
- return (-1);
-
- return (dt_print_quantline(dtp, fp, data[bin], normal,
- total, positives, negatives));
-}
-
/*ARGSUSED*/
static int
dt_print_average(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
@@ -828,7 +708,7 @@ dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
/*ARGSUSED*/
int
dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
- size_t nbytes, int width, int quiet, int forceraw)
+ size_t nbytes, int width, int quiet)
{
/*
* If the byte stream is a series of printable characters, followed by
@@ -841,9 +721,6 @@ dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
if (nbytes == 0)
return (0);
- if (forceraw)
- goto raw;
-
if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET)
goto raw;
@@ -1520,9 +1397,6 @@ dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
case DTRACEAGG_LQUANTIZE:
return (dt_print_lquantize(dtp, fp, addr, size, normal));
- case DTRACEAGG_LLQUANTIZE:
- return (dt_print_llquantize(dtp, fp, addr, size, normal));
-
case DTRACEAGG_AVG:
return (dt_print_average(dtp, fp, addr, size, normal));
@@ -1554,7 +1428,7 @@ dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
(uint32_t)normal);
break;
default:
- err = dt_print_bytes(dtp, fp, addr, size, 50, 0, 0);
+ err = dt_print_bytes(dtp, fp, addr, size, 50, 0);
break;
}
@@ -1709,7 +1583,6 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf,
int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
int rval, i, n;
dtrace_epid_t last = DTRACE_EPIDNONE;
- uint64_t tracememsize = 0;
dtrace_probedata_t data;
uint64_t drops;
caddr_t addr;
@@ -1878,13 +1751,6 @@ again:
}
}
- if (act == DTRACEACT_TRACEMEM_DYNSIZE &&
- rec->dtrd_size == sizeof (uint64_t)) {
- /* LINTED - alignment */
- tracememsize = *((unsigned long long *)addr);
- continue;
- }
-
rval = (*rfunc)(&data, rec, arg);
if (rval == DTRACE_CONSUME_NEXT)
@@ -1976,35 +1842,6 @@ again:
goto nextrec;
}
- /*
- * If this is a DIF expression, and the record has a
- * format set, this indicates we have a CTF type name
- * associated with the data and we should try to print
- * it out by type.
- */
- if (act == DTRACEACT_DIFEXPR) {
- const char *strdata = dt_strdata_lookup(dtp,
- rec->dtrd_format);
- if (strdata != NULL) {
- n = dtrace_print(dtp, fp, strdata,
- addr, rec->dtrd_size);
-
- /*
- * dtrace_print() will return -1 on
- * error, or return the number of bytes
- * consumed. It will return 0 if the
- * type couldn't be determined, and we
- * should fall through to the normal
- * trace method.
- */
- if (n < 0)
- return (-1);
-
- if (n > 0)
- goto nextrec;
- }
- }
-
nofmt:
if (act == DTRACEACT_PRINTA) {
dt_print_aggdata_t pd;
@@ -2073,23 +1910,6 @@ nofmt:
goto nextrec;
}
- if (act == DTRACEACT_TRACEMEM) {
- if (tracememsize == 0 ||
- tracememsize > rec->dtrd_size) {
- tracememsize = rec->dtrd_size;
- }
-
- n = dt_print_bytes(dtp, fp, addr,
- tracememsize, 33, quiet, 1);
-
- tracememsize = 0;
-
- if (n < 0)
- return (-1);
-
- goto nextrec;
- }
-
switch (rec->dtrd_size) {
case sizeof (uint64_t):
n = dt_printf(dtp, fp,
@@ -2113,7 +1933,7 @@ nofmt:
break;
default:
n = dt_print_bytes(dtp, fp, addr,
- rec->dtrd_size, 33, quiet, 0);
+ rec->dtrd_size, 33, quiet);
break;
}
diff --git a/lib/libdtrace/common/dt_dof.c b/lib/libdtrace/common/dt_dof.c
index 04c4c89cdbdb..a7eb8e4d239f 100644
--- a/lib/libdtrace/common/dt_dof.c
+++ b/lib/libdtrace/common/dt_dof.c
@@ -21,7 +21,6 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <sys/types.h>
@@ -755,23 +754,16 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
dofa[i].dofa_difo = DOF_SECIDX_NONE;
/*
- * If the first action in a statement has string data,
- * add the string to the global string table. This can
- * be due either to a printf() format string
- * (dtsd_fmtdata) or a print() type string
- * (dtsd_strdata).
+ * If the first action in a statement has format data,
+ * add the format string to the global string table.
*/
if (sdp != NULL && ap == sdp->dtsd_action) {
if (sdp->dtsd_fmtdata != NULL) {
(void) dtrace_printf_format(dtp,
sdp->dtsd_fmtdata, fmt, maxfmt + 1);
strndx = dof_add_string(ddo, fmt);
- } else if (sdp->dtsd_strdata != NULL) {
- strndx = dof_add_string(ddo,
- sdp->dtsd_strdata);
- } else {
+ } else
strndx = 0; /* use dtad_arg instead */
- }
if ((next = dt_list_next(next)) != NULL)
sdp = next->ds_desc;
diff --git a/lib/libdtrace/common/dt_errtags.h b/lib/libdtrace/common/dt_errtags.h
index 473e2addc789..9e32dfdf2492 100644
--- a/lib/libdtrace/common/dt_errtags.h
+++ b/lib/libdtrace/common/dt_errtags.h
@@ -24,14 +24,11 @@
* Use is subject to license terms.
*/
-/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
- */
-
#ifndef _DT_ERRTAGS_H
#define _DT_ERRTAGS_H
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -190,12 +187,8 @@ typedef enum {
D_PRINTA_AGGPROTO, /* printa() aggregation mismatch */
D_TRACE_VOID, /* trace() argument has void type */
D_TRACE_DYN, /* trace() argument has dynamic type */
- D_PRINT_VOID, /* print() argument has void type */
- D_PRINT_DYN, /* print() argument has dynamic type */
D_TRACEMEM_ADDR, /* tracemem() address bad type */
D_TRACEMEM_SIZE, /* tracemem() size bad type */
- D_TRACEMEM_ARGS, /* tracemem() illegal number of args */
- D_TRACEMEM_DYNSIZE, /* tracemem() dynamic size bad type */
D_STACK_PROTO, /* stack() prototype mismatch */
D_STACK_SIZE, /* stack() size argument bad type */
D_USTACK_FRAMES, /* ustack() frames arg bad type */
@@ -242,24 +235,7 @@ typedef enum {
D_FREOPEN_INVALID, /* frename() filename is invalid */
D_LQUANT_MATCHBASE, /* lquantize() mismatch on base */
D_LQUANT_MATCHLIM, /* lquantize() mismatch on limit */
- D_LQUANT_MATCHSTEP, /* lquantize() mismatch on step */
- D_LLQUANT_FACTORTYPE, /* llquantize() bad magnitude type */
- D_LLQUANT_FACTORVAL, /* llquantize() bad magnitude value */
- D_LLQUANT_FACTORMATCH, /* llquantize() mismatch on magnitude */
- D_LLQUANT_LOWTYPE, /* llquantize() bad low mag type */
- D_LLQUANT_LOWVAL, /* llquantize() bad low mag value */
- D_LLQUANT_LOWMATCH, /* llquantize() mismatch on low mag */
- D_LLQUANT_HIGHTYPE, /* llquantize() bad high mag type */
- D_LLQUANT_HIGHVAL, /* llquantize() bad high mag value */
- D_LLQUANT_HIGHMATCH, /* llquantize() mismatch on high mag */
- D_LLQUANT_NSTEPTYPE, /* llquantize() bad # steps type */
- D_LLQUANT_NSTEPVAL, /* llquantize() bad # steps value */
- D_LLQUANT_NSTEPMATCH, /* llquantize() mismatch on # steps */
- D_LLQUANT_MAGRANGE, /* llquantize() bad magnitude range */
- D_LLQUANT_FACTORNSTEPS, /* llquantize() # steps < factor */
- D_LLQUANT_FACTOREVEN, /* llquantize() bad # steps/factor */
- D_LLQUANT_FACTORSMALL, /* llquantize() magnitude too small */
- D_LLQUANT_MAGTOOBIG /* llquantize() high mag too large */
+ D_LQUANT_MATCHSTEP /* lquantize() mismatch on step */
} dt_errtag_t;
extern const char *dt_errtag(dt_errtag_t);
diff --git a/lib/libdtrace/common/dt_impl.h b/lib/libdtrace/common/dt_impl.h
index b06fd6477d7a..1937ce06474d 100644
--- a/lib/libdtrace/common/dt_impl.h
+++ b/lib/libdtrace/common/dt_impl.h
@@ -24,11 +24,6 @@
* Use is subject to license terms.
*/
-/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
- */
-
#ifndef _DT_IMPL_H
#define _DT_IMPL_H
@@ -241,8 +236,6 @@ struct dtrace_hdl {
dtrace_aggdesc_t **dt_aggdesc; /* aggregation descriptions */
int dt_maxformat; /* max format ID */
void **dt_formats; /* pointer to format array */
- int dt_maxstrdata; /* max strdata ID */
- char **dt_strdata; /* pointer to strdata array */
dt_aggregate_t dt_aggregate; /* aggregate */
dtrace_bufdesc_t dt_buf; /* staging buffer */
struct dt_pfdict *dt_pfdict; /* dictionary of printf conversions */
@@ -420,7 +413,6 @@ struct dtrace_hdl {
#define DT_ACT_UMOD DT_ACT(26) /* umod() action */
#define DT_ACT_UADDR DT_ACT(27) /* uaddr() action */
#define DT_ACT_SETOPT DT_ACT(28) /* setopt() action */
-#define DT_ACT_PRINT DT_ACT(29) /* print() action */
/*
* Sentinel to tell freopen() to restore the saved stdout. This must not
@@ -604,15 +596,10 @@ extern void dt_aggid_destroy(dtrace_hdl_t *);
extern void *dt_format_lookup(dtrace_hdl_t *, int);
extern void dt_format_destroy(dtrace_hdl_t *);
-extern const char *dt_strdata_lookup(dtrace_hdl_t *, int);
-extern void dt_strdata_destroy(dtrace_hdl_t *);
-
extern int dt_print_quantize(dtrace_hdl_t *, FILE *,
const void *, size_t, uint64_t);
extern int dt_print_lquantize(dtrace_hdl_t *, FILE *,
const void *, size_t, uint64_t);
-extern int dt_print_llquantize(dtrace_hdl_t *, FILE *,
- const void *, size_t, uint64_t);
extern int dt_print_agg(const dtrace_aggdata_t *, void *);
extern int dt_handle(dtrace_hdl_t *, dtrace_probedata_t *);
diff --git a/lib/libdtrace/common/dt_map.c b/lib/libdtrace/common/dt_map.c
index 8a3ce817e4d7..15361862de8f 100644
--- a/lib/libdtrace/common/dt_map.c
+++ b/lib/libdtrace/common/dt_map.c
@@ -23,9 +23,7 @@
* Use is subject to license terms.
*/
-/*
- * Copyright (c) 2011 by Delphix. All rights reserved.
- */
+#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <strings.h>
@@ -37,81 +35,10 @@
#include <dt_printf.h>
static int
-dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max)
-{
- int maxformat;
- dtrace_fmtdesc_t fmt;
- void *result;
-
- if (rec->dtrd_format == 0)
- return (0);
-
- if (rec->dtrd_format <= *max &&
- (*data)[rec->dtrd_format - 1] != NULL) {
- return (0);
- }
-
- bzero(&fmt, sizeof (fmt));
- fmt.dtfd_format = rec->dtrd_format;
- fmt.dtfd_string = NULL;
- fmt.dtfd_length = 0;
-
- if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1)
- return (dt_set_errno(dtp, errno));
-
- if ((fmt.dtfd_string = dt_alloc(dtp, fmt.dtfd_length)) == NULL)
- return (dt_set_errno(dtp, EDT_NOMEM));
-
- if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
- free(fmt.dtfd_string);
- return (dt_set_errno(dtp, errno));
- }
-
- while (rec->dtrd_format > (maxformat = *max)) {
- int new_max = maxformat ? (maxformat << 1) : 1;
- size_t nsize = new_max * sizeof (void *);
- size_t osize = maxformat * sizeof (void *);
- void **new_data = dt_zalloc(dtp, nsize);
-
- if (new_data == NULL) {
- dt_free(dtp, fmt.dtfd_string);
- return (dt_set_errno(dtp, EDT_NOMEM));
- }
-
- bcopy(*data, new_data, osize);
- free(*data);
-
- *data = new_data;
- *max = new_max;
- }
-
- switch (rec->dtrd_action) {
- case DTRACEACT_DIFEXPR:
- result = fmt.dtfd_string;
- break;
- case DTRACEACT_PRINTA:
- result = dtrace_printa_create(dtp, fmt.dtfd_string);
- dt_free(dtp, fmt.dtfd_string);
- break;
- default:
- result = dtrace_printf_create(dtp, fmt.dtfd_string);
- dt_free(dtp, fmt.dtfd_string);
- break;
- }
-
- if (result == NULL)
- return (-1);
-
- (*data)[rec->dtrd_format - 1] = result;
-
- return (0);
-}
-
-static int
dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
{
dtrace_id_t max;
- int rval, i;
+ int rval, i, maxformat;
dtrace_eprobedesc_t *enabled, *nenabled;
dtrace_probedesc_t *probe;
@@ -197,23 +124,71 @@ dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
}
for (i = 0; i < enabled->dtepd_nrecs; i++) {
+ dtrace_fmtdesc_t fmt;
dtrace_recdesc_t *rec = &enabled->dtepd_rec[i];
- if (DTRACEACT_ISPRINTFLIKE(rec->dtrd_action)) {
- if (dt_strdata_add(dtp, rec, &dtp->dt_formats,
- &dtp->dt_maxformat) != 0) {
- rval = -1;
- goto err;
- }
- } else if (rec->dtrd_action == DTRACEACT_DIFEXPR) {
- if (dt_strdata_add(dtp, rec,
- (void ***)&dtp->dt_strdata,
- &dtp->dt_maxstrdata) != 0) {
- rval = -1;
+ if (!DTRACEACT_ISPRINTFLIKE(rec->dtrd_action))
+ continue;
+
+ if (rec->dtrd_format == 0)
+ continue;
+
+ if (rec->dtrd_format <= dtp->dt_maxformat &&
+ dtp->dt_formats[rec->dtrd_format - 1] != NULL)
+ continue;
+
+ bzero(&fmt, sizeof (fmt));
+ fmt.dtfd_format = rec->dtrd_format;
+ fmt.dtfd_string = NULL;
+ fmt.dtfd_length = 0;
+
+ if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
+ rval = dt_set_errno(dtp, errno);
+ goto err;
+ }
+
+ if ((fmt.dtfd_string = malloc(fmt.dtfd_length)) == NULL) {
+ rval = dt_set_errno(dtp, EDT_NOMEM);
+ goto err;
+ }
+
+ if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
+ rval = dt_set_errno(dtp, errno);
+ free(fmt.dtfd_string);
+ goto err;
+ }
+
+ while (rec->dtrd_format > (maxformat = dtp->dt_maxformat)) {
+ int new_max = maxformat ? (maxformat << 1) : 1;
+ size_t nsize = new_max * sizeof (void *);
+ size_t osize = maxformat * sizeof (void *);
+ void **new_formats = malloc(nsize);
+
+ if (new_formats == NULL) {
+ rval = dt_set_errno(dtp, EDT_NOMEM);
+ free(fmt.dtfd_string);
goto err;
}
+
+ bzero(new_formats, nsize);
+ bcopy(dtp->dt_formats, new_formats, osize);
+ free(dtp->dt_formats);
+
+ dtp->dt_formats = new_formats;
+ dtp->dt_maxformat = new_max;
}
+ dtp->dt_formats[rec->dtrd_format - 1] =
+ rec->dtrd_action == DTRACEACT_PRINTA ?
+ dtrace_printa_create(dtp, fmt.dtfd_string) :
+ dtrace_printf_create(dtp, fmt.dtfd_string);
+
+ free(fmt.dtfd_string);
+
+ if (dtp->dt_formats[rec->dtrd_format - 1] == NULL) {
+ rval = -1; /* dt_errno is set for us */
+ goto err;
+ }
}
dtp->dt_pdesc[id] = probe;
@@ -449,28 +424,3 @@ dt_aggid_destroy(dtrace_hdl_t *dtp)
dtp->dt_aggdesc = NULL;
dtp->dt_maxagg = 0;
}
-
-const char *
-dt_strdata_lookup(dtrace_hdl_t *dtp, int idx)
-{
- if (idx == 0 || idx > dtp->dt_maxstrdata)
- return (NULL);
-
- if (dtp->dt_strdata == NULL)
- return (NULL);
-
- return (dtp->dt_strdata[idx - 1]);
-}
-
-void
-dt_strdata_destroy(dtrace_hdl_t *dtp)
-{
- int i;
-
- for (i = 0; i < dtp->dt_maxstrdata; i++) {
- free(dtp->dt_strdata[i]);
- }
-
- free(dtp->dt_strdata);
- dtp->dt_strdata = NULL;
-}
diff --git a/lib/libdtrace/common/dt_open.c b/lib/libdtrace/common/dt_open.c
index 502a9d42ad73..2b9cd7c414da 100644
--- a/lib/libdtrace/common/dt_open.c
+++ b/lib/libdtrace/common/dt_open.c
@@ -21,8 +21,6 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <sys/types.h>
@@ -105,13 +103,8 @@
#define DT_VERS_1_6_1 DT_VERSION_NUMBER(1, 6, 1)
#define DT_VERS_1_6_2 DT_VERSION_NUMBER(1, 6, 2)
#define DT_VERS_1_6_3 DT_VERSION_NUMBER(1, 6, 3)
-#define DT_VERS_1_7 DT_VERSION_NUMBER(1, 7, 0)
-#define DT_VERS_1_7_1 DT_VERSION_NUMBER(1, 7, 1)
-#define DT_VERS_1_8 DT_VERSION_NUMBER(1, 8, 0)
-#define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1)
-#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
-#define DT_VERS_LATEST DT_VERS_1_9
-#define DT_VERS_STRING "Sun D 1.9"
+#define DT_VERS_LATEST DT_VERS_1_6_3
+#define DT_VERS_STRING "Sun D 1.6.3"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -127,11 +120,6 @@ const dt_version_t _dtrace_versions[] = {
DT_VERS_1_6_1, /* D API 1.6.1 */
DT_VERS_1_6_2, /* D API 1.6.2 */
DT_VERS_1_6_3, /* D API 1.6.3 */
- DT_VERS_1_7, /* D API 1.7 */
- DT_VERS_1_7_1, /* D API 1.7.1 */
- DT_VERS_1_8, /* D API 1.8 */
- DT_VERS_1_8_1, /* D API 1.8.1 */
- DT_VERS_1_9, /* D API 1.9 */
0
};
@@ -262,10 +250,7 @@ static const dt_ident_t _dtrace_globals[] = {
{ "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "stack(...)" },
{ "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
- &dt_idops_func, "string(int64_t, [int])" },
-{ "llquantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_LLQUANTIZE, DT_ATTR_STABCMN,
- DT_VERS_1_7, &dt_idops_func,
- "void(@, int32_t, int32_t, int32_t, int32_t, ...)" },
+ &dt_idops_func, "string(int64_t)" },
{ "lquantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_LQUANTIZE,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void(@, int32_t, int32_t, ...)" },
@@ -307,8 +292,6 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_type, "pid_t" },
{ "ppid", DT_IDENT_SCALAR, 0, DIF_VAR_PPID, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "pid_t" },
-{ "print", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINT, DT_ATTR_STABCMN, DT_VERS_1_9,
- &dt_idops_func, "void(@)" },
{ "printa", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTA, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void(@, ...)" },
{ "printf", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTF, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -388,15 +371,11 @@ static const dt_ident_t _dtrace_globals[] = {
{ "timestamp", DT_IDENT_SCALAR, 0, DIF_VAR_TIMESTAMP,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uint64_t" },
-{ "tolower", DT_IDENT_FUNC, 0, DIF_SUBR_TOLOWER, DT_ATTR_STABCMN, DT_VERS_1_8,
- &dt_idops_func, "string(const char *)" },
-{ "toupper", DT_IDENT_FUNC, 0, DIF_SUBR_TOUPPER, DT_ATTR_STABCMN, DT_VERS_1_8,
- &dt_idops_func, "string(const char *)" },
{ "trace", DT_IDENT_ACTFUNC, 0, DT_ACT_TRACE, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void(@)" },
{ "tracemem", DT_IDENT_ACTFUNC, 0, DT_ACT_TRACEMEM,
DT_ATTR_STABCMN, DT_VERS_1_0,
- &dt_idops_func, "void(@, size_t, ...)" },
+ &dt_idops_func, "void(@, size_t)" },
{ "trunc", DT_IDENT_ACTFUNC, 0, DT_ACT_TRUNC, DT_ATTR_STABCMN,
DT_VERS_1_0, &dt_idops_func, "void(...)" },
{ "uaddr", DT_IDENT_ACTFUNC, 0, DT_ACT_UADDR, DT_ATTR_STABCMN,
@@ -418,8 +397,6 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_type, "uint32_t" },
{ "usym", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
-{ "vmregs", DT_IDENT_ARRAY, 0, DIF_VAR_VMREGS, DT_ATTR_STABCMN, DT_VERS_1_7,
- &dt_idops_regs, NULL },
{ "vtimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_VTIMESTAMP,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uint64_t" },
@@ -1362,7 +1339,6 @@ dtrace_close(dtrace_hdl_t *dtp)
dt_epid_destroy(dtp);
dt_aggid_destroy(dtp);
dt_format_destroy(dtp);
- dt_strdata_destroy(dtp);
dt_buffered_destroy(dtp);
dt_aggregate_destroy(dtp);
free(dtp->dt_buf.dtbd_data);
diff --git a/lib/libdtrace/common/dt_options.c b/lib/libdtrace/common/dt_options.c
index 426f8cb73c7a..5353bfae528d 100644
--- a/lib/libdtrace/common/dt_options.c
+++ b/lib/libdtrace/common/dt_options.c
@@ -24,6 +24,8 @@
* Use is subject to license terms.
*/
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/types.h>
@@ -835,6 +837,30 @@ dt_options_load(dtrace_hdl_t *dtp)
return (0);
}
+/*ARGSUSED*/
+static int
+dt_opt_preallocate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
+{
+ dtrace_optval_t size;
+ void *p;
+
+ if (arg == NULL || dt_optval_parse(arg, &size) != 0)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ if (size > SIZE_MAX)
+ size = SIZE_MAX;
+
+ if ((p = dt_zalloc(dtp, size)) == NULL) {
+ do {
+ size /= 2;
+ } while ((p = dt_zalloc(dtp, size)) == NULL);
+ }
+
+ dt_free(dtp, p);
+
+ return (0);
+}
+
typedef struct dt_option {
const char *o_name;
int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
@@ -873,6 +899,7 @@ static const dt_option_t _dtrace_ctoptions[] = {
{ "linktype", dt_opt_linktype },
{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
{ "pgmax", dt_opt_pgmax },
+ { "preallocate", dt_opt_preallocate },
{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
{ "stdc", dt_opt_stdc },
{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
diff --git a/lib/libdtrace/common/dt_parser.c b/lib/libdtrace/common/dt_parser.c
index 05715894a7df..6ad30a9ac52a 100644
--- a/lib/libdtrace/common/dt_parser.c
+++ b/lib/libdtrace/common/dt_parser.c
@@ -21,7 +21,6 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
*/
/*
@@ -720,19 +719,12 @@ dt_node_type_name(const dt_node_t *dnp, char *buf, size_t len)
size_t
dt_node_type_size(const dt_node_t *dnp)
{
- ctf_id_t base;
-
if (dnp->dn_kind == DT_NODE_STRING)
return (strlen(dnp->dn_string) + 1);
if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL)
return (dt_ident_size(dnp->dn_ident));
- base = ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type);
-
- if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)
- return (0);
-
return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));
}
diff --git a/lib/libdtrace/common/dt_pragma.c b/lib/libdtrace/common/dt_pragma.c
index 9fae5ac42c40..9cb3c3b8d615 100644
--- a/lib/libdtrace/common/dt_pragma.c
+++ b/lib/libdtrace/common/dt_pragma.c
@@ -21,19 +21,14 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
*/
#include <assert.h>
#include <strings.h>
#include <alloca.h>
-#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
#include <dt_parser.h>
#include <dt_impl.h>
#include <dt_provider.h>
@@ -201,29 +196,6 @@ dt_pragma_binding(const char *prname, dt_node_t *dnp)
dtp->dt_globals->dh_defer = &dt_pragma_apply;
}
-static void
-dt_pragma_depends_finddep(dtrace_hdl_t *dtp, const char *lname, char *lib,
- size_t len)
-{
- dt_dirpath_t *dirp;
- struct stat sbuf;
- int found = 0;
-
- for (dirp = dt_list_next(&dtp->dt_lib_path); dirp != NULL;
- dirp = dt_list_next(dirp)) {
- (void) snprintf(lib, len, "%s/%s", dirp->dir_path, lname);
-
- if (stat(lib, &sbuf) == 0) {
- found = 1;
- break;
- }
- }
-
- if (!found)
- xyerror(D_PRAGMA_DEPEND,
- "failed to find dependency in libpath: %s", lname);
-}
-
/*
* The #pragma depends_on directive can be used to express a dependency on a
* module, provider or library which if not present will cause processing to
@@ -253,13 +225,16 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp)
if (yypcb->pcb_cflags & DTRACE_C_CTL) {
assert(dtp->dt_filetag != NULL);
- dt_pragma_depends_finddep(dtp, nnp->dn_string, lib,
- sizeof (lib));
-
+ /*
+ * We have the file we are working on in dtp->dt_filetag
+ * so find that node and add the dependency in.
+ */
dld = dt_lib_depend_lookup(&dtp->dt_lib_dep,
dtp->dt_filetag);
assert(dld != NULL);
+ (void) snprintf(lib, sizeof (lib), "%s%s",
+ dld->dtld_libpath, nnp->dn_string);
if ((dt_lib_depend_add(dtp, &dld->dtld_dependencies,
lib)) != 0) {
xyerror(D_PRAGMA_DEPEND,
@@ -281,8 +256,8 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp)
dtp->dt_filetag);
assert(dld != NULL);
- dt_pragma_depends_finddep(dtp, nnp->dn_string, lib,
- sizeof (lib));
+ (void) snprintf(lib, sizeof (lib), "%s%s",
+ dld->dtld_libpath, nnp->dn_string);
dld = dt_lib_depend_lookup(&dtp->dt_lib_dep_sorted,
lib);
assert(dld != NULL);
diff --git a/lib/libdtrace/common/dt_print.c b/lib/libdtrace/common/dt_print.c
deleted file mode 100644
index 261fc8ced4d5..000000000000
--- a/lib/libdtrace/common/dt_print.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2011 by Delphix. All rights reserved.
- */
-
-/*
- * DTrace print() action
- *
- * This file contains the post-processing logic for the print() action. The
- * print action behaves identically to trace() in that it generates a
- * DTRACEACT_DIFEXPR action, but the action argument field refers to a CTF type
- * string stored in the DOF string table (similar to printf formats). We
- * take the result of the trace action and post-process it in the fashion of
- * MDB's ::print dcmd.
- *
- * This implementation differs from MDB's in the following ways:
- *
- * - We do not expose any options or flags. The behavior of print() is
- * equivalent to "::print -tn".
- *
- * - MDB will display "holes" in structures (unused padding between
- * members).
- *
- * - When printing arrays of structures, MDB will leave a trailing ','
- * after the last element.
- *
- * - MDB will print time_t types as date and time.
- *
- * - MDB will detect when an enum is actually the OR of several flags,
- * and print it out with the constituent flags separated.
- *
- * - For large arrays, MDB will print the first few members and then
- * print a "..." continuation line.
- *
- * - MDB will break and wrap arrays at 80 columns.
- *
- * - MDB prints out floats and doubles by hand, as it must run in kmdb
- * context. We're able to leverage the printf() format strings,
- * but the result is a slightly different format.
- */
-
-#include <sys/sysmacros.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <alloca.h>
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-
-#include <dt_module.h>
-#include <dt_printf.h>
-#include <dt_string.h>
-#include <dt_impl.h>
-
-/* determines whether the given integer CTF encoding is a character */
-#define CTF_IS_CHAR(e) \
- (((e).cte_format & (CTF_INT_CHAR | CTF_INT_SIGNED)) == \
- (CTF_INT_CHAR | CTF_INT_SIGNED) && (e).cte_bits == NBBY)
-/* determines whether the given CTF kind is a struct or union */
-#define CTF_IS_STRUCTLIKE(k) \
- ((k) == CTF_K_STRUCT || (k) == CTF_K_UNION)
-
-/*
- * Print structure passed down recursively through printing algorithm.
- */
-typedef struct dt_printarg {
- caddr_t pa_addr; /* base address of trace data */
- ctf_file_t *pa_ctfp; /* CTF container */
- int pa_depth; /* member depth */
- int pa_nest; /* nested array depth */
- FILE *pa_file; /* output file */
-} dt_printarg_t;
-
-static int dt_print_member(const char *, ctf_id_t, ulong_t, int, void *);
-
-/*
- * Safe version of ctf_type_name() that will fall back to just "<ctfid>" if it
- * can't resolve the type.
- */
-static void
-dt_print_type_name(ctf_file_t *ctfp, ctf_id_t id, char *buf, size_t buflen)
-{
- if (ctf_type_name(ctfp, id, buf, buflen) == NULL)
- (void) snprintf(buf, buflen, "<%ld>", id);
-}
-
-/*
- * Print any necessary trailing braces for structures or unions. We don't get
- * invoked when a struct or union ends, so we infer the need to print braces
- * based on the depth the last time we printed something and the new depth.
- */
-static void
-dt_print_trailing_braces(dt_printarg_t *pap, int depth)
-{
- int d;
-
- for (d = pap->pa_depth; d > depth; d--) {
- (void) fprintf(pap->pa_file, "%*s}%s",
- (d + pap->pa_nest - 1) * 4, "",
- d == depth + 1 ? "" : "\n");
- }
-}
-
-/*
- * Print the appropriate amount of indentation given the current depth and
- * array nesting.
- */
-static void
-dt_print_indent(dt_printarg_t *pap)
-{
- (void) fprintf(pap->pa_file, "%*s",
- (pap->pa_depth + pap->pa_nest) * 4, "");
-}
-
-/*
- * Print a bitfield. It's worth noting that the D compiler support for
- * bitfields is currently broken; printing "D`user_desc_t" (pulled in by the
- * various D provider files) will produce incorrect results compared to
- * "genunix`user_desc_t".
- */
-static void
-print_bitfield(dt_printarg_t *pap, ulong_t off, ctf_encoding_t *ep)
-{
- FILE *fp = pap->pa_file;
- caddr_t addr = pap->pa_addr + off / NBBY;
- uint64_t mask = (1ULL << ep->cte_bits) - 1;
- uint64_t value = 0;
- size_t size = (ep->cte_bits + (NBBY - 1)) / NBBY;
- uint8_t *buf = (uint8_t *)&value;
- uint8_t shift;
-
- /*
- * On big-endian machines, we need to adjust the buf pointer to refer
- * to the lowest 'size' bytes in 'value', and we need to shift based on
- * the offset from the end of the data, not the offset of the start.
- */
-#ifdef _BIG_ENDIAN
- buf += sizeof (value) - size;
- off += ep->cte_bits;
-#endif
- bcopy(addr, buf, size);
- shift = off % NBBY;
-
- /*
- * Offsets are counted from opposite ends on little- and
- * big-endian machines.
- */
-#ifdef _BIG_ENDIAN
- shift = NBBY - shift;
-#endif
-
- /*
- * If the bits we want do not begin on a byte boundary, shift the data
- * right so that the value is in the lowest 'cte_bits' of 'value'.
- */
- if (off % NBBY != 0)
- value >>= shift;
- value &= mask;
-
- (void) fprintf(fp, "%#llx", (u_longlong_t)value);
-}
-
-/*
- * Dump the contents of memory as a fixed-size integer in hex.
- */
-static void
-dt_print_hex(FILE *fp, caddr_t addr, size_t size)
-{
- switch (size) {
- case sizeof (uint8_t):
- (void) fprintf(fp, "%#x", *(uint8_t *)addr);
- break;
- case sizeof (uint16_t):
- /* LINTED - alignment */
- (void) fprintf(fp, "%#x", *(uint16_t *)addr);
- break;
- case sizeof (uint32_t):
- /* LINTED - alignment */
- (void) fprintf(fp, "%#x", *(uint32_t *)addr);
- break;
- case sizeof (uint64_t):
- (void) fprintf(fp, "%#llx",
- /* LINTED - alignment */
- (unsigned long long)*(uint64_t *)addr);
- break;
- default:
- (void) fprintf(fp, "<invalid size %u>", (uint_t)size);
- }
-}
-
-/*
- * Print an integer type. Before dumping the contents via dt_print_hex(), we
- * first check the encoding to see if it's part of a bitfield or a character.
- */
-static void
-dt_print_int(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
-{
- FILE *fp = pap->pa_file;
- ctf_file_t *ctfp = pap->pa_ctfp;
- ctf_encoding_t e;
- size_t size;
- caddr_t addr = pap->pa_addr + off / NBBY;
-
- if (ctf_type_encoding(ctfp, base, &e) == CTF_ERR) {
- (void) fprintf(fp, "<unknown encoding>");
- return;
- }
-
- /*
- * This comes from MDB - it's not clear under what circumstances this
- * would be found.
- */
- if (e.cte_format & CTF_INT_VARARGS) {
- (void) fprintf(fp, "...");
- return;
- }
-
- /*
- * We print this as a bitfield if the bit encoding indicates it's not
- * an even power of two byte size, or is larger than 8 bytes.
- */
- size = e.cte_bits / NBBY;
- if (size > 8 || (e.cte_bits % NBBY) != 0 || (size & (size - 1)) != 0) {
- print_bitfield(pap, off, &e);
- return;
- }
-
- /*
- * If this is a character, print it out as such.
- */
- if (CTF_IS_CHAR(e)) {
- char c = *(char *)addr;
- if (isprint(c))
- (void) fprintf(fp, "'%c'", c);
- else if (c == 0)
- (void) fprintf(fp, "'\\0'");
- else
- (void) fprintf(fp, "'\\%03o'", c);
- return;
- }
-
- dt_print_hex(fp, addr, size);
-}
-
-/*
- * Print a floating point (float, double, long double) value.
- */
-/* ARGSUSED */
-static void
-dt_print_float(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
-{
- FILE *fp = pap->pa_file;
- ctf_file_t *ctfp = pap->pa_ctfp;
- ctf_encoding_t e;
- caddr_t addr = pap->pa_addr + off / NBBY;
-
- if (ctf_type_encoding(ctfp, base, &e) == 0) {
- if (e.cte_format == CTF_FP_SINGLE &&
- e.cte_bits == sizeof (float) * NBBY) {
- /* LINTED - alignment */
- (void) fprintf(fp, "%+.7e", *((float *)addr));
- } else if (e.cte_format == CTF_FP_DOUBLE &&
- e.cte_bits == sizeof (double) * NBBY) {
- /* LINTED - alignment */
- (void) fprintf(fp, "%+.7e", *((double *)addr));
- } else if (e.cte_format == CTF_FP_LDOUBLE &&
- e.cte_bits == sizeof (long double) * NBBY) {
- /* LINTED - alignment */
- (void) fprintf(fp, "%+.16LE", *((long double *)addr));
- } else {
- (void) fprintf(fp, "<unknown encoding>");
- }
- }
-}
-
-/*
- * A pointer is printed as a fixed-size integer. This is used both for
- * pointers and functions.
- */
-static void
-dt_print_ptr(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
-{
- FILE *fp = pap->pa_file;
- ctf_file_t *ctfp = pap->pa_ctfp;
- caddr_t addr = pap->pa_addr + off / NBBY;
- size_t size = ctf_type_size(ctfp, base);
-
- dt_print_hex(fp, addr, size);
-}
-
-/*
- * Print out an array. This is somewhat complex, as we must manually visit
- * each member, and recursively invoke ctf_type_visit() for each member. If
- * the members are non-structs, then we print them out directly:
- *
- * [ 0x14, 0x2e, 0 ]
- *
- * If they are structs, then we print out the necessary leading and trailing
- * braces, to end up with:
- *
- * [
- * type {
- * ...
- * },
- * type {
- * ...
- * }
- * ]
- *
- * We also use a heuristic to detect whether the array looks like a character
- * array. If the encoding indicates it's a character, and we have all
- * printable characters followed by a null byte, then we display it as a
- * string:
- *
- * [ "string" ]
- */
-static void
-dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
-{
- FILE *fp = pap->pa_file;
- ctf_file_t *ctfp = pap->pa_ctfp;
- caddr_t addr = pap->pa_addr + off / NBBY;
- ctf_arinfo_t car;
- ssize_t eltsize;
- ctf_encoding_t e;
- int i;
- boolean_t isstring;
- int kind;
- ctf_id_t rtype;
-
- if (ctf_array_info(ctfp, base, &car) == CTF_ERR) {
- (void) fprintf(fp, "0x%p", (void *)addr);
- return;
- }
-
- if ((eltsize = ctf_type_size(ctfp, car.ctr_contents)) < 0 ||
- (rtype = ctf_type_resolve(ctfp, car.ctr_contents)) == CTF_ERR ||
- (kind = ctf_type_kind(ctfp, rtype)) == CTF_ERR) {
- (void) fprintf(fp, "<invalid type %lu>", car.ctr_contents);
- return;
- }
-
- /* see if this looks like a string */
- isstring = B_FALSE;
- if (kind == CTF_K_INTEGER &&
- ctf_type_encoding(ctfp, rtype, &e) != CTF_ERR && CTF_IS_CHAR(e)) {
- char c;
- for (i = 0; i < car.ctr_nelems; i++) {
- c = *((char *)addr + eltsize * i);
- if (!isprint(c) || c == '\0')
- break;
- }
-
- if (i != car.ctr_nelems && c == '\0')
- isstring = B_TRUE;
- }
-
- /*
- * As a slight aesthetic optimization, if we are a top-level type, then
- * don't bother printing out the brackets. This lets print("foo") look
- * like:
- *
- * string "foo"
- *
- * As D will internally represent this as a char[256] array.
- */
- if (!isstring || pap->pa_depth != 0)
- (void) fprintf(fp, "[ ");
-
- if (isstring)
- (void) fprintf(fp, "\"");
-
- for (i = 0; i < car.ctr_nelems; i++) {
- if (isstring) {
- char c = *((char *)addr + eltsize * i);
- if (c == '\0')
- break;
- (void) fprintf(fp, "%c", c);
- } else {
- /*
- * Recursively invoke ctf_type_visit() on each member.
- * We setup a new printarg struct with 'pa_nest' set to
- * indicate that we are within a nested array.
- */
- dt_printarg_t pa = *pap;
- pa.pa_nest += pap->pa_depth + 1;
- pa.pa_depth = 0;
- pa.pa_addr = addr + eltsize * i;
- (void) ctf_type_visit(ctfp, car.ctr_contents,
- dt_print_member, &pa);
-
- dt_print_trailing_braces(&pa, 0);
- if (i != car.ctr_nelems - 1)
- (void) fprintf(fp, ", ");
- else if (CTF_IS_STRUCTLIKE(kind))
- (void) fprintf(fp, "\n");
- }
- }
-
- if (isstring)
- (void) fprintf(fp, "\"");
-
- if (!isstring || pap->pa_depth != 0) {
- if (CTF_IS_STRUCTLIKE(kind))
- dt_print_indent(pap);
- else
- (void) fprintf(fp, " ");
- (void) fprintf(fp, "]");
- }
-}
-
-/*
- * This isued by both structs and unions to print the leading brace.
- */
-/* ARGSUSED */
-static void
-dt_print_structlike(ctf_id_t id, ulong_t off, dt_printarg_t *pap)
-{
- (void) fprintf(pap->pa_file, "{");
-}
-
-/*
- * For enums, we try to print the enum name, and fall back to the value if it
- * can't be determined. We do not do any fancy flag processing like mdb.
- */
-/* ARGSUSED */
-static void
-dt_print_enum(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
-{
- FILE *fp = pap->pa_file;
- ctf_file_t *ctfp = pap->pa_ctfp;
- const char *ename;
- int value = 0;
-
- if ((ename = ctf_enum_name(ctfp, base, value)) != NULL)
- (void) fprintf(fp, "%s", ename);
- else
- (void) fprintf(fp, "%d", value);
-}
-
-/*
- * Forward declaration. There's not much to do here without the complete
- * type information, so just print out this fact and drive on.
- */
-/* ARGSUSED */
-static void
-dt_print_tag(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
-{
- (void) fprintf(pap->pa_file, "<forward decl>");
-}
-
-typedef void dt_printarg_f(ctf_id_t, ulong_t, dt_printarg_t *);
-
-static dt_printarg_f *const dt_printfuncs[] = {
- dt_print_int, /* CTF_K_INTEGER */
- dt_print_float, /* CTF_K_FLOAT */
- dt_print_ptr, /* CTF_K_POINTER */
- dt_print_array, /* CTF_K_ARRAY */
- dt_print_ptr, /* CTF_K_FUNCTION */
- dt_print_structlike, /* CTF_K_STRUCT */
- dt_print_structlike, /* CTF_K_UNION */
- dt_print_enum, /* CTF_K_ENUM */
- dt_print_tag /* CTF_K_FORWARD */
-};
-
-/*
- * Print one member of a structure. This callback is invoked from
- * ctf_type_visit() recursively.
- */
-static int
-dt_print_member(const char *name, ctf_id_t id, ulong_t off, int depth,
- void *data)
-{
- char type[DT_TYPE_NAMELEN];
- int kind;
- dt_printarg_t *pap = data;
- FILE *fp = pap->pa_file;
- ctf_file_t *ctfp = pap->pa_ctfp;
- boolean_t arraymember;
- boolean_t brief;
- ctf_encoding_t e;
- ctf_id_t rtype;
-
- dt_print_trailing_braces(pap, depth);
- /*
- * dt_print_trailing_braces() doesn't include the trailing newline; add
- * it here if necessary.
- */
- if (depth < pap->pa_depth)
- (void) fprintf(fp, "\n");
- pap->pa_depth = depth;
-
- if ((rtype = ctf_type_resolve(ctfp, id)) == CTF_ERR ||
- (kind = ctf_type_kind(ctfp, rtype)) == CTF_ERR ||
- kind < CTF_K_INTEGER || kind > CTF_K_FORWARD) {
- dt_print_indent(pap);
- (void) fprintf(fp, "%s = <invalid type %lu>", name, id);
- return (0);
- }
-
- dt_print_type_name(ctfp, id, type, sizeof (type));
-
- arraymember = (pap->pa_nest != 0 && depth == 0);
- brief = (arraymember && !CTF_IS_STRUCTLIKE(kind));
-
- if (!brief) {
- /*
- * If this is a direct array member and a struct (otherwise
- * brief would be true), then print a trailing newline, as the
- * array printing code doesn't include it because it might be a
- * simple type.
- */
- if (arraymember)
- (void) fprintf(fp, "\n");
- dt_print_indent(pap);
-
- /* always print the type */
- (void) fprintf(fp, "%s", type);
- if (name[0] != '\0') {
- /*
- * For aesthetics, we don't include a space between the
- * type name and member name if the type is a pointer.
- * This will give us "void *foo =" instead of "void *
- * foo =". Unions also have the odd behavior that the
- * type name is returned as "union ", with a trailing
- * space, so we also avoid printing a space if the type
- * name already ends with a space.
- */
- if (type[strlen(type) - 1] != '*' &&
- type[strlen(type) -1] != ' ') {
- (void) fprintf(fp, " ");
- }
- (void) fprintf(fp, "%s", name);
-
- /*
- * If this looks like a bitfield, or is an integer not
- * aligned on a byte boundary, print the number of
- * bits after the name.
- */
- if (kind == CTF_K_INTEGER &&
- ctf_type_encoding(ctfp, id, &e) == 0) {
- ulong_t bits = e.cte_bits;
- ulong_t size = bits / NBBY;
-
- if (bits % NBBY != 0 ||
- off % NBBY != 0 ||
- size > 8 ||
- size != ctf_type_size(ctfp, id)) {
- (void) fprintf(fp, " :%lu", bits);
- }
- }
-
- (void) fprintf(fp, " =");
- }
- (void) fprintf(fp, " ");
- }
-
- dt_printfuncs[kind - 1](rtype, off, pap);
-
- /* direct simple array members are not separated by newlines */
- if (!brief)
- (void) fprintf(fp, "\n");
-
- return (0);
-}
-
-/*
- * Main print function invoked by dt_consume_cpu().
- */
-int
-dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
- caddr_t addr, size_t len)
-{
- const char *s;
- char *object;
- dt_printarg_t pa;
- ctf_id_t id;
- dt_module_t *dmp;
-
- /*
- * Split the fully-qualified type ID (module`id). This should
- * always be the format, but if for some reason we don't find the
- * expected value, return 0 to fall back to the generic trace()
- * behavior.
- */
- for (s = typename; *s != '\0' && *s != '`'; s++)
- ;
-
- if (*s != '`')
- return (0);
-
- object = alloca(s - typename + 1);
- bcopy(typename, object, s - typename);
- object[s - typename] = '\0';
- id = atoi(s + 1);
-
- /*
- * Try to get the CTF kind for this id. If something has gone horribly
- * wrong and we can't resolve the ID, bail out and let trace() do the
- * work.
- */
- dmp = dt_module_lookup_by_name(dtp, object);
- if (dmp == NULL || ctf_type_kind(dt_module_getctf(dtp, dmp),
- id) == CTF_ERR) {
- return (0);
- }
-
- /* setup the print structure and kick off the main print routine */
- pa.pa_addr = addr;
- pa.pa_ctfp = dt_module_getctf(dtp, dmp);
- pa.pa_nest = 0;
- pa.pa_depth = 0;
- pa.pa_file = fp;
- (void) ctf_type_visit(pa.pa_ctfp, id, dt_print_member, &pa);
-
- dt_print_trailing_braces(&pa, 0);
-
- return (len);
-}
diff --git a/lib/libdtrace/common/dt_printf.c b/lib/libdtrace/common/dt_printf.c
index eabc42338bcc..52904789bc7e 100644
--- a/lib/libdtrace/common/dt_printf.c
+++ b/lib/libdtrace/common/dt_printf.c
@@ -21,7 +21,6 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
*/
#include <sys/sysmacros.h>
@@ -1301,14 +1300,6 @@ pfprint_lquantize(dtrace_hdl_t *dtp, FILE *fp, const char *format,
return (dt_print_lquantize(dtp, fp, addr, size, normal));
}
-/*ARGSUSED*/
-static int
-pfprint_llquantize(dtrace_hdl_t *dtp, FILE *fp, const char *format,
- const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal)
-{
- return (dt_print_llquantize(dtp, fp, addr, size, normal));
-}
-
static int
dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,
const dtrace_recdesc_t *recs, uint_t nrecs, const void *buf,
@@ -1494,9 +1485,6 @@ dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,
case DTRACEAGG_LQUANTIZE:
func = pfprint_lquantize;
break;
- case DTRACEAGG_LLQUANTIZE:
- func = pfprint_llquantize;
- break;
case DTRACEACT_MOD:
func = pfprint_mod;
break;
diff --git a/lib/libdtrace/common/dt_program.c b/lib/libdtrace/common/dt_program.c
index 7d725bd0af86..19f377de26ac 100644
--- a/lib/libdtrace/common/dt_program.c
+++ b/lib/libdtrace/common/dt_program.c
@@ -21,7 +21,6 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <unistd.h>
@@ -348,7 +347,6 @@ dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
if (sdp->dtsd_fmtdata != NULL)
dt_printf_destroy(sdp->dtsd_fmtdata);
- dt_free(dtp, sdp->dtsd_strdata);
dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc);
dt_free(dtp, sdp);
diff --git a/lib/libdtrace/common/dtrace.h b/lib/libdtrace/common/dtrace.h
index 87df1ca4402a..1c041207c0ae 100644
--- a/lib/libdtrace/common/dtrace.h
+++ b/lib/libdtrace/common/dtrace.h
@@ -24,13 +24,11 @@
* Use is subject to license terms.
*/
-/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- */
-
#ifndef _DTRACE_H
#define _DTRACE_H
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include <sys/dtrace.h>
#include <stdarg.h>
#include <stdio.h>
@@ -150,7 +148,6 @@ typedef struct dtrace_stmtdesc {
dtrace_actdesc_t *dtsd_action_last; /* last action in action list */
void *dtsd_aggdata; /* aggregation data */
void *dtsd_fmtdata; /* type-specific output data */
- void *dtsd_strdata; /* type-specific string data */
void (*dtsd_callback)(); /* callback function for EPID */
void *dtsd_data; /* callback data pointer */
dtrace_attribute_t dtsd_descattr; /* probedesc attributes */
@@ -243,18 +240,6 @@ extern int dtrace_freopen(dtrace_hdl_t *, FILE *, void *,
const void *, size_t);
/*
- * Type-specific output printing
- *
- * The print() action will associate a string data record that is actually the
- * fully-qualified type name of the data traced by the DIFEXPR action. This is
- * stored in the same 'format' record from the kernel, but we know by virtue of
- * the fact that the action is still DIFEXPR that it is actually a reference to
- * plain string data.
- */
-extern int dtrace_print(dtrace_hdl_t *, FILE *, const char *,
- caddr_t, size_t);
-
-/*
* DTrace Work Interface
*/
typedef enum {
diff --git a/lib/libdtrace/i386/regs.d.in b/lib/libdtrace/i386/regs.d.in
index d18c5f7ff1fb..3328f33515b0 100644
--- a/lib/libdtrace/i386/regs.d.in
+++ b/lib/libdtrace/i386/regs.d.in
@@ -23,9 +23,8 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-/*
- * Copyright 2011 Joyent, Inc. All rights reserved.
- */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
inline int R_GS = @GS@;
#pragma D binding "1.0" R_GS
@@ -116,149 +115,3 @@ inline int R_R14 = @REG_R14@;
inline int R_R15 = @REG_R15@;
#pragma D binding "1.0" R_R15
-enum vmregs_vmx {
- VMX_VIRTUAL_PROCESSOR_ID = 0x00000000,
- VMX_GUEST_ES_SELECTOR = 0x00000800,
- VMX_GUEST_CS_SELECTOR = 0x00000802,
- VMX_GUEST_SS_SELECTOR = 0x00000804,
- VMX_GUEST_DS_SELECTOR = 0x00000806,
- VMX_GUEST_FS_SELECTOR = 0x00000808,
- VMX_GUEST_GS_SELECTOR = 0x0000080a,
- VMX_GUEST_LDTR_SELECTOR = 0x0000080c,
- VMX_GUEST_TR_SELECTOR = 0x0000080e,
- VMX_HOST_ES_SELECTOR = 0x00000c00,
- VMX_HOST_CS_SELECTOR = 0x00000c02,
- VMX_HOST_SS_SELECTOR = 0x00000c04,
- VMX_HOST_DS_SELECTOR = 0x00000c06,
- VMX_HOST_FS_SELECTOR = 0x00000c08,
- VMX_HOST_GS_SELECTOR = 0x00000c0a,
- VMX_HOST_TR_SELECTOR = 0x00000c0c,
- VMX_IO_BITMAP_A = 0x00002000,
- VMX_IO_BITMAP_A_HIGH = 0x00002001,
- VMX_IO_BITMAP_B = 0x00002002,
- VMX_IO_BITMAP_B_HIGH = 0x00002003,
- VMX_MSR_BITMAP = 0x00002004,
- VMX_MSR_BITMAP_HIGH = 0x00002005,
- VMX_VM_EXIT_MSR_STORE_ADDR = 0x00002006,
- VMX_VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007,
- VMX_VM_EXIT_MSR_LOAD_ADDR = 0x00002008,
- VMX_VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009,
- VMX_VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,
- VMX_VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b,
- VMX_TSC_OFFSET = 0x00002010,
- VMX_TSC_OFFSET_HIGH = 0x00002011,
- VMX_VIRTUAL_APIC_PAGE_ADDR = 0x00002012,
- VMX_VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
- VMX_APIC_ACCESS_ADDR = 0x00002014,
- VMX_APIC_ACCESS_ADDR_HIGH = 0x00002015,
- VMX_EPT_POINTER = 0x0000201a,
- VMX_EPT_POINTER_HIGH = 0x0000201b,
- VMX_GUEST_PHYSICAL_ADDRESS = 0x00002400,
- VMX_GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,
- VMX_VMCS_LINK_POINTER = 0x00002800,
- VMX_VMCS_LINK_POINTER_HIGH = 0x00002801,
- VMX_GUEST_IA32_DEBUGCTL = 0x00002802,
- VMX_GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
- VMX_GUEST_IA32_PAT = 0x00002804,
- VMX_GUEST_IA32_PAT_HIGH = 0x00002805,
- VMX_GUEST_PDPTR0 = 0x0000280a,
- VMX_GUEST_PDPTR0_HIGH = 0x0000280b,
- VMX_GUEST_PDPTR1 = 0x0000280c,
- VMX_GUEST_PDPTR1_HIGH = 0x0000280d,
- VMX_GUEST_PDPTR2 = 0x0000280e,
- VMX_GUEST_PDPTR2_HIGH = 0x0000280f,
- VMX_GUEST_PDPTR3 = 0x00002810,
- VMX_GUEST_PDPTR3_HIGH = 0x00002811,
- VMX_HOST_IA32_PAT = 0x00002c00,
- VMX_HOST_IA32_PAT_HIGH = 0x00002c01,
- VMX_PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
- VMX_CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
- VMX_EXCEPTION_BITMAP = 0x00004004,
- VMX_PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
- VMX_PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
- VMX_CR3_TARGET_COUNT = 0x0000400a,
- VMX_VM_EXIT_CONTROLS = 0x0000400c,
- VMX_VM_EXIT_MSR_STORE_COUNT = 0x0000400e,
- VMX_VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
- VMX_VM_ENTRY_CONTROLS = 0x00004012,
- VMX_VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
- VMX_VM_ENTRY_INTR_INFO_FIELD = 0x00004016,
- VMX_VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
- VMX_VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
- VMX_TPR_THRESHOLD = 0x0000401c,
- VMX_SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
- VMX_PLE_GAP = 0x00004020,
- VMX_PLE_WINDOW = 0x00004022,
- VMX_VM_INSTRUCTION_ERROR = 0x00004400,
- VMX_VM_EXIT_REASON = 0x00004402,
- VMX_VM_EXIT_INTR_INFO = 0x00004404,
- VMX_VM_EXIT_INTR_ERROR_CODE = 0x00004406,
- VMX_IDT_VECTORING_INFO_FIELD = 0x00004408,
- VMX_IDT_VECTORING_ERROR_CODE = 0x0000440a,
- VMX_VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
- VMX_VMX_INSTRUCTION_INFO = 0x0000440e,
- VMX_GUEST_ES_LIMIT = 0x00004800,
- VMX_GUEST_CS_LIMIT = 0x00004802,
- VMX_GUEST_SS_LIMIT = 0x00004804,
- VMX_GUEST_DS_LIMIT = 0x00004806,
- VMX_GUEST_FS_LIMIT = 0x00004808,
- VMX_GUEST_GS_LIMIT = 0x0000480a,
- VMX_GUEST_LDTR_LIMIT = 0x0000480c,
- VMX_GUEST_TR_LIMIT = 0x0000480e,
- VMX_GUEST_GDTR_LIMIT = 0x00004810,
- VMX_GUEST_IDTR_LIMIT = 0x00004812,
- VMX_GUEST_ES_AR_BYTES = 0x00004814,
- VMX_GUEST_CS_AR_BYTES = 0x00004816,
- VMX_GUEST_SS_AR_BYTES = 0x00004818,
- VMX_GUEST_DS_AR_BYTES = 0x0000481a,
- VMX_GUEST_FS_AR_BYTES = 0x0000481c,
- VMX_GUEST_GS_AR_BYTES = 0x0000481e,
- VMX_GUEST_LDTR_AR_BYTES = 0x00004820,
- VMX_GUEST_TR_AR_BYTES = 0x00004822,
- VMX_GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
- VMX_GUEST_ACTIVITY_STATE = 0X00004826,
- VMX_GUEST_SYSENTER_CS = 0x0000482A,
- VMX_HOST_IA32_SYSENTER_CS = 0x00004c00,
- VMX_CR0_GUEST_HOST_MASK = 0x00006000,
- VMX_CR4_GUEST_HOST_MASK = 0x00006002,
- VMX_CR0_READ_SHADOW = 0x00006004,
- VMX_CR4_READ_SHADOW = 0x00006006,
- VMX_CR3_TARGET_VALUE0 = 0x00006008,
- VMX_CR3_TARGET_VALUE1 = 0x0000600a,
- VMX_CR3_TARGET_VALUE2 = 0x0000600c,
- VMX_CR3_TARGET_VALUE3 = 0x0000600e,
- VMX_EXIT_QUALIFICATION = 0x00006400,
- VMX_GUEST_LINEAR_ADDRESS = 0x0000640a,
- VMX_GUEST_CR0 = 0x00006800,
- VMX_GUEST_CR3 = 0x00006802,
- VMX_GUEST_CR4 = 0x00006804,
- VMX_GUEST_ES_BASE = 0x00006806,
- VMX_GUEST_CS_BASE = 0x00006808,
- VMX_GUEST_SS_BASE = 0x0000680a,
- VMX_GUEST_DS_BASE = 0x0000680c,
- VMX_GUEST_FS_BASE = 0x0000680e,
- VMX_GUEST_GS_BASE = 0x00006810,
- VMX_GUEST_LDTR_BASE = 0x00006812,
- VMX_GUEST_TR_BASE = 0x00006814,
- VMX_GUEST_GDTR_BASE = 0x00006816,
- VMX_GUEST_IDTR_BASE = 0x00006818,
- VMX_GUEST_DR7 = 0x0000681a,
- VMX_GUEST_RSP = 0x0000681c,
- VMX_GUEST_RIP = 0x0000681e,
- VMX_GUEST_RFLAGS = 0x00006820,
- VMX_GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,
- VMX_GUEST_SYSENTER_ESP = 0x00006824,
- VMX_GUEST_SYSENTER_EIP = 0x00006826,
- VMX_HOST_CR0 = 0x00006c00,
- VMX_HOST_CR3 = 0x00006c02,
- VMX_HOST_CR4 = 0x00006c04,
- VMX_HOST_FS_BASE = 0x00006c06,
- VMX_HOST_GS_BASE = 0x00006c08,
- VMX_HOST_TR_BASE = 0x00006c0a,
- VMX_HOST_GDTR_BASE = 0x00006c0c,
- VMX_HOST_IDTR_BASE = 0x00006c0e,
- VMX_HOST_IA32_SYSENTER_ESP = 0x00006c10,
- VMX_HOST_IA32_SYSENTER_EIP = 0x00006c12,
- VMX_HOST_RSP = 0x00006c14,
- VMX_HOST_RIP = 0x00006c16
-};
diff --git a/lib/libnvpair/libnvpair.c b/lib/libnvpair/libnvpair.c
index c2e5a1b46dad..16bce483bee5 100644
--- a/lib/libnvpair/libnvpair.c
+++ b/lib/libnvpair/libnvpair.c
@@ -20,7 +20,6 @@
*/
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <unistd.h>
@@ -804,10 +803,6 @@ dump_nvlist(nvlist_t *list, int indent)
while ((elem = nvlist_next_nvpair(list, elem)) != NULL) {
switch (nvpair_type(elem)) {
- case DATA_TYPE_BOOLEAN:
- (void) printf("%*s%s\n", indent, "", nvpair_name(elem));
- break;
-
case DATA_TYPE_BOOLEAN_VALUE:
(void) nvpair_value_boolean_value(elem, &bool_value);
(void) printf("%*s%s: %s\n", indent, "",
diff --git a/lib/libuutil/common/uu_list.c b/lib/libuutil/common/uu_list.c
index 93795e5289b2..35c7ba800103 100644
--- a/lib/libuutil/common/uu_list.c
+++ b/lib/libuutil/common/uu_list.c
@@ -18,14 +18,13 @@
*
* CDDL HEADER END
*/
-
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- *
- * Copyright 2011 Jason King. All rights reserved.
*/
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include "libuutil_common.h"
#include <stdlib.h>
@@ -319,8 +318,6 @@ uu_list_find(uu_list_t *lp, void *elem, void *private, uu_list_index_t *out)
uu_compare_fn_t *func = lp->ul_pool->ulp_cmp;
uu_list_node_impl_t *np;
- uu_set_error(UU_ERROR_NONE);
-
if (func == NULL) {
if (out != NULL)
*out = 0;
diff --git a/lib/libzfs/common/libzfs.h b/lib/libzfs/common/libzfs.h
index 56ebf530daf5..ea34cc9efa31 100644
--- a/lib/libzfs/common/libzfs.h
+++ b/lib/libzfs/common/libzfs.h
@@ -21,9 +21,6 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#ifndef _LIBZFS_H
@@ -54,8 +51,7 @@ extern "C" {
/*
* libzfs errors
*/
-typedef enum zfs_error {
- EZFS_SUCCESS = 0, /* no error -- success */
+enum {
EZFS_NOMEM = 2000, /* out of memory */
EZFS_BADPROP, /* invalid property value */
EZFS_PROPREADONLY, /* cannot set readonly property */
@@ -127,7 +123,7 @@ typedef enum zfs_error {
EZFS_DIFFDATA, /* bad zfs diff data */
EZFS_POOLREADONLY, /* pool is in read-only mode */
EZFS_UNKNOWN
-} zfs_error_t;
+};
/*
* The following data structures are all part
@@ -183,9 +179,6 @@ extern libzfs_handle_t *zfs_get_handle(zfs_handle_t *);
extern void libzfs_print_on_error(libzfs_handle_t *, boolean_t);
-extern void zfs_save_arguments(int argc, char **, char *, int);
-extern int zpool_log_history(libzfs_handle_t *, const char *);
-
extern int libzfs_errno(libzfs_handle_t *);
extern const char *libzfs_error_action(libzfs_handle_t *);
extern const char *libzfs_error_description(libzfs_handle_t *);
@@ -220,7 +213,7 @@ extern int zpool_iter(libzfs_handle_t *, zpool_iter_f, void *);
*/
extern int zpool_create(libzfs_handle_t *, const char *, nvlist_t *,
nvlist_t *, nvlist_t *);
-extern int zpool_destroy(zpool_handle_t *, const char *);
+extern int zpool_destroy(zpool_handle_t *);
extern int zpool_add(zpool_handle_t *, nvlist_t *);
typedef struct splitflags {
@@ -236,8 +229,6 @@ typedef struct splitflags {
*/
extern int zpool_scan(zpool_handle_t *, pool_scan_func_t);
extern int zpool_clear(zpool_handle_t *, const char *, nvlist_t *);
-extern int zpool_reguid(zpool_handle_t *);
-extern int zpool_reopen(zpool_handle_t *);
extern int zpool_vdev_online(zpool_handle_t *, const char *, int,
vdev_state_t *);
@@ -295,15 +286,6 @@ typedef enum {
ZPOOL_STATUS_BAD_LOG, /* cannot read log chain(s) */
/*
- * If the pool has unsupported features but can still be opened in
- * read-only mode, its status is ZPOOL_STATUS_UNSUP_FEAT_WRITE. If the
- * pool has unsupported features but cannot be opened at all, its
- * status is ZPOOL_STATUS_UNSUP_FEAT_READ.
- */
- ZPOOL_STATUS_UNSUP_FEAT_READ, /* unsupported features for read */
- ZPOOL_STATUS_UNSUP_FEAT_WRITE, /* unsupported features for write */
-
- /*
* These faults have no corresponding message ID. At the time we are
* checking the status, the original reason for the FMA fault (I/O or
* checksum errors) has been lost.
@@ -335,20 +317,18 @@ extern void zpool_dump_ddt(const ddt_stat_t *dds, const ddt_histogram_t *ddh);
* Statistics and configuration functions.
*/
extern nvlist_t *zpool_get_config(zpool_handle_t *, nvlist_t **);
-extern nvlist_t *zpool_get_features(zpool_handle_t *);
extern int zpool_refresh_stats(zpool_handle_t *, boolean_t *);
extern int zpool_get_errlog(zpool_handle_t *, nvlist_t **);
/*
* Import and export functions
*/
-extern int zpool_export(zpool_handle_t *, boolean_t, const char *);
-extern int zpool_export_force(zpool_handle_t *, const char *);
+extern int zpool_export(zpool_handle_t *, boolean_t);
+extern int zpool_export_force(zpool_handle_t *);
extern int zpool_import(libzfs_handle_t *, nvlist_t *, const char *,
char *altroot);
extern int zpool_import_props(libzfs_handle_t *, nvlist_t *, const char *,
nvlist_t *, int);
-extern void zpool_print_unsup_feat(nvlist_t *config);
/*
* Search for pools to import
@@ -377,7 +357,7 @@ extern nvlist_t *zpool_find_import_cached(libzfs_handle_t *, const char *,
*/
struct zfs_cmd;
-extern const char *zfs_history_event_names[];
+extern const char *zfs_history_event_names[LOG_END];
extern char *zpool_vdev_name(libzfs_handle_t *, zpool_handle_t *, nvlist_t *,
boolean_t verbose);
@@ -385,6 +365,9 @@ extern int zpool_upgrade(zpool_handle_t *, uint64_t);
extern int zpool_get_history(zpool_handle_t *, nvlist_t **);
extern int zpool_history_unpack(char *, uint64_t, uint64_t *,
nvlist_t ***, uint_t *);
+extern void zpool_set_history_str(const char *subcommand, int argc,
+ char **argv, char *history_str);
+extern int zpool_stage_history(libzfs_handle_t *, const char *);
extern void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *,
size_t len);
extern int zfs_ioctl(libzfs_handle_t *, int, struct zfs_cmd *);
@@ -397,7 +380,6 @@ extern void zpool_explain_recover(libzfs_handle_t *, const char *, int,
* underlying datasets, only the references to them.
*/
extern zfs_handle_t *zfs_open(libzfs_handle_t *, const char *, int);
-extern zfs_handle_t *zfs_handle_dup(zfs_handle_t *);
extern void zfs_close(zfs_handle_t *);
extern zfs_type_t zfs_get_type(const zfs_handle_t *);
extern const char *zfs_get_name(const zfs_handle_t *);
@@ -431,20 +413,12 @@ extern int zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
uint64_t *propvalue);
extern int zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
char *propbuf, int proplen, boolean_t literal);
-extern int zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
- uint64_t *propvalue);
-extern int zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
- char *propbuf, int proplen, boolean_t literal);
-extern int zfs_prop_get_feature(zfs_handle_t *zhp, const char *propname,
- char *buf, size_t len);
extern uint64_t zfs_prop_get_int(zfs_handle_t *, zfs_prop_t);
extern int zfs_prop_inherit(zfs_handle_t *, const char *, boolean_t);
extern const char *zfs_prop_values(zfs_prop_t);
extern int zfs_prop_is_string(zfs_prop_t prop);
extern nvlist_t *zfs_get_user_props(zfs_handle_t *);
extern nvlist_t *zfs_get_recvd_props(zfs_handle_t *);
-extern nvlist_t *zfs_get_clones_nvl(zfs_handle_t *);
-
typedef struct zprop_list {
int pl_prop;
@@ -462,19 +436,10 @@ extern void zfs_prune_proplist(zfs_handle_t *, uint8_t *);
#define ZFS_MOUNTPOINT_NONE "none"
#define ZFS_MOUNTPOINT_LEGACY "legacy"
-#define ZFS_FEATURE_DISABLED "disabled"
-#define ZFS_FEATURE_ENABLED "enabled"
-#define ZFS_FEATURE_ACTIVE "active"
-
-#define ZFS_UNSUPPORTED_INACTIVE "inactive"
-#define ZFS_UNSUPPORTED_READONLY "readonly"
-
/*
* zpool property management
*/
extern int zpool_expand_proplist(zpool_handle_t *, zprop_list_t **);
-extern int zpool_prop_get_feature(zpool_handle_t *, const char *, char *,
- size_t);
extern const char *zpool_prop_default_string(zpool_prop_t);
extern uint64_t zpool_prop_default_numeric(zpool_prop_t);
extern const char *zpool_prop_column_name(zpool_prop_t);
@@ -528,7 +493,6 @@ 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_sorted(zfs_handle_t *, zfs_iter_f, void *);
-extern int zfs_iter_snapspec(zfs_handle_t *, const char *, zfs_iter_f, void *);
typedef struct get_all_cb {
zfs_handle_t **cb_handles;
@@ -549,94 +513,79 @@ extern int zfs_create(libzfs_handle_t *, const char *, zfs_type_t,
extern int zfs_create_ancestors(libzfs_handle_t *, const char *);
extern int zfs_destroy(zfs_handle_t *, boolean_t);
extern int zfs_destroy_snaps(zfs_handle_t *, char *, boolean_t);
-extern int zfs_destroy_snaps_nvl(zfs_handle_t *, nvlist_t *, boolean_t);
extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *);
extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *);
-extern int zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps,
- nvlist_t *props);
extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t);
-extern int zfs_rename(zfs_handle_t *, const char *, boolean_t, boolean_t);
+extern int zfs_rename(zfs_handle_t *, const char *, boolean_t);
typedef struct sendflags {
/* print informational messages (ie, -v was specified) */
- boolean_t verbose;
+ int verbose : 1;
/* recursive send (ie, -R) */
- boolean_t replicate;
+ int replicate : 1;
/* for incrementals, do all intermediate snapshots */
- boolean_t doall;
+ int doall : 1; /* (ie, -I) */
/* if dataset is a clone, do incremental from its origin */
- boolean_t fromorigin;
+ int fromorigin : 1;
/* do deduplication */
- boolean_t dedup;
+ int dedup : 1;
/* send properties (ie, -p) */
- boolean_t props;
-
- /* do not send (no-op, ie. -n) */
- boolean_t dryrun;
-
- /* parsable verbose output (ie. -P) */
- boolean_t parsable;
-
- /* show progress (ie. -v) */
- boolean_t progress;
+ int props : 1;
} sendflags_t;
typedef boolean_t (snapfilter_cb_t)(zfs_handle_t *, void *);
-extern int zfs_send(zfs_handle_t *, const char *, const char *,
- sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **);
+extern int zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
+ sendflags_t flags, int outfd, snapfilter_cb_t filter_func,
+ void *cb_arg, nvlist_t **debugnvp);
extern int zfs_promote(zfs_handle_t *);
extern int zfs_hold(zfs_handle_t *, const char *, const char *, boolean_t,
boolean_t, boolean_t, int, uint64_t, uint64_t);
extern int zfs_release(zfs_handle_t *, const char *, const char *, boolean_t);
-extern int zfs_get_holds(zfs_handle_t *, nvlist_t **);
extern uint64_t zvol_volsize_to_reservation(uint64_t, nvlist_t *);
typedef int (*zfs_userspace_cb_t)(void *arg, const char *domain,
uid_t rid, uint64_t space);
-extern int zfs_userspace(zfs_handle_t *, zfs_userquota_prop_t,
- zfs_userspace_cb_t, void *);
-
-extern int zfs_get_fsacl(zfs_handle_t *, nvlist_t **);
-extern int zfs_set_fsacl(zfs_handle_t *, boolean_t, nvlist_t *);
+extern int zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
+ zfs_userspace_cb_t func, void *arg);
typedef struct recvflags {
/* print informational messages (ie, -v was specified) */
- boolean_t verbose;
+ int verbose : 1;
/* the destination is a prefix, not the exact fs (ie, -d) */
- boolean_t isprefix;
+ int isprefix : 1;
/*
* Only the tail of the sent snapshot path is appended to the
* destination to determine the received snapshot name (ie, -e).
*/
- boolean_t istail;
+ int istail : 1;
/* do not actually do the recv, just check if it would work (ie, -n) */
- boolean_t dryrun;
+ int dryrun : 1;
/* rollback/destroy filesystems as necessary (eg, -F) */
- boolean_t force;
+ int force : 1;
/* set "canmount=off" on all modified filesystems */
- boolean_t canmountoff;
+ int canmountoff : 1;
/* byteswap flag is used internally; callers need not specify */
- boolean_t byteswap;
+ int byteswap : 1;
/* do not mount file systems as they are extracted (private) */
- boolean_t nomount;
+ int nomount : 1;
} recvflags_t;
-extern int zfs_receive(libzfs_handle_t *, const char *, recvflags_t *,
+extern int zfs_receive(libzfs_handle_t *, const char *, recvflags_t,
int, avl_tree_t *);
typedef enum diff_flags {
diff --git a/lib/libzfs/common/libzfs_config.c b/lib/libzfs/common/libzfs_config.c
index d5ba20fde0cf..dc27238c9cf3 100644
--- a/lib/libzfs/common/libzfs_config.c
+++ b/lib/libzfs/common/libzfs_config.c
@@ -18,17 +18,12 @@
*
* CDDL HEADER END
*/
-
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
- * Copyright (c) 2012 by Delphix. All rights reserved.
- */
-
-/*
* The pool configuration repository is stored in /etc/zfs/zpool.cache as a
* single packed nvlist. While it would be nice to just read in this
* file from userland, this wouldn't work from a local zone. So we have to have
@@ -223,36 +218,6 @@ zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig)
}
/*
- * Retrieves a list of enabled features and their refcounts and caches it in
- * the pool handle.
- */
-nvlist_t *
-zpool_get_features(zpool_handle_t *zhp)
-{
- nvlist_t *config, *features;
-
- config = zpool_get_config(zhp, NULL);
-
- if (config == NULL || !nvlist_exists(config,
- ZPOOL_CONFIG_FEATURE_STATS)) {
- int error;
- boolean_t missing = B_FALSE;
-
- error = zpool_refresh_stats(zhp, &missing);
-
- if (error != 0 || missing)
- return (NULL);
-
- config = zpool_get_config(zhp, NULL);
- }
-
- verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
- &features) == 0);
-
- return (features);
-}
-
-/*
* Refresh the vdev statistics associated with the given pool. This is used in
* iostat to show configuration changes and determine the delta from the last
* time the function was called. This function can fail, in case the pool has
@@ -337,48 +302,6 @@ zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing)
}
/*
- * If the __ZFS_POOL_RESTRICT environment variable is set we only iterate over
- * pools it lists.
- *
- * This is an undocumented feature for use during testing only.
- *
- * This function returns B_TRUE if the pool should be skipped
- * during iteration.
- */
-static boolean_t
-check_restricted(const char *poolname)
-{
- static boolean_t initialized = B_FALSE;
- static char *restricted = NULL;
-
- const char *cur, *end;
- int len, namelen;
-
- if (!initialized) {
- initialized = B_TRUE;
- restricted = getenv("__ZFS_POOL_RESTRICT");
- }
-
- if (NULL == restricted)
- return (B_FALSE);
-
- cur = restricted;
- namelen = strlen(poolname);
- do {
- end = strchr(cur, ' ');
- len = (NULL == end) ? strlen(cur) : (end - cur);
-
- if (len == namelen && 0 == strncmp(cur, poolname, len)) {
- return (B_FALSE);
- }
-
- cur += (len + 1);
- } while (NULL != end);
-
- return (B_TRUE);
-}
-
-/*
* Iterate over all pools in the system.
*/
int
@@ -401,9 +324,6 @@ zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data)
for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
- if (check_restricted(cn->cn_name))
- continue;
-
if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) {
hdl->libzfs_pool_iter--;
return (-1);
@@ -439,9 +359,6 @@ zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data)
for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
- if (check_restricted(cn->cn_name))
- continue;
-
if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL)
continue;
diff --git a/lib/libzfs/common/libzfs_dataset.c b/lib/libzfs/common/libzfs_dataset.c
index cc2603cf890b..b7c1360db4b7 100644
--- a/lib/libzfs/common/libzfs_dataset.c
+++ b/lib/libzfs/common/libzfs_dataset.c
@@ -21,9 +21,6 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
*/
#include <ctype.h>
@@ -135,7 +132,6 @@ zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
namecheck_err_t why;
char what;
- (void) zfs_prop_get_table();
if (dataset_namecheck(path, &why, &what) != 0) {
if (hdl != NULL) {
switch (why) {
@@ -497,7 +493,7 @@ make_dataset_handle(libzfs_handle_t *hdl, const char *path)
return (zhp);
}
-zfs_handle_t *
+static zfs_handle_t *
make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
{
zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
@@ -514,53 +510,6 @@ make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
return (zhp);
}
-zfs_handle_t *
-zfs_handle_dup(zfs_handle_t *zhp_orig)
-{
- zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
-
- if (zhp == NULL)
- return (NULL);
-
- zhp->zfs_hdl = zhp_orig->zfs_hdl;
- zhp->zpool_hdl = zhp_orig->zpool_hdl;
- (void) strlcpy(zhp->zfs_name, zhp_orig->zfs_name,
- sizeof (zhp->zfs_name));
- zhp->zfs_type = zhp_orig->zfs_type;
- zhp->zfs_head_type = zhp_orig->zfs_head_type;
- zhp->zfs_dmustats = zhp_orig->zfs_dmustats;
- if (zhp_orig->zfs_props != NULL) {
- if (nvlist_dup(zhp_orig->zfs_props, &zhp->zfs_props, 0) != 0) {
- (void) no_memory(zhp->zfs_hdl);
- zfs_close(zhp);
- return (NULL);
- }
- }
- if (zhp_orig->zfs_user_props != NULL) {
- if (nvlist_dup(zhp_orig->zfs_user_props,
- &zhp->zfs_user_props, 0) != 0) {
- (void) no_memory(zhp->zfs_hdl);
- zfs_close(zhp);
- return (NULL);
- }
- }
- if (zhp_orig->zfs_recvd_props != NULL) {
- if (nvlist_dup(zhp_orig->zfs_recvd_props,
- &zhp->zfs_recvd_props, 0)) {
- (void) no_memory(zhp->zfs_hdl);
- zfs_close(zhp);
- return (NULL);
- }
- }
- zhp->zfs_mntcheck = zhp_orig->zfs_mntcheck;
- if (zhp_orig->zfs_mntopts != NULL) {
- zhp->zfs_mntopts = zfs_strdup(zhp_orig->zfs_hdl,
- zhp_orig->zfs_mntopts);
- }
- zhp->zfs_props_table = zhp_orig->zfs_props_table;
- return (zhp);
-}
-
/*
* Opens the given snapshot, filesystem, or volume. The 'types'
* argument is a mask of acceptable types. The function will print an
@@ -924,12 +873,6 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
goto error;
}
continue;
- } else if (prop == ZPROP_INVAL && zfs_prop_written(propname)) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "'%s' is readonly"),
- propname);
- (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
- goto error;
}
if (prop == ZPROP_INVAL) {
@@ -1407,7 +1350,8 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
libzfs_handle_t *hdl = zhp->zfs_hdl;
nvlist_t *nvl = NULL, *realprops;
zfs_prop_t prop;
- boolean_t do_prefix = B_TRUE;
+ boolean_t do_prefix;
+ uint64_t idx;
int added_resv;
(void) snprintf(errbuf, sizeof (errbuf),
@@ -1446,17 +1390,12 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
}
/*
- * We don't want to unmount & remount the dataset when changing
- * its canmount property to 'on' or 'noauto'. We only use
- * the changelist logic to unmount when setting canmount=off.
+ * If the dataset's canmount property is being set to noauto,
+ * then we want to prevent unmounting & remounting it.
*/
- if (prop == ZFS_PROP_CANMOUNT) {
- uint64_t idx;
- int err = zprop_string_to_index(prop, propval, &idx,
- ZFS_TYPE_DATASET);
- if (err == 0 && idx != ZFS_CANMOUNT_OFF)
- do_prefix = B_FALSE;
- }
+ do_prefix = !((prop == ZFS_PROP_CANMOUNT) &&
+ (zprop_string_to_index(prop, propval, &idx,
+ ZFS_TYPE_DATASET) == 0) && (idx == ZFS_CANMOUNT_NOAUTO));
if (do_prefix && (ret = changelist_prefix(cl)) != 0)
goto error;
@@ -1907,6 +1846,8 @@ zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
err = zfs_prop_get(zhp, prop, propbuf, proplen,
NULL, NULL, 0, literal);
zfs_unset_recvd_props_mode(zhp, &cookie);
+ } else if (zfs_prop_userquota(propname)) {
+ return (-1);
} else {
nvlist_t *propval;
char *recvdval;
@@ -1921,120 +1862,6 @@ zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
return (err == 0 ? 0 : -1);
}
-static int
-get_clones_string(zfs_handle_t *zhp, char *propbuf, size_t proplen)
-{
- nvlist_t *value;
- nvpair_t *pair;
-
- value = zfs_get_clones_nvl(zhp);
- if (value == NULL)
- return (-1);
-
- propbuf[0] = '\0';
- for (pair = nvlist_next_nvpair(value, NULL); pair != NULL;
- pair = nvlist_next_nvpair(value, pair)) {
- if (propbuf[0] != '\0')
- (void) strlcat(propbuf, ",", proplen);
- (void) strlcat(propbuf, nvpair_name(pair), proplen);
- }
-
- return (0);
-}
-
-struct get_clones_arg {
- uint64_t numclones;
- nvlist_t *value;
- const char *origin;
- char buf[ZFS_MAXNAMELEN];
-};
-
-int
-get_clones_cb(zfs_handle_t *zhp, void *arg)
-{
- struct get_clones_arg *gca = arg;
-
- if (gca->numclones == 0) {
- zfs_close(zhp);
- return (0);
- }
-
- if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, gca->buf, sizeof (gca->buf),
- NULL, NULL, 0, B_TRUE) != 0)
- goto out;
- if (strcmp(gca->buf, gca->origin) == 0) {
- if (nvlist_add_boolean(gca->value, zfs_get_name(zhp)) != 0) {
- zfs_close(zhp);
- return (no_memory(zhp->zfs_hdl));
- }
- gca->numclones--;
- }
-
-out:
- (void) zfs_iter_children(zhp, get_clones_cb, gca);
- zfs_close(zhp);
- return (0);
-}
-
-nvlist_t *
-zfs_get_clones_nvl(zfs_handle_t *zhp)
-{
- nvlist_t *nv, *value;
-
- if (nvlist_lookup_nvlist(zhp->zfs_props,
- zfs_prop_to_name(ZFS_PROP_CLONES), &nv) != 0) {
- struct get_clones_arg gca;
-
- /*
- * if this is a snapshot, then the kernel wasn't able
- * to get the clones. Do it by slowly iterating.
- */
- if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT)
- return (NULL);
- if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 0) != 0)
- return (NULL);
- if (nvlist_alloc(&value, NV_UNIQUE_NAME, 0) != 0) {
- nvlist_free(nv);
- return (NULL);
- }
-
- gca.numclones = zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES);
- gca.value = value;
- gca.origin = zhp->zfs_name;
-
- if (gca.numclones != 0) {
- zfs_handle_t *root;
- char pool[ZFS_MAXNAMELEN];
- char *cp = pool;
-
- /* get the pool name */
- (void) strlcpy(pool, zhp->zfs_name, sizeof (pool));
- (void) strsep(&cp, "/@");
- root = zfs_open(zhp->zfs_hdl, pool,
- ZFS_TYPE_FILESYSTEM);
-
- (void) get_clones_cb(root, &gca);
- }
-
- if (gca.numclones != 0 ||
- nvlist_add_nvlist(nv, ZPROP_VALUE, value) != 0 ||
- nvlist_add_nvlist(zhp->zfs_props,
- zfs_prop_to_name(ZFS_PROP_CLONES), nv) != 0) {
- nvlist_free(nv);
- nvlist_free(value);
- return (NULL);
- }
- nvlist_free(nv);
- nvlist_free(value);
- verify(0 == nvlist_lookup_nvlist(zhp->zfs_props,
- zfs_prop_to_name(ZFS_PROP_CLONES), &nv));
- }
-
- verify(nvlist_lookup_nvlist(nv, ZPROP_VALUE, &value) == 0);
-
- return (value);
-}
-
/*
* Retrieve a property from the given object. If 'literal' is specified, then
* numbers are left as exact values. Otherwise, numbers are converted to a
@@ -2163,11 +1990,6 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
return (-1);
break;
- case ZFS_PROP_CLONES:
- if (get_clones_string(zhp, propbuf, proplen) != 0)
- return (-1);
- break;
-
case ZFS_PROP_QUOTA:
case ZFS_PROP_REFQUOTA:
case ZFS_PROP_RESERVATION:
@@ -2196,7 +2018,6 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
}
break;
- case ZFS_PROP_REFRATIO:
case ZFS_PROP_COMPRESSRATIO:
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
return (-1);
@@ -2285,17 +2106,6 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
}
break;
- case ZFS_PROP_GUID:
- /*
- * GUIDs are stored as numbers, but they are identifiers.
- * We don't want them to be pretty printed, because pretty
- * printing mangles the ID into a truncated and useless value.
- */
- if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
- return (-1);
- (void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
- break;
-
default:
switch (zfs_prop_get_type(prop)) {
case PROP_TYPE_NUMBER:
@@ -2539,7 +2349,7 @@ zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname,
int err;
zfs_cmd_t zc = { 0 };
- (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
+ (void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
err = userquota_propname_decode(propname,
zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
@@ -2591,76 +2401,144 @@ zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
return (0);
}
-int
-zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
- uint64_t *propvalue)
+/*
+ * Returns the name of the given zfs handle.
+ */
+const char *
+zfs_get_name(const zfs_handle_t *zhp)
{
- int err;
- zfs_cmd_t zc = { 0 };
- const char *snapname;
+ return (zhp->zfs_name);
+}
- (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
+/*
+ * Returns the type of the given zfs handle.
+ */
+zfs_type_t
+zfs_get_type(const zfs_handle_t *zhp)
+{
+ return (zhp->zfs_type);
+}
- snapname = strchr(propname, '@') + 1;
- if (strchr(snapname, '@')) {
- (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
- } else {
- /* snapname is the short name, append it to zhp's fsname */
- char *cp;
-
- (void) strlcpy(zc.zc_value, zhp->zfs_name,
- sizeof (zc.zc_value));
- cp = strchr(zc.zc_value, '@');
- if (cp != NULL)
- *cp = '\0';
- (void) strlcat(zc.zc_value, "@", sizeof (zc.zc_value));
- (void) strlcat(zc.zc_value, snapname, sizeof (zc.zc_value));
- }
+static int
+zfs_do_list_ioctl(zfs_handle_t *zhp, int arg, zfs_cmd_t *zc)
+{
+ int rc;
+ uint64_t orig_cookie;
- err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_WRITTEN, &zc);
- if (err)
- return (err);
+ orig_cookie = zc->zc_cookie;
+top:
+ (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
+ rc = ioctl(zhp->zfs_hdl->libzfs_fd, arg, zc);
- *propvalue = zc.zc_cookie;
- return (0);
+ if (rc == -1) {
+ switch (errno) {
+ case ENOMEM:
+ /* expand nvlist memory and try again */
+ if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, zc) != 0) {
+ zcmd_free_nvlists(zc);
+ return (-1);
+ }
+ zc->zc_cookie = orig_cookie;
+ goto top;
+ /*
+ * An errno value of ESRCH indicates normal completion.
+ * If ENOENT is returned, then the underlying dataset
+ * has been removed since we obtained the handle.
+ */
+ case ESRCH:
+ case ENOENT:
+ rc = 1;
+ break;
+ default:
+ rc = zfs_standard_error(zhp->zfs_hdl, errno,
+ dgettext(TEXT_DOMAIN,
+ "cannot iterate filesystems"));
+ break;
+ }
+ }
+ return (rc);
}
+/*
+ * Iterate over all child filesystems
+ */
int
-zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
- char *propbuf, int proplen, boolean_t literal)
+zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
- int err;
- uint64_t propvalue;
+ zfs_cmd_t zc = { 0 };
+ zfs_handle_t *nzhp;
+ int ret;
- err = zfs_prop_get_written_int(zhp, propname, &propvalue);
+ if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM)
+ return (0);
- if (err)
- return (err);
+ if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
+ return (-1);
- if (literal) {
- (void) snprintf(propbuf, proplen, "%llu", propvalue);
- } else {
- zfs_nicenum(propvalue, propbuf, proplen);
+ while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT,
+ &zc)) == 0) {
+ /*
+ * Silently ignore errors, as the only plausible explanation is
+ * that the pool has since been removed.
+ */
+ if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
+ &zc)) == NULL) {
+ continue;
+ }
+
+ if ((ret = func(nzhp, data)) != 0) {
+ zcmd_free_nvlists(&zc);
+ return (ret);
+ }
}
- return (0);
+ zcmd_free_nvlists(&zc);
+ return ((ret < 0) ? ret : 0);
}
/*
- * Returns the name of the given zfs handle.
+ * Iterate over all snapshots
*/
-const char *
-zfs_get_name(const zfs_handle_t *zhp)
+int
+zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
- return (zhp->zfs_name);
+ zfs_cmd_t zc = { 0 };
+ zfs_handle_t *nzhp;
+ int ret;
+
+ if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
+ return (0);
+
+ 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) {
+ continue;
+ }
+
+ if ((ret = func(nzhp, data)) != 0) {
+ zcmd_free_nvlists(&zc);
+ return (ret);
+ }
+ }
+ zcmd_free_nvlists(&zc);
+ return ((ret < 0) ? ret : 0);
}
/*
- * Returns the type of the given zfs handle.
+ * Iterate over all children, snapshots and filesystems
*/
-zfs_type_t
-zfs_get_type(const zfs_handle_t *zhp)
+int
+zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
- return (zhp->zfs_type);
+ int ret;
+
+ if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0)
+ return (ret);
+
+ return (zfs_iter_snapshots(zhp, func, data));
}
/*
@@ -2686,19 +2564,18 @@ is_descendant(const char *ds1, const char *ds2)
/*
* Given a complete name, return just the portion that refers to the parent.
- * Will return -1 if there is no parent (path is just the name of the
- * pool).
+ * Can return NULL if this is a pool.
*/
static int
parent_name(const char *path, char *buf, size_t buflen)
{
- char *slashp;
-
- (void) strlcpy(buf, path, buflen);
+ char *loc;
- if ((slashp = strrchr(buf, '/')) == NULL)
+ if ((loc = strrchr(path, '/')) == NULL)
return (-1);
- *slashp = '\0';
+
+ (void) strncpy(buf, path, MIN(buflen, loc - path));
+ buf[loc - path] = '\0';
return (0);
}
@@ -2845,6 +2722,7 @@ create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
*/
for (cp = target + prefixlen + 1;
cp = strchr(cp, '/'); *cp = '/', cp++) {
+ char *logstr;
*cp = '\0';
@@ -2855,12 +2733,16 @@ create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
continue;
}
+ logstr = hdl->libzfs_log_str;
+ hdl->libzfs_log_str = NULL;
if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
NULL) != 0) {
+ hdl->libzfs_log_str = logstr;
opname = dgettext(TEXT_DOMAIN, "create");
goto ancestorerr;
}
+ hdl->libzfs_log_str = logstr;
h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
if (h == NULL) {
opname = dgettext(TEXT_DOMAIN, "open");
@@ -2918,12 +2800,12 @@ int
zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
nvlist_t *props)
{
+ zfs_cmd_t zc = { 0 };
int ret;
uint64_t size = 0;
uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
char errbuf[1024];
uint64_t zoned;
- dmu_objset_type_t ost;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot create '%s'"), path);
@@ -2943,16 +2825,17 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
* will return ENOENT, not EEXIST. To prevent this from happening, we
* first try to see if the dataset exists.
*/
- if (zfs_dataset_exists(hdl, path, ZFS_TYPE_DATASET)) {
+ (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name));
+ if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"dataset already exists"));
return (zfs_error(hdl, EZFS_EXISTS, errbuf));
}
if (type == ZFS_TYPE_VOLUME)
- ost = DMU_OST_ZVOL;
+ zc.zc_objset_type = DMU_OST_ZVOL;
else
- ost = DMU_OST_ZFS;
+ zc.zc_objset_type = DMU_OST_ZFS;
if (props && (props = zfs_valid_proplist(hdl, type, props,
zoned, NULL, errbuf)) == 0)
@@ -3004,10 +2887,15 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
}
}
- /* create the dataset */
- ret = lzc_create(path, ost, props);
+ if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0)
+ return (-1);
nvlist_free(props);
+ /* create the dataset */
+ ret = zfs_ioctl(hdl, ZFS_IOC_CREATE, &zc);
+
+ zcmd_free_nvlists(&zc);
+
/* check for failure */
if (ret != 0) {
char parent[ZFS_MAXNAMELEN];
@@ -3058,8 +2946,7 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
/*
* Destroys the given dataset. The caller must make sure that the filesystem
- * isn't mounted, and that there are no active dependents. If the file system
- * does not exist this function does nothing.
+ * isn't mounted, and that there are no active dependents.
*/
int
zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
@@ -3075,8 +2962,7 @@ zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
}
zc.zc_defer_destroy = defer;
- if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0 &&
- errno != ENOENT) {
+ if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0) {
return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
zhp->zfs_name));
@@ -3088,8 +2974,9 @@ zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
}
struct destroydata {
- nvlist_t *nvl;
- const char *snapname;
+ char *snapname;
+ boolean_t gotone;
+ boolean_t closezhp;
};
static int
@@ -3098,19 +2985,24 @@ zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
struct destroydata *dd = arg;
zfs_handle_t *szhp;
char name[ZFS_MAXNAMELEN];
+ boolean_t closezhp = dd->closezhp;
int rv = 0;
- (void) snprintf(name, sizeof (name),
- "%s@%s", zhp->zfs_name, dd->snapname);
+ (void) strlcpy(name, zhp->zfs_name, sizeof (name));
+ (void) strlcat(name, "@", sizeof (name));
+ (void) strlcat(name, dd->snapname, sizeof (name));
szhp = make_dataset_handle(zhp->zfs_hdl, name);
if (szhp) {
- verify(nvlist_add_boolean(dd->nvl, name) == 0);
+ dd->gotone = B_TRUE;
zfs_close(szhp);
}
- rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, dd);
- zfs_close(zhp);
+ dd->closezhp = B_TRUE;
+ if (!dd->gotone)
+ rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, arg);
+ if (closezhp)
+ zfs_close(zhp);
return (rv);
}
@@ -3120,61 +3012,43 @@ zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
int
zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
{
+ zfs_cmd_t zc = { 0 };
int ret;
struct destroydata dd = { 0 };
dd.snapname = snapname;
- verify(nvlist_alloc(&dd.nvl, NV_UNIQUE_NAME, 0) == 0);
- (void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd);
+ (void) zfs_check_snap_cb(zhp, &dd);
- if (nvlist_next_nvpair(dd.nvl, NULL) == NULL) {
- ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
+ if (!dd.gotone) {
+ return (zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
- zhp->zfs_name, snapname);
- } else {
- ret = zfs_destroy_snaps_nvl(zhp, dd.nvl, defer);
+ zhp->zfs_name, snapname));
}
- nvlist_free(dd.nvl);
- return (ret);
-}
-/*
- * Destroys all the snapshots named in the nvlist. They must be underneath
- * the zhp (either snapshots of it, or snapshots of its descendants).
- */
-int
-zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
-{
- int ret;
- nvlist_t *errlist;
-
- ret = lzc_destroy_snaps(snaps, defer, &errlist);
+ (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
+ (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
+ zc.zc_defer_destroy = defer;
+ ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS, &zc);
if (ret != 0) {
- for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL);
- pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) {
- char errbuf[1024];
- (void) snprintf(errbuf, sizeof (errbuf),
- dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"),
- nvpair_name(pair));
-
- switch (fnvpair_value_int32(pair)) {
- case EEXIST:
- zfs_error_aux(zhp->zfs_hdl,
- dgettext(TEXT_DOMAIN,
- "snapshot is cloned"));
- ret = zfs_error(zhp->zfs_hdl, EZFS_EXISTS,
- errbuf);
- break;
- default:
- ret = zfs_standard_error(zhp->zfs_hdl, errno,
- errbuf);
- break;
- }
+ char errbuf[1024];
+
+ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
+ "cannot destroy '%s@%s'"), zc.zc_name, snapname);
+
+ switch (errno) {
+ case EEXIST:
+ zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
+ "snapshot is cloned"));
+ return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf));
+
+ default:
+ return (zfs_standard_error(zhp->zfs_hdl, errno,
+ errbuf));
}
}
- return (ret);
+ return (0);
}
/*
@@ -3183,10 +3057,12 @@ zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
int
zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
{
+ zfs_cmd_t zc = { 0 };
char parent[ZFS_MAXNAMELEN];
int ret;
char errbuf[1024];
libzfs_handle_t *hdl = zhp->zfs_hdl;
+ zfs_type_t type;
uint64_t zoned;
assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
@@ -3194,7 +3070,7 @@ zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot create '%s'"), target);
- /* validate the target/clone name */
+ /* validate the target name */
if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
@@ -3205,21 +3081,32 @@ zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
(void) parent_name(target, parent, sizeof (parent));
/* do the clone */
+ if (ZFS_IS_VOLUME(zhp)) {
+ zc.zc_objset_type = DMU_OST_ZVOL;
+ type = ZFS_TYPE_VOLUME;
+ } else {
+ zc.zc_objset_type = DMU_OST_ZFS;
+ type = ZFS_TYPE_FILESYSTEM;
+ }
if (props) {
- zfs_type_t type;
- if (ZFS_IS_VOLUME(zhp)) {
- type = ZFS_TYPE_VOLUME;
- } else {
- type = ZFS_TYPE_FILESYSTEM;
- }
if ((props = zfs_valid_proplist(hdl, type, props, zoned,
zhp, errbuf)) == NULL)
return (-1);
+
+ if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
+ nvlist_free(props);
+ return (-1);
+ }
+
+ nvlist_free(props);
}
- ret = lzc_clone(target, zhp->zfs_name, props);
- nvlist_free(props);
+ (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name));
+ (void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value));
+ ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_CREATE, &zc);
+
+ zcmd_free_nvlists(&zc);
if (ret != 0) {
switch (errno) {
@@ -3304,134 +3191,74 @@ zfs_promote(zfs_handle_t *zhp)
return (ret);
}
-typedef struct snapdata {
- nvlist_t *sd_nvl;
- const char *sd_snapname;
-} snapdata_t;
-
-static int
-zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
-{
- snapdata_t *sd = arg;
- char name[ZFS_MAXNAMELEN];
- int rv = 0;
-
- (void) snprintf(name, sizeof (name),
- "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
-
- fnvlist_add_boolean(sd->sd_nvl, name);
-
- rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
- zfs_close(zhp);
- return (rv);
-}
-
/*
- * Creates snapshots. The keys in the snaps nvlist are the snapshots to be
- * created.
+ * Takes a snapshot of the given dataset.
*/
int
-zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
+zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
+ nvlist_t *props)
{
+ const char *delim;
+ char parent[ZFS_MAXNAMELEN];
+ zfs_handle_t *zhp;
+ zfs_cmd_t zc = { 0 };
int ret;
char errbuf[1024];
- nvpair_t *elem;
- nvlist_t *errors;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
- "cannot create snapshots "));
-
- elem = NULL;
- while ((elem = nvlist_next_nvpair(snaps, elem)) != NULL) {
- const char *snapname = nvpair_name(elem);
+ "cannot snapshot '%s'"), path);
- /* validate the target name */
- if (!zfs_validate_name(hdl, snapname, ZFS_TYPE_SNAPSHOT,
- B_TRUE)) {
- (void) snprintf(errbuf, sizeof (errbuf),
- dgettext(TEXT_DOMAIN,
- "cannot create snapshot '%s'"), snapname);
- return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
- }
- }
-
- if (props != NULL &&
- (props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
- props, B_FALSE, NULL, errbuf)) == NULL) {
- return (-1);
- }
+ /* validate the target name */
+ if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
+ return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
- ret = lzc_snapshot(snaps, props, &errors);
+ if (props) {
+ if ((props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
+ props, B_FALSE, NULL, errbuf)) == NULL)
+ return (-1);
- if (ret != 0) {
- boolean_t printed = B_FALSE;
- for (elem = nvlist_next_nvpair(errors, NULL);
- elem != NULL;
- elem = nvlist_next_nvpair(errors, elem)) {
- (void) snprintf(errbuf, sizeof (errbuf),
- dgettext(TEXT_DOMAIN,
- "cannot create snapshot '%s'"), nvpair_name(elem));
- (void) zfs_standard_error(hdl,
- fnvpair_value_int32(elem), errbuf);
- printed = B_TRUE;
+ if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
+ nvlist_free(props);
+ return (-1);
}
- if (!printed) {
- switch (ret) {
- case EXDEV:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "multiple snapshots of same "
- "fs not allowed"));
- (void) zfs_error(hdl, EZFS_EXISTS, errbuf);
- break;
- default:
- (void) zfs_standard_error(hdl, ret, errbuf);
- }
- }
+ nvlist_free(props);
}
- nvlist_free(props);
- nvlist_free(errors);
- return (ret);
-}
-
-int
-zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
- nvlist_t *props)
-{
- int ret;
- snapdata_t sd = { 0 };
- char fsname[ZFS_MAXNAMELEN];
- char *cp;
- zfs_handle_t *zhp;
- char errbuf[1024];
-
- (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
- "cannot snapshot %s"), path);
-
- if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
- return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
-
- (void) strlcpy(fsname, path, sizeof (fsname));
- cp = strchr(fsname, '@');
- *cp = '\0';
- sd.sd_snapname = cp + 1;
+ /* make sure the parent exists and is of the appropriate type */
+ delim = strchr(path, '@');
+ (void) strncpy(parent, path, delim - path);
+ parent[delim - path] = '\0';
- if ((zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM |
+ if ((zhp = zfs_open(hdl, parent, ZFS_TYPE_FILESYSTEM |
ZFS_TYPE_VOLUME)) == NULL) {
+ zcmd_free_nvlists(&zc);
return (-1);
}
- verify(nvlist_alloc(&sd.sd_nvl, NV_UNIQUE_NAME, 0) == 0);
- if (recursive) {
- (void) zfs_snapshot_cb(zfs_handle_dup(zhp), &sd);
- } else {
- fnvlist_add_boolean(sd.sd_nvl, path);
+ (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
+ (void) strlcpy(zc.zc_value, delim+1, sizeof (zc.zc_value));
+ if (ZFS_IS_VOLUME(zhp))
+ zc.zc_objset_type = DMU_OST_ZVOL;
+ else
+ zc.zc_objset_type = DMU_OST_ZFS;
+ zc.zc_cookie = recursive;
+ ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SNAPSHOT, &zc);
+
+ zcmd_free_nvlists(&zc);
+
+ /*
+ * if it was recursive, the one that actually failed will be in
+ * zc.zc_name.
+ */
+ if (ret != 0) {
+ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
+ "cannot create snapshot '%s@%s'"), zc.zc_name, zc.zc_value);
+ (void) zfs_standard_error(hdl, errno, errbuf);
}
- ret = zfs_snapshot_nvl(hdl, sd.sd_nvl, props);
- nvlist_free(sd.sd_nvl);
zfs_close(zhp);
+
return (ret);
}
@@ -3459,13 +3286,17 @@ rollback_destroy(zfs_handle_t *zhp, void *data)
zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
cbp->cb_create) {
+ char *logstr;
cbp->cb_dependent = B_TRUE;
cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
rollback_destroy, cbp);
cbp->cb_dependent = B_FALSE;
+ logstr = zhp->zfs_hdl->libzfs_log_str;
+ zhp->zfs_hdl->libzfs_log_str = NULL;
cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
+ zhp->zfs_hdl->libzfs_log_str = logstr;
}
} else {
/* We must destroy this clone; first unmount it */
@@ -3576,11 +3407,46 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
}
/*
+ * Iterate over all dependents for a given dataset. This includes both
+ * hierarchical dependents (children) and data dependents (snapshots and
+ * clones). The bulk of the processing occurs in get_dependents() in
+ * libzfs_graph.c.
+ */
+int
+zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion,
+ zfs_iter_f func, void *data)
+{
+ char **dependents;
+ size_t count;
+ int i;
+ zfs_handle_t *child;
+ int ret = 0;
+
+ if (get_dependents(zhp->zfs_hdl, allowrecursion, zhp->zfs_name,
+ &dependents, &count) != 0)
+ return (-1);
+
+ for (i = 0; i < count; i++) {
+ if ((child = make_dataset_handle(zhp->zfs_hdl,
+ dependents[i])) == NULL)
+ continue;
+
+ if ((ret = func(child, data)) != 0)
+ break;
+ }
+
+ for (i = 0; i < count; i++)
+ free(dependents[i]);
+ free(dependents);
+
+ return (ret);
+}
+
+/*
* Renames the given dataset.
*/
int
-zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
- boolean_t force_unmount)
+zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
{
int ret;
zfs_cmd_t zc = { 0 };
@@ -3692,8 +3558,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
}
} else {
- if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0,
- force_unmount ? MS_FORCE : 0)) == NULL)
+ if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0)) == NULL)
return (-1);
if (changelist_haszonedchild(cl)) {
@@ -4026,7 +3891,7 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
int error;
zfs_useracct_t buf[100];
- (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
+ (void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
zc.zc_objset_type = type;
zc.zc_nvlist_dst = (uintptr_t)buf;
@@ -4154,193 +4019,6 @@ zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
return (0);
}
-int
-zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl)
-{
- zfs_cmd_t zc = { 0 };
- libzfs_handle_t *hdl = zhp->zfs_hdl;
- int nvsz = 2048;
- void *nvbuf;
- int err = 0;
- char errbuf[ZFS_MAXNAMELEN+32];
-
- assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
- zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
-
-tryagain:
-
- nvbuf = malloc(nvsz);
- if (nvbuf == NULL) {
- err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
- goto out;
- }
-
- zc.zc_nvlist_dst_size = nvsz;
- zc.zc_nvlist_dst = (uintptr_t)nvbuf;
-
- (void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
-
- if (ioctl(hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) {
- (void) snprintf(errbuf, sizeof (errbuf),
- dgettext(TEXT_DOMAIN, "cannot get permissions on '%s'"),
- zc.zc_name);
- switch (errno) {
- case ENOMEM:
- free(nvbuf);
- nvsz = zc.zc_nvlist_dst_size;
- goto tryagain;
-
- case ENOTSUP:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "pool must be upgraded"));
- err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
- break;
- case EINVAL:
- err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
- break;
- case ENOENT:
- err = zfs_error(hdl, EZFS_NOENT, errbuf);
- break;
- default:
- err = zfs_standard_error_fmt(hdl, errno, errbuf);
- break;
- }
- } else {
- /* success */
- int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
- if (rc) {
- (void) snprintf(errbuf, sizeof (errbuf), dgettext(
- TEXT_DOMAIN, "cannot get permissions on '%s'"),
- zc.zc_name);
- err = zfs_standard_error_fmt(hdl, rc, errbuf);
- }
- }
-
- free(nvbuf);
-out:
- return (err);
-}
-
-int
-zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
-{
- zfs_cmd_t zc = { 0 };
- libzfs_handle_t *hdl = zhp->zfs_hdl;
- char *nvbuf;
- char errbuf[ZFS_MAXNAMELEN+32];
- size_t nvsz;
- int err;
-
- assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
- zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
-
- err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
- assert(err == 0);
-
- nvbuf = malloc(nvsz);
-
- err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
- assert(err == 0);
-
- zc.zc_nvlist_src_size = nvsz;
- zc.zc_nvlist_src = (uintptr_t)nvbuf;
- zc.zc_perm_action = un;
-
- (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
-
- if (zfs_ioctl(hdl, ZFS_IOC_SET_FSACL, &zc) != 0) {
- (void) snprintf(errbuf, sizeof (errbuf),
- dgettext(TEXT_DOMAIN, "cannot set permissions on '%s'"),
- zc.zc_name);
- switch (errno) {
- case ENOTSUP:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "pool must be upgraded"));
- err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
- break;
- case EINVAL:
- err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
- break;
- case ENOENT:
- err = zfs_error(hdl, EZFS_NOENT, errbuf);
- break;
- default:
- err = zfs_standard_error_fmt(hdl, errno, errbuf);
- break;
- }
- }
-
- free(nvbuf);
-
- return (err);
-}
-
-int
-zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl)
-{
- zfs_cmd_t zc = { 0 };
- libzfs_handle_t *hdl = zhp->zfs_hdl;
- int nvsz = 2048;
- void *nvbuf;
- int err = 0;
- char errbuf[ZFS_MAXNAMELEN+32];
-
- assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
-
-tryagain:
-
- nvbuf = malloc(nvsz);
- if (nvbuf == NULL) {
- err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
- goto out;
- }
-
- zc.zc_nvlist_dst_size = nvsz;
- zc.zc_nvlist_dst = (uintptr_t)nvbuf;
-
- (void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
-
- if (zfs_ioctl(hdl, ZFS_IOC_GET_HOLDS, &zc) != 0) {
- (void) snprintf(errbuf, sizeof (errbuf),
- dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
- zc.zc_name);
- switch (errno) {
- case ENOMEM:
- free(nvbuf);
- nvsz = zc.zc_nvlist_dst_size;
- goto tryagain;
-
- case ENOTSUP:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "pool must be upgraded"));
- err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
- break;
- case EINVAL:
- err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
- break;
- case ENOENT:
- err = zfs_error(hdl, EZFS_NOENT, errbuf);
- break;
- default:
- err = zfs_standard_error_fmt(hdl, errno, errbuf);
- break;
- }
- } else {
- /* success */
- int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
- if (rc) {
- (void) snprintf(errbuf, sizeof (errbuf),
- dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
- zc.zc_name);
- err = zfs_standard_error_fmt(hdl, rc, errbuf);
- }
- }
-
- free(nvbuf);
-out:
- return (err);
-}
-
uint64_t
zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props)
{
diff --git a/lib/libzfs/common/libzfs_graph.c b/lib/libzfs/common/libzfs_graph.c
new file mode 100644
index 000000000000..bc21c51ae26c
--- /dev/null
+++ b/lib/libzfs/common/libzfs_graph.c
@@ -0,0 +1,653 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Iterate over all children of the current object. This includes the normal
+ * dataset hierarchy, but also arbitrary hierarchies due to clones. We want to
+ * walk all datasets in the pool, and construct a directed graph of the form:
+ *
+ * home
+ * |
+ * +----+----+
+ * | |
+ * v v ws
+ * bar baz |
+ * | |
+ * v v
+ * @yesterday ----> foo
+ *
+ * In order to construct this graph, we have to walk every dataset in the pool,
+ * because the clone parent is stored as a property of the child, not the
+ * parent. The parent only keeps track of the number of clones.
+ *
+ * In the normal case (without clones) this would be rather expensive. To avoid
+ * unnecessary computation, we first try a walk of the subtree hierarchy
+ * starting from the initial node. At each dataset, we construct a node in the
+ * graph and an edge leading from its parent. If we don't see any snapshots
+ * with a non-zero clone count, then we are finished.
+ *
+ * If we do find a cloned snapshot, then we finish the walk of the current
+ * subtree, but indicate that we need to do a complete walk. We then perform a
+ * global walk of all datasets, avoiding the subtree we already processed.
+ *
+ * At the end of this, we'll end up with a directed graph of all relevant (and
+ * possible some irrelevant) datasets in the system. We need to both find our
+ * limiting subgraph and determine a safe ordering in which to destroy the
+ * datasets. We do a topological ordering of our graph starting at our target
+ * dataset, and then walk the results in reverse.
+ *
+ * It's possible for the graph to have cycles if, for example, the user renames
+ * a clone to be the parent of its origin snapshot. The user can request to
+ * generate an error in this case, or ignore the cycle and continue.
+ *
+ * When removing datasets, we want to destroy the snapshots in chronological
+ * order (because this is the most efficient method). In order to accomplish
+ * this, we store the creation transaction group with each vertex and keep each
+ * vertex's edges sorted according to this value. The topological sort will
+ * automatically walk the snapshots in the correct order.
+ */
+
+#include <assert.h>
+#include <libintl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include <libzfs.h>
+
+#include "libzfs_impl.h"
+#include "zfs_namecheck.h"
+
+#define MIN_EDGECOUNT 4
+
+/*
+ * Vertex structure. Indexed by dataset name, this structure maintains a list
+ * of edges to other vertices.
+ */
+struct zfs_edge;
+typedef struct zfs_vertex {
+ char zv_dataset[ZFS_MAXNAMELEN];
+ struct zfs_vertex *zv_next;
+ int zv_visited;
+ uint64_t zv_txg;
+ struct zfs_edge **zv_edges;
+ int zv_edgecount;
+ int zv_edgealloc;
+} zfs_vertex_t;
+
+enum {
+ VISIT_SEEN = 1,
+ VISIT_SORT_PRE,
+ VISIT_SORT_POST
+};
+
+/*
+ * Edge structure. Simply maintains a pointer to the destination vertex. There
+ * is no need to store the source vertex, since we only use edges in the context
+ * of the source vertex.
+ */
+typedef struct zfs_edge {
+ zfs_vertex_t *ze_dest;
+ struct zfs_edge *ze_next;
+} zfs_edge_t;
+
+#define ZFS_GRAPH_SIZE 1027 /* this could be dynamic some day */
+
+/*
+ * Graph structure. Vertices are maintained in a hash indexed by dataset name.
+ */
+typedef struct zfs_graph {
+ zfs_vertex_t **zg_hash;
+ size_t zg_size;
+ size_t zg_nvertex;
+ const char *zg_root;
+ int zg_clone_count;
+} zfs_graph_t;
+
+/*
+ * Allocate a new edge pointing to the target vertex.
+ */
+static zfs_edge_t *
+zfs_edge_create(libzfs_handle_t *hdl, zfs_vertex_t *dest)
+{
+ zfs_edge_t *zep = zfs_alloc(hdl, sizeof (zfs_edge_t));
+
+ if (zep == NULL)
+ return (NULL);
+
+ zep->ze_dest = dest;
+
+ return (zep);
+}
+
+/*
+ * Destroy an edge.
+ */
+static void
+zfs_edge_destroy(zfs_edge_t *zep)
+{
+ free(zep);
+}
+
+/*
+ * Allocate a new vertex with the given name.
+ */
+static zfs_vertex_t *
+zfs_vertex_create(libzfs_handle_t *hdl, const char *dataset)
+{
+ zfs_vertex_t *zvp = zfs_alloc(hdl, sizeof (zfs_vertex_t));
+
+ if (zvp == NULL)
+ return (NULL);
+
+ assert(strlen(dataset) < ZFS_MAXNAMELEN);
+
+ (void) strlcpy(zvp->zv_dataset, dataset, sizeof (zvp->zv_dataset));
+
+ if ((zvp->zv_edges = zfs_alloc(hdl,
+ MIN_EDGECOUNT * sizeof (void *))) == NULL) {
+ free(zvp);
+ return (NULL);
+ }
+
+ zvp->zv_edgealloc = MIN_EDGECOUNT;
+
+ return (zvp);
+}
+
+/*
+ * Destroy a vertex. Frees up any associated edges.
+ */
+static void
+zfs_vertex_destroy(zfs_vertex_t *zvp)
+{
+ int i;
+
+ for (i = 0; i < zvp->zv_edgecount; i++)
+ zfs_edge_destroy(zvp->zv_edges[i]);
+
+ free(zvp->zv_edges);
+ free(zvp);
+}
+
+/*
+ * Given a vertex, add an edge to the destination vertex.
+ */
+static int
+zfs_vertex_add_edge(libzfs_handle_t *hdl, zfs_vertex_t *zvp,
+ zfs_vertex_t *dest)
+{
+ zfs_edge_t *zep = zfs_edge_create(hdl, dest);
+
+ if (zep == NULL)
+ return (-1);
+
+ if (zvp->zv_edgecount == zvp->zv_edgealloc) {
+ void *ptr;
+
+ if ((ptr = zfs_realloc(hdl, zvp->zv_edges,
+ zvp->zv_edgealloc * sizeof (void *),
+ zvp->zv_edgealloc * 2 * sizeof (void *))) == NULL)
+ return (-1);
+
+ zvp->zv_edges = ptr;
+ zvp->zv_edgealloc *= 2;
+ }
+
+ zvp->zv_edges[zvp->zv_edgecount++] = zep;
+
+ return (0);
+}
+
+static int
+zfs_edge_compare(const void *a, const void *b)
+{
+ const zfs_edge_t *ea = *((zfs_edge_t **)a);
+ const zfs_edge_t *eb = *((zfs_edge_t **)b);
+
+ if (ea->ze_dest->zv_txg < eb->ze_dest->zv_txg)
+ return (-1);
+ if (ea->ze_dest->zv_txg > eb->ze_dest->zv_txg)
+ return (1);
+ return (0);
+}
+
+/*
+ * Sort the given vertex edges according to the creation txg of each vertex.
+ */
+static void
+zfs_vertex_sort_edges(zfs_vertex_t *zvp)
+{
+ if (zvp->zv_edgecount == 0)
+ return;
+
+ qsort(zvp->zv_edges, zvp->zv_edgecount, sizeof (void *),
+ zfs_edge_compare);
+}
+
+/*
+ * Construct a new graph object. We allow the size to be specified as a
+ * parameter so in the future we can size the hash according to the number of
+ * datasets in the pool.
+ */
+static zfs_graph_t *
+zfs_graph_create(libzfs_handle_t *hdl, const char *dataset, size_t size)
+{
+ zfs_graph_t *zgp = zfs_alloc(hdl, sizeof (zfs_graph_t));
+
+ if (zgp == NULL)
+ return (NULL);
+
+ zgp->zg_size = size;
+ if ((zgp->zg_hash = zfs_alloc(hdl,
+ size * sizeof (zfs_vertex_t *))) == NULL) {
+ free(zgp);
+ return (NULL);
+ }
+
+ zgp->zg_root = dataset;
+ zgp->zg_clone_count = 0;
+
+ return (zgp);
+}
+
+/*
+ * Destroy a graph object. We have to iterate over all the hash chains,
+ * destroying each vertex in the process.
+ */
+static void
+zfs_graph_destroy(zfs_graph_t *zgp)
+{
+ int i;
+ zfs_vertex_t *current, *next;
+
+ for (i = 0; i < zgp->zg_size; i++) {
+ current = zgp->zg_hash[i];
+ while (current != NULL) {
+ next = current->zv_next;
+ zfs_vertex_destroy(current);
+ current = next;
+ }
+ }
+
+ free(zgp->zg_hash);
+ free(zgp);
+}
+
+/*
+ * Graph hash function. Classic bernstein k=33 hash function, taken from
+ * usr/src/cmd/sgs/tools/common/strhash.c
+ */
+static size_t
+zfs_graph_hash(zfs_graph_t *zgp, const char *str)
+{
+ size_t hash = 5381;
+ int c;
+
+ while ((c = *str++) != 0)
+ hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+
+ return (hash % zgp->zg_size);
+}
+
+/*
+ * Given a dataset name, finds the associated vertex, creating it if necessary.
+ */
+static zfs_vertex_t *
+zfs_graph_lookup(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset,
+ uint64_t txg)
+{
+ size_t idx = zfs_graph_hash(zgp, dataset);
+ zfs_vertex_t *zvp;
+
+ for (zvp = zgp->zg_hash[idx]; zvp != NULL; zvp = zvp->zv_next) {
+ if (strcmp(zvp->zv_dataset, dataset) == 0) {
+ if (zvp->zv_txg == 0)
+ zvp->zv_txg = txg;
+ return (zvp);
+ }
+ }
+
+ if ((zvp = zfs_vertex_create(hdl, dataset)) == NULL)
+ return (NULL);
+
+ zvp->zv_next = zgp->zg_hash[idx];
+ zvp->zv_txg = txg;
+ zgp->zg_hash[idx] = zvp;
+ zgp->zg_nvertex++;
+
+ return (zvp);
+}
+
+/*
+ * Given two dataset names, create an edge between them. For the source vertex,
+ * mark 'zv_visited' to indicate that we have seen this vertex, and not simply
+ * created it as a destination of another edge. If 'dest' is NULL, then this
+ * is an individual vertex (i.e. the starting vertex), so don't add an edge.
+ */
+static int
+zfs_graph_add(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *source,
+ const char *dest, uint64_t txg)
+{
+ zfs_vertex_t *svp, *dvp;
+
+ if ((svp = zfs_graph_lookup(hdl, zgp, source, 0)) == NULL)
+ return (-1);
+ svp->zv_visited = VISIT_SEEN;
+ if (dest != NULL) {
+ dvp = zfs_graph_lookup(hdl, zgp, dest, txg);
+ if (dvp == NULL)
+ return (-1);
+ if (zfs_vertex_add_edge(hdl, svp, dvp) != 0)
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Iterate over all children of the given dataset, adding any vertices
+ * as necessary. Returns -1 if there was an error, or 0 otherwise.
+ * This is a simple recursive algorithm - the ZFS namespace typically
+ * is very flat. We manually invoke the necessary ioctl() calls to
+ * avoid the overhead and additional semantics of zfs_open().
+ */
+static int
+iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
+{
+ zfs_cmd_t zc = { 0 };
+ zfs_vertex_t *zvp;
+
+ /*
+ * Look up the source vertex, and avoid it if we've seen it before.
+ */
+ zvp = zfs_graph_lookup(hdl, zgp, dataset, 0);
+ if (zvp == NULL)
+ return (-1);
+ if (zvp->zv_visited == VISIT_SEEN)
+ return (0);
+
+ /*
+ * Iterate over all children
+ */
+ for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
+ ioctl(hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0;
+ (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) {
+ /*
+ * Get statistics for this dataset, to determine the type of the
+ * dataset and clone statistics. If this fails, the dataset has
+ * since been removed, and we're pretty much screwed anyway.
+ */
+ zc.zc_objset_stats.dds_origin[0] = '\0';
+ if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0)
+ continue;
+
+ if (zc.zc_objset_stats.dds_origin[0] != '\0') {
+ if (zfs_graph_add(hdl, zgp,
+ zc.zc_objset_stats.dds_origin, zc.zc_name,
+ zc.zc_objset_stats.dds_creation_txg) != 0)
+ return (-1);
+ /*
+ * Count origins only if they are contained in the graph
+ */
+ if (isa_child_of(zc.zc_objset_stats.dds_origin,
+ zgp->zg_root))
+ zgp->zg_clone_count--;
+ }
+
+ /*
+ * Add an edge between the parent and the child.
+ */
+ if (zfs_graph_add(hdl, zgp, dataset, zc.zc_name,
+ zc.zc_objset_stats.dds_creation_txg) != 0)
+ return (-1);
+
+ /*
+ * Recursively visit child
+ */
+ if (iterate_children(hdl, zgp, zc.zc_name))
+ return (-1);
+ }
+
+ /*
+ * Now iterate over all snapshots.
+ */
+ bzero(&zc, sizeof (zc));
+
+ for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
+ ioctl(hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc) == 0;
+ (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) {
+
+ /*
+ * Get statistics for this dataset, to determine the type of the
+ * dataset and clone statistics. If this fails, the dataset has
+ * since been removed, and we're pretty much screwed anyway.
+ */
+ if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0)
+ continue;
+
+ /*
+ * Add an edge between the parent and the child.
+ */
+ if (zfs_graph_add(hdl, zgp, dataset, zc.zc_name,
+ zc.zc_objset_stats.dds_creation_txg) != 0)
+ return (-1);
+
+ zgp->zg_clone_count += zc.zc_objset_stats.dds_num_clones;
+ }
+
+ zvp->zv_visited = VISIT_SEEN;
+
+ return (0);
+}
+
+/*
+ * Returns false if there are no snapshots with dependent clones in this
+ * subtree or if all of those clones are also in this subtree. Returns
+ * true if there is an error or there are external dependents.
+ */
+static boolean_t
+external_dependents(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
+{
+ zfs_cmd_t zc = { 0 };
+
+ /*
+ * Check whether this dataset is a clone or has clones since
+ * iterate_children() only checks the children.
+ */
+ (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
+ if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0)
+ return (B_TRUE);
+
+ if (zc.zc_objset_stats.dds_origin[0] != '\0') {
+ if (zfs_graph_add(hdl, zgp,
+ zc.zc_objset_stats.dds_origin, zc.zc_name,
+ zc.zc_objset_stats.dds_creation_txg) != 0)
+ return (B_TRUE);
+ if (isa_child_of(zc.zc_objset_stats.dds_origin, dataset))
+ zgp->zg_clone_count--;
+ }
+
+ if ((zc.zc_objset_stats.dds_num_clones) ||
+ iterate_children(hdl, zgp, dataset))
+ return (B_TRUE);
+
+ return (zgp->zg_clone_count != 0);
+}
+
+/*
+ * Construct a complete graph of all necessary vertices. First, iterate over
+ * only our object's children. If no cloned snapshots are found, or all of
+ * the cloned snapshots are in this subtree then return a graph of the subtree.
+ * Otherwise, start at the root of the pool and iterate over all datasets.
+ */
+static zfs_graph_t *
+construct_graph(libzfs_handle_t *hdl, const char *dataset)
+{
+ zfs_graph_t *zgp = zfs_graph_create(hdl, dataset, ZFS_GRAPH_SIZE);
+ int ret = 0;
+
+ if (zgp == NULL)
+ return (zgp);
+
+ if ((strchr(dataset, '/') == NULL) ||
+ (external_dependents(hdl, zgp, dataset))) {
+ /*
+ * Determine pool name and try again.
+ */
+ int len = strcspn(dataset, "/@") + 1;
+ char *pool = zfs_alloc(hdl, len);
+
+ if (pool == NULL) {
+ zfs_graph_destroy(zgp);
+ return (NULL);
+ }
+ (void) strlcpy(pool, dataset, len);
+
+ if (iterate_children(hdl, zgp, pool) == -1 ||
+ zfs_graph_add(hdl, zgp, pool, NULL, 0) != 0) {
+ free(pool);
+ zfs_graph_destroy(zgp);
+ return (NULL);
+ }
+ free(pool);
+ }
+
+ if (ret == -1 || zfs_graph_add(hdl, zgp, dataset, NULL, 0) != 0) {
+ zfs_graph_destroy(zgp);
+ return (NULL);
+ }
+
+ return (zgp);
+}
+
+/*
+ * Given a graph, do a recursive topological sort into the given array. This is
+ * really just a depth first search, so that the deepest nodes appear first.
+ * hijack the 'zv_visited' marker to avoid visiting the same vertex twice.
+ */
+static int
+topo_sort(libzfs_handle_t *hdl, boolean_t allowrecursion, char **result,
+ size_t *idx, zfs_vertex_t *zgv)
+{
+ int i;
+
+ if (zgv->zv_visited == VISIT_SORT_PRE && !allowrecursion) {
+ /*
+ * If we've already seen this vertex as part of our depth-first
+ * search, then we have a cyclic dependency, and we must return
+ * an error.
+ */
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "recursive dependency at '%s'"),
+ zgv->zv_dataset);
+ return (zfs_error(hdl, EZFS_RECURSIVE,
+ dgettext(TEXT_DOMAIN,
+ "cannot determine dependent datasets")));
+ } else if (zgv->zv_visited >= VISIT_SORT_PRE) {
+ /*
+ * If we've already processed this as part of the topological
+ * sort, then don't bother doing so again.
+ */
+ return (0);
+ }
+
+ zgv->zv_visited = VISIT_SORT_PRE;
+
+ /* avoid doing a search if we don't have to */
+ zfs_vertex_sort_edges(zgv);
+ for (i = 0; i < zgv->zv_edgecount; i++) {
+ if (topo_sort(hdl, allowrecursion, result, idx,
+ zgv->zv_edges[i]->ze_dest) != 0)
+ return (-1);
+ }
+
+ /* we may have visited this in the course of the above */
+ if (zgv->zv_visited == VISIT_SORT_POST)
+ return (0);
+
+ if ((result[*idx] = zfs_alloc(hdl,
+ strlen(zgv->zv_dataset) + 1)) == NULL)
+ return (-1);
+
+ (void) strcpy(result[*idx], zgv->zv_dataset);
+ *idx += 1;
+ zgv->zv_visited = VISIT_SORT_POST;
+ return (0);
+}
+
+/*
+ * The only public interface for this file. Do the dirty work of constructing a
+ * child list for the given object. Construct the graph, do the toplogical
+ * sort, and then return the array of strings to the caller.
+ *
+ * The 'allowrecursion' parameter controls behavior when cycles are found. If
+ * it is set, the the cycle is ignored and the results returned as if the cycle
+ * did not exist. If it is not set, then the routine will generate an error if
+ * a cycle is found.
+ */
+int
+get_dependents(libzfs_handle_t *hdl, boolean_t allowrecursion,
+ const char *dataset, char ***result, size_t *count)
+{
+ zfs_graph_t *zgp;
+ zfs_vertex_t *zvp;
+
+ if ((zgp = construct_graph(hdl, dataset)) == NULL)
+ return (-1);
+
+ if ((*result = zfs_alloc(hdl,
+ zgp->zg_nvertex * sizeof (char *))) == NULL) {
+ zfs_graph_destroy(zgp);
+ return (-1);
+ }
+
+ if ((zvp = zfs_graph_lookup(hdl, zgp, dataset, 0)) == NULL) {
+ free(*result);
+ zfs_graph_destroy(zgp);
+ return (-1);
+ }
+
+ *count = 0;
+ if (topo_sort(hdl, allowrecursion, *result, count, zvp) != 0) {
+ free(*result);
+ zfs_graph_destroy(zgp);
+ return (-1);
+ }
+
+ /*
+ * Get rid of the last entry, which is our starting vertex and not
+ * strictly a dependent.
+ */
+ assert(*count > 0);
+ free((*result)[*count - 1]);
+ (*count)--;
+
+ zfs_graph_destroy(zgp);
+
+ return (0);
+}
diff --git a/lib/libzfs/common/libzfs_impl.h b/lib/libzfs/common/libzfs_impl.h
index 576b2af5d2c2..c9b09a205024 100644
--- a/lib/libzfs/common/libzfs_impl.h
+++ b/lib/libzfs/common/libzfs_impl.h
@@ -21,11 +21,10 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
*/
-#ifndef _LIBZFS_IMPL_H
-#define _LIBZFS_IMPL_H
+#ifndef _LIBFS_IMPL_H
+#define _LIBFS_IMPL_H
#include <sys/dmu.h>
#include <sys/fs/zfs.h>
@@ -36,7 +35,6 @@
#include <libuutil.h>
#include <libzfs.h>
#include <libshare.h>
-#include <libzfs_core.h>
#include <fm/libtopo.h>
@@ -68,6 +66,7 @@ struct libzfs_handle {
int libzfs_desc_active;
char libzfs_action[1024];
char libzfs_desc[1024];
+ char *libzfs_log_str;
int libzfs_printerr;
int libzfs_storeerr; /* stuff error messages into buffer */
void *libzfs_sharehdl; /* libshare handle */
@@ -116,7 +115,7 @@ struct zpool_handle {
diskaddr_t zpool_start_block;
};
-typedef enum {
+typedef enum {
PROTO_NFS = 0,
PROTO_SMB = 1,
PROTO_END = 2
@@ -148,7 +147,6 @@ 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 *);
int zprop_parse_value(libzfs_handle_t *, nvpair_t *, int, zfs_type_t,
@@ -213,4 +211,4 @@ extern void libzfs_fru_clear(libzfs_handle_t *, boolean_t);
}
#endif
-#endif /* _LIBZFS_IMPL_H */
+#endif /* _LIBFS_IMPL_H */
diff --git a/lib/libzfs/common/libzfs_import.c b/lib/libzfs/common/libzfs_import.c
index 414aa2f747b1..e1370350fd52 100644
--- a/lib/libzfs/common/libzfs_import.c
+++ b/lib/libzfs/common/libzfs_import.c
@@ -20,8 +20,6 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
*/
/*
@@ -439,7 +437,7 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
uint_t i, nspares, nl2cache;
boolean_t config_seen;
uint64_t best_txg;
- char *name, *hostname, *comment;
+ char *name, *hostname;
uint64_t version, guid;
uint_t children = 0;
nvlist_t **child = NULL;
@@ -528,7 +526,6 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
* version
* pool guid
* name
- * comment (if available)
* pool state
* hostid (if available)
* hostname (if available)
@@ -550,24 +547,11 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
if (nvlist_add_string(config,
ZPOOL_CONFIG_POOL_NAME, name) != 0)
goto nomem;
-
- /*
- * COMMENT is optional, don't bail if it's not
- * there, instead, set it to NULL.
- */
- if (nvlist_lookup_string(tmp,
- ZPOOL_CONFIG_COMMENT, &comment) != 0)
- comment = NULL;
- else if (nvlist_add_string(config,
- ZPOOL_CONFIG_COMMENT, comment) != 0)
- goto nomem;
-
verify(nvlist_lookup_uint64(tmp,
ZPOOL_CONFIG_POOL_STATE, &state) == 0);
if (nvlist_add_uint64(config,
ZPOOL_CONFIG_POOL_STATE, state) != 0)
goto nomem;
-
hostid = 0;
if (nvlist_lookup_uint64(tmp,
ZPOOL_CONFIG_HOSTID, &hostid) == 0) {
diff --git a/lib/libzfs/common/libzfs_iter.c b/lib/libzfs/common/libzfs_iter.c
deleted file mode 100644
index be5767f542d6..000000000000
--- a/lib/libzfs/common/libzfs_iter.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <unistd.h>
-#include <stddef.h>
-#include <libintl.h>
-#include <libzfs.h>
-
-#include "libzfs_impl.h"
-
-int
-zfs_iter_clones(zfs_handle_t *zhp, zfs_iter_f func, void *data)
-{
- nvlist_t *nvl = zfs_get_clones_nvl(zhp);
- nvpair_t *pair;
-
- if (nvl == NULL)
- return (0);
-
- for (pair = nvlist_next_nvpair(nvl, NULL); pair != NULL;
- pair = nvlist_next_nvpair(nvl, pair)) {
- zfs_handle_t *clone = zfs_open(zhp->zfs_hdl, nvpair_name(pair),
- ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
- if (clone != NULL) {
- int err = func(clone, data);
- if (err != 0)
- return (err);
- }
- }
- return (0);
-}
-
-static int
-zfs_do_list_ioctl(zfs_handle_t *zhp, int arg, zfs_cmd_t *zc)
-{
- int rc;
- uint64_t orig_cookie;
-
- orig_cookie = zc->zc_cookie;
-top:
- (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
- rc = ioctl(zhp->zfs_hdl->libzfs_fd, arg, zc);
-
- if (rc == -1) {
- switch (errno) {
- case ENOMEM:
- /* expand nvlist memory and try again */
- if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, zc) != 0) {
- zcmd_free_nvlists(zc);
- return (-1);
- }
- zc->zc_cookie = orig_cookie;
- goto top;
- /*
- * An errno value of ESRCH indicates normal completion.
- * If ENOENT is returned, then the underlying dataset
- * has been removed since we obtained the handle.
- */
- case ESRCH:
- case ENOENT:
- rc = 1;
- break;
- default:
- rc = zfs_standard_error(zhp->zfs_hdl, errno,
- dgettext(TEXT_DOMAIN,
- "cannot iterate filesystems"));
- break;
- }
- }
- return (rc);
-}
-
-/*
- * Iterate over all child filesystems
- */
-int
-zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
-{
- zfs_cmd_t zc = { 0 };
- zfs_handle_t *nzhp;
- int ret;
-
- if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM)
- return (0);
-
- if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
- return (-1);
-
- while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT,
- &zc)) == 0) {
- /*
- * Silently ignore errors, as the only plausible explanation is
- * that the pool has since been removed.
- */
- if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
- &zc)) == NULL) {
- continue;
- }
-
- if ((ret = func(nzhp, data)) != 0) {
- zcmd_free_nvlists(&zc);
- return (ret);
- }
- }
- zcmd_free_nvlists(&zc);
- return ((ret < 0) ? ret : 0);
-}
-
-/*
- * Iterate over all snapshots
- */
-int
-zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
-{
- zfs_cmd_t zc = { 0 };
- zfs_handle_t *nzhp;
- int ret;
-
- if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
- return (0);
-
- 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) {
- continue;
- }
-
- if ((ret = func(nzhp, data)) != 0) {
- zcmd_free_nvlists(&zc);
- return (ret);
- }
- }
- zcmd_free_nvlists(&zc);
- return ((ret < 0) ? ret : 0);
-}
-
-/*
- * Routines for dealing with the sorted snapshot functionality
- */
-typedef struct zfs_node {
- zfs_handle_t *zn_handle;
- avl_node_t zn_avlnode;
-} zfs_node_t;
-
-static int
-zfs_sort_snaps(zfs_handle_t *zhp, void *data)
-{
- avl_tree_t *avl = data;
- zfs_node_t *node;
- zfs_node_t search;
-
- search.zn_handle = zhp;
- node = avl_find(avl, &search, NULL);
- if (node) {
- /*
- * If this snapshot was renamed while we were creating the
- * AVL tree, it's possible that we already inserted it under
- * its old name. Remove the old handle before adding the new
- * one.
- */
- zfs_close(node->zn_handle);
- avl_remove(avl, node);
- free(node);
- }
-
- node = zfs_alloc(zhp->zfs_hdl, sizeof (zfs_node_t));
- node->zn_handle = zhp;
- avl_add(avl, node);
-
- return (0);
-}
-
-static int
-zfs_snapshot_compare(const void *larg, const void *rarg)
-{
- zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
- zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
- uint64_t lcreate, rcreate;
-
- /*
- * Sort them according to creation time. We use the hidden
- * CREATETXG property to get an absolute ordering of snapshots.
- */
- lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG);
- rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG);
-
- if (lcreate < rcreate)
- return (-1);
- else if (lcreate > rcreate)
- return (+1);
- else
- return (0);
-}
-
-int
-zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data)
-{
- int ret = 0;
- zfs_node_t *node;
- avl_tree_t avl;
- void *cookie = NULL;
-
- 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);
-
- for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node))
- ret |= callback(node->zn_handle, data);
-
- while ((node = avl_destroy_nodes(&avl, &cookie)) != NULL)
- free(node);
-
- avl_destroy(&avl);
-
- return (ret);
-}
-
-typedef struct {
- char *ssa_first;
- char *ssa_last;
- boolean_t ssa_seenfirst;
- boolean_t ssa_seenlast;
- zfs_iter_f ssa_func;
- void *ssa_arg;
-} snapspec_arg_t;
-
-static int
-snapspec_cb(zfs_handle_t *zhp, void *arg) {
- snapspec_arg_t *ssa = arg;
- char *shortsnapname;
- int err = 0;
-
- if (ssa->ssa_seenlast)
- return (0);
- shortsnapname = zfs_strdup(zhp->zfs_hdl,
- strchr(zfs_get_name(zhp), '@') + 1);
-
- if (!ssa->ssa_seenfirst && strcmp(shortsnapname, ssa->ssa_first) == 0)
- ssa->ssa_seenfirst = B_TRUE;
-
- if (ssa->ssa_seenfirst) {
- err = ssa->ssa_func(zhp, ssa->ssa_arg);
- } else {
- zfs_close(zhp);
- }
-
- if (strcmp(shortsnapname, ssa->ssa_last) == 0)
- ssa->ssa_seenlast = B_TRUE;
- free(shortsnapname);
-
- return (err);
-}
-
-/*
- * spec is a string like "A,B%C,D"
- *
- * <snaps>, where <snaps> can be:
- * <snap> (single snapshot)
- * <snap>%<snap> (range of snapshots, inclusive)
- * %<snap> (range of snapshots, starting with earliest)
- * <snap>% (range of snapshots, ending with last)
- * % (all snapshots)
- * <snaps>[,...] (comma separated list of the above)
- *
- * If a snapshot can not be opened, continue trying to open the others, but
- * return ENOENT at the end.
- */
-int
-zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
- zfs_iter_f func, void *arg)
-{
- char *buf, *comma_separated, *cp;
- int err = 0;
- int ret = 0;
-
- buf = zfs_strdup(fs_zhp->zfs_hdl, spec_orig);
- cp = buf;
-
- while ((comma_separated = strsep(&cp, ",")) != NULL) {
- char *pct = strchr(comma_separated, '%');
- if (pct != NULL) {
- snapspec_arg_t ssa = { 0 };
- ssa.ssa_func = func;
- ssa.ssa_arg = arg;
-
- if (pct == comma_separated)
- ssa.ssa_seenfirst = B_TRUE;
- else
- ssa.ssa_first = comma_separated;
- *pct = '\0';
- ssa.ssa_last = pct + 1;
-
- /*
- * If there is a lastname specified, make sure it
- * exists.
- */
- if (ssa.ssa_last[0] != '\0') {
- char snapname[ZFS_MAXNAMELEN];
- (void) snprintf(snapname, sizeof (snapname),
- "%s@%s", zfs_get_name(fs_zhp),
- ssa.ssa_last);
- if (!zfs_dataset_exists(fs_zhp->zfs_hdl,
- snapname, ZFS_TYPE_SNAPSHOT)) {
- ret = ENOENT;
- continue;
- }
- }
-
- err = zfs_iter_snapshots_sorted(fs_zhp,
- snapspec_cb, &ssa);
- if (ret == 0)
- ret = err;
- if (ret == 0 && (!ssa.ssa_seenfirst ||
- (ssa.ssa_last[0] != '\0' && !ssa.ssa_seenlast))) {
- ret = ENOENT;
- }
- } else {
- char snapname[ZFS_MAXNAMELEN];
- zfs_handle_t *snap_zhp;
- (void) snprintf(snapname, sizeof (snapname), "%s@%s",
- zfs_get_name(fs_zhp), comma_separated);
- snap_zhp = make_dataset_handle(fs_zhp->zfs_hdl,
- snapname);
- if (snap_zhp == NULL) {
- ret = ENOENT;
- continue;
- }
- err = func(snap_zhp, arg);
- if (ret == 0)
- ret = err;
- }
- }
-
- free(buf);
- return (ret);
-}
-
-/*
- * Iterate over all children, snapshots and filesystems
- */
-int
-zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
-{
- int ret;
-
- if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0)
- return (ret);
-
- return (zfs_iter_snapshots(zhp, func, data));
-}
-
-
-typedef struct iter_stack_frame {
- struct iter_stack_frame *next;
- zfs_handle_t *zhp;
-} iter_stack_frame_t;
-
-typedef struct iter_dependents_arg {
- boolean_t first;
- boolean_t allowrecursion;
- iter_stack_frame_t *stack;
- zfs_iter_f func;
- void *data;
-} iter_dependents_arg_t;
-
-static int
-iter_dependents_cb(zfs_handle_t *zhp, void *arg)
-{
- iter_dependents_arg_t *ida = arg;
- int err;
- boolean_t first = ida->first;
- ida->first = B_FALSE;
-
- if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
- err = zfs_iter_clones(zhp, iter_dependents_cb, ida);
- } else {
- iter_stack_frame_t isf;
- iter_stack_frame_t *f;
-
- /*
- * check if there is a cycle by seeing if this fs is already
- * on the stack.
- */
- for (f = ida->stack; f != NULL; f = f->next) {
- if (f->zhp->zfs_dmustats.dds_guid ==
- zhp->zfs_dmustats.dds_guid) {
- if (ida->allowrecursion) {
- zfs_close(zhp);
- return (0);
- } else {
- zfs_error_aux(zhp->zfs_hdl,
- dgettext(TEXT_DOMAIN,
- "recursive dependency at '%s'"),
- zfs_get_name(zhp));
- err = zfs_error(zhp->zfs_hdl,
- EZFS_RECURSIVE,
- dgettext(TEXT_DOMAIN,
- "cannot determine dependent "
- "datasets"));
- zfs_close(zhp);
- return (err);
- }
- }
- }
-
- isf.zhp = zhp;
- 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);
- ida->stack = isf.next;
- }
- if (!first && err == 0)
- err = ida->func(zhp, ida->data);
- return (err);
-}
-
-int
-zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion,
- zfs_iter_f func, void *data)
-{
- iter_dependents_arg_t ida;
- ida.allowrecursion = allowrecursion;
- ida.stack = NULL;
- ida.func = func;
- ida.data = data;
- ida.first = B_TRUE;
- return (iter_dependents_cb(zfs_handle_dup(zhp), &ida));
-}
diff --git a/lib/libzfs/common/libzfs_pool.c b/lib/libzfs/common/libzfs_pool.c
index 1c6fb371e3bc..7df7e910ddc5 100644
--- a/lib/libzfs/common/libzfs_pool.c
+++ b/lib/libzfs/common/libzfs_pool.c
@@ -21,8 +21,6 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <ctype.h>
@@ -34,7 +32,6 @@
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
-#include <libgen.h>
#include <sys/efi_partition.h>
#include <sys/vtoc.h>
#include <sys/zfs_ioctl.h>
@@ -44,7 +41,6 @@
#include "zfs_prop.h"
#include "libzfs_impl.h"
#include "zfs_comutil.h"
-#include "zfeature_common.h"
static int read_efi_label(nvlist_t *config, diskaddr_t *sb);
@@ -237,7 +233,6 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
case ZPOOL_PROP_ALTROOT:
case ZPOOL_PROP_CACHEFILE:
- case ZPOOL_PROP_COMMENT:
if (zhp->zpool_props != NULL ||
zpool_get_all_props(zhp) == 0) {
(void) strlcpy(buf,
@@ -275,8 +270,6 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
case ZPOOL_PROP_SIZE:
case ZPOOL_PROP_ALLOCATED:
case ZPOOL_PROP_FREE:
- case ZPOOL_PROP_FREEING:
- case ZPOOL_PROP_EXPANDSZ:
(void) zfs_nicenum(intval, buf, len);
break;
@@ -301,12 +294,6 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
(void) strlcpy(buf, zpool_state_to_name(intval,
vs->vs_aux), len);
break;
- case ZPOOL_PROP_VERSION:
- if (intval >= SPA_VERSION_FEATURES) {
- (void) snprintf(buf, len, "-");
- break;
- }
- /* FALLTHROUGH */
default:
(void) snprintf(buf, len, "%llu", intval);
}
@@ -370,8 +357,8 @@ pool_uses_efi(nvlist_t *config)
return (B_FALSE);
}
-boolean_t
-zpool_is_bootable(zpool_handle_t *zhp)
+static boolean_t
+pool_is_bootable(zpool_handle_t *zhp)
{
char bootfs[ZPOOL_MAXNAMELEN];
@@ -395,7 +382,7 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
zpool_prop_t prop;
char *strval;
uint64_t intval;
- char *slash, *check;
+ char *slash;
struct stat64 statbuf;
zpool_handle_t *zhp;
nvlist_t *nvroot;
@@ -409,48 +396,10 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
const char *propname = nvpair_name(elem);
- prop = zpool_name_to_prop(propname);
- if (prop == ZPROP_INVAL && zpool_prop_feature(propname)) {
- int err;
- zfeature_info_t *feature;
- char *fname = strchr(propname, '@') + 1;
-
- err = zfeature_lookup_name(fname, &feature);
- if (err != 0) {
- ASSERT3U(err, ==, ENOENT);
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "invalid feature '%s'"), fname);
- (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
- goto error;
- }
-
- if (nvpair_type(elem) != DATA_TYPE_STRING) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "'%s' must be a string"), propname);
- (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
- goto error;
- }
-
- (void) nvpair_value_string(elem, &strval);
- if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "property '%s' can only be set to "
- "'enabled'"), propname);
- (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
- goto error;
- }
-
- if (nvlist_add_uint64(retprops, propname, 0) != 0) {
- (void) no_memory(hdl);
- goto error;
- }
- continue;
- }
-
/*
* Make sure this property is valid and applies to this type.
*/
- if (prop == ZPROP_INVAL) {
+ if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"invalid property '%s'"), propname);
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
@@ -473,8 +422,7 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
*/
switch (prop) {
case ZPOOL_PROP_VERSION:
- if (intval < version ||
- !SPA_VERSION_IS_SUPPORTED(intval)) {
+ if (intval < version || intval > SPA_VERSION) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"property '%s' number %d is invalid."),
propname, intval);
@@ -593,26 +541,6 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
*slash = '/';
break;
- case ZPOOL_PROP_COMMENT:
- for (check = strval; *check != '\0'; check++) {
- if (!isprint(*check)) {
- zfs_error_aux(hdl,
- dgettext(TEXT_DOMAIN,
- "comment may only have printable "
- "characters"));
- (void) zfs_error(hdl, EZFS_BADPROP,
- errbuf);
- goto error;
- }
- }
- if (strlen(strval) > ZPROP_MAX_COMMENT) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "comment must not exceed %d characters"),
- ZPROP_MAX_COMMENT);
- (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
- goto error;
- }
- break;
case ZPOOL_PROP_READONLY:
if (!flags.import) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -696,77 +624,10 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
libzfs_handle_t *hdl = zhp->zpool_hdl;
zprop_list_t *entry;
char buf[ZFS_MAXPROPLEN];
- nvlist_t *features = NULL;
- zprop_list_t **last;
- boolean_t firstexpand = (NULL == *plp);
if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
return (-1);
- last = plp;
- while (*last != NULL)
- last = &(*last)->pl_next;
-
- if ((*plp)->pl_all)
- features = zpool_get_features(zhp);
-
- if ((*plp)->pl_all && firstexpand) {
- for (int i = 0; i < SPA_FEATURES; i++) {
- zprop_list_t *entry = zfs_alloc(hdl,
- sizeof (zprop_list_t));
- entry->pl_prop = ZPROP_INVAL;
- entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s",
- spa_feature_table[i].fi_uname);
- entry->pl_width = strlen(entry->pl_user_prop);
- entry->pl_all = B_TRUE;
-
- *last = entry;
- last = &entry->pl_next;
- }
- }
-
- /* add any unsupported features */
- for (nvpair_t *nvp = nvlist_next_nvpair(features, NULL);
- nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) {
- char *propname;
- boolean_t found;
- zprop_list_t *entry;
-
- if (zfeature_is_supported(nvpair_name(nvp)))
- continue;
-
- propname = zfs_asprintf(hdl, "unsupported@%s",
- nvpair_name(nvp));
-
- /*
- * Before adding the property to the list make sure that no
- * other pool already added the same property.
- */
- found = B_FALSE;
- entry = *plp;
- while (entry != NULL) {
- if (entry->pl_user_prop != NULL &&
- strcmp(propname, entry->pl_user_prop) == 0) {
- found = B_TRUE;
- break;
- }
- entry = entry->pl_next;
- }
- if (found) {
- free(propname);
- continue;
- }
-
- entry = zfs_alloc(hdl, sizeof (zprop_list_t));
- entry->pl_prop = ZPROP_INVAL;
- entry->pl_user_prop = propname;
- entry->pl_width = strlen(entry->pl_user_prop);
- entry->pl_all = B_TRUE;
-
- *last = entry;
- last = &entry->pl_next;
- }
-
for (entry = *plp; entry != NULL; entry = entry->pl_next) {
if (entry->pl_fixed)
@@ -783,66 +644,6 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
return (0);
}
-/*
- * Get the state for the given feature on the given ZFS pool.
- */
-int
-zpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf,
- size_t len)
-{
- uint64_t refcount;
- boolean_t found = B_FALSE;
- nvlist_t *features = zpool_get_features(zhp);
- boolean_t supported;
- const char *feature = strchr(propname, '@') + 1;
-
- supported = zpool_prop_feature(propname);
- ASSERT(supported || zfs_prop_unsupported(propname));
-
- /*
- * Convert from feature name to feature guid. This conversion is
- * unecessary for unsupported@... properties because they already
- * use guids.
- */
- if (supported) {
- int ret;
- zfeature_info_t *fi;
-
- ret = zfeature_lookup_name(feature, &fi);
- if (ret != 0) {
- (void) strlcpy(buf, "-", len);
- return (ENOTSUP);
- }
- feature = fi->fi_guid;
- }
-
- if (nvlist_lookup_uint64(features, feature, &refcount) == 0)
- found = B_TRUE;
-
- if (supported) {
- if (!found) {
- (void) strlcpy(buf, ZFS_FEATURE_DISABLED, len);
- } else {
- if (refcount == 0)
- (void) strlcpy(buf, ZFS_FEATURE_ENABLED, len);
- else
- (void) strlcpy(buf, ZFS_FEATURE_ACTIVE, len);
- }
- } else {
- if (found) {
- if (refcount == 0) {
- (void) strcpy(buf, ZFS_UNSUPPORTED_INACTIVE);
- } else {
- (void) strcpy(buf, ZFS_UNSUPPORTED_READONLY);
- }
- } else {
- (void) strlcpy(buf, "-", len);
- return (ENOTSUP);
- }
- }
-
- return (0);
-}
/*
* Don't start the slice at the default block of 34; many storage
@@ -1206,7 +1007,7 @@ create_failed:
* datasets left in the pool.
*/
int
-zpool_destroy(zpool_handle_t *zhp, const char *log_str)
+zpool_destroy(zpool_handle_t *zhp)
{
zfs_cmd_t zc = { 0 };
zfs_handle_t *zfp = NULL;
@@ -1218,7 +1019,6 @@ zpool_destroy(zpool_handle_t *zhp, const char *log_str)
return (-1);
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
- zc.zc_history = (uint64_t)(uintptr_t)log_str;
if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -1271,7 +1071,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
return (zfs_error(hdl, EZFS_BADVERSION, msg));
}
- if (zpool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
+ if (pool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) {
uint64_t s;
@@ -1373,9 +1173,8 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
* Exports the pool from the system. The caller must ensure that there are no
* mounted datasets in the pool.
*/
-static int
-zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
- const char *log_str)
+int
+zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
{
zfs_cmd_t zc = { 0 };
char msg[1024];
@@ -1386,7 +1185,6 @@ zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
zc.zc_cookie = force;
zc.zc_guid = hardforce;
- zc.zc_history = (uint64_t)(uintptr_t)log_str;
if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
switch (errno) {
@@ -1408,15 +1206,15 @@ zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
}
int
-zpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str)
+zpool_export(zpool_handle_t *zhp, boolean_t force)
{
- return (zpool_export_common(zhp, force, B_FALSE, log_str));
+ return (zpool_export_common(zhp, force, B_FALSE));
}
int
-zpool_export_force(zpool_handle_t *zhp, const char *log_str)
+zpool_export_force(zpool_handle_t *zhp)
{
- return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str));
+ return (zpool_export_common(zhp, B_TRUE, B_TRUE));
}
static void
@@ -1432,10 +1230,8 @@ zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun,
if (!hdl->libzfs_printerr || config == NULL)
return;
- if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
- nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0) {
+ if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0)
return;
- }
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
return;
@@ -1491,7 +1287,6 @@ zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
/* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
- nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 ||
nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
goto no_info;
@@ -1614,30 +1409,6 @@ print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv,
}
}
-void
-zpool_print_unsup_feat(nvlist_t *config)
-{
- nvlist_t *nvinfo, *unsup_feat;
-
- verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nvinfo) ==
- 0);
- verify(nvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT,
- &unsup_feat) == 0);
-
- for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL); nvp != NULL;
- nvp = nvlist_next_nvpair(unsup_feat, nvp)) {
- char *desc;
-
- verify(nvpair_type(nvp) == DATA_TYPE_STRING);
- verify(nvpair_value_string(nvp, &desc) == 0);
-
- if (strlen(desc) > 0)
- (void) printf("\t%s (%s)\n", nvpair_name(nvp), desc);
- else
- (void) printf("\t%s\n", nvpair_name(nvp));
- }
-}
-
/*
* Import the given pool using the known configuration and a list of
* properties to be set. The configuration should have come from
@@ -1744,22 +1515,6 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
switch (error) {
case ENOTSUP:
- if (nv != NULL && nvlist_lookup_nvlist(nv,
- ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
- nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) {
- (void) printf(dgettext(TEXT_DOMAIN, "This "
- "pool uses the following feature(s) not "
- "supported by this system:\n"));
- zpool_print_unsup_feat(nv);
- if (nvlist_exists(nvinfo,
- ZPOOL_CONFIG_CAN_RDONLY)) {
- (void) printf(dgettext(TEXT_DOMAIN,
- "All unsupported features are only "
- "required for writing to the pool."
- "\nThe pool can be imported using "
- "'-o readonly=on'.\n"));
- }
- }
/*
* Unsupported version.
*/
@@ -2600,7 +2355,7 @@ zpool_vdev_attach(zpool_handle_t *zhp,
uint_t children;
nvlist_t *config_root;
libzfs_handle_t *hdl = zhp->zpool_hdl;
- boolean_t rootpool = zpool_is_bootable(zhp);
+ boolean_t rootpool = pool_is_bootable(zhp);
if (replacing)
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -3212,46 +2967,6 @@ zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
}
/*
- * Change the GUID for a pool.
- */
-int
-zpool_reguid(zpool_handle_t *zhp)
-{
- char msg[1024];
- libzfs_handle_t *hdl = zhp->zpool_hdl;
- zfs_cmd_t zc = { 0 };
-
- (void) snprintf(msg, sizeof (msg),
- dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name);
-
- (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
- if (zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc) == 0)
- return (0);
-
- return (zpool_standard_error(hdl, errno, msg));
-}
-
-/*
- * Reopen the pool.
- */
-int
-zpool_reopen(zpool_handle_t *zhp)
-{
- zfs_cmd_t zc = { 0 };
- char msg[1024];
- libzfs_handle_t *hdl = zhp->zpool_hdl;
-
- (void) snprintf(msg, sizeof (msg),
- dgettext(TEXT_DOMAIN, "cannot reopen '%s'"),
- zhp->zpool_name);
-
- (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
- if (zfs_ioctl(hdl, ZFS_IOC_POOL_REOPEN, &zc) == 0)
- return (0);
- return (zpool_standard_error(hdl, errno, msg));
-}
-
-/*
* Convert from a devid string to a path.
*/
static char *
@@ -3578,30 +3293,40 @@ zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
}
void
-zfs_save_arguments(int argc, char **argv, char *string, int len)
+zpool_set_history_str(const char *subcommand, int argc, char **argv,
+ char *history_str)
{
- (void) strlcpy(string, basename(argv[0]), len);
- for (int i = 1; i < argc; i++) {
- (void) strlcat(string, " ", len);
- (void) strlcat(string, argv[i], len);
+ int i;
+
+ (void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN);
+ for (i = 1; i < argc; i++) {
+ if (strlen(history_str) + 1 + strlen(argv[i]) >
+ HIS_MAX_RECORD_LEN)
+ break;
+ (void) strlcat(history_str, " ", HIS_MAX_RECORD_LEN);
+ (void) strlcat(history_str, argv[i], HIS_MAX_RECORD_LEN);
}
}
+/*
+ * Stage command history for logging.
+ */
int
-zpool_log_history(libzfs_handle_t *hdl, const char *message)
+zpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
{
- zfs_cmd_t zc = { 0 };
- nvlist_t *args;
- int err;
-
- args = fnvlist_alloc();
- fnvlist_add_string(args, "message", message);
- err = zcmd_write_src_nvlist(hdl, &zc, args);
- if (err == 0)
- err = ioctl(hdl->libzfs_fd, ZFS_IOC_LOG_HISTORY, &zc);
- nvlist_free(args);
- zcmd_free_nvlists(&zc);
- return (err);
+ if (history_str == NULL)
+ return (EINVAL);
+
+ if (strlen(history_str) > HIS_MAX_RECORD_LEN)
+ return (EINVAL);
+
+ if (hdl->libzfs_log_str != NULL)
+ free(hdl->libzfs_log_str);
+
+ if ((hdl->libzfs_log_str = strdup(history_str)) == NULL)
+ return (no_memory(hdl));
+
+ return (0);
}
/*
@@ -3874,7 +3599,7 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
if (zhp) {
nvlist_t *nvroot;
- if (zpool_is_bootable(zhp)) {
+ if (pool_is_bootable(zhp)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"EFI labeled devices are not supported on root "
"pools."));
diff --git a/lib/libzfs/common/libzfs_sendrecv.c b/lib/libzfs/common/libzfs_sendrecv.c
index ee6e64319e40..3093ab974d06 100644
--- a/lib/libzfs/common/libzfs_sendrecv.c
+++ b/lib/libzfs/common/libzfs_sendrecv.c
@@ -21,8 +21,6 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#include <assert.h>
@@ -38,7 +36,6 @@
#include <sys/mount.h>
#include <pthread.h>
#include <umem.h>
-#include <time.h>
#include <libzfs.h>
@@ -53,7 +50,7 @@
/* in libzfs_dataset.c */
extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
-static int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t *,
+static int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t,
int, const char *, nvlist_t *, avl_tree_t *, char **, int, uint64_t *);
static const zio_cksum_t zero_cksum = { 0 };
@@ -64,12 +61,6 @@ typedef struct dedup_arg {
libzfs_handle_t *dedup_hdl;
} dedup_arg_t;
-typedef struct progress_arg {
- zfs_handle_t *pa_zhp;
- int pa_fd;
- boolean_t pa_parsable;
-} progress_arg_t;
-
typedef struct dataref {
uint64_t ref_guid;
uint64_t ref_object;
@@ -780,6 +771,88 @@ gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
}
/*
+ * Routines for dealing with the sorted snapshot functionality
+ */
+typedef struct zfs_node {
+ zfs_handle_t *zn_handle;
+ avl_node_t zn_avlnode;
+} zfs_node_t;
+
+static int
+zfs_sort_snaps(zfs_handle_t *zhp, void *data)
+{
+ avl_tree_t *avl = data;
+ zfs_node_t *node;
+ zfs_node_t search;
+
+ search.zn_handle = zhp;
+ node = avl_find(avl, &search, NULL);
+ if (node) {
+ /*
+ * If this snapshot was renamed while we were creating the
+ * AVL tree, it's possible that we already inserted it under
+ * its old name. Remove the old handle before adding the new
+ * one.
+ */
+ zfs_close(node->zn_handle);
+ avl_remove(avl, node);
+ free(node);
+ }
+
+ node = zfs_alloc(zhp->zfs_hdl, sizeof (zfs_node_t));
+ node->zn_handle = zhp;
+ avl_add(avl, node);
+
+ return (0);
+}
+
+static int
+zfs_snapshot_compare(const void *larg, const void *rarg)
+{
+ zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
+ zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
+ uint64_t lcreate, rcreate;
+
+ /*
+ * Sort them according to creation time. We use the hidden
+ * CREATETXG property to get an absolute ordering of snapshots.
+ */
+ lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG);
+ rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG);
+
+ if (lcreate < rcreate)
+ return (-1);
+ else if (lcreate > rcreate)
+ return (+1);
+ else
+ return (0);
+}
+
+int
+zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data)
+{
+ int ret = 0;
+ zfs_node_t *node;
+ avl_tree_t avl;
+ void *cookie = NULL;
+
+ 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);
+
+ for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node))
+ ret |= callback(node->zn_handle, data);
+
+ while ((node = avl_destroy_nodes(&avl, &cookie)) != NULL)
+ free(node);
+
+ avl_destroy(&avl);
+
+ return (ret);
+}
+
+/*
* Routines specific to "zfs send"
*/
typedef struct send_dump_data {
@@ -789,7 +862,7 @@ typedef struct send_dump_data {
char prevsnap[ZFS_MAXNAMELEN];
uint64_t prevsnap_obj;
boolean_t seenfrom, seento, replicate, doall, fromorigin;
- boolean_t verbose, dryrun, parsable, progress;
+ boolean_t verbose;
int outfd;
boolean_t err;
nvlist_t *fss;
@@ -799,69 +872,8 @@ typedef struct send_dump_data {
nvlist_t *debugnv;
char holdtag[ZFS_MAXNAMELEN];
int cleanup_fd;
- uint64_t size;
} send_dump_data_t;
-static int
-estimate_ioctl(zfs_handle_t *zhp, uint64_t fromsnap_obj,
- boolean_t fromorigin, uint64_t *sizep)
-{
- zfs_cmd_t zc = { 0 };
- libzfs_handle_t *hdl = zhp->zfs_hdl;
-
- assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
- assert(fromsnap_obj == 0 || !fromorigin);
-
- (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
- zc.zc_obj = fromorigin;
- zc.zc_sendobj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
- zc.zc_fromobj = fromsnap_obj;
- zc.zc_guid = 1; /* estimate flag */
-
- if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND, &zc) != 0) {
- char errbuf[1024];
- (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
- "warning: cannot estimate space for '%s'"), zhp->zfs_name);
-
- switch (errno) {
- case EXDEV:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "not an earlier snapshot from the same fs"));
- return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
-
- case ENOENT:
- if (zfs_dataset_exists(hdl, zc.zc_name,
- ZFS_TYPE_SNAPSHOT)) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "incremental source (@%s) does not exist"),
- zc.zc_value);
- }
- return (zfs_error(hdl, EZFS_NOENT, errbuf));
-
- case EDQUOT:
- case EFBIG:
- case EIO:
- case ENOLINK:
- case ENOSPC:
- case ENOSTR:
- case ENXIO:
- case EPIPE:
- case ERANGE:
- case EFAULT:
- case EROFS:
- zfs_error_aux(hdl, strerror(errno));
- return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
-
- default:
- return (zfs_standard_error(hdl, errno, errbuf));
- }
- }
-
- *sizep = zc.zc_objset_type;
-
- return (0);
-}
-
/*
* Dumps a backup of the given snapshot (incremental from fromsnap if it's not
* NULL) to the file descriptor specified by outfd.
@@ -889,7 +901,7 @@ dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj,
"fromsnap", fromsnap));
}
- if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND, &zc) != 0) {
+ if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SEND, &zc) != 0) {
char errbuf[1024];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"warning: cannot send '%s'"), zhp->zfs_name);
@@ -902,6 +914,7 @@ dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj,
nvlist_free(thisdbg);
switch (errno) {
+
case EXDEV:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"not an earlier snapshot from the same fs"));
@@ -951,9 +964,6 @@ hold_for_send(zfs_handle_t *zhp, send_dump_data_t *sdd)
assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
- if (sdd->dryrun)
- return (0);
-
/*
* zfs_send() only opens a cleanup_fd for sends that need it,
* e.g. replication and doall.
@@ -981,63 +991,13 @@ hold_for_send(zfs_handle_t *zhp, send_dump_data_t *sdd)
return (error);
}
-static void *
-send_progress_thread(void *arg)
-{
- progress_arg_t *pa = arg;
-
- zfs_cmd_t zc = { 0 };
- zfs_handle_t *zhp = pa->pa_zhp;
- libzfs_handle_t *hdl = zhp->zfs_hdl;
- unsigned long long bytes;
- char buf[16];
-
- time_t t;
- struct tm *tm;
-
- assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
- (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
-
- if (!pa->pa_parsable)
- (void) fprintf(stderr, "TIME SENT SNAPSHOT\n");
-
- /*
- * Print the progress from ZFS_IOC_SEND_PROGRESS every second.
- */
- for (;;) {
- (void) sleep(1);
-
- zc.zc_cookie = pa->pa_fd;
- if (zfs_ioctl(hdl, ZFS_IOC_SEND_PROGRESS, &zc) != 0)
- return ((void *)-1);
-
- (void) time(&t);
- tm = localtime(&t);
- bytes = zc.zc_cookie;
-
- if (pa->pa_parsable) {
- (void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n",
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- bytes, zhp->zfs_name);
- } else {
- zfs_nicenum(bytes, buf, sizeof (buf));
- (void) fprintf(stderr, "%02d:%02d:%02d %5s %s\n",
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- buf, zhp->zfs_name);
- }
- }
-}
-
static int
dump_snapshot(zfs_handle_t *zhp, void *arg)
{
send_dump_data_t *sdd = arg;
- progress_arg_t pa = { 0 };
- pthread_t tid;
-
char *thissnap;
int err;
- boolean_t isfromsnap, istosnap, fromorigin;
+ boolean_t isfromsnap, istosnap;
boolean_t exclude = B_FALSE;
thissnap = strchr(zhp->zfs_name, '@') + 1;
@@ -1114,68 +1074,15 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
return (err);
}
- fromorigin = sdd->prevsnap[0] == '\0' &&
- (sdd->fromorigin || sdd->replicate);
-
+ /* send it */
if (sdd->verbose) {
- uint64_t size;
- err = estimate_ioctl(zhp, sdd->prevsnap_obj,
- fromorigin, &size);
-
- if (sdd->parsable) {
- if (sdd->prevsnap[0] != '\0') {
- (void) fprintf(stderr, "incremental\t%s\t%s",
- sdd->prevsnap, zhp->zfs_name);
- } else {
- (void) fprintf(stderr, "full\t%s",
- zhp->zfs_name);
- }
- } else {
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
- "send from @%s to %s"),
- sdd->prevsnap, zhp->zfs_name);
- }
- if (err == 0) {
- if (sdd->parsable) {
- (void) fprintf(stderr, "\t%llu\n",
- (longlong_t)size);
- } else {
- char buf[16];
- zfs_nicenum(size, buf, sizeof (buf));
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
- " estimated size is %s\n"), buf);
- }
- sdd->size += size;
- } else {
- (void) fprintf(stderr, "\n");
- }
+ (void) fprintf(stderr, "sending from @%s to %s\n",
+ sdd->prevsnap, zhp->zfs_name);
}
- if (!sdd->dryrun) {
- /*
- * If progress reporting is requested, spawn a new thread to
- * poll ZFS_IOC_SEND_PROGRESS at a regular interval.
- */
- if (sdd->progress) {
- pa.pa_zhp = zhp;
- pa.pa_fd = sdd->outfd;
- pa.pa_parsable = sdd->parsable;
-
- if (err = pthread_create(&tid, NULL,
- send_progress_thread, &pa)) {
- zfs_close(zhp);
- return (err);
- }
- }
-
- err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj,
- fromorigin, sdd->outfd, sdd->debugnv);
-
- if (sdd->progress) {
- (void) pthread_cancel(tid);
- (void) pthread_join(tid, NULL);
- }
- }
+ err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj,
+ sdd->prevsnap[0] == '\0' && (sdd->fromorigin || sdd->replicate),
+ sdd->outfd, sdd->debugnv);
(void) strcpy(sdd->prevsnap, thissnap);
sdd->prevsnap_obj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
@@ -1194,8 +1101,8 @@ dump_filesystem(zfs_handle_t *zhp, void *arg)
(void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
zhp->zfs_name, sdd->tosnap);
if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) {
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
- "WARNING: could not send %s@%s: does not exist\n"),
+ (void) fprintf(stderr, "WARNING: "
+ "could not send %s@%s: does not exist\n",
zhp->zfs_name, sdd->tosnap);
sdd->err = B_TRUE;
return (0);
@@ -1224,24 +1131,23 @@ dump_filesystem(zfs_handle_t *zhp, void *arg)
rv = zfs_iter_snapshots_sorted(zhp, dump_snapshot, arg);
if (!sdd->seenfrom) {
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ (void) fprintf(stderr,
"WARNING: could not send %s@%s:\n"
- "incremental source (%s@%s) does not exist\n"),
+ "incremental source (%s@%s) does not exist\n",
zhp->zfs_name, sdd->tosnap,
zhp->zfs_name, sdd->fromsnap);
sdd->err = B_TRUE;
} else if (!sdd->seento) {
if (sdd->fromsnap) {
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ (void) fprintf(stderr,
"WARNING: could not send %s@%s:\n"
"incremental source (%s@%s) "
- "is not earlier than it\n"),
+ "is not earlier than it\n",
zhp->zfs_name, sdd->tosnap,
zhp->zfs_name, sdd->fromsnap);
} else {
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
- "WARNING: "
- "could not send %s@%s: does not exist\n"),
+ (void) fprintf(stderr, "WARNING: "
+ "could not send %s@%s: does not exist\n",
zhp->zfs_name, sdd->tosnap);
}
sdd->err = B_TRUE;
@@ -1287,12 +1193,11 @@ again:
needagain = progress = B_FALSE;
for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
- nvlist_t *fslist, *parent_nv;
+ nvlist_t *fslist;
char *fsname;
zfs_handle_t *zhp;
int err;
uint64_t origin_guid = 0;
- uint64_t parent_guid = 0;
VERIFY(nvpair_value_nvlist(fspair, &fslist) == 0);
if (nvlist_lookup_boolean(fslist, "sent") == 0)
@@ -1300,23 +1205,13 @@ again:
VERIFY(nvlist_lookup_string(fslist, "name", &fsname) == 0);
(void) nvlist_lookup_uint64(fslist, "origin", &origin_guid);
- (void) nvlist_lookup_uint64(fslist, "parentfromsnap",
- &parent_guid);
-
- if (parent_guid != 0) {
- parent_nv = fsavl_find(sdd->fsavl, parent_guid, NULL);
- if (!nvlist_exists(parent_nv, "sent")) {
- /* parent has not been sent; skip this one */
- needagain = B_TRUE;
- continue;
- }
- }
if (origin_guid != 0) {
nvlist_t *origin_nv = fsavl_find(sdd->fsavl,
origin_guid, NULL);
if (origin_nv != NULL &&
- !nvlist_exists(origin_nv, "sent")) {
+ nvlist_lookup_boolean(origin_nv,
+ "sent") == ENOENT) {
/*
* origin has not been sent yet;
* skip this clone.
@@ -1340,16 +1235,6 @@ again:
assert(progress);
goto again;
}
-
- /* clean out the sent flags in case we reuse this fss */
- for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
- fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
- nvlist_t *fslist;
-
- VERIFY(nvpair_value_nvlist(fspair, &fslist) == 0);
- (void) nvlist_remove_all(fslist, "sent");
- }
-
return (0);
}
@@ -1371,16 +1256,17 @@ again:
*/
int
zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
- sendflags_t *flags, int outfd, snapfilter_cb_t filter_func,
+ sendflags_t flags, int outfd, snapfilter_cb_t filter_func,
void *cb_arg, nvlist_t **debugnvp)
{
char errbuf[1024];
send_dump_data_t sdd = { 0 };
- int err = 0;
+ int err;
nvlist_t *fss = NULL;
avl_tree_t *fsavl = NULL;
static uint64_t holdseq;
int spa_version;
+ boolean_t holdsnaps = B_FALSE;
pthread_t tid;
int pipefd[2];
dedup_arg_t dda = { 0 };
@@ -1403,7 +1289,12 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
}
}
- if (flags->dedup && !flags->dryrun) {
+ if (zfs_spa_version(zhp, &spa_version) == 0 &&
+ spa_version >= SPA_VERSION_USERREFS &&
+ (flags.doall || flags.replicate))
+ holdsnaps = B_TRUE;
+
+ if (flags.dedup) {
featureflags |= (DMU_BACKUP_FEATURE_DEDUP |
DMU_BACKUP_FEATURE_DEDUPPROPS);
if (err = pipe(pipefd)) {
@@ -1423,13 +1314,13 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
}
}
- if (flags->replicate || flags->doall || flags->props) {
+ if (flags.replicate || flags.doall || flags.props) {
dmu_replay_record_t drr = { 0 };
char *packbuf = NULL;
size_t buflen = 0;
zio_cksum_t zc = { 0 };
- if (flags->replicate || flags->props) {
+ if (flags.replicate || flags.props) {
nvlist_t *hdrnv;
VERIFY(0 == nvlist_alloc(&hdrnv, NV_UNIQUE_NAME, 0));
@@ -1438,13 +1329,13 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
"fromsnap", fromsnap));
}
VERIFY(0 == nvlist_add_string(hdrnv, "tosnap", tosnap));
- if (!flags->replicate) {
+ if (!flags.replicate) {
VERIFY(0 == nvlist_add_boolean(hdrnv,
"not_recursive"));
}
err = gather_nvlist(zhp->zfs_hdl, zhp->zfs_name,
- fromsnap, tosnap, flags->replicate, &fss, &fsavl);
+ fromsnap, tosnap, flags.replicate, &fss, &fsavl);
if (err)
goto err_out;
VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
@@ -1461,34 +1352,33 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
}
}
- if (!flags->dryrun) {
- /* write first begin record */
- drr.drr_type = DRR_BEGIN;
- drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
- DMU_SET_STREAM_HDRTYPE(drr.drr_u.drr_begin.
- drr_versioninfo, DMU_COMPOUNDSTREAM);
- DMU_SET_FEATUREFLAGS(drr.drr_u.drr_begin.
- drr_versioninfo, featureflags);
- (void) snprintf(drr.drr_u.drr_begin.drr_toname,
- sizeof (drr.drr_u.drr_begin.drr_toname),
- "%s@%s", zhp->zfs_name, tosnap);
- drr.drr_payloadlen = buflen;
- err = cksum_and_write(&drr, sizeof (drr), &zc, outfd);
-
- /* write header nvlist */
- if (err != -1 && packbuf != NULL) {
- err = cksum_and_write(packbuf, buflen, &zc,
- outfd);
- }
- free(packbuf);
- if (err == -1) {
- fsavl_destroy(fsavl);
- nvlist_free(fss);
- err = errno;
- goto stderr_out;
- }
+ /* write first begin record */
+ drr.drr_type = DRR_BEGIN;
+ drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
+ DMU_SET_STREAM_HDRTYPE(drr.drr_u.drr_begin.drr_versioninfo,
+ DMU_COMPOUNDSTREAM);
+ DMU_SET_FEATUREFLAGS(drr.drr_u.drr_begin.drr_versioninfo,
+ featureflags);
+ (void) snprintf(drr.drr_u.drr_begin.drr_toname,
+ sizeof (drr.drr_u.drr_begin.drr_toname),
+ "%s@%s", zhp->zfs_name, tosnap);
+ drr.drr_payloadlen = buflen;
+ err = cksum_and_write(&drr, sizeof (drr), &zc, outfd);
+
+ /* write header nvlist */
+ if (err != -1 && packbuf != NULL) {
+ err = cksum_and_write(packbuf, buflen, &zc, outfd);
+ }
+ free(packbuf);
+ if (err == -1) {
+ fsavl_destroy(fsavl);
+ nvlist_free(fss);
+ err = errno;
+ goto stderr_out;
+ }
- /* write end record */
+ /* write end record */
+ if (err != -1) {
bzero(&drr, sizeof (drr));
drr.drr_type = DRR_END;
drr.drr_u.drr_end.drr_checksum = zc;
@@ -1499,43 +1389,27 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
err = errno;
goto stderr_out;
}
-
- err = 0;
}
}
/* dump each stream */
sdd.fromsnap = fromsnap;
sdd.tosnap = tosnap;
- if (flags->dedup)
+ if (flags.dedup)
sdd.outfd = pipefd[0];
else
sdd.outfd = outfd;
- sdd.replicate = flags->replicate;
- sdd.doall = flags->doall;
- sdd.fromorigin = flags->fromorigin;
+ sdd.replicate = flags.replicate;
+ sdd.doall = flags.doall;
+ sdd.fromorigin = flags.fromorigin;
sdd.fss = fss;
sdd.fsavl = fsavl;
- sdd.verbose = flags->verbose;
- sdd.parsable = flags->parsable;
- sdd.progress = flags->progress;
- sdd.dryrun = flags->dryrun;
+ sdd.verbose = flags.verbose;
sdd.filter_cb = filter_func;
sdd.filter_cb_arg = cb_arg;
if (debugnvp)
sdd.debugnv = *debugnvp;
-
- /*
- * Some flags require that we place user holds on the datasets that are
- * being sent so they don't get destroyed during the send. We can skip
- * this step if the pool is imported read-only since the datasets cannot
- * be destroyed.
- */
- if (!flags->dryrun && !zpool_get_prop_int(zfs_get_pool_handle(zhp),
- ZPOOL_PROP_READONLY, NULL) &&
- zfs_spa_version(zhp, &spa_version) == 0 &&
- spa_version >= SPA_VERSION_USERREFS &&
- (flags->doall || flags->replicate)) {
+ if (holdsnaps) {
++holdseq;
(void) snprintf(sdd.holdtag, sizeof (sdd.holdtag),
".send-%d-%llu", getpid(), (u_longlong_t)holdseq);
@@ -1547,31 +1421,11 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
} else {
sdd.cleanup_fd = -1;
}
- if (flags->verbose) {
- /*
- * Do a verbose no-op dry run to get all the verbose output
- * before generating any data. Then do a non-verbose real
- * run to generate the streams.
- */
- sdd.dryrun = B_TRUE;
- err = dump_filesystems(zhp, &sdd);
- sdd.dryrun = flags->dryrun;
- sdd.verbose = B_FALSE;
- if (flags->parsable) {
- (void) fprintf(stderr, "size\t%llu\n",
- (longlong_t)sdd.size);
- } else {
- char buf[16];
- zfs_nicenum(sdd.size, buf, sizeof (buf));
- (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
- "total estimated size is %s\n"), buf);
- }
- }
err = dump_filesystems(zhp, &sdd);
fsavl_destroy(fsavl);
nvlist_free(fss);
- if (flags->dedup) {
+ if (flags.dedup) {
(void) close(pipefd[0]);
(void) pthread_join(tid, NULL);
}
@@ -1581,8 +1435,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
sdd.cleanup_fd = -1;
}
- if (!flags->dryrun && (flags->replicate || flags->doall ||
- flags->props)) {
+ if (flags.replicate || flags.doall || flags.props) {
/*
* write final end record. NB: want to do this even if
* there was some error, because it might not be totally
@@ -1603,7 +1456,7 @@ stderr_out:
err_out:
if (sdd.cleanup_fd != -1)
VERIFY(0 == close(sdd.cleanup_fd));
- if (flags->dedup) {
+ if (flags.dedup) {
(void) pthread_cancel(tid);
(void) pthread_join(tid, NULL);
(void) close(pipefd[0]);
@@ -1674,7 +1527,7 @@ recv_read_nvlist(libzfs_handle_t *hdl, int fd, int len, nvlist_t **nvp,
static int
recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
- int baselen, char *newname, recvflags_t *flags)
+ int baselen, char *newname, recvflags_t flags)
{
static int seq;
zfs_cmd_t zc = { 0 };
@@ -1686,7 +1539,7 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
if (zhp == NULL)
return (-1);
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
- flags->force ? MS_FORCE : 0);
+ flags.force ? MS_FORCE : 0);
zfs_close(zhp);
if (clp == NULL)
return (-1);
@@ -1702,7 +1555,7 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
(void) strlcpy(zc.zc_value, tryname, sizeof (zc.zc_value));
- if (flags->verbose) {
+ if (flags.verbose) {
(void) printf("attempting rename %s to %s\n",
zc.zc_name, zc.zc_value);
}
@@ -1721,19 +1574,19 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
"recv-%u-%u", getpid(), seq);
(void) strlcpy(zc.zc_value, newname, sizeof (zc.zc_value));
- if (flags->verbose) {
+ if (flags.verbose) {
(void) printf("failed - trying rename %s to %s\n",
zc.zc_name, zc.zc_value);
}
err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
if (err == 0)
changelist_rename(clp, name, newname);
- if (err && flags->verbose) {
+ if (err && flags.verbose) {
(void) printf("failed (%u) - "
"will try again on next pass\n", errno);
}
err = EAGAIN;
- } else if (flags->verbose) {
+ } else if (flags.verbose) {
if (err == 0)
(void) printf("success\n");
else
@@ -1748,7 +1601,7 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
static int
recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
- char *newname, recvflags_t *flags)
+ char *newname, recvflags_t flags)
{
zfs_cmd_t zc = { 0 };
int err = 0;
@@ -1761,7 +1614,7 @@ recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
if (zhp == NULL)
return (-1);
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
- flags->force ? MS_FORCE : 0);
+ flags.force ? MS_FORCE : 0);
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
zfs_spa_version(zhp, &spa_version) == 0 &&
spa_version >= SPA_VERSION_USERREFS)
@@ -1777,11 +1630,11 @@ recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
zc.zc_defer_destroy = defer;
(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
- if (flags->verbose)
+ if (flags.verbose)
(void) printf("attempting destroy %s\n", zc.zc_name);
err = ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc);
if (err == 0) {
- if (flags->verbose)
+ if (flags.verbose)
(void) printf("success\n");
changelist_remove(clp, zc.zc_name);
}
@@ -1804,7 +1657,6 @@ recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
typedef struct guid_to_name_data {
uint64_t guid;
char *name;
- char *skip;
} guid_to_name_data_t;
static int
@@ -1813,35 +1665,21 @@ guid_to_name_cb(zfs_handle_t *zhp, void *arg)
guid_to_name_data_t *gtnd = arg;
int err;
- if (gtnd->skip != NULL &&
- strcmp(zhp->zfs_name, gtnd->skip) == 0) {
- return (0);
- }
-
if (zhp->zfs_dmustats.dds_guid == gtnd->guid) {
(void) strcpy(gtnd->name, zhp->zfs_name);
zfs_close(zhp);
return (EEXIST);
}
-
err = zfs_iter_children(zhp, guid_to_name_cb, gtnd);
zfs_close(zhp);
return (err);
}
-/*
- * Attempt to find the local dataset associated with this guid. In the case of
- * multiple matches, we attempt to find the "best" match by searching
- * progressively larger portions of the hierarchy. This allows one to send a
- * tree of datasets individually and guarantee that we will find the source
- * guid within that hierarchy, even if there are multiple matches elsewhere.
- */
static int
guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid,
char *name)
{
/* exhaustive search all local snapshots */
- char pname[ZFS_MAXNAMELEN];
guid_to_name_data_t gtnd;
int err = 0;
zfs_handle_t *zhp;
@@ -1849,42 +1687,35 @@ guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid,
gtnd.guid = guid;
gtnd.name = name;
- gtnd.skip = NULL;
- (void) strlcpy(pname, parent, sizeof (pname));
-
- /*
- * Search progressively larger portions of the hierarchy. This will
- * select the "most local" version of the origin snapshot in the case
- * that there are multiple matching snapshots in the system.
- */
- while ((cp = strrchr(pname, '/')) != NULL) {
+ if (strchr(parent, '@') == NULL) {
+ zhp = make_dataset_handle(hdl, parent);
+ if (zhp != NULL) {
+ err = zfs_iter_children(zhp, guid_to_name_cb, &gtnd);
+ zfs_close(zhp);
+ if (err == EEXIST)
+ return (0);
+ }
+ }
- /* Chop off the last component and open the parent */
+ cp = strchr(parent, '/');
+ if (cp)
*cp = '\0';
- zhp = make_dataset_handle(hdl, pname);
-
- if (zhp == NULL)
- continue;
+ zhp = make_dataset_handle(hdl, parent);
+ if (cp)
+ *cp = '/';
+ if (zhp) {
err = zfs_iter_children(zhp, guid_to_name_cb, &gtnd);
zfs_close(zhp);
- if (err == EEXIST)
- return (0);
-
- /*
- * Remember the dataset that we already searched, so we
- * skip it next time through.
- */
- gtnd.skip = pname;
}
- return (ENOENT);
+ return (err == EEXIST ? 0 : ENOENT);
+
}
/*
- * Return +1 if guid1 is before guid2, 0 if they are the same, and -1 if
- * guid1 is after guid2.
+ * Return true if dataset guid1 is created before guid2.
*/
static int
created_before(libzfs_handle_t *hdl, avl_tree_t *avl,
@@ -1894,8 +1725,7 @@ created_before(libzfs_handle_t *hdl, avl_tree_t *avl,
char *fsname, *snapname;
char buf[ZFS_MAXNAMELEN];
int rv;
- zfs_handle_t *guid1hdl, *guid2hdl;
- uint64_t create1, create2;
+ zfs_node_t zn1, zn2;
if (guid2 == 0)
return (0);
@@ -1905,38 +1735,30 @@ created_before(libzfs_handle_t *hdl, avl_tree_t *avl,
nvfs = fsavl_find(avl, guid1, &snapname);
VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
(void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
- guid1hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
- if (guid1hdl == NULL)
+ zn1.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
+ if (zn1.zn_handle == NULL)
return (-1);
nvfs = fsavl_find(avl, guid2, &snapname);
VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
(void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
- guid2hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
- if (guid2hdl == NULL) {
- zfs_close(guid1hdl);
+ zn2.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
+ if (zn2.zn_handle == NULL) {
+ zfs_close(zn2.zn_handle);
return (-1);
}
- create1 = zfs_prop_get_int(guid1hdl, ZFS_PROP_CREATETXG);
- create2 = zfs_prop_get_int(guid2hdl, ZFS_PROP_CREATETXG);
+ rv = (zfs_snapshot_compare(&zn1, &zn2) == -1);
- if (create1 < create2)
- rv = -1;
- else if (create1 > create2)
- rv = +1;
- else
- rv = 0;
-
- zfs_close(guid1hdl);
- zfs_close(guid2hdl);
+ zfs_close(zn1.zn_handle);
+ zfs_close(zn2.zn_handle);
return (rv);
}
static int
recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
- recvflags_t *flags, nvlist_t *stream_nv, avl_tree_t *stream_avl,
+ recvflags_t flags, nvlist_t *stream_nv, avl_tree_t *stream_avl,
nvlist_t *renamed)
{
nvlist_t *local_nv;
@@ -1953,7 +1775,7 @@ recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
ENOENT);
- if (flags->dryrun)
+ if (flags.dryrun)
return (0);
again:
@@ -2013,7 +1835,7 @@ again:
nvlist_t *origin_nvfs;
char *origin_fsname;
- if (flags->verbose)
+ if (flags.verbose)
(void) printf("promoting %s\n", fsname);
origin_nvfs = fsavl_find(local_avl, originguid,
@@ -2061,7 +1883,7 @@ again:
if (found == NULL) {
char name[ZFS_MAXNAMELEN];
- if (!flags->force)
+ if (!flags.force)
continue;
(void) snprintf(name, sizeof (name), "%s@%s",
@@ -2119,7 +1941,7 @@ again:
/* check for delete */
if (stream_nvfs == NULL) {
- if (!flags->force)
+ if (!flags.force)
continue;
error = recv_destroy(hdl, fsname, strlen(tofs)+1,
@@ -2132,7 +1954,7 @@ again:
}
if (fromguid == 0) {
- if (flags->verbose) {
+ if (flags.verbose) {
(void) printf("local fs %s does not have "
"fromsnap (%s in stream); must have "
"been deleted locally; ignoring\n",
@@ -2157,7 +1979,7 @@ again:
if ((stream_parent_fromsnap_guid != 0 &&
parent_fromsnap_guid != 0 &&
stream_parent_fromsnap_guid != parent_fromsnap_guid) ||
- ((flags->isprefix || strcmp(tofs, fsname) != 0) &&
+ ((flags.isprefix || strcmp(tofs, fsname) != 0) &&
(s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) {
nvlist_t *parent;
char tryname[ZFS_MAXNAMELEN];
@@ -2180,7 +2002,7 @@ again:
"%s%s", pname, strrchr(stream_fsname, '/'));
} else {
tryname[0] = '\0';
- if (flags->verbose) {
+ if (flags.verbose) {
(void) printf("local fs %s new parent "
"not found\n", fsname);
}
@@ -2208,7 +2030,7 @@ again:
if (needagain && progress) {
/* do another pass to fix up temporary names */
- if (flags->verbose)
+ if (flags.verbose)
(void) printf("another pass:\n");
goto again;
}
@@ -2218,7 +2040,7 @@ again:
static int
zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
- recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
+ recvflags_t flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
{
nvlist_t *stream_nv = NULL;
@@ -2247,7 +2069,7 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
*/
if (drr->drr_payloadlen != 0) {
error = recv_read_nvlist(hdl, fd, drr->drr_payloadlen,
- &stream_nv, flags->byteswap, zc);
+ &stream_nv, flags.byteswap, zc);
if (error) {
error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
goto out;
@@ -2268,9 +2090,9 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
* Read in the end record and verify checksum.
*/
if (0 != (error = recv_read(hdl, fd, &drre, sizeof (drre),
- flags->byteswap, NULL)))
+ flags.byteswap, NULL)))
goto out;
- if (flags->byteswap) {
+ if (flags.byteswap) {
drre.drr_type = BSWAP_32(drre.drr_type);
drre.drr_u.drr_end.drr_checksum.zc_word[0] =
BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[0]);
@@ -2311,11 +2133,11 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
nvpair_t *pair = NULL;
(void) strlcpy(tofs, destname, ZFS_MAXNAMELEN);
- if (flags->isprefix) {
+ if (flags.isprefix) {
struct drr_begin *drrb = &drr->drr_u.drr_begin;
int i;
- if (flags->istail) {
+ if (flags.istail) {
cp = strrchr(drrb->drr_toname, '/');
if (cp == NULL) {
(void) strlcat(tofs, "/",
@@ -2333,7 +2155,7 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
*strchr(tofs, '@') = '\0';
}
- if (recursive && !flags->dryrun && !flags->nomount) {
+ if (recursive && !flags.dryrun && !flags.nomount) {
VERIFY(0 == nvlist_alloc(&renamed,
NV_UNIQUE_NAME, 0));
}
@@ -2507,7 +2329,7 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
*/
static int
zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
- recvflags_t *flags, dmu_replay_record_t *drr,
+ recvflags_t flags, dmu_replay_record_t *drr,
dmu_replay_record_t *drr_noswap, const char *sendfs,
nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
uint64_t *action_handlep)
@@ -2549,7 +2371,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
if (err)
VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
- if (flags->canmountoff) {
+ if (flags.canmountoff) {
VERIFY(0 == nvlist_add_uint64(props,
zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
}
@@ -2576,7 +2398,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
* If they specified a snapshot, chop the entire name stored in
* the stream.
*/
- if (flags->istail) {
+ if (flags.istail) {
/*
* A filesystem was specified with -e. We want to tack on only
* the tail of the sent snapshot path.
@@ -2602,7 +2424,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
} else {
chopprefix = drrb->drr_toname + (chopprefix - sendfs);
}
- } else if (flags->isprefix) {
+ } else if (flags.isprefix) {
/*
* A filesystem was specified with -d. We want to tack on
* everything but the first element of the sent snapshot path
@@ -2656,7 +2478,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
* Determine the name of the origin snapshot, store in zc_string.
*/
if (drrb->drr_flags & DRR_FLAG_CLONE) {
- if (guid_to_name(hdl, zc.zc_value,
+ if (guid_to_name(hdl, tosnap,
drrb->drr_fromguid, zc.zc_string) != 0) {
zcmd_free_nvlists(&zc);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -2664,7 +2486,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
zc.zc_value);
return (zfs_error(hdl, EZFS_NOENT, errbuf));
}
- if (flags->verbose)
+ if (flags.verbose)
(void) printf("found clone origin %s\n", zc.zc_string);
}
@@ -2687,7 +2509,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
!zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
char suffix[ZFS_MAXNAMELEN];
(void) strcpy(suffix, strrchr(zc.zc_value, '/'));
- if (guid_to_name(hdl, zc.zc_name, parent_snapguid,
+ if (guid_to_name(hdl, tosnap, parent_snapguid,
zc.zc_value) == 0) {
*strchr(zc.zc_value, '@') = '\0';
(void) strcat(zc.zc_value, suffix);
@@ -2709,12 +2531,12 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
* topmost path in the stream, then if the fs does not exist we
* should look no further.
*/
- if ((flags->isprefix || (*(chopprefix = drrb->drr_toname +
+ if ((flags.isprefix || (*(chopprefix = drrb->drr_toname +
strlen(sendfs)) != '\0' && *chopprefix != '@')) &&
!zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
char snap[ZFS_MAXNAMELEN];
(void) strcpy(snap, strchr(zc.zc_value, '@'));
- if (guid_to_name(hdl, zc.zc_name, drrb->drr_fromguid,
+ if (guid_to_name(hdl, tosnap, drrb->drr_fromguid,
zc.zc_value) == 0) {
*strchr(zc.zc_value, '@') = '\0';
(void) strcat(zc.zc_value, snap);
@@ -2736,7 +2558,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
* snapshots).
*/
if (stream_wantsnewfs) {
- if (!flags->force) {
+ if (!flags.force) {
zcmd_free_nvlists(&zc);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"destination '%s' exists\n"
@@ -2772,7 +2594,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
return (zfs_error(hdl, EZFS_EXISTS, errbuf));
}
- if (!flags->dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
+ if (!flags.dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
stream_wantsnewfs) {
/* We can't do online recv in this case */
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0);
@@ -2811,7 +2633,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*/
*cp = '\0';
- if (flags->isprefix && !flags->istail && !flags->dryrun &&
+ if (flags.isprefix && !flags.istail && !flags.dryrun &&
create_parents(hdl, zc.zc_value, strlen(tosnap)) != 0) {
zcmd_free_nvlists(&zc);
return (zfs_error(hdl, EZFS_BADRESTORE, errbuf));
@@ -2822,18 +2644,18 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
zc.zc_begin_record = drr_noswap->drr_u.drr_begin;
zc.zc_cookie = infd;
- zc.zc_guid = flags->force;
- if (flags->verbose) {
+ zc.zc_guid = flags.force;
+ if (flags.verbose) {
(void) printf("%s %s stream of %s into %s\n",
- flags->dryrun ? "would receive" : "receiving",
+ flags.dryrun ? "would receive" : "receiving",
drrb->drr_fromguid ? "incremental" : "full",
drrb->drr_toname, zc.zc_value);
(void) fflush(stdout);
}
- if (flags->dryrun) {
+ if (flags.dryrun) {
zcmd_free_nvlists(&zc);
- return (recv_skip(hdl, infd, flags->byteswap));
+ return (recv_skip(hdl, infd, flags.byteswap));
}
zc.zc_nvlist_dst = (uint64_t)(uintptr_t)prop_errbuf;
@@ -2914,12 +2736,12 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
nvlist_free(local_nv);
if (fs != NULL) {
- if (flags->verbose) {
+ if (flags.verbose) {
(void) printf("snap %s already exists; "
"ignoring\n", zc.zc_value);
}
err = ioctl_err = recv_skip(hdl, infd,
- flags->byteswap);
+ flags.byteswap);
}
}
*cp = '@';
@@ -2971,7 +2793,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
case EDQUOT:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"destination %s space quota exceeded"), zc.zc_name);
- (void) zfs_error(hdl, EZFS_NOSPC, errbuf);
+ (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
break;
default:
(void) zfs_standard_error(hdl, ioctl_errno, errbuf);
@@ -3029,7 +2851,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*action_handlep = zc.zc_action_handle;
- if (flags->verbose) {
+ if (flags.verbose) {
char buf1[64];
char buf2[64];
uint64_t bytes = zc.zc_cookie;
@@ -3047,7 +2869,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
}
static int
-zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
+zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags,
int infd, const char *sendfs, nvlist_t *stream_nv, avl_tree_t *stream_avl,
char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
{
@@ -3062,7 +2884,7 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot receive"));
- if (flags->isprefix &&
+ if (flags.isprefix &&
!zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
"(%s) does not exist"), tosnap);
@@ -3082,7 +2904,7 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
/* the kernel needs the non-byteswapped begin record */
drr_noswap = drr;
- flags->byteswap = B_FALSE;
+ flags.byteswap = B_FALSE;
if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
/*
* We computed the checksum in the wrong byteorder in
@@ -3090,7 +2912,7 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
*/
bzero(&zcksum, sizeof (zio_cksum_t));
fletcher_4_incremental_byteswap(&drr, sizeof (drr), &zcksum);
- flags->byteswap = B_TRUE;
+ flags.byteswap = B_TRUE;
drr.drr_type = BSWAP_32(drr.drr_type);
drr.drr_payloadlen = BSWAP_32(drr.drr_payloadlen);
@@ -3158,7 +2980,7 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
* (-1 will override -2).
*/
int
-zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
+zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags,
int infd, avl_tree_t *stream_avl)
{
char *top_zfs = NULL;
@@ -3174,7 +2996,7 @@ zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
VERIFY(0 == close(cleanup_fd));
- if (err == 0 && !flags->nomount && top_zfs) {
+ if (err == 0 && !flags.nomount && top_zfs) {
zfs_handle_t *zhp;
prop_changelist_t *clp;
diff --git a/lib/libzfs/common/libzfs_status.c b/lib/libzfs/common/libzfs_status.c
index af0707a62058..24725ec044ec 100644
--- a/lib/libzfs/common/libzfs_status.c
+++ b/lib/libzfs/common/libzfs_status.c
@@ -18,10 +18,8 @@
*
* CDDL HEADER END
*/
-
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
@@ -216,20 +214,6 @@ check_status(nvlist_t *config, boolean_t isimport)
return (ZPOOL_STATUS_VERSION_NEWER);
/*
- * Unsupported feature(s).
- */
- if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
- vs->vs_aux == VDEV_AUX_UNSUP_FEAT) {
- nvlist_t *nvinfo;
-
- verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO,
- &nvinfo) == 0);
- if (nvlist_exists(nvinfo, ZPOOL_CONFIG_CAN_RDONLY))
- return (ZPOOL_STATUS_UNSUP_FEAT_WRITE);
- return (ZPOOL_STATUS_UNSUP_FEAT_READ);
- }
-
- /*
* Check that the config is complete.
*/
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
@@ -316,7 +300,7 @@ check_status(nvlist_t *config, boolean_t isimport)
/*
* Outdated, but usable, version
*/
- if (SPA_VERSION_IS_SUPPORTED(version) && version != SPA_VERSION)
+ if (version < SPA_VERSION)
return (ZPOOL_STATUS_VERSION_OLDER);
return (ZPOOL_STATUS_OK);
diff --git a/lib/libzfs/common/libzfs_util.c b/lib/libzfs/common/libzfs_util.c
index 41e25e9100a0..01b7c8732efd 100644
--- a/lib/libzfs/common/libzfs_util.c
+++ b/lib/libzfs/common/libzfs_util.c
@@ -18,10 +18,8 @@
*
* CDDL HEADER END
*/
-
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
@@ -43,11 +41,9 @@
#include <sys/types.h>
#include <libzfs.h>
-#include <libzfs_core.h>
#include "libzfs_impl.h"
#include "zfs_prop.h"
-#include "zfeature_common.h"
int
libzfs_errno(libzfs_handle_t *hdl)
@@ -115,8 +111,7 @@ libzfs_error_description(libzfs_handle_t *hdl)
case EZFS_RESILVERING:
return (dgettext(TEXT_DOMAIN, "currently resilvering"));
case EZFS_BADVERSION:
- return (dgettext(TEXT_DOMAIN, "unsupported version or "
- "feature"));
+ return (dgettext(TEXT_DOMAIN, "unsupported version"));
case EZFS_POOLUNAVAIL:
return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
case EZFS_DEVOVERFLOW:
@@ -349,7 +344,6 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
switch (error) {
case ENXIO:
case ENODEV:
- case EPIPE:
zfs_verror(hdl, EZFS_IO, fmt, ap);
break;
@@ -631,17 +625,8 @@ libzfs_init(void)
hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
- if (libzfs_core_init() != 0) {
- (void) close(hdl->libzfs_fd);
- (void) fclose(hdl->libzfs_mnttab);
- (void) fclose(hdl->libzfs_sharetab);
- free(hdl);
- return (NULL);
- }
-
zfs_prop_init();
zpool_prop_init();
- zpool_feature_init();
libzfs_mnttab_init(hdl);
return (hdl);
@@ -656,11 +641,12 @@ libzfs_fini(libzfs_handle_t *hdl)
if (hdl->libzfs_sharetab)
(void) fclose(hdl->libzfs_sharetab);
zfs_uninit_libshare(hdl);
+ if (hdl->libzfs_log_str)
+ (void) free(hdl->libzfs_log_str);
zpool_free_handles(hdl);
libzfs_fru_clear(hdl, B_TRUE);
namespace_clear(hdl);
libzfs_mnttab_fini(hdl);
- libzfs_core_fini();
free(hdl);
}
@@ -822,7 +808,17 @@ zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
int
zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
{
- return (ioctl(hdl->libzfs_fd, request, zc));
+ int error;
+
+ zc->zc_history = (uint64_t)(uintptr_t)hdl->libzfs_log_str;
+ error = ioctl(hdl->libzfs_fd, request, zc);
+ if (hdl->libzfs_log_str) {
+ free(hdl->libzfs_log_str);
+ hdl->libzfs_log_str = NULL;
+ }
+ zc->zc_history = 0;
+
+ return (error);
}
/*
@@ -1284,11 +1280,8 @@ addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
* this is a pool property or if this isn't a user-defined
* dataset property,
*/
- if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
- !zpool_prop_feature(propname) &&
- !zpool_prop_unsupported(propname)) ||
- (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) &&
- !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) {
+ if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL ||
+ (!zfs_prop_user(propname) && !zfs_prop_userquota(propname)))) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"invalid property '%s'"), propname);
return (zfs_error(hdl, EZFS_BADPROP,
@@ -1300,8 +1293,7 @@ addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
entry->pl_prop = prop;
if (prop == ZPROP_INVAL) {
- if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) ==
- NULL) {
+ if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == NULL) {
free(entry);
return (-1);
}
diff --git a/lib/libzfs_core/common/libzfs_core.c b/lib/libzfs_core/common/libzfs_core.c
deleted file mode 100644
index 73afd50b8de2..000000000000
--- a/lib/libzfs_core/common/libzfs_core.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2012 by Delphix. All rights reserved.
- */
-
-/*
- * LibZFS_Core (lzc) is intended to replace most functionality in libzfs.
- * It has the following characteristics:
- *
- * - Thread Safe. libzfs_core is accessible concurrently from multiple
- * threads. This is accomplished primarily by avoiding global data
- * (e.g. caching). Since it's thread-safe, there is no reason for a
- * process to have multiple libzfs "instances". Therefore, we store
- * our few pieces of data (e.g. the file descriptor) in global
- * variables. The fd is reference-counted so that the libzfs_core
- * library can be "initialized" multiple times (e.g. by different
- * consumers within the same process).
- *
- * - Committed Interface. The libzfs_core interface will be committed,
- * therefore consumers can compile against it and be confident that
- * their code will continue to work on future releases of this code.
- * Currently, the interface is Evolving (not Committed), but we intend
- * to commit to it once it is more complete and we determine that it
- * meets the needs of all consumers.
- *
- * - Programatic Error Handling. libzfs_core communicates errors with
- * defined error numbers, and doesn't print anything to stdout/stderr.
- *
- * - Thin Layer. libzfs_core is a thin layer, marshaling arguments
- * to/from the kernel ioctls. There is generally a 1:1 correspondence
- * between libzfs_core functions and ioctls to /dev/zfs.
- *
- * - Clear Atomicity. Because libzfs_core functions are generally 1:1
- * with kernel ioctls, and kernel ioctls are general atomic, each
- * libzfs_core function is atomic. For example, creating multiple
- * snapshots with a single call to lzc_snapshot() is atomic -- it
- * can't fail with only some of the requested snapshots created, even
- * in the event of power loss or system crash.
- *
- * - Continued libzfs Support. Some higher-level operations (e.g.
- * support for "zfs send -R") are too complicated to fit the scope of
- * libzfs_core. This functionality will continue to live in libzfs.
- * Where appropriate, libzfs will use the underlying atomic operations
- * of libzfs_core. For example, libzfs may implement "zfs send -R |
- * zfs receive" by using individual "send one snapshot", rename,
- * destroy, and "receive one snapshot" operations in libzfs_core.
- * /sbin/zfs and /zbin/zpool will link with both libzfs and
- * libzfs_core. Other consumers should aim to use only libzfs_core,
- * since that will be the supported, stable interface going forwards.
- */
-
-#include <libzfs_core.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <sys/nvpair.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/zfs_ioctl.h>
-
-static int g_fd;
-static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
-static int g_refcount;
-
-int
-libzfs_core_init(void)
-{
- (void) pthread_mutex_lock(&g_lock);
- if (g_refcount == 0) {
- g_fd = open("/dev/zfs", O_RDWR);
- if (g_fd < 0) {
- (void) pthread_mutex_unlock(&g_lock);
- return (errno);
- }
- }
- g_refcount++;
- (void) pthread_mutex_unlock(&g_lock);
- return (0);
-}
-
-void
-libzfs_core_fini(void)
-{
- (void) pthread_mutex_lock(&g_lock);
- ASSERT3S(g_refcount, >, 0);
- g_refcount--;
- if (g_refcount == 0)
- (void) close(g_fd);
- (void) pthread_mutex_unlock(&g_lock);
-}
-
-static int
-lzc_ioctl(zfs_ioc_t ioc, const char *name,
- nvlist_t *source, nvlist_t **resultp)
-{
- zfs_cmd_t zc = { 0 };
- int error = 0;
- char *packed;
- size_t size;
-
- ASSERT3S(g_refcount, >, 0);
-
- (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
-
- packed = fnvlist_pack(source, &size);
- zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
- zc.zc_nvlist_src_size = size;
-
- if (resultp != NULL) {
- zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024);
- zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
- malloc(zc.zc_nvlist_dst_size);
- if (zc.zc_nvlist_dst == NULL) {
- error = ENOMEM;
- goto out;
- }
- }
-
- while (ioctl(g_fd, ioc, &zc) != 0) {
- if (errno == ENOMEM && resultp != NULL) {
- free((void *)(uintptr_t)zc.zc_nvlist_dst);
- zc.zc_nvlist_dst_size *= 2;
- zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
- malloc(zc.zc_nvlist_dst_size);
- if (zc.zc_nvlist_dst == NULL) {
- error = ENOMEM;
- goto out;
- }
- } else {
- error = errno;
- break;
- }
- }
- if (zc.zc_nvlist_dst_filled) {
- *resultp = fnvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
- zc.zc_nvlist_dst_size);
- } else if (resultp != NULL) {
- *resultp = NULL;
- }
-
-out:
- fnvlist_pack_free(packed, size);
- free((void *)(uintptr_t)zc.zc_nvlist_dst);
- return (error);
-}
-
-int
-lzc_create(const char *fsname, dmu_objset_type_t type, nvlist_t *props)
-{
- int error;
- nvlist_t *args = fnvlist_alloc();
- fnvlist_add_int32(args, "type", type);
- if (props != NULL)
- fnvlist_add_nvlist(args, "props", props);
- error = lzc_ioctl(ZFS_IOC_CREATE, fsname, args, NULL);
- nvlist_free(args);
- return (error);
-}
-
-int
-lzc_clone(const char *fsname, const char *origin,
- nvlist_t *props)
-{
- int error;
- nvlist_t *args = fnvlist_alloc();
- fnvlist_add_string(args, "origin", origin);
- if (props != NULL)
- fnvlist_add_nvlist(args, "props", props);
- error = lzc_ioctl(ZFS_IOC_CLONE, fsname, args, NULL);
- nvlist_free(args);
- return (error);
-}
-
-/*
- * Creates snapshots.
- *
- * The keys in the snaps nvlist are the snapshots to be created.
- * They must all be in the same pool.
- *
- * The props nvlist is properties to set. Currently only user properties
- * are supported. { user:prop_name -> string value }
- *
- * The returned results nvlist will have an entry for each snapshot that failed.
- * The value will be the (int32) error code.
- *
- * The return value will be 0 if all snapshots were created, otherwise it will
- * be the errno of a (undetermined) snapshot that failed.
- */
-int
-lzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist)
-{
- nvpair_t *elem;
- nvlist_t *args;
- int error;
- char pool[MAXNAMELEN];
-
- *errlist = NULL;
-
- /* determine the pool name */
- elem = nvlist_next_nvpair(snaps, NULL);
- if (elem == NULL)
- return (0);
- (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
- pool[strcspn(pool, "/@")] = '\0';
-
- args = fnvlist_alloc();
- fnvlist_add_nvlist(args, "snaps", snaps);
- if (props != NULL)
- fnvlist_add_nvlist(args, "props", props);
-
- error = lzc_ioctl(ZFS_IOC_SNAPSHOT, pool, args, errlist);
- nvlist_free(args);
-
- return (error);
-}
-
-/*
- * Destroys snapshots.
- *
- * The keys in the snaps nvlist are the snapshots to be destroyed.
- * They must all be in the same pool.
- *
- * Snapshots that do not exist will be silently ignored.
- *
- * If 'defer' is not set, and a snapshot has user holds or clones, the
- * destroy operation will fail and none of the snapshots will be
- * destroyed.
- *
- * If 'defer' is set, and a snapshot has user holds or clones, it will be
- * marked for deferred destruction, and will be destroyed when the last hold
- * or clone is removed/destroyed.
- *
- * The return value will be 0 if all snapshots were destroyed (or marked for
- * later destruction if 'defer' is set) or didn't exist to begin with.
- *
- * Otherwise the return value will be the errno of a (undetermined) snapshot
- * that failed, no snapshots will be destroyed, and the errlist will have an
- * entry for each snapshot that failed. The value in the errlist will be
- * the (int32) error code.
- */
-int
-lzc_destroy_snaps(nvlist_t *snaps, boolean_t defer, nvlist_t **errlist)
-{
- nvpair_t *elem;
- nvlist_t *args;
- int error;
- char pool[MAXNAMELEN];
-
- /* determine the pool name */
- elem = nvlist_next_nvpair(snaps, NULL);
- if (elem == NULL)
- return (0);
- (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
- pool[strcspn(pool, "/@")] = '\0';
-
- args = fnvlist_alloc();
- fnvlist_add_nvlist(args, "snaps", snaps);
- if (defer)
- fnvlist_add_boolean(args, "defer");
-
- error = lzc_ioctl(ZFS_IOC_DESTROY_SNAPS, pool, args, errlist);
- nvlist_free(args);
-
- return (error);
-
-}
-
-int
-lzc_snaprange_space(const char *firstsnap, const char *lastsnap,
- uint64_t *usedp)
-{
- nvlist_t *args;
- nvlist_t *result;
- int err;
- char fs[MAXNAMELEN];
- char *atp;
-
- /* determine the fs name */
- (void) strlcpy(fs, firstsnap, sizeof (fs));
- atp = strchr(fs, '@');
- if (atp == NULL)
- return (EINVAL);
- *atp = '\0';
-
- args = fnvlist_alloc();
- fnvlist_add_string(args, "firstsnap", firstsnap);
-
- err = lzc_ioctl(ZFS_IOC_SPACE_SNAPS, lastsnap, args, &result);
- nvlist_free(args);
- if (err == 0)
- *usedp = fnvlist_lookup_uint64(result, "used");
- fnvlist_free(result);
-
- return (err);
-}
-
-boolean_t
-lzc_exists(const char *dataset)
-{
- /*
- * The objset_stats ioctl is still legacy, so we need to construct our
- * own zfs_cmd_t rather than using zfsc_ioctl().
- */
- zfs_cmd_t zc = { 0 };
-
- (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
- return (ioctl(g_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0);
-}
-
-/*
- * If fromsnap is NULL, a full (non-incremental) stream will be sent.
- */
-int
-lzc_send(const char *snapname, const char *fromsnap, int fd)
-{
- nvlist_t *args;
- int err;
-
- args = fnvlist_alloc();
- fnvlist_add_int32(args, "fd", fd);
- if (fromsnap != NULL)
- fnvlist_add_string(args, "fromsnap", fromsnap);
- err = lzc_ioctl(ZFS_IOC_SEND_NEW, snapname, args, NULL);
- nvlist_free(args);
- return (err);
-}
-
-/*
- * If fromsnap is NULL, a full (non-incremental) stream will be estimated.
- */
-int
-lzc_send_space(const char *snapname, const char *fromsnap, uint64_t *spacep)
-{
- nvlist_t *args;
- nvlist_t *result;
- int err;
-
- args = fnvlist_alloc();
- if (fromsnap != NULL)
- fnvlist_add_string(args, "fromsnap", fromsnap);
- err = lzc_ioctl(ZFS_IOC_SEND_SPACE, snapname, args, &result);
- nvlist_free(args);
- if (err == 0)
- *spacep = fnvlist_lookup_uint64(result, "space");
- nvlist_free(result);
- return (err);
-}
-
-static int
-recv_read(int fd, void *buf, int ilen)
-{
- char *cp = buf;
- int rv;
- int len = ilen;
-
- do {
- rv = read(fd, cp, len);
- cp += rv;
- len -= rv;
- } while (rv > 0);
-
- if (rv < 0 || len != 0)
- return (EIO);
-
- return (0);
-}
-
-/*
- * The simplest receive case: receive from the specified fd, creating the
- * specified snapshot. Apply the specified properties a "received" properties
- * (which can be overridden by locally-set properties). If the stream is a
- * clone, its origin snapshot must be specified by 'origin'. The 'force'
- * flag will cause the target filesystem to be rolled back or destroyed if
- * necessary to receive.
- *
- * Return 0 on success or an errno on failure.
- *
- * Note: this interface does not work on dedup'd streams
- * (those with DMU_BACKUP_FEATURE_DEDUP).
- */
-int
-lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
- boolean_t force, int fd)
-{
- /*
- * The receive ioctl is still legacy, so we need to construct our own
- * zfs_cmd_t rather than using zfsc_ioctl().
- */
- zfs_cmd_t zc = { 0 };
- char *atp;
- char *packed = NULL;
- size_t size;
- dmu_replay_record_t drr;
- int error;
-
- ASSERT3S(g_refcount, >, 0);
-
- /* zc_name is name of containing filesystem */
- (void) strlcpy(zc.zc_name, snapname, sizeof (zc.zc_name));
- atp = strchr(zc.zc_name, '@');
- if (atp == NULL)
- return (EINVAL);
- *atp = '\0';
-
- /* if the fs does not exist, try its parent. */
- if (!lzc_exists(zc.zc_name)) {
- char *slashp = strrchr(zc.zc_name, '/');
- if (slashp == NULL)
- return (ENOENT);
- *slashp = '\0';
-
- }
-
- /* zc_value is full name of the snapshot to create */
- (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
-
- if (props != NULL) {
- /* zc_nvlist_src is props to set */
- packed = fnvlist_pack(props, &size);
- zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
- zc.zc_nvlist_src_size = size;
- }
-
- /* zc_string is name of clone origin (if DRR_FLAG_CLONE) */
- if (origin != NULL)
- (void) strlcpy(zc.zc_string, origin, sizeof (zc.zc_string));
-
- /* zc_begin_record is non-byteswapped BEGIN record */
- error = recv_read(fd, &drr, sizeof (drr));
- if (error != 0)
- goto out;
- zc.zc_begin_record = drr.drr_u.drr_begin;
-
- /* zc_cookie is fd to read from */
- zc.zc_cookie = fd;
-
- /* zc guid is force flag */
- zc.zc_guid = force;
-
- /* zc_cleanup_fd is unused */
- zc.zc_cleanup_fd = -1;
-
- error = ioctl(g_fd, ZFS_IOC_RECV, &zc);
- if (error != 0)
- error = errno;
-
-out:
- if (packed != NULL)
- fnvlist_pack_free(packed, size);
- free((void*)(uintptr_t)zc.zc_nvlist_dst);
- return (error);
-}
diff --git a/lib/libzfs_core/common/libzfs_core.h b/lib/libzfs_core/common/libzfs_core.h
deleted file mode 100644
index 9edc884a14d1..000000000000
--- a/lib/libzfs_core/common/libzfs_core.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2012 by Delphix. All rights reserved.
- */
-
-#ifndef _LIBZFS_CORE_H
-#define _LIBZFS_CORE_H
-
-#include <libnvpair.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/fs/zfs.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int libzfs_core_init(void);
-void libzfs_core_fini(void);
-
-int lzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist);
-int lzc_create(const char *fsname, dmu_objset_type_t type, nvlist_t *props);
-int lzc_clone(const char *fsname, const char *origin, nvlist_t *props);
-int lzc_destroy_snaps(nvlist_t *snaps, boolean_t defer, nvlist_t **errlist);
-
-int lzc_snaprange_space(const char *firstsnap, const char *lastsnap,
- uint64_t *usedp);
-
-int lzc_send(const char *snapname, const char *fromsnap, int fd);
-int lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
- boolean_t force, int fd);
-int lzc_send_space(const char *snapname, const char *fromsnap,
- uint64_t *result);
-
-boolean_t lzc_exists(const char *dataset);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LIBZFS_CORE_H */
diff --git a/lib/libzpool/common/kernel.c b/lib/libzpool/common/kernel.c
index 04d530727f5c..f323bf60b099 100644
--- a/lib/libzpool/common/kernel.c
+++ b/lib/libzpool/common/kernel.c
@@ -20,7 +20,6 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <assert.h>
@@ -46,7 +45,6 @@ int aok;
uint64_t physmem;
vnode_t *rootdir = (vnode_t *)0xabcd1234;
char hw_serial[HW_HOSTID_LEN];
-vmem_t *zio_arena = NULL;
struct utsname utsname = {
"userland", "libzpool", "1", "1", "na"
@@ -426,9 +424,7 @@ vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
* To simulate partial disk writes, we split writes into two
* system calls so that the process can be killed in between.
*/
- int sectors = len >> SPA_MINBLOCKSHIFT;
- split = (sectors > 0 ? rand() % sectors : 0) <<
- SPA_MINBLOCKSHIFT;
+ split = (len > 0 ? rand() % len : 0);
iolen = pwrite64(vp->v_fd, addr, split, offset);
iolen += pwrite64(vp->v_fd, (char *)addr + split,
len - split, offset + split);
@@ -871,12 +867,6 @@ crgetuid(cred_t *cr)
return (0);
}
-uid_t
-crgetruid(cred_t *cr)
-{
- return (0);
-}
-
gid_t
crgetgid(cred_t *cr)
{
diff --git a/lib/libzpool/common/sys/zfs_context.h b/lib/libzpool/common/sys/zfs_context.h
index 39af927f7105..3b0390dca566 100644
--- a/lib/libzpool/common/sys/zfs_context.h
+++ b/lib/libzpool/common/sys/zfs_context.h
@@ -20,9 +20,6 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#ifndef _SYS_ZFS_CONTEXT_H
@@ -215,7 +212,6 @@ struct proc {
};
extern struct proc p0;
-#define curproc (&p0)
#define PS_NONE -1
@@ -286,7 +282,6 @@ extern void rw_exit(krwlock_t *rwlp);
#define rw_downgrade(rwlp) do { } while (0)
extern uid_t crgetuid(cred_t *cr);
-extern uid_t crgetruid(cred_t *cr);
extern gid_t crgetgid(cred_t *cr);
extern int crgetngroups(cred_t *cr);
extern gid_t *crgetgroups(cred_t *cr);
@@ -332,12 +327,9 @@ extern void kstat_delete(kstat_t *);
#define kmem_debugging() 0
#define kmem_cache_reap_now(_c) /* nothing */
#define kmem_cache_set_move(_c, _cb) /* nothing */
-#define vmem_qcache_reap(_v) /* nothing */
#define POINTER_INVALIDATE(_pp) /* nothing */
#define POINTER_IS_VALID(_p) 0
-extern vmem_t *zio_arena;
-
typedef umem_cache_t kmem_cache_t;
typedef enum kmem_cbrc {
@@ -355,16 +347,6 @@ typedef struct taskq taskq_t;
typedef uintptr_t taskqid_t;
typedef void (task_func_t)(void *);
-typedef struct taskq_ent {
- struct taskq_ent *tqent_next;
- struct taskq_ent *tqent_prev;
- task_func_t *tqent_func;
- void *tqent_arg;
- uintptr_t tqent_flags;
-} taskq_ent_t;
-
-#define TQENT_FLAG_PREALLOC 0x1 /* taskq_dispatch_ent used */
-
#define TASKQ_PREPOPULATE 0x0001
#define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */
#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
@@ -376,7 +358,6 @@ typedef struct taskq_ent {
#define TQ_NOQUEUE 0x02 /* Do not enqueue if can't dispatch */
#define TQ_FRONT 0x08 /* Queue in front */
-
extern taskq_t *system_taskq;
extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
@@ -385,8 +366,6 @@ extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
#define taskq_create_sysdc(a, b, d, e, p, dc, f) \
(taskq_create(a, b, maxclsyspri, d, e, f))
extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
-extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
- taskq_ent_t *);
extern void taskq_destroy(taskq_t *);
extern void taskq_wait(taskq_t *);
extern int taskq_member(taskq_t *, void *);
diff --git a/lib/libzpool/common/taskq.c b/lib/libzpool/common/taskq.c
index 2c5dfd86dcc0..8db5d11c1327 100644
--- a/lib/libzpool/common/taskq.c
+++ b/lib/libzpool/common/taskq.c
@@ -22,16 +22,19 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
- */
#include <sys/zfs_context.h>
int taskq_now;
taskq_t *system_taskq;
+typedef struct task {
+ struct task *task_next;
+ struct task *task_prev;
+ task_func_t *task_func;
+ void *task_arg;
+} task_t;
+
#define TASKQ_ACTIVE 0x00010000
struct taskq {
@@ -48,18 +51,18 @@ struct taskq {
int tq_maxalloc;
kcondvar_t tq_maxalloc_cv;
int tq_maxalloc_wait;
- taskq_ent_t *tq_freelist;
- taskq_ent_t tq_task;
+ task_t *tq_freelist;
+ task_t tq_task;
};
-static taskq_ent_t *
+static task_t *
task_alloc(taskq_t *tq, int tqflags)
{
- taskq_ent_t *t;
+ task_t *t;
int rv;
again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
- tq->tq_freelist = t->tqent_next;
+ tq->tq_freelist = t->task_next;
} else {
if (tq->tq_nalloc >= tq->tq_maxalloc) {
if (!(tqflags & KM_SLEEP))
@@ -84,7 +87,7 @@ again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
}
mutex_exit(&tq->tq_lock);
- t = kmem_alloc(sizeof (taskq_ent_t), tqflags);
+ t = kmem_alloc(sizeof (task_t), tqflags);
mutex_enter(&tq->tq_lock);
if (t != NULL)
@@ -94,15 +97,15 @@ again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
}
static void
-task_free(taskq_t *tq, taskq_ent_t *t)
+task_free(taskq_t *tq, task_t *t)
{
if (tq->tq_nalloc <= tq->tq_minalloc) {
- t->tqent_next = tq->tq_freelist;
+ t->task_next = tq->tq_freelist;
tq->tq_freelist = t;
} else {
tq->tq_nalloc--;
mutex_exit(&tq->tq_lock);
- kmem_free(t, sizeof (taskq_ent_t));
+ kmem_free(t, sizeof (task_t));
mutex_enter(&tq->tq_lock);
}
@@ -113,7 +116,7 @@ task_free(taskq_t *tq, taskq_ent_t *t)
taskqid_t
taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags)
{
- taskq_ent_t *t;
+ task_t *t;
if (taskq_now) {
func(arg);
@@ -127,59 +130,26 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags)
return (0);
}
if (tqflags & TQ_FRONT) {
- t->tqent_next = tq->tq_task.tqent_next;
- t->tqent_prev = &tq->tq_task;
+ t->task_next = tq->tq_task.task_next;
+ t->task_prev = &tq->tq_task;
} else {
- t->tqent_next = &tq->tq_task;
- t->tqent_prev = tq->tq_task.tqent_prev;
+ t->task_next = &tq->tq_task;
+ t->task_prev = tq->tq_task.task_prev;
}
- t->tqent_next->tqent_prev = t;
- t->tqent_prev->tqent_next = t;
- t->tqent_func = func;
- t->tqent_arg = arg;
- t->tqent_flags = 0;
+ t->task_next->task_prev = t;
+ t->task_prev->task_next = t;
+ t->task_func = func;
+ t->task_arg = arg;
cv_signal(&tq->tq_dispatch_cv);
mutex_exit(&tq->tq_lock);
return (1);
}
void
-taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
- taskq_ent_t *t)
-{
- ASSERT(func != NULL);
- ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC));
-
- /*
- * Mark it as a prealloc'd task. This is important
- * to ensure that we don't free it later.
- */
- t->tqent_flags |= TQENT_FLAG_PREALLOC;
- /*
- * Enqueue the task to the underlying queue.
- */
- mutex_enter(&tq->tq_lock);
-
- if (flags & TQ_FRONT) {
- t->tqent_next = tq->tq_task.tqent_next;
- t->tqent_prev = &tq->tq_task;
- } else {
- t->tqent_next = &tq->tq_task;
- t->tqent_prev = tq->tq_task.tqent_prev;
- }
- t->tqent_next->tqent_prev = t;
- t->tqent_prev->tqent_next = t;
- t->tqent_func = func;
- t->tqent_arg = arg;
- cv_signal(&tq->tq_dispatch_cv);
- mutex_exit(&tq->tq_lock);
-}
-
-void
taskq_wait(taskq_t *tq)
{
mutex_enter(&tq->tq_lock);
- while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0)
+ while (tq->tq_task.task_next != &tq->tq_task || tq->tq_active != 0)
cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
mutex_exit(&tq->tq_lock);
}
@@ -188,32 +158,27 @@ static void *
taskq_thread(void *arg)
{
taskq_t *tq = arg;
- taskq_ent_t *t;
- boolean_t prealloc;
+ task_t *t;
mutex_enter(&tq->tq_lock);
while (tq->tq_flags & TASKQ_ACTIVE) {
- if ((t = tq->tq_task.tqent_next) == &tq->tq_task) {
+ if ((t = tq->tq_task.task_next) == &tq->tq_task) {
if (--tq->tq_active == 0)
cv_broadcast(&tq->tq_wait_cv);
cv_wait(&tq->tq_dispatch_cv, &tq->tq_lock);
tq->tq_active++;
continue;
}
- t->tqent_prev->tqent_next = t->tqent_next;
- t->tqent_next->tqent_prev = t->tqent_prev;
- t->tqent_next = NULL;
- t->tqent_prev = NULL;
- prealloc = t->tqent_flags & TQENT_FLAG_PREALLOC;
+ t->task_prev->task_next = t->task_next;
+ t->task_next->task_prev = t->task_prev;
mutex_exit(&tq->tq_lock);
rw_enter(&tq->tq_threadlock, RW_READER);
- t->tqent_func(t->tqent_arg);
+ t->task_func(t->task_arg);
rw_exit(&tq->tq_threadlock);
mutex_enter(&tq->tq_lock);
- if (!prealloc)
- task_free(tq, t);
+ task_free(tq, t);
}
tq->tq_nthreads--;
cv_broadcast(&tq->tq_wait_cv);
@@ -252,8 +217,8 @@ taskq_create(const char *name, int nthreads, pri_t pri,
tq->tq_nthreads = nthreads;
tq->tq_minalloc = minalloc;
tq->tq_maxalloc = maxalloc;
- tq->tq_task.tqent_next = &tq->tq_task;
- tq->tq_task.tqent_prev = &tq->tq_task;
+ tq->tq_task.task_next = &tq->tq_task;
+ tq->tq_task.task_prev = &tq->tq_task;
tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP);
if (flags & TASKQ_PREPOPULATE) {