WiP merge of libzfs_core (MFV r238590, r238592)
not yet working, ioctl handling needs to be changed
This commit is contained in:
commit
dce1a726f2
@ -1389,6 +1389,7 @@ _prebuild_libs= ${_kerberos5_lib_libasn1} \
|
|||||||
lib/libopie lib/libpam ${_lib_libthr} \
|
lib/libopie lib/libpam ${_lib_libthr} \
|
||||||
lib/libradius lib/libsbuf lib/libtacplus \
|
lib/libradius lib/libsbuf lib/libtacplus \
|
||||||
${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \
|
${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \
|
||||||
|
${_cddl_lib_libzfs_core} \
|
||||||
lib/libutil ${_lib_libypclnt} lib/libz lib/msun \
|
lib/libutil ${_lib_libypclnt} lib/libz lib/msun \
|
||||||
${_secure_lib_libcrypto} ${_secure_lib_libssh} \
|
${_secure_lib_libcrypto} ${_secure_lib_libssh} \
|
||||||
${_secure_lib_libssl}
|
${_secure_lib_libssl}
|
||||||
@ -1417,6 +1418,7 @@ lib/libopie__L lib/libtacplus__L: lib/libmd__L
|
|||||||
.if ${MK_CDDL} != "no"
|
.if ${MK_CDDL} != "no"
|
||||||
_cddl_lib_libumem= cddl/lib/libumem
|
_cddl_lib_libumem= cddl/lib/libumem
|
||||||
_cddl_lib_libnvpair= cddl/lib/libnvpair
|
_cddl_lib_libnvpair= cddl/lib/libnvpair
|
||||||
|
_cddl_lib_libzfs_core= cddl/lib/libzfs_core
|
||||||
_cddl_lib= cddl/lib
|
_cddl_lib= cddl/lib
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#include <sys/arc.h>
|
#include <sys/arc.h>
|
||||||
#include <sys/ddt.h>
|
#include <sys/ddt.h>
|
||||||
#include <sys/zfeature.h>
|
#include <sys/zfeature.h>
|
||||||
|
#include <zfs_comutil.h>
|
||||||
#undef ZFS_MAXNAMELEN
|
#undef ZFS_MAXNAMELEN
|
||||||
#undef verify
|
#undef verify
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
@ -206,6 +207,27 @@ dump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
|
|||||||
nvlist_free(nv);
|
nvlist_free(nv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
|
static void
|
||||||
|
dump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size)
|
||||||
|
{
|
||||||
|
spa_history_phys_t *shp = data;
|
||||||
|
|
||||||
|
if (shp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
(void) printf("\t\tpool_create_len = %llu\n",
|
||||||
|
(u_longlong_t)shp->sh_pool_create_len);
|
||||||
|
(void) printf("\t\tphys_max_off = %llu\n",
|
||||||
|
(u_longlong_t)shp->sh_phys_max_off);
|
||||||
|
(void) printf("\t\tbof = %llu\n",
|
||||||
|
(u_longlong_t)shp->sh_bof);
|
||||||
|
(void) printf("\t\teof = %llu\n",
|
||||||
|
(u_longlong_t)shp->sh_eof);
|
||||||
|
(void) printf("\t\trecords_lost = %llu\n",
|
||||||
|
(u_longlong_t)shp->sh_records_lost);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zdb_nicenum(uint64_t num, char *buf)
|
zdb_nicenum(uint64_t num, char *buf)
|
||||||
{
|
{
|
||||||
@ -857,21 +879,22 @@ dump_history(spa_t *spa)
|
|||||||
for (int i = 0; i < num; i++) {
|
for (int i = 0; i < num; i++) {
|
||||||
uint64_t time, txg, ievent;
|
uint64_t time, txg, ievent;
|
||||||
char *cmd, *intstr;
|
char *cmd, *intstr;
|
||||||
|
boolean_t printed = B_FALSE;
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME,
|
if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME,
|
||||||
&time) != 0)
|
&time) != 0)
|
||||||
continue;
|
goto next;
|
||||||
if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD,
|
if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD,
|
||||||
&cmd) != 0) {
|
&cmd) != 0) {
|
||||||
if (nvlist_lookup_uint64(events[i],
|
if (nvlist_lookup_uint64(events[i],
|
||||||
ZPOOL_HIST_INT_EVENT, &ievent) != 0)
|
ZPOOL_HIST_INT_EVENT, &ievent) != 0)
|
||||||
continue;
|
goto next;
|
||||||
verify(nvlist_lookup_uint64(events[i],
|
verify(nvlist_lookup_uint64(events[i],
|
||||||
ZPOOL_HIST_TXG, &txg) == 0);
|
ZPOOL_HIST_TXG, &txg) == 0);
|
||||||
verify(nvlist_lookup_string(events[i],
|
verify(nvlist_lookup_string(events[i],
|
||||||
ZPOOL_HIST_INT_STR, &intstr) == 0);
|
ZPOOL_HIST_INT_STR, &intstr) == 0);
|
||||||
if (ievent >= LOG_END)
|
if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS)
|
||||||
continue;
|
goto next;
|
||||||
|
|
||||||
(void) snprintf(internalstr,
|
(void) snprintf(internalstr,
|
||||||
sizeof (internalstr),
|
sizeof (internalstr),
|
||||||
@ -884,6 +907,14 @@ dump_history(spa_t *spa)
|
|||||||
(void) localtime_r(&tsec, &t);
|
(void) localtime_r(&tsec, &t);
|
||||||
(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
|
(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
|
||||||
(void) printf("%s %s\n", tbuf, cmd);
|
(void) printf("%s %s\n", tbuf, cmd);
|
||||||
|
printed = B_TRUE;
|
||||||
|
|
||||||
|
next:
|
||||||
|
if (dump_opt['h'] > 1) {
|
||||||
|
if (!printed)
|
||||||
|
(void) printf("unrecognized record:\n");
|
||||||
|
dump_nvlist(events[i], 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1460,7 +1491,7 @@ static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
|
|||||||
dump_zap, /* other ZAP */
|
dump_zap, /* other ZAP */
|
||||||
dump_zap, /* persistent error log */
|
dump_zap, /* persistent error log */
|
||||||
dump_uint8, /* SPA history */
|
dump_uint8, /* SPA history */
|
||||||
dump_uint64, /* SPA history offsets */
|
dump_history_offsets, /* SPA history offsets */
|
||||||
dump_zap, /* Pool properties */
|
dump_zap, /* Pool properties */
|
||||||
dump_zap, /* DSL permissions */
|
dump_zap, /* DSL permissions */
|
||||||
dump_acl, /* ZFS ACL */
|
dump_acl, /* ZFS ACL */
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
.Op Fl r
|
.Op Fl r
|
||||||
.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ...
|
.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ...
|
||||||
.Ar filesystem@snapname Ns | Ns Ar volume@snapname
|
.Ar filesystem@snapname Ns | Ns Ar volume@snapname
|
||||||
|
.Ar filesystem@snapname Ns | Ns Ar volume@snapname Ns ...
|
||||||
.Nm
|
.Nm
|
||||||
.Cm rollback
|
.Cm rollback
|
||||||
.Op Fl rRf
|
.Op Fl rRf
|
||||||
@ -1645,17 +1646,18 @@ behavior for mounted file systems in use.
|
|||||||
.Op Fl r
|
.Op Fl r
|
||||||
.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ...
|
.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ...
|
||||||
.Ar filesystem@snapname Ns | Ns volume@snapname
|
.Ar filesystem@snapname Ns | Ns volume@snapname
|
||||||
|
.Ar filesystem@snapname Ns | Ns volume@snapname Ns ...
|
||||||
.Xc
|
.Xc
|
||||||
.Pp
|
.Pp
|
||||||
Creates a snapshot with the given name. All previous modifications by
|
Creates snapshots with the given names. All previous modifications by
|
||||||
successful system calls to the file system are part of the snapshot. See the
|
successful system calls to the file system are part of the snapshots.
|
||||||
|
Snapshots are taken atomically, so that all snapshots correspond to the same
|
||||||
|
moment in time. See the
|
||||||
.Qq Sx Snapshots
|
.Qq Sx Snapshots
|
||||||
section for details.
|
section for details.
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Fl r
|
.It Fl r
|
||||||
Recursively create snapshots of all descendent datasets. Snapshots are taken
|
Recursively create snapshots of all descendent datasets
|
||||||
atomically, so that all recursive snapshots correspond to the same moment in
|
|
||||||
time.
|
|
||||||
.It Fl o Ar property Ns = Ns Ar value
|
.It Fl o Ar property Ns = Ns Ar value
|
||||||
Sets the specified property; see
|
Sets the specified property; see
|
||||||
.Qq Nm Cm create
|
.Qq Nm Cm create
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
|
#include <libzfs_core.h>
|
||||||
#include <zfs_prop.h>
|
#include <zfs_prop.h>
|
||||||
#include <zfs_deleg.h>
|
#include <zfs_deleg.h>
|
||||||
#include <libuutil.h>
|
#include <libuutil.h>
|
||||||
@ -74,6 +75,7 @@ libzfs_handle_t *g_zfs;
|
|||||||
|
|
||||||
static FILE *mnttab_file;
|
static FILE *mnttab_file;
|
||||||
static char history_str[HIS_MAX_RECORD_LEN];
|
static char history_str[HIS_MAX_RECORD_LEN];
|
||||||
|
static boolean_t log_history = B_TRUE;
|
||||||
|
|
||||||
static int zfs_do_clone(int argc, char **argv);
|
static int zfs_do_clone(int argc, char **argv);
|
||||||
static int zfs_do_create(int argc, char **argv);
|
static int zfs_do_create(int argc, char **argv);
|
||||||
@ -276,7 +278,7 @@ get_usage(zfs_help_t idx)
|
|||||||
return (gettext("\tshare <-a | filesystem>\n"));
|
return (gettext("\tshare <-a | filesystem>\n"));
|
||||||
case HELP_SNAPSHOT:
|
case HELP_SNAPSHOT:
|
||||||
return (gettext("\tsnapshot [-r] [-o property=value] ... "
|
return (gettext("\tsnapshot [-r] [-o property=value] ... "
|
||||||
"<filesystem@snapname|volume@snapname>\n"));
|
"<filesystem@snapname|volume@snapname> ...\n"));
|
||||||
case HELP_UNMOUNT:
|
case HELP_UNMOUNT:
|
||||||
return (gettext("\tunmount [-f] "
|
return (gettext("\tunmount [-f] "
|
||||||
"<-a | filesystem|mountpoint>\n"));
|
"<-a | filesystem|mountpoint>\n"));
|
||||||
@ -916,9 +918,9 @@ typedef struct destroy_cbdata {
|
|||||||
nvlist_t *cb_nvl;
|
nvlist_t *cb_nvl;
|
||||||
|
|
||||||
/* first snap in contiguous run */
|
/* first snap in contiguous run */
|
||||||
zfs_handle_t *cb_firstsnap;
|
char *cb_firstsnap;
|
||||||
/* previous snap in contiguous run */
|
/* previous snap in contiguous run */
|
||||||
zfs_handle_t *cb_prevsnap;
|
char *cb_prevsnap;
|
||||||
int64_t cb_snapused;
|
int64_t cb_snapused;
|
||||||
char *cb_snapspec;
|
char *cb_snapspec;
|
||||||
} destroy_cbdata_t;
|
} destroy_cbdata_t;
|
||||||
@ -1032,11 +1034,13 @@ destroy_print_cb(zfs_handle_t *zhp, void *arg)
|
|||||||
|
|
||||||
if (nvlist_exists(cb->cb_nvl, name)) {
|
if (nvlist_exists(cb->cb_nvl, name)) {
|
||||||
if (cb->cb_firstsnap == NULL)
|
if (cb->cb_firstsnap == NULL)
|
||||||
cb->cb_firstsnap = zfs_handle_dup(zhp);
|
cb->cb_firstsnap = strdup(name);
|
||||||
if (cb->cb_prevsnap != NULL)
|
if (cb->cb_prevsnap != NULL)
|
||||||
zfs_close(cb->cb_prevsnap);
|
free(cb->cb_prevsnap);
|
||||||
/* this snap continues the current range */
|
/* this snap continues the current range */
|
||||||
cb->cb_prevsnap = zfs_handle_dup(zhp);
|
cb->cb_prevsnap = strdup(name);
|
||||||
|
if (cb->cb_firstsnap == NULL || cb->cb_prevsnap == NULL)
|
||||||
|
nomem();
|
||||||
if (cb->cb_verbose) {
|
if (cb->cb_verbose) {
|
||||||
if (cb->cb_parsable) {
|
if (cb->cb_parsable) {
|
||||||
(void) printf("destroy\t%s\n", name);
|
(void) printf("destroy\t%s\n", name);
|
||||||
@ -1051,12 +1055,12 @@ destroy_print_cb(zfs_handle_t *zhp, void *arg)
|
|||||||
} else if (cb->cb_firstsnap != NULL) {
|
} else if (cb->cb_firstsnap != NULL) {
|
||||||
/* end of this range */
|
/* end of this range */
|
||||||
uint64_t used = 0;
|
uint64_t used = 0;
|
||||||
err = zfs_get_snapused_int(cb->cb_firstsnap,
|
err = lzc_snaprange_space(cb->cb_firstsnap,
|
||||||
cb->cb_prevsnap, &used);
|
cb->cb_prevsnap, &used);
|
||||||
cb->cb_snapused += used;
|
cb->cb_snapused += used;
|
||||||
zfs_close(cb->cb_firstsnap);
|
free(cb->cb_firstsnap);
|
||||||
cb->cb_firstsnap = NULL;
|
cb->cb_firstsnap = NULL;
|
||||||
zfs_close(cb->cb_prevsnap);
|
free(cb->cb_prevsnap);
|
||||||
cb->cb_prevsnap = NULL;
|
cb->cb_prevsnap = NULL;
|
||||||
}
|
}
|
||||||
zfs_close(zhp);
|
zfs_close(zhp);
|
||||||
@ -1073,13 +1077,13 @@ destroy_print_snapshots(zfs_handle_t *fs_zhp, destroy_cbdata_t *cb)
|
|||||||
if (cb->cb_firstsnap != NULL) {
|
if (cb->cb_firstsnap != NULL) {
|
||||||
uint64_t used = 0;
|
uint64_t used = 0;
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
err = zfs_get_snapused_int(cb->cb_firstsnap,
|
err = lzc_snaprange_space(cb->cb_firstsnap,
|
||||||
cb->cb_prevsnap, &used);
|
cb->cb_prevsnap, &used);
|
||||||
}
|
}
|
||||||
cb->cb_snapused += used;
|
cb->cb_snapused += used;
|
||||||
zfs_close(cb->cb_firstsnap);
|
free(cb->cb_firstsnap);
|
||||||
cb->cb_firstsnap = NULL;
|
cb->cb_firstsnap = NULL;
|
||||||
zfs_close(cb->cb_prevsnap);
|
free(cb->cb_prevsnap);
|
||||||
cb->cb_prevsnap = NULL;
|
cb->cb_prevsnap = NULL;
|
||||||
}
|
}
|
||||||
return (err);
|
return (err);
|
||||||
@ -1932,9 +1936,11 @@ upgrade_set_callback(zfs_handle_t *zhp, void *data)
|
|||||||
/*
|
/*
|
||||||
* If they did "zfs upgrade -a", then we could
|
* If they did "zfs upgrade -a", then we could
|
||||||
* be doing ioctls to different pools. We need
|
* be doing ioctls to different pools. We need
|
||||||
* to log this history once to each pool.
|
* to log this history once to each pool, and bypass
|
||||||
|
* the normal history logging that happens in main().
|
||||||
*/
|
*/
|
||||||
verify(zpool_stage_history(g_zfs, history_str) == 0);
|
(void) zpool_log_history(g_zfs, history_str);
|
||||||
|
log_history = B_FALSE;
|
||||||
}
|
}
|
||||||
if (zfs_prop_set(zhp, "version", verstr) == 0)
|
if (zfs_prop_set(zhp, "version", verstr) == 0)
|
||||||
cb->cb_numupgraded++;
|
cb->cb_numupgraded++;
|
||||||
@ -3472,6 +3478,32 @@ zfs_do_set(int argc, char **argv)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct snap_cbdata {
|
||||||
|
nvlist_t *sd_nvl;
|
||||||
|
boolean_t sd_recursive;
|
||||||
|
const char *sd_snapname;
|
||||||
|
} snap_cbdata_t;
|
||||||
|
|
||||||
|
static int
|
||||||
|
zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
|
||||||
|
{
|
||||||
|
snap_cbdata_t *sd = arg;
|
||||||
|
char *name;
|
||||||
|
int rv = 0;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = asprintf(&name, "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
|
||||||
|
if (error == -1)
|
||||||
|
nomem();
|
||||||
|
fnvlist_add_boolean(sd->sd_nvl, name);
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
if (sd->sd_recursive)
|
||||||
|
rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
|
||||||
|
zfs_close(zhp);
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* zfs snapshot [-r] [-o prop=value] ... <fs@snap>
|
* zfs snapshot [-r] [-o prop=value] ... <fs@snap>
|
||||||
*
|
*
|
||||||
@ -3481,13 +3513,16 @@ zfs_do_set(int argc, char **argv)
|
|||||||
static int
|
static int
|
||||||
zfs_do_snapshot(int argc, char **argv)
|
zfs_do_snapshot(int argc, char **argv)
|
||||||
{
|
{
|
||||||
boolean_t recursive = B_FALSE;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char c;
|
char c;
|
||||||
nvlist_t *props;
|
nvlist_t *props;
|
||||||
|
snap_cbdata_t sd = { 0 };
|
||||||
|
boolean_t multiple_snaps = B_FALSE;
|
||||||
|
|
||||||
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
|
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
|
||||||
nomem();
|
nomem();
|
||||||
|
if (nvlist_alloc(&sd.sd_nvl, NV_UNIQUE_NAME, 0) != 0)
|
||||||
|
nomem();
|
||||||
|
|
||||||
/* check options */
|
/* check options */
|
||||||
while ((c = getopt(argc, argv, "ro:")) != -1) {
|
while ((c = getopt(argc, argv, "ro:")) != -1) {
|
||||||
@ -3497,7 +3532,8 @@ zfs_do_snapshot(int argc, char **argv)
|
|||||||
return (1);
|
return (1);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
recursive = B_TRUE;
|
sd.sd_recursive = B_TRUE;
|
||||||
|
multiple_snaps = B_TRUE;
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
||||||
@ -3514,18 +3550,35 @@ zfs_do_snapshot(int argc, char **argv)
|
|||||||
(void) fprintf(stderr, gettext("missing snapshot argument\n"));
|
(void) fprintf(stderr, gettext("missing snapshot argument\n"));
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
if (argc > 1) {
|
|
||||||
(void) fprintf(stderr, gettext("too many arguments\n"));
|
if (argc > 1)
|
||||||
goto usage;
|
multiple_snaps = B_TRUE;
|
||||||
|
for (; argc > 0; argc--, argv++) {
|
||||||
|
char *atp;
|
||||||
|
zfs_handle_t *zhp;
|
||||||
|
|
||||||
|
atp = strchr(argv[0], '@');
|
||||||
|
if (atp == NULL)
|
||||||
|
goto usage;
|
||||||
|
*atp = '\0';
|
||||||
|
sd.sd_snapname = atp + 1;
|
||||||
|
zhp = zfs_open(g_zfs, argv[0],
|
||||||
|
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
|
||||||
|
if (zhp == NULL)
|
||||||
|
goto usage;
|
||||||
|
if (zfs_snapshot_cb(zhp, &sd) != 0)
|
||||||
|
goto usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = zfs_snapshot(g_zfs, argv[0], recursive, props);
|
ret = zfs_snapshot_nvl(g_zfs, sd.sd_nvl, props);
|
||||||
|
nvlist_free(sd.sd_nvl);
|
||||||
nvlist_free(props);
|
nvlist_free(props);
|
||||||
if (ret && recursive)
|
if (ret != 0 && multiple_snaps)
|
||||||
(void) fprintf(stderr, gettext("no snapshots were created\n"));
|
(void) fprintf(stderr, gettext("no snapshots were created\n"));
|
||||||
return (ret != 0);
|
return (ret != 0);
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
|
nvlist_free(sd.sd_nvl);
|
||||||
nvlist_free(props);
|
nvlist_free(props);
|
||||||
usage(B_FALSE);
|
usage(B_FALSE);
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -6602,8 +6655,7 @@ main(int argc, char **argv)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
zpool_set_history_str("zfs", argc, argv, history_str);
|
zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
|
||||||
verify(zpool_stage_history(g_zfs, history_str) == 0);
|
|
||||||
|
|
||||||
libzfs_print_on_error(g_zfs, B_TRUE);
|
libzfs_print_on_error(g_zfs, B_TRUE);
|
||||||
|
|
||||||
@ -6672,6 +6724,9 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
(void) fclose(mnttab_file);
|
(void) fclose(mnttab_file);
|
||||||
|
|
||||||
|
if (ret == 0 && log_history)
|
||||||
|
(void) zpool_log_history(g_zfs, history_str);
|
||||||
|
|
||||||
libzfs_fini(g_zfs);
|
libzfs_fini(g_zfs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -279,6 +279,9 @@ feature_enable_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
zfeature_info_t *feature = arg2;
|
zfeature_info_t *feature = arg2;
|
||||||
|
|
||||||
spa_feature_enable(spa, feature, tx);
|
spa_feature_enable(spa, feature, tx);
|
||||||
|
spa_history_log_internal(spa, "zhack enable feature", tx,
|
||||||
|
"name=%s can_readonly=%u",
|
||||||
|
feature->fi_guid, feature->fi_can_readonly);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -356,6 +359,8 @@ feature_incr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
zfeature_info_t *feature = arg2;
|
zfeature_info_t *feature = arg2;
|
||||||
|
|
||||||
spa_feature_incr(spa, feature, tx);
|
spa_feature_incr(spa, feature, tx);
|
||||||
|
spa_history_log_internal(spa, "zhack feature incr", tx,
|
||||||
|
"name=%s", feature->fi_guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -365,6 +370,8 @@ feature_decr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
zfeature_info_t *feature = arg2;
|
zfeature_info_t *feature = arg2;
|
||||||
|
|
||||||
spa_feature_decr(spa, feature, tx);
|
spa_feature_decr(spa, feature, tx);
|
||||||
|
spa_history_log_internal(spa, "zhack feature decr", tx,
|
||||||
|
"name=%s", feature->fi_guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -192,9 +192,9 @@ static zpool_command_t command_table[] = {
|
|||||||
|
|
||||||
#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
|
#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
|
||||||
|
|
||||||
zpool_command_t *current_command;
|
static zpool_command_t *current_command;
|
||||||
static char history_str[HIS_MAX_RECORD_LEN];
|
static char history_str[HIS_MAX_RECORD_LEN];
|
||||||
|
static boolean_t log_history = B_TRUE;
|
||||||
static uint_t timestamp_fmt = NODATE;
|
static uint_t timestamp_fmt = NODATE;
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
@ -1093,7 +1093,10 @@ zpool_do_destroy(int argc, char **argv)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (zpool_destroy(zhp) != 0);
|
/* The history must be logged as part of the export */
|
||||||
|
log_history = B_FALSE;
|
||||||
|
|
||||||
|
ret = (zpool_destroy(zhp, history_str) != 0);
|
||||||
|
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
|
|
||||||
@ -1157,10 +1160,13 @@ zpool_do_export(int argc, char **argv)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The history must be logged as part of the export */
|
||||||
|
log_history = B_FALSE;
|
||||||
|
|
||||||
if (hardforce) {
|
if (hardforce) {
|
||||||
if (zpool_export_force(zhp) != 0)
|
if (zpool_export_force(zhp, history_str) != 0)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else if (zpool_export(zhp, force) != 0) {
|
} else if (zpool_export(zhp, force, history_str) != 0) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4560,6 +4566,14 @@ upgrade_cb(zpool_handle_t *zhp, void *arg)
|
|||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
cbp->cb_first = B_FALSE;
|
cbp->cb_first = B_FALSE;
|
||||||
printnl = B_TRUE;
|
printnl = B_TRUE;
|
||||||
|
/*
|
||||||
|
* If they did "zpool upgrade -a", then we could
|
||||||
|
* be doing ioctls to different pools. We need
|
||||||
|
* to log this history once to each pool, and bypass
|
||||||
|
* the normal history logging that happens in main().
|
||||||
|
*/
|
||||||
|
(void) zpool_log_history(g_zfs, history_str);
|
||||||
|
log_history = B_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4921,8 +4935,8 @@ zpool_do_upgrade(int argc, char **argv)
|
|||||||
|
|
||||||
typedef struct hist_cbdata {
|
typedef struct hist_cbdata {
|
||||||
boolean_t first;
|
boolean_t first;
|
||||||
int longfmt;
|
boolean_t longfmt;
|
||||||
int internal;
|
boolean_t internal;
|
||||||
} hist_cbdata_t;
|
} hist_cbdata_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4934,21 +4948,8 @@ get_history_one(zpool_handle_t *zhp, void *data)
|
|||||||
nvlist_t *nvhis;
|
nvlist_t *nvhis;
|
||||||
nvlist_t **records;
|
nvlist_t **records;
|
||||||
uint_t numrecords;
|
uint_t numrecords;
|
||||||
char *cmdstr;
|
|
||||||
char *pathstr;
|
|
||||||
uint64_t dst_time;
|
|
||||||
time_t tsec;
|
|
||||||
struct tm t;
|
|
||||||
char tbuf[30];
|
|
||||||
int ret, i;
|
int ret, i;
|
||||||
uint64_t who;
|
|
||||||
struct passwd *pwd;
|
|
||||||
char *hostname;
|
|
||||||
char *zonename;
|
|
||||||
char internalstr[MAXPATHLEN];
|
|
||||||
hist_cbdata_t *cb = (hist_cbdata_t *)data;
|
hist_cbdata_t *cb = (hist_cbdata_t *)data;
|
||||||
uint64_t txg;
|
|
||||||
uint64_t ievent;
|
|
||||||
|
|
||||||
cb->first = B_FALSE;
|
cb->first = B_FALSE;
|
||||||
|
|
||||||
@ -4960,64 +4961,94 @@ get_history_one(zpool_handle_t *zhp, void *data)
|
|||||||
verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
|
verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
|
||||||
&records, &numrecords) == 0);
|
&records, &numrecords) == 0);
|
||||||
for (i = 0; i < numrecords; i++) {
|
for (i = 0; i < numrecords; i++) {
|
||||||
if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
|
nvlist_t *rec = records[i];
|
||||||
&dst_time) != 0)
|
char tbuf[30] = "";
|
||||||
continue;
|
|
||||||
|
|
||||||
/* is it an internal event or a standard event? */
|
if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
|
||||||
if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
|
time_t tsec;
|
||||||
&cmdstr) != 0) {
|
struct tm t;
|
||||||
if (cb->internal == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(records[i],
|
tsec = fnvlist_lookup_uint64(records[i],
|
||||||
ZPOOL_HIST_INT_EVENT, &ievent) != 0)
|
ZPOOL_HIST_TIME);
|
||||||
continue;
|
(void) localtime_r(&tsec, &t);
|
||||||
verify(nvlist_lookup_uint64(records[i],
|
(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
|
||||||
ZPOOL_HIST_TXG, &txg) == 0);
|
}
|
||||||
verify(nvlist_lookup_string(records[i],
|
|
||||||
ZPOOL_HIST_INT_STR, &pathstr) == 0);
|
if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
|
||||||
if (ievent >= LOG_END)
|
(void) printf("%s %s", tbuf,
|
||||||
continue;
|
fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
|
||||||
(void) snprintf(internalstr,
|
} else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
|
||||||
sizeof (internalstr),
|
int ievent =
|
||||||
"[internal %s txg:%lld] %s",
|
fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
|
||||||
zfs_history_event_names[ievent], txg,
|
if (!cb->internal)
|
||||||
pathstr);
|
continue;
|
||||||
cmdstr = internalstr;
|
if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
|
||||||
|
(void) printf("%s unrecognized record:\n",
|
||||||
|
tbuf);
|
||||||
|
dump_nvlist(rec, 4);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(void) printf("%s [internal %s txg:%lld] %s", tbuf,
|
||||||
|
zfs_history_event_names[ievent],
|
||||||
|
fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
|
||||||
|
fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
|
||||||
|
} else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
|
||||||
|
if (!cb->internal)
|
||||||
|
continue;
|
||||||
|
(void) printf("%s [txg:%lld] %s", tbuf,
|
||||||
|
fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
|
||||||
|
fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
|
||||||
|
if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
|
||||||
|
(void) printf(" %s (%llu)",
|
||||||
|
fnvlist_lookup_string(rec,
|
||||||
|
ZPOOL_HIST_DSNAME),
|
||||||
|
fnvlist_lookup_uint64(rec,
|
||||||
|
ZPOOL_HIST_DSID));
|
||||||
|
}
|
||||||
|
(void) printf(" %s", fnvlist_lookup_string(rec,
|
||||||
|
ZPOOL_HIST_INT_STR));
|
||||||
|
} else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
|
||||||
|
if (!cb->internal)
|
||||||
|
continue;
|
||||||
|
(void) printf("%s ioctl %s\n", tbuf,
|
||||||
|
fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
|
||||||
|
if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
|
||||||
|
(void) printf(" input:\n");
|
||||||
|
dump_nvlist(fnvlist_lookup_nvlist(rec,
|
||||||
|
ZPOOL_HIST_INPUT_NVL), 8);
|
||||||
|
}
|
||||||
|
if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
|
||||||
|
(void) printf(" output:\n");
|
||||||
|
dump_nvlist(fnvlist_lookup_nvlist(rec,
|
||||||
|
ZPOOL_HIST_OUTPUT_NVL), 8);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!cb->internal)
|
||||||
|
continue;
|
||||||
|
(void) printf("%s unrecognized record:\n", tbuf);
|
||||||
|
dump_nvlist(rec, 4);
|
||||||
}
|
}
|
||||||
tsec = dst_time;
|
|
||||||
(void) localtime_r(&tsec, &t);
|
|
||||||
(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
|
|
||||||
(void) printf("%s %s", tbuf, cmdstr);
|
|
||||||
|
|
||||||
if (!cb->longfmt) {
|
if (!cb->longfmt) {
|
||||||
(void) printf("\n");
|
(void) printf("\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(void) printf(" [");
|
(void) printf(" [");
|
||||||
if (nvlist_lookup_uint64(records[i],
|
if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
|
||||||
ZPOOL_HIST_WHO, &who) == 0) {
|
uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
|
||||||
pwd = getpwuid((uid_t)who);
|
struct passwd *pwd = getpwuid(who);
|
||||||
if (pwd)
|
(void) printf("user %d ", (int)who);
|
||||||
(void) printf("user %s on",
|
if (pwd != NULL)
|
||||||
pwd->pw_name);
|
(void) printf("(%s) ", pwd->pw_name);
|
||||||
else
|
|
||||||
(void) printf("user %d on",
|
|
||||||
(int)who);
|
|
||||||
} else {
|
|
||||||
(void) printf(gettext("no info]\n"));
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (nvlist_lookup_string(records[i],
|
if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
|
||||||
ZPOOL_HIST_HOST, &hostname) == 0) {
|
(void) printf("on %s",
|
||||||
(void) printf(" %s", hostname);
|
fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
|
||||||
}
|
}
|
||||||
if (nvlist_lookup_string(records[i],
|
if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
|
||||||
ZPOOL_HIST_ZONE, &zonename) == 0) {
|
(void) printf(":%s",
|
||||||
(void) printf(":%s", zonename);
|
fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) printf("]");
|
(void) printf("]");
|
||||||
(void) printf("\n");
|
(void) printf("\n");
|
||||||
}
|
}
|
||||||
@ -5032,8 +5063,6 @@ get_history_one(zpool_handle_t *zhp, void *data)
|
|||||||
*
|
*
|
||||||
* Displays the history of commands that modified pools.
|
* Displays the history of commands that modified pools.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
zpool_do_history(int argc, char **argv)
|
zpool_do_history(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -5046,10 +5075,10 @@ zpool_do_history(int argc, char **argv)
|
|||||||
while ((c = getopt(argc, argv, "li")) != -1) {
|
while ((c = getopt(argc, argv, "li")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'l':
|
case 'l':
|
||||||
cbdata.longfmt = 1;
|
cbdata.longfmt = B_TRUE;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
cbdata.internal = 1;
|
cbdata.internal = B_TRUE;
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
||||||
@ -5274,8 +5303,7 @@ main(int argc, char **argv)
|
|||||||
if (strcmp(cmdname, "-?") == 0)
|
if (strcmp(cmdname, "-?") == 0)
|
||||||
usage(B_TRUE);
|
usage(B_TRUE);
|
||||||
|
|
||||||
zpool_set_history_str("zpool", argc, argv, history_str);
|
zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
|
||||||
verify(zpool_stage_history(g_zfs, history_str) == 0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run the appropriate command.
|
* Run the appropriate command.
|
||||||
@ -5302,6 +5330,9 @@ main(int argc, char **argv)
|
|||||||
usage(B_FALSE);
|
usage(B_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == 0 && log_history)
|
||||||
|
(void) zpool_log_history(g_zfs, history_str);
|
||||||
|
|
||||||
libzfs_fini(g_zfs);
|
libzfs_fini(g_zfs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2332,7 +2332,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
|
|||||||
*/
|
*/
|
||||||
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 0, 1);
|
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 0, 1);
|
||||||
VERIFY3U(ENOENT, ==,
|
VERIFY3U(ENOENT, ==,
|
||||||
spa_create("ztest_bad_file", nvroot, NULL, NULL, NULL));
|
spa_create("ztest_bad_file", nvroot, NULL, NULL));
|
||||||
nvlist_free(nvroot);
|
nvlist_free(nvroot);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2340,7 +2340,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
|
|||||||
*/
|
*/
|
||||||
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 2, 1);
|
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 2, 1);
|
||||||
VERIFY3U(ENOENT, ==,
|
VERIFY3U(ENOENT, ==,
|
||||||
spa_create("ztest_bad_mirror", nvroot, NULL, NULL, NULL));
|
spa_create("ztest_bad_mirror", nvroot, NULL, NULL));
|
||||||
nvlist_free(nvroot);
|
nvlist_free(nvroot);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2349,7 +2349,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
|
|||||||
*/
|
*/
|
||||||
(void) rw_rdlock(&ztest_name_lock);
|
(void) rw_rdlock(&ztest_name_lock);
|
||||||
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 0, 1);
|
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 0, 1);
|
||||||
VERIFY3U(EEXIST, ==, spa_create(zo->zo_pool, nvroot, NULL, NULL, NULL));
|
VERIFY3U(EEXIST, ==, spa_create(zo->zo_pool, nvroot, NULL, NULL));
|
||||||
nvlist_free(nvroot);
|
nvlist_free(nvroot);
|
||||||
VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG));
|
VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG));
|
||||||
VERIFY3U(EBUSY, ==, spa_destroy(zo->zo_pool));
|
VERIFY3U(EBUSY, ==, spa_destroy(zo->zo_pool));
|
||||||
@ -2407,7 +2407,7 @@ ztest_spa_upgrade(ztest_ds_t *zd, uint64_t id)
|
|||||||
props = fnvlist_alloc();
|
props = fnvlist_alloc();
|
||||||
fnvlist_add_uint64(props,
|
fnvlist_add_uint64(props,
|
||||||
zpool_prop_to_name(ZPOOL_PROP_VERSION), version);
|
zpool_prop_to_name(ZPOOL_PROP_VERSION), version);
|
||||||
VERIFY0(spa_create(name, nvroot, props, NULL, NULL));
|
VERIFY0(spa_create(name, nvroot, props, NULL));
|
||||||
fnvlist_free(nvroot);
|
fnvlist_free(nvroot);
|
||||||
fnvlist_free(props);
|
fnvlist_free(props);
|
||||||
|
|
||||||
@ -3208,8 +3208,7 @@ ztest_snapshot_create(char *osname, uint64_t id)
|
|||||||
(void) snprintf(snapname, MAXNAMELEN, "%s@%llu", osname,
|
(void) snprintf(snapname, MAXNAMELEN, "%s@%llu", osname,
|
||||||
(u_longlong_t)id);
|
(u_longlong_t)id);
|
||||||
|
|
||||||
error = dmu_objset_snapshot(osname, strchr(snapname, '@') + 1,
|
error = dmu_objset_snapshot_one(osname, strchr(snapname, '@') + 1);
|
||||||
NULL, NULL, B_FALSE, B_FALSE, -1);
|
|
||||||
if (error == ENOSPC) {
|
if (error == ENOSPC) {
|
||||||
ztest_record_enospc(FTAG);
|
ztest_record_enospc(FTAG);
|
||||||
return (B_FALSE);
|
return (B_FALSE);
|
||||||
@ -3409,8 +3408,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
|
|||||||
(void) snprintf(clone2name, MAXNAMELEN, "%s/c2_%llu", osname, id);
|
(void) snprintf(clone2name, MAXNAMELEN, "%s/c2_%llu", osname, id);
|
||||||
(void) snprintf(snap3name, MAXNAMELEN, "%s@s3_%llu", clone1name, id);
|
(void) snprintf(snap3name, MAXNAMELEN, "%s@s3_%llu", clone1name, id);
|
||||||
|
|
||||||
error = dmu_objset_snapshot(osname, strchr(snap1name, '@')+1,
|
error = dmu_objset_snapshot_one(osname, strchr(snap1name, '@') + 1);
|
||||||
NULL, NULL, B_FALSE, B_FALSE, -1);
|
|
||||||
if (error && error != EEXIST) {
|
if (error && error != EEXIST) {
|
||||||
if (error == ENOSPC) {
|
if (error == ENOSPC) {
|
||||||
ztest_record_enospc(FTAG);
|
ztest_record_enospc(FTAG);
|
||||||
@ -3433,8 +3431,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
|
|||||||
fatal(0, "dmu_objset_create(%s) = %d", clone1name, error);
|
fatal(0, "dmu_objset_create(%s) = %d", clone1name, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = dmu_objset_snapshot(clone1name, strchr(snap2name, '@')+1,
|
error = dmu_objset_snapshot_one(clone1name, strchr(snap2name, '@') + 1);
|
||||||
NULL, NULL, B_FALSE, B_FALSE, -1);
|
|
||||||
if (error && error != EEXIST) {
|
if (error && error != EEXIST) {
|
||||||
if (error == ENOSPC) {
|
if (error == ENOSPC) {
|
||||||
ztest_record_enospc(FTAG);
|
ztest_record_enospc(FTAG);
|
||||||
@ -3443,8 +3440,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
|
|||||||
fatal(0, "dmu_open_snapshot(%s) = %d", snap2name, error);
|
fatal(0, "dmu_open_snapshot(%s) = %d", snap2name, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = dmu_objset_snapshot(clone1name, strchr(snap3name, '@')+1,
|
error = dmu_objset_snapshot_one(clone1name, strchr(snap3name, '@') + 1);
|
||||||
NULL, NULL, B_FALSE, B_FALSE, -1);
|
|
||||||
if (error && error != EEXIST) {
|
if (error && error != EEXIST) {
|
||||||
if (error == ENOSPC) {
|
if (error == ENOSPC) {
|
||||||
ztest_record_enospc(FTAG);
|
ztest_record_enospc(FTAG);
|
||||||
@ -4632,8 +4628,7 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
|
|||||||
* Create snapshot, clone it, mark snap for deferred destroy,
|
* Create snapshot, clone it, mark snap for deferred destroy,
|
||||||
* destroy clone, verify snap was also destroyed.
|
* destroy clone, verify snap was also destroyed.
|
||||||
*/
|
*/
|
||||||
error = dmu_objset_snapshot(osname, snapname, NULL, NULL, FALSE,
|
error = dmu_objset_snapshot_one(osname, snapname);
|
||||||
FALSE, -1);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error == ENOSPC) {
|
if (error == ENOSPC) {
|
||||||
ztest_record_enospc("dmu_objset_snapshot");
|
ztest_record_enospc("dmu_objset_snapshot");
|
||||||
@ -4675,8 +4670,7 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
|
|||||||
* destroy a held snapshot, mark for deferred destroy,
|
* destroy a held snapshot, mark for deferred destroy,
|
||||||
* release hold, verify snapshot was destroyed.
|
* release hold, verify snapshot was destroyed.
|
||||||
*/
|
*/
|
||||||
error = dmu_objset_snapshot(osname, snapname, NULL, NULL, FALSE,
|
error = dmu_objset_snapshot_one(osname, snapname);
|
||||||
FALSE, -1);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error == ENOSPC) {
|
if (error == ENOSPC) {
|
||||||
ztest_record_enospc("dmu_objset_snapshot");
|
ztest_record_enospc("dmu_objset_snapshot");
|
||||||
@ -5791,8 +5785,7 @@ ztest_init(ztest_shared_t *zs)
|
|||||||
spa_feature_table[i].fi_uname);
|
spa_feature_table[i].fi_uname);
|
||||||
VERIFY3U(0, ==, nvlist_add_uint64(props, buf, 0));
|
VERIFY3U(0, ==, nvlist_add_uint64(props, buf, 0));
|
||||||
}
|
}
|
||||||
VERIFY3U(0, ==, spa_create(ztest_opts.zo_pool, nvroot, props,
|
VERIFY3U(0, ==, spa_create(ztest_opts.zo_pool, nvroot, props, NULL));
|
||||||
NULL, NULL));
|
|
||||||
nvlist_free(nvroot);
|
nvlist_free(nvroot);
|
||||||
|
|
||||||
VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG));
|
VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG));
|
||||||
|
@ -57,7 +57,8 @@ extern "C" {
|
|||||||
/*
|
/*
|
||||||
* libzfs errors
|
* libzfs errors
|
||||||
*/
|
*/
|
||||||
enum {
|
typedef enum zfs_error {
|
||||||
|
EZFS_SUCCESS = 0, /* no error -- success */
|
||||||
EZFS_NOMEM = 2000, /* out of memory */
|
EZFS_NOMEM = 2000, /* out of memory */
|
||||||
EZFS_BADPROP, /* invalid property value */
|
EZFS_BADPROP, /* invalid property value */
|
||||||
EZFS_PROPREADONLY, /* cannot set readonly property */
|
EZFS_PROPREADONLY, /* cannot set readonly property */
|
||||||
@ -129,7 +130,7 @@ enum {
|
|||||||
EZFS_DIFFDATA, /* bad zfs diff data */
|
EZFS_DIFFDATA, /* bad zfs diff data */
|
||||||
EZFS_POOLREADONLY, /* pool is in read-only mode */
|
EZFS_POOLREADONLY, /* pool is in read-only mode */
|
||||||
EZFS_UNKNOWN
|
EZFS_UNKNOWN
|
||||||
};
|
} zfs_error_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following data structures are all part
|
* The following data structures are all part
|
||||||
@ -185,6 +186,9 @@ extern libzfs_handle_t *zfs_get_handle(zfs_handle_t *);
|
|||||||
|
|
||||||
extern void libzfs_print_on_error(libzfs_handle_t *, boolean_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 int libzfs_errno(libzfs_handle_t *);
|
||||||
extern const char *libzfs_error_action(libzfs_handle_t *);
|
extern const char *libzfs_error_action(libzfs_handle_t *);
|
||||||
extern const char *libzfs_error_description(libzfs_handle_t *);
|
extern const char *libzfs_error_description(libzfs_handle_t *);
|
||||||
@ -220,7 +224,7 @@ extern int zpool_iter(libzfs_handle_t *, zpool_iter_f, void *);
|
|||||||
*/
|
*/
|
||||||
extern int zpool_create(libzfs_handle_t *, const char *, nvlist_t *,
|
extern int zpool_create(libzfs_handle_t *, const char *, nvlist_t *,
|
||||||
nvlist_t *, nvlist_t *);
|
nvlist_t *, nvlist_t *);
|
||||||
extern int zpool_destroy(zpool_handle_t *);
|
extern int zpool_destroy(zpool_handle_t *, const char *);
|
||||||
extern int zpool_add(zpool_handle_t *, nvlist_t *);
|
extern int zpool_add(zpool_handle_t *, nvlist_t *);
|
||||||
|
|
||||||
typedef struct splitflags {
|
typedef struct splitflags {
|
||||||
@ -343,8 +347,8 @@ extern int zpool_get_errlog(zpool_handle_t *, nvlist_t **);
|
|||||||
/*
|
/*
|
||||||
* Import and export functions
|
* Import and export functions
|
||||||
*/
|
*/
|
||||||
extern int zpool_export(zpool_handle_t *, boolean_t);
|
extern int zpool_export(zpool_handle_t *, boolean_t, const char *);
|
||||||
extern int zpool_export_force(zpool_handle_t *);
|
extern int zpool_export_force(zpool_handle_t *, const char *);
|
||||||
extern int zpool_import(libzfs_handle_t *, nvlist_t *, const char *,
|
extern int zpool_import(libzfs_handle_t *, nvlist_t *, const char *,
|
||||||
char *altroot);
|
char *altroot);
|
||||||
extern int zpool_import_props(libzfs_handle_t *, nvlist_t *, const char *,
|
extern int zpool_import_props(libzfs_handle_t *, nvlist_t *, const char *,
|
||||||
@ -378,7 +382,7 @@ extern nvlist_t *zpool_find_import_cached(libzfs_handle_t *, const char *,
|
|||||||
*/
|
*/
|
||||||
struct zfs_cmd;
|
struct zfs_cmd;
|
||||||
|
|
||||||
extern const char *zfs_history_event_names[LOG_END];
|
extern const char *zfs_history_event_names[];
|
||||||
|
|
||||||
extern char *zpool_vdev_name(libzfs_handle_t *, zpool_handle_t *, nvlist_t *,
|
extern char *zpool_vdev_name(libzfs_handle_t *, zpool_handle_t *, nvlist_t *,
|
||||||
boolean_t verbose);
|
boolean_t verbose);
|
||||||
@ -386,12 +390,9 @@ extern int zpool_upgrade(zpool_handle_t *, uint64_t);
|
|||||||
extern int zpool_get_history(zpool_handle_t *, nvlist_t **);
|
extern int zpool_get_history(zpool_handle_t *, nvlist_t **);
|
||||||
extern int zpool_history_unpack(char *, uint64_t, uint64_t *,
|
extern int zpool_history_unpack(char *, uint64_t, uint64_t *,
|
||||||
nvlist_t ***, uint_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 *,
|
extern void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *,
|
||||||
size_t len);
|
size_t len);
|
||||||
extern int zfs_ioctl(libzfs_handle_t *, unsigned long, struct zfs_cmd *);
|
extern int zfs_ioctl(libzfs_handle_t *, int request, struct zfs_cmd *);
|
||||||
extern int zpool_get_physpath(zpool_handle_t *, char *, size_t);
|
extern int zpool_get_physpath(zpool_handle_t *, char *, size_t);
|
||||||
extern void zpool_explain_recover(libzfs_handle_t *, const char *, int,
|
extern void zpool_explain_recover(libzfs_handle_t *, const char *, int,
|
||||||
nvlist_t *);
|
nvlist_t *);
|
||||||
@ -441,8 +442,6 @@ extern int zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
|
|||||||
char *propbuf, int proplen, boolean_t literal);
|
char *propbuf, int proplen, boolean_t literal);
|
||||||
extern int zfs_prop_get_feature(zfs_handle_t *zhp, const char *propname,
|
extern int zfs_prop_get_feature(zfs_handle_t *zhp, const char *propname,
|
||||||
char *buf, size_t len);
|
char *buf, size_t len);
|
||||||
extern int zfs_get_snapused_int(zfs_handle_t *firstsnap, zfs_handle_t *lastsnap,
|
|
||||||
uint64_t *usedp);
|
|
||||||
extern uint64_t zfs_prop_get_int(zfs_handle_t *, zfs_prop_t);
|
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 int zfs_prop_inherit(zfs_handle_t *, const char *, boolean_t);
|
||||||
extern const char *zfs_prop_values(zfs_prop_t);
|
extern const char *zfs_prop_values(zfs_prop_t);
|
||||||
@ -558,6 +557,8 @@ 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_destroy_snaps_nvl(zfs_handle_t *, nvlist_t *, boolean_t);
|
||||||
extern int zfs_clone(zfs_handle_t *, const char *, nvlist_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(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_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t);
|
||||||
|
|
||||||
typedef struct renameflags {
|
typedef struct renameflags {
|
||||||
|
@ -1447,7 +1447,6 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
|
|||||||
nvlist_t *nvl = NULL, *realprops;
|
nvlist_t *nvl = NULL, *realprops;
|
||||||
zfs_prop_t prop;
|
zfs_prop_t prop;
|
||||||
boolean_t do_prefix = B_TRUE;
|
boolean_t do_prefix = B_TRUE;
|
||||||
uint64_t idx;
|
|
||||||
int added_resv;
|
int added_resv;
|
||||||
|
|
||||||
(void) snprintf(errbuf, sizeof (errbuf),
|
(void) snprintf(errbuf, sizeof (errbuf),
|
||||||
@ -2711,25 +2710,6 @@ zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
zfs_get_snapused_int(zfs_handle_t *firstsnap, zfs_handle_t *lastsnap,
|
|
||||||
uint64_t *usedp)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
zfs_cmd_t zc = { 0 };
|
|
||||||
|
|
||||||
(void) strlcpy(zc.zc_name, lastsnap->zfs_name, sizeof (zc.zc_name));
|
|
||||||
(void) strlcpy(zc.zc_value, firstsnap->zfs_name, sizeof (zc.zc_value));
|
|
||||||
|
|
||||||
err = ioctl(lastsnap->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_SNAPS, &zc);
|
|
||||||
if (err)
|
|
||||||
return (err);
|
|
||||||
|
|
||||||
*usedp = zc.zc_cookie;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the name of the given zfs handle.
|
* Returns the name of the given zfs handle.
|
||||||
*/
|
*/
|
||||||
@ -2930,7 +2910,6 @@ create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
|
|||||||
*/
|
*/
|
||||||
for (cp = target + prefixlen + 1;
|
for (cp = target + prefixlen + 1;
|
||||||
cp = strchr(cp, '/'); *cp = '/', cp++) {
|
cp = strchr(cp, '/'); *cp = '/', cp++) {
|
||||||
char *logstr;
|
|
||||||
|
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
|
|
||||||
@ -2941,16 +2920,12 @@ create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
logstr = hdl->libzfs_log_str;
|
|
||||||
hdl->libzfs_log_str = NULL;
|
|
||||||
if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
|
if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
|
||||||
NULL) != 0) {
|
NULL) != 0) {
|
||||||
hdl->libzfs_log_str = logstr;
|
|
||||||
opname = dgettext(TEXT_DOMAIN, "create");
|
opname = dgettext(TEXT_DOMAIN, "create");
|
||||||
goto ancestorerr;
|
goto ancestorerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdl->libzfs_log_str = logstr;
|
|
||||||
h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
|
h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
|
||||||
if (h == NULL) {
|
if (h == NULL) {
|
||||||
opname = dgettext(TEXT_DOMAIN, "open");
|
opname = dgettext(TEXT_DOMAIN, "open");
|
||||||
@ -3008,12 +2983,12 @@ int
|
|||||||
zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
|
zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
|
||||||
nvlist_t *props)
|
nvlist_t *props)
|
||||||
{
|
{
|
||||||
zfs_cmd_t zc = { 0 };
|
|
||||||
int ret;
|
int ret;
|
||||||
uint64_t size = 0;
|
uint64_t size = 0;
|
||||||
uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
|
uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
|
||||||
char errbuf[1024];
|
char errbuf[1024];
|
||||||
uint64_t zoned;
|
uint64_t zoned;
|
||||||
|
dmu_objset_type_t ost;
|
||||||
|
|
||||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||||
"cannot create '%s'"), path);
|
"cannot create '%s'"), path);
|
||||||
@ -3033,17 +3008,16 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
|
|||||||
* will return ENOENT, not EEXIST. To prevent this from happening, we
|
* will return ENOENT, not EEXIST. To prevent this from happening, we
|
||||||
* first try to see if the dataset exists.
|
* first try to see if the dataset exists.
|
||||||
*/
|
*/
|
||||||
(void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name));
|
if (zfs_dataset_exists(hdl, path, ZFS_TYPE_DATASET)) {
|
||||||
if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
|
|
||||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||||
"dataset already exists"));
|
"dataset already exists"));
|
||||||
return (zfs_error(hdl, EZFS_EXISTS, errbuf));
|
return (zfs_error(hdl, EZFS_EXISTS, errbuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == ZFS_TYPE_VOLUME)
|
if (type == ZFS_TYPE_VOLUME)
|
||||||
zc.zc_objset_type = DMU_OST_ZVOL;
|
ost = DMU_OST_ZVOL;
|
||||||
else
|
else
|
||||||
zc.zc_objset_type = DMU_OST_ZFS;
|
ost = DMU_OST_ZFS;
|
||||||
|
|
||||||
if (props && (props = zfs_valid_proplist(hdl, type, props,
|
if (props && (props = zfs_valid_proplist(hdl, type, props,
|
||||||
zoned, NULL, errbuf)) == 0)
|
zoned, NULL, errbuf)) == 0)
|
||||||
@ -3095,14 +3069,9 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0)
|
|
||||||
return (-1);
|
|
||||||
nvlist_free(props);
|
|
||||||
|
|
||||||
/* create the dataset */
|
/* create the dataset */
|
||||||
ret = zfs_ioctl(hdl, ZFS_IOC_CREATE, &zc);
|
ret = lzc_create(path, ost, props);
|
||||||
|
nvlist_free(props);
|
||||||
zcmd_free_nvlists(&zc);
|
|
||||||
|
|
||||||
/* check for failure */
|
/* check for failure */
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@ -3242,33 +3211,35 @@ int
|
|||||||
zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
|
zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
zfs_cmd_t zc = { 0 };
|
nvlist_t *errlist;
|
||||||
|
|
||||||
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
|
ret = lzc_destroy_snaps(snaps, defer, &errlist);
|
||||||
if (zcmd_write_src_nvlist(zhp->zfs_hdl, &zc, snaps) != 0)
|
|
||||||
return (-1);
|
|
||||||
zc.zc_defer_destroy = defer;
|
|
||||||
|
|
||||||
ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS_NVL, &zc);
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
char errbuf[1024];
|
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));
|
||||||
|
|
||||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
switch (fnvpair_value_int32(pair)) {
|
||||||
"cannot destroy snapshots in %s"), zc.zc_name);
|
case EEXIST:
|
||||||
|
zfs_error_aux(zhp->zfs_hdl,
|
||||||
switch (errno) {
|
dgettext(TEXT_DOMAIN,
|
||||||
case EEXIST:
|
"snapshot is cloned"));
|
||||||
zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
|
ret = zfs_error(zhp->zfs_hdl, EZFS_EXISTS,
|
||||||
"snapshot is cloned"));
|
errbuf);
|
||||||
return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf));
|
break;
|
||||||
|
default:
|
||||||
default:
|
ret = zfs_standard_error(zhp->zfs_hdl, errno,
|
||||||
return (zfs_standard_error(zhp->zfs_hdl, errno,
|
errbuf);
|
||||||
errbuf));
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3277,12 +3248,10 @@ zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
|
|||||||
int
|
int
|
||||||
zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
|
zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
|
||||||
{
|
{
|
||||||
zfs_cmd_t zc = { 0 };
|
|
||||||
char parent[ZFS_MAXNAMELEN];
|
char parent[ZFS_MAXNAMELEN];
|
||||||
int ret;
|
int ret;
|
||||||
char errbuf[1024];
|
char errbuf[1024];
|
||||||
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
||||||
zfs_type_t type;
|
|
||||||
uint64_t zoned;
|
uint64_t zoned;
|
||||||
|
|
||||||
assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
|
assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
|
||||||
@ -3301,32 +3270,21 @@ zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
|
|||||||
(void) parent_name(target, parent, sizeof (parent));
|
(void) parent_name(target, parent, sizeof (parent));
|
||||||
|
|
||||||
/* do the clone */
|
/* 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) {
|
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,
|
if ((props = zfs_valid_proplist(hdl, type, props, zoned,
|
||||||
zhp, errbuf)) == NULL)
|
zhp, errbuf)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
|
|
||||||
nvlist_free(props);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
nvlist_free(props);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name));
|
ret = lzc_clone(target, zhp->zfs_name, props);
|
||||||
(void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value));
|
nvlist_free(props);
|
||||||
ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_CREATE, &zc);
|
|
||||||
|
|
||||||
zcmd_free_nvlists(&zc);
|
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
@ -3411,74 +3369,134 @@ zfs_promote(zfs_handle_t *zhp)
|
|||||||
return (ret);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Takes a snapshot of the given dataset.
|
* Creates snapshots. The keys in the snaps nvlist are the snapshots to be
|
||||||
|
* created.
|
||||||
*/
|
*/
|
||||||
|
int
|
||||||
|
zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = lzc_snapshot(snaps, props, &errors);
|
||||||
|
|
||||||
|
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 (!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(errors);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
|
zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
|
||||||
nvlist_t *props)
|
nvlist_t *props)
|
||||||
{
|
{
|
||||||
const char *delim;
|
|
||||||
char parent[ZFS_MAXNAMELEN];
|
|
||||||
zfs_handle_t *zhp;
|
|
||||||
zfs_cmd_t zc = { 0 };
|
|
||||||
int ret;
|
int ret;
|
||||||
|
snapdata_t sd = { 0 };
|
||||||
|
char fsname[ZFS_MAXNAMELEN];
|
||||||
|
char *cp;
|
||||||
|
zfs_handle_t *zhp;
|
||||||
char errbuf[1024];
|
char errbuf[1024];
|
||||||
|
|
||||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||||
"cannot snapshot '%s'"), path);
|
"cannot snapshot %s"), path);
|
||||||
|
|
||||||
/* validate the target name */
|
|
||||||
if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
|
if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
|
||||||
return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
|
return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
|
||||||
|
|
||||||
if (props) {
|
(void) strlcpy(fsname, path, sizeof (fsname));
|
||||||
if ((props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
|
cp = strchr(fsname, '@');
|
||||||
props, B_FALSE, NULL, errbuf)) == NULL)
|
*cp = '\0';
|
||||||
return (-1);
|
sd.sd_snapname = cp + 1;
|
||||||
|
|
||||||
if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
|
if ((zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM |
|
||||||
nvlist_free(props);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
nvlist_free(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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, parent, ZFS_TYPE_FILESYSTEM |
|
|
||||||
ZFS_TYPE_VOLUME)) == NULL) {
|
ZFS_TYPE_VOLUME)) == NULL) {
|
||||||
zcmd_free_nvlists(&zc);
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
|
verify(nvlist_alloc(&sd.sd_nvl, NV_UNIQUE_NAME, 0) == 0);
|
||||||
(void) strlcpy(zc.zc_value, delim+1, sizeof (zc.zc_value));
|
if (recursive) {
|
||||||
if (ZFS_IS_VOLUME(zhp))
|
(void) zfs_snapshot_cb(zfs_handle_dup(zhp), &sd);
|
||||||
zc.zc_objset_type = DMU_OST_ZVOL;
|
} else {
|
||||||
else
|
fnvlist_add_boolean(sd.sd_nvl, path);
|
||||||
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);
|
zfs_close(zhp);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3506,17 +3524,13 @@ rollback_destroy(zfs_handle_t *zhp, void *data)
|
|||||||
zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
|
zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
|
||||||
zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
|
zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
|
||||||
cbp->cb_create) {
|
cbp->cb_create) {
|
||||||
char *logstr;
|
|
||||||
|
|
||||||
cbp->cb_dependent = B_TRUE;
|
cbp->cb_dependent = B_TRUE;
|
||||||
cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
|
cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
|
||||||
rollback_destroy, cbp);
|
rollback_destroy, cbp);
|
||||||
cbp->cb_dependent = B_FALSE;
|
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);
|
cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
|
||||||
zhp->zfs_hdl->libzfs_log_str = logstr;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* We must destroy this clone; first unmount it */
|
/* We must destroy this clone; first unmount it */
|
||||||
|
@ -23,12 +23,12 @@
|
|||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
* Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LIBFS_IMPL_H
|
#ifndef _LIBZFS_IMPL_H
|
||||||
#define _LIBFS_IMPL_H
|
#define _LIBZFS_IMPL_H
|
||||||
|
|
||||||
#include <sys/dmu.h>
|
#include <sys/dmu.h>
|
||||||
#include <sys/fs/zfs.h>
|
#include <sys/fs/zfs.h>
|
||||||
@ -39,6 +39,7 @@
|
|||||||
#include <libshare.h>
|
#include <libshare.h>
|
||||||
#include <libuutil.h>
|
#include <libuutil.h>
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
|
#include <libzfs_core.h>
|
||||||
|
|
||||||
#include "zfs_ioctl_compat.h"
|
#include "zfs_ioctl_compat.h"
|
||||||
|
|
||||||
@ -70,7 +71,6 @@ struct libzfs_handle {
|
|||||||
int libzfs_desc_active;
|
int libzfs_desc_active;
|
||||||
char libzfs_action[1024];
|
char libzfs_action[1024];
|
||||||
char libzfs_desc[1024];
|
char libzfs_desc[1024];
|
||||||
char *libzfs_log_str;
|
|
||||||
int libzfs_printerr;
|
int libzfs_printerr;
|
||||||
int libzfs_storeerr; /* stuff error messages into buffer */
|
int libzfs_storeerr; /* stuff error messages into buffer */
|
||||||
void *libzfs_sharehdl; /* libshare handle */
|
void *libzfs_sharehdl; /* libshare handle */
|
||||||
@ -225,11 +225,14 @@ static int zfs_ioctl_version = 0;
|
|||||||
* error is returned zc_nvlist_dst_size won't be updated.
|
* error is returned zc_nvlist_dst_size won't be updated.
|
||||||
*/
|
*/
|
||||||
static __inline int
|
static __inline int
|
||||||
zcmd_ioctl(int fd, unsigned long cmd, zfs_cmd_t *zc)
|
zcmd_ioctl(int fd, int request, zfs_cmd_t *zc)
|
||||||
{
|
{
|
||||||
|
unsigned long cmd;
|
||||||
size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size;
|
size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size;
|
||||||
int version, ret, cflag = ZFS_CMD_COMPAT_NONE;
|
int version, ret, cflag = ZFS_CMD_COMPAT_NONE;
|
||||||
|
|
||||||
|
cmd = _IOWR('Z', request, struct zfs_cmd);
|
||||||
|
|
||||||
zfs_ioctl_version_size = sizeof(zfs_ioctl_version);
|
zfs_ioctl_version_size = sizeof(zfs_ioctl_version);
|
||||||
if (zfs_ioctl_version == 0) {
|
if (zfs_ioctl_version == 0) {
|
||||||
sysctlbyname("vfs.zfs.version.ioctl", &zfs_ioctl_version,
|
sysctlbyname("vfs.zfs.version.ioctl", &zfs_ioctl_version,
|
||||||
@ -273,4 +276,4 @@ zcmd_ioctl(int fd, unsigned long cmd, zfs_cmd_t *zc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _LIBFS_IMPL_H */
|
#endif /* _LIBZFS_IMPL_H */
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright 2010 Nexenta Systems, Inc. All rights reserved.
|
* Copyright 2010 Nexenta Systems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*/
|
*/
|
||||||
@ -308,12 +308,11 @@ int
|
|||||||
zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
|
zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
|
||||||
zfs_iter_f func, void *arg)
|
zfs_iter_f func, void *arg)
|
||||||
{
|
{
|
||||||
char buf[ZFS_MAXNAMELEN];
|
char *buf, *comma_separated, *cp;
|
||||||
char *comma_separated, *cp;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
(void) strlcpy(buf, spec_orig, sizeof (buf));
|
buf = zfs_strdup(fs_zhp->zfs_hdl, spec_orig);
|
||||||
cp = buf;
|
cp = buf;
|
||||||
|
|
||||||
while ((comma_separated = strsep(&cp, ",")) != NULL) {
|
while ((comma_separated = strsep(&cp, ",")) != NULL) {
|
||||||
@ -371,6 +370,7 @@ zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <sys/zfs_ioctl.h>
|
#include <sys/zfs_ioctl.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
@ -1237,7 +1238,7 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
|
|||||||
* datasets left in the pool.
|
* datasets left in the pool.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
zpool_destroy(zpool_handle_t *zhp)
|
zpool_destroy(zpool_handle_t *zhp, const char *log_str)
|
||||||
{
|
{
|
||||||
zfs_cmd_t zc = { 0 };
|
zfs_cmd_t zc = { 0 };
|
||||||
zfs_handle_t *zfp = NULL;
|
zfs_handle_t *zfp = NULL;
|
||||||
@ -1249,6 +1250,7 @@ zpool_destroy(zpool_handle_t *zhp)
|
|||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
|
(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) {
|
if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
|
||||||
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
|
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
|
||||||
@ -1403,8 +1405,9 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
|
|||||||
* Exports the pool from the system. The caller must ensure that there are no
|
* Exports the pool from the system. The caller must ensure that there are no
|
||||||
* mounted datasets in the pool.
|
* mounted datasets in the pool.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
|
zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
|
||||||
|
const char *log_str)
|
||||||
{
|
{
|
||||||
zfs_cmd_t zc = { 0 };
|
zfs_cmd_t zc = { 0 };
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
@ -1415,6 +1418,7 @@ 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));
|
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
|
||||||
zc.zc_cookie = force;
|
zc.zc_cookie = force;
|
||||||
zc.zc_guid = hardforce;
|
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) {
|
if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
@ -1436,15 +1440,15 @@ zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
zpool_export(zpool_handle_t *zhp, boolean_t force)
|
zpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str)
|
||||||
{
|
{
|
||||||
return (zpool_export_common(zhp, force, B_FALSE));
|
return (zpool_export_common(zhp, force, B_FALSE, log_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
zpool_export_force(zpool_handle_t *zhp)
|
zpool_export_force(zpool_handle_t *zhp, const char *log_str)
|
||||||
{
|
{
|
||||||
return (zpool_export_common(zhp, B_TRUE, B_TRUE));
|
return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3632,40 +3636,30 @@ zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
zpool_set_history_str(const char *subcommand, int argc, char **argv,
|
zfs_save_arguments(int argc, char **argv, char *string, int len)
|
||||||
char *history_str)
|
|
||||||
{
|
{
|
||||||
int i;
|
(void) strlcpy(string, basename(argv[0]), len);
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
(void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN);
|
(void) strlcat(string, " ", len);
|
||||||
for (i = 1; i < argc; i++) {
|
(void) strlcat(string, argv[i], len);
|
||||||
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
|
int
|
||||||
zpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
|
zpool_log_history(libzfs_handle_t *hdl, const char *message)
|
||||||
{
|
{
|
||||||
if (history_str == NULL)
|
zfs_cmd_t zc = { 0 };
|
||||||
return (EINVAL);
|
nvlist_t *args;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (strlen(history_str) > HIS_MAX_RECORD_LEN)
|
args = fnvlist_alloc();
|
||||||
return (EINVAL);
|
fnvlist_add_string(args, "message", message);
|
||||||
|
err = zcmd_write_src_nvlist(hdl, &zc, args);
|
||||||
if (hdl->libzfs_log_str != NULL)
|
if (err == 0)
|
||||||
free(hdl->libzfs_log_str);
|
err = ioctl(hdl->libzfs_fd, ZFS_IOC_LOG_HISTORY, &zc);
|
||||||
|
nvlist_free(args);
|
||||||
if ((hdl->libzfs_log_str = strdup(history_str)) == NULL)
|
zcmd_free_nvlists(&zc);
|
||||||
return (no_memory(hdl));
|
return (err);
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
|
#include <libzfs_core.h>
|
||||||
|
|
||||||
#include "libzfs_impl.h"
|
#include "libzfs_impl.h"
|
||||||
#include "zfs_prop.h"
|
#include "zfs_prop.h"
|
||||||
@ -659,6 +660,14 @@ libzfs_init(void)
|
|||||||
|
|
||||||
hdl->libzfs_sharetab = fopen(ZFS_EXPORTS_PATH, "r");
|
hdl->libzfs_sharetab = fopen(ZFS_EXPORTS_PATH, "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();
|
zfs_prop_init();
|
||||||
zpool_prop_init();
|
zpool_prop_init();
|
||||||
zpool_feature_init();
|
zpool_feature_init();
|
||||||
@ -676,14 +685,13 @@ libzfs_fini(libzfs_handle_t *hdl)
|
|||||||
if (hdl->libzfs_sharetab)
|
if (hdl->libzfs_sharetab)
|
||||||
(void) fclose(hdl->libzfs_sharetab);
|
(void) fclose(hdl->libzfs_sharetab);
|
||||||
zfs_uninit_libshare(hdl);
|
zfs_uninit_libshare(hdl);
|
||||||
if (hdl->libzfs_log_str)
|
|
||||||
(void) free(hdl->libzfs_log_str);
|
|
||||||
zpool_free_handles(hdl);
|
zpool_free_handles(hdl);
|
||||||
#ifdef sun
|
#ifdef sun
|
||||||
libzfs_fru_clear(hdl, B_TRUE);
|
libzfs_fru_clear(hdl, B_TRUE);
|
||||||
#endif
|
#endif
|
||||||
namespace_clear(hdl);
|
namespace_clear(hdl);
|
||||||
libzfs_mnttab_fini(hdl);
|
libzfs_mnttab_fini(hdl);
|
||||||
|
libzfs_core_fini();
|
||||||
free(hdl);
|
free(hdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,19 +865,9 @@ zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
zfs_ioctl(libzfs_handle_t *hdl, unsigned long request, zfs_cmd_t *zc)
|
zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
|
||||||
{
|
{
|
||||||
int error;
|
return (ioctl(hdl->libzfs_fd, request, zc));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
488
cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
Normal file
488
cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
Normal file
@ -0,0 +1,488 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _IN_LIBZFS_CORE_
|
||||||
|
|
||||||
|
#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>
|
||||||
|
#include <libzfs_impl.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);
|
||||||
|
#ifdef illumos
|
||||||
|
if (zc.zc_nvlist_dst == NULL) {
|
||||||
|
#else
|
||||||
|
if (zc.zc_nvlist_dst == 0) {
|
||||||
|
#endif
|
||||||
|
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);
|
||||||
|
#ifdef illumos
|
||||||
|
if (zc.zc_nvlist_dst == NULL) {
|
||||||
|
#else
|
||||||
|
if (zc.zc_nvlist_dst == 0) {
|
||||||
|
#endif
|
||||||
|
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);
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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 */
|
@ -952,6 +952,12 @@ crgetuid(cred_t *cr)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uid_t
|
||||||
|
crgetruid(cred_t *cr)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
gid_t
|
gid_t
|
||||||
crgetgid(cred_t *cr)
|
crgetgid(cred_t *cr)
|
||||||
{
|
{
|
||||||
|
@ -252,6 +252,7 @@ extern int rw_lock_held(krwlock_t *rwlp);
|
|||||||
#define rw_downgrade(rwlp) do { } while (0)
|
#define rw_downgrade(rwlp) do { } while (0)
|
||||||
|
|
||||||
extern uid_t crgetuid(cred_t *cr);
|
extern uid_t crgetuid(cred_t *cr);
|
||||||
|
extern uid_t crgetruid(cred_t *cr);
|
||||||
extern gid_t crgetgid(cred_t *cr);
|
extern gid_t crgetgid(cred_t *cr);
|
||||||
extern int crgetngroups(cred_t *cr);
|
extern int crgetngroups(cred_t *cr);
|
||||||
extern gid_t *crgetgroups(cred_t *cr);
|
extern gid_t *crgetgroups(cred_t *cr);
|
||||||
|
@ -9,10 +9,12 @@ SUBDIR= ${_drti} \
|
|||||||
libnvpair \
|
libnvpair \
|
||||||
libumem \
|
libumem \
|
||||||
libuutil \
|
libuutil \
|
||||||
|
${_libzfs_core} \
|
||||||
${_libzfs} \
|
${_libzfs} \
|
||||||
${_libzpool}
|
${_libzpool}
|
||||||
|
|
||||||
.if ${MK_ZFS} != "no"
|
.if ${MK_ZFS} != "no"
|
||||||
|
_libzfs_core= libzfs_core
|
||||||
_libzfs= libzfs
|
_libzfs= libzfs
|
||||||
.if ${MK_LIBTHR} != "no"
|
.if ${MK_LIBTHR} != "no"
|
||||||
_libzpool= libzpool
|
_libzpool= libzpool
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
||||||
|
|
||||||
LIB= zfs
|
LIB= zfs
|
||||||
DPADD= ${LIBMD} ${LIBPTHREAD} ${LIBUMEM} ${LIBUTIL} ${LIBM} ${LIBNVPAIR}
|
DPADD= ${LIBMD} ${LIBPTHREAD} ${LIBUMEM} ${LIBUTIL} ${LIBM} ${LIBNVPAIR} \
|
||||||
LDADD= -lmd -lpthread -lumem -lutil -lm -lnvpair
|
${LIBZFS_CORE}
|
||||||
|
LDADD= -lmd -lpthread -lumem -lutil -lm -lnvpair -lzfs_core
|
||||||
|
|
||||||
SRCS= deviceid.c \
|
SRCS= deviceid.c \
|
||||||
fsshare.c \
|
fsshare.c \
|
||||||
@ -54,5 +55,6 @@ CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
|||||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair
|
||||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libuutil/common
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libuutil/common
|
||||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs_core/common
|
||||||
|
|
||||||
.include <bsd.lib.mk>
|
.include <bsd.lib.mk>
|
||||||
|
33
cddl/lib/libzfs_core/Makefile
Normal file
33
cddl/lib/libzfs_core/Makefile
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# $FreeBSD$
|
||||||
|
|
||||||
|
.PATH: ${.CURDIR}/../../../cddl/compat/opensolaris/misc
|
||||||
|
.PATH: ${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs
|
||||||
|
.PATH: ${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs
|
||||||
|
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs_core/common
|
||||||
|
|
||||||
|
LIB= zfs_core
|
||||||
|
DPADD= ${LIBNVPAIR}
|
||||||
|
LDADD= -lnvpair
|
||||||
|
|
||||||
|
SRCS= libzfs_core.c
|
||||||
|
|
||||||
|
WARNS?= 0
|
||||||
|
CSTD= c99
|
||||||
|
CFLAGS+= -DZFS_NO_ACL
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../sbin/mount
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/lib/libumem
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzpool/common
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libuutil/common
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs_core/common
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
||||||
|
|
||||||
|
.include <bsd.lib.mk>
|
@ -14,6 +14,7 @@ CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
|
|||||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
|
||||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libuutil/common
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libuutil/common
|
||||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
||||||
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs_core/common
|
||||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libumem/common
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libumem/common
|
||||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair
|
||||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
||||||
@ -22,7 +23,7 @@ CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys
|
|||||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs
|
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs
|
||||||
|
|
||||||
DPADD= ${LIBGEOM} ${LIBJAIL} ${LIBNVPAIR} ${LIBUMEM} \
|
DPADD= ${LIBGEOM} ${LIBJAIL} ${LIBNVPAIR} ${LIBUMEM} \
|
||||||
${LIBUTIL} ${LIBUUTIL} ${LIBZFS}
|
${LIBUTIL} ${LIBUUTIL} ${LIBZFS_CORE} ${LIBZFS}
|
||||||
LDADD= -lgeom -ljail -lnvpair -lumem -lutil -luutil -lzfs
|
LDADD= -lgeom -ljail -lnvpair -lumem -lutil -luutil -lzfs_core -lzfs
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -27,7 +27,7 @@ CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzpool/common
|
|||||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/stat/common
|
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/stat/common
|
||||||
|
|
||||||
DPADD= ${LIBAVL} ${LIBGEOM} ${LIBNVPAIR} \
|
DPADD= ${LIBAVL} ${LIBGEOM} ${LIBNVPAIR} \
|
||||||
${LIBUMEM} ${LIBUTIL} ${LIBUUTIL} ${LIBZFS}
|
${LIBUMEM} ${LIBUTIL} ${LIBUUTIL} ${LIBZFS_CORE} ${LIBZFS}
|
||||||
LDADD= -lavl -lgeom -lnvpair -lumem -lutil -luutil -lzfs
|
LDADD= -lavl -lgeom -lnvpair -lumem -lutil -luutil -lzfs_core -lzfs
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -20,7 +20,7 @@ CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/head
|
|||||||
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
||||||
|
|
||||||
DPADD= ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBUMEM} ${LIBUUTIL} \
|
DPADD= ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBUMEM} ${LIBUUTIL} \
|
||||||
${LIBZFS} ${LIBZPOOL}
|
${LIBZFS_CORE} ${LIBZFS} ${LIBZPOOL}
|
||||||
LDADD= -lgeom -lm -lnvpair -lumem -luutil -lzfs -lzpool
|
LDADD= -lgeom -lm -lnvpair -lumem -luutil -lzfs_core -lzfs -lzpool
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -19,8 +19,9 @@ CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/head
|
|||||||
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
||||||
|
|
||||||
DPADD= ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBUMEM} ${LIBZPOOL} \
|
DPADD= ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBUMEM} ${LIBZPOOL} \
|
||||||
${LIBPTHREAD} ${LIBAVL} ${LIBZFS} ${LIBUUTIL}
|
${LIBPTHREAD} ${LIBAVL} ${LIBZFS_CORE} ${LIBZFS} ${LIBUUTIL}
|
||||||
LDADD= -lgeom -lm -lnvpair -lumem -lzpool -lpthread -lavl -lzfs -luutil
|
LDADD= -lgeom -lm -lnvpair -lumem -lzpool -lpthread -lavl -lzfs_core -lzfs \
|
||||||
|
-luutil
|
||||||
|
|
||||||
CSTD= c99
|
CSTD= c99
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
|
|||||||
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
||||||
|
|
||||||
DPADD= ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBPTHREAD} ${LIBUMEM} \
|
DPADD= ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBPTHREAD} ${LIBUMEM} \
|
||||||
${LIBUUTIL} ${LIBZFS} ${LIBZPOOL}
|
${LIBUUTIL} ${LIBZFS_CORE} ${LIBZFS} ${LIBZPOOL}
|
||||||
LDADD= -lgeom -lm -lnvpair -lpthread -lumem -luutil -lzfs -lzpool
|
LDADD= -lgeom -lm -lnvpair -lpthread -lumem -luutil -lzfs_core -lzfs -lzpool
|
||||||
|
|
||||||
CFLAGS+= -DDEBUG=1
|
CFLAGS+= -DDEBUG=1
|
||||||
#DEBUG_FLAGS+= -g
|
#DEBUG_FLAGS+= -g
|
||||||
|
@ -23,8 +23,8 @@ CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
|
|||||||
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
||||||
|
|
||||||
DPADD= ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBPTHREAD} ${LIBUMEM} \
|
DPADD= ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBPTHREAD} ${LIBUMEM} \
|
||||||
${LIBUUTIL} ${LIBZFS} ${LIBZPOOL}
|
${LIBUUTIL} ${LIBZFS_CORE} ${LIBZFS} ${LIBZPOOL}
|
||||||
LDADD= -lgeom -lm -lnvpair -lpthread -lumem -luutil -lzfs -lzpool
|
LDADD= -lgeom -lm -lnvpair -lpthread -lumem -luutil -lzfs_core -lzfs -lzpool
|
||||||
|
|
||||||
CFLAGS+= -DDEBUG=1
|
CFLAGS+= -DDEBUG=1
|
||||||
#DEBUG_FLAGS+= -g
|
#DEBUG_FLAGS+= -g
|
||||||
|
@ -123,7 +123,7 @@ CRUNCH_LIBS+= -lalias -lcam -lcurses -ldevstat -lipsec
|
|||||||
CRUNCH_LIBS+= -lipx
|
CRUNCH_LIBS+= -lipx
|
||||||
.endif
|
.endif
|
||||||
.if ${MK_ZFS} != "no"
|
.if ${MK_ZFS} != "no"
|
||||||
CRUNCH_LIBS+= -lavl -ljail -lzfs -lnvpair -lpthread -luutil -lumem
|
CRUNCH_LIBS+= -lavl -ljail -lzfs_core -lzfs -lnvpair -lpthread -luutil -lumem
|
||||||
.endif
|
.endif
|
||||||
CRUNCH_LIBS+= -lgeom -lbsdxml -lkiconv -lmd -lsbuf -lufs -lz
|
CRUNCH_LIBS+= -lgeom -lbsdxml -lkiconv -lmd -lsbuf -lufs -lz
|
||||||
|
|
||||||
|
@ -173,4 +173,5 @@ LIBY?= ${DESTDIR}${LIBDIR}/liby.a
|
|||||||
LIBYPCLNT?= ${DESTDIR}${LIBDIR}/libypclnt.a
|
LIBYPCLNT?= ${DESTDIR}${LIBDIR}/libypclnt.a
|
||||||
LIBZ?= ${DESTDIR}${LIBDIR}/libz.a
|
LIBZ?= ${DESTDIR}${LIBDIR}/libz.a
|
||||||
LIBZFS?= ${DESTDIR}${LIBDIR}/libzfs.a
|
LIBZFS?= ${DESTDIR}${LIBDIR}/libzfs.a
|
||||||
|
LIBZFS_CORE?= ${DESTDIR}${LIBDIR}/libzfs_core.a
|
||||||
LIBZPOOL?= ${DESTDIR}${LIBDIR}/libzpool.a
|
LIBZPOOL?= ${DESTDIR}${LIBDIR}/libzpool.a
|
||||||
|
@ -46,6 +46,7 @@ typedef struct ucred ucred_t;
|
|||||||
#define kcred (thread0.td_ucred)
|
#define kcred (thread0.td_ucred)
|
||||||
|
|
||||||
#define crgetuid(cred) ((cred)->cr_uid)
|
#define crgetuid(cred) ((cred)->cr_uid)
|
||||||
|
#define crgetruid(cred) ((cred)->cr_ruid)
|
||||||
#define crgetgid(cred) ((cred)->cr_gid)
|
#define crgetgid(cred) ((cred)->cr_gid)
|
||||||
#define crgetgroups(cred) ((cred)->cr_groups)
|
#define crgetgroups(cred) ((cred)->cr_groups)
|
||||||
#define crgetngroups(cred) ((cred)->cr_ngroups)
|
#define crgetngroups(cred) ((cred)->cr_ngroups)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -156,7 +157,11 @@ zfs_spa_version_map(int zpl_version)
|
|||||||
return (version);
|
return (version);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *zfs_history_event_names[LOG_END] = {
|
/*
|
||||||
|
* This is the table of legacy internal event names; it should not be modified.
|
||||||
|
* The internal events are now stored in the history log as strings.
|
||||||
|
*/
|
||||||
|
const char *zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS] = {
|
||||||
"invalid event",
|
"invalid event",
|
||||||
"pool create",
|
"pool create",
|
||||||
"vdev add",
|
"vdev add",
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ZFS_COMUTIL_H
|
#ifndef _ZFS_COMUTIL_H
|
||||||
@ -37,7 +38,8 @@ extern void zpool_get_rewind_policy(nvlist_t *, zpool_rewind_policy_t *);
|
|||||||
|
|
||||||
extern int zfs_zpl_version_map(int spa_version);
|
extern int zfs_zpl_version_map(int spa_version);
|
||||||
extern int zfs_spa_version_map(int zpl_version);
|
extern int zfs_spa_version_map(int zpl_version);
|
||||||
extern const char *zfs_history_event_names[LOG_END];
|
#define ZFS_NUM_LEGACY_HISTORY_EVENTS 41
|
||||||
|
extern const char *zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS];
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -488,10 +488,10 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
|
|||||||
return (ret);
|
return (ret);
|
||||||
case ZFS_CMD_COMPAT_V28:
|
case ZFS_CMD_COMPAT_V28:
|
||||||
zc_c = malloc(sizeof(zfs_cmd_v28_t));
|
zc_c = malloc(sizeof(zfs_cmd_v28_t));
|
||||||
ncmd = _IOWR('Z', ZFS_IOC(cmd), struct zfs_cmd_v28);
|
ncmd = _IOWR('Z', ZFS_IOCREQ(cmd), struct zfs_cmd_v28);
|
||||||
break;
|
break;
|
||||||
case ZFS_CMD_COMPAT_V15:
|
case ZFS_CMD_COMPAT_V15:
|
||||||
nc = zfs_ioctl_v28_to_v15[ZFS_IOC(cmd)];
|
nc = zfs_ioctl_v28_to_v15[ZFS_IOCREQ(cmd)];
|
||||||
zc_c = malloc(sizeof(zfs_cmd_v15_t));
|
zc_c = malloc(sizeof(zfs_cmd_v15_t));
|
||||||
ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
|
ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
|
||||||
break;
|
break;
|
||||||
@ -499,7 +499,7 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ZFS_IOC(ncmd) == ZFS_IOC_COMPAT_FAIL)
|
if (ZFS_IOCREQ(ncmd) == ZFS_IOC_COMPAT_FAIL)
|
||||||
return (ENOTSUP);
|
return (ENOTSUP);
|
||||||
|
|
||||||
zfs_cmd_compat_put(zc, (caddr_t)zc_c, cflag);
|
zfs_cmd_compat_put(zc, (caddr_t)zc_c, cflag);
|
||||||
|
@ -56,6 +56,8 @@ extern "C" {
|
|||||||
#define ZFS_IOC_COMPAT_PASS 254
|
#define ZFS_IOC_COMPAT_PASS 254
|
||||||
#define ZFS_IOC_COMPAT_FAIL 255
|
#define ZFS_IOC_COMPAT_FAIL 255
|
||||||
|
|
||||||
|
#define ZFS_IOCREQ(ioreq) ((ioreq) & 0xff)
|
||||||
|
|
||||||
typedef struct zinject_record_v15 {
|
typedef struct zinject_record_v15 {
|
||||||
uint64_t zi_objset;
|
uint64_t zi_objset;
|
||||||
uint64_t zi_object;
|
uint64_t zi_object;
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common routines used by zfs and zpool property management.
|
* Common routines used by zfs and zpool property management.
|
||||||
@ -129,7 +132,8 @@ zprop_register_hidden(int prop, const char *name, zprop_type_t type,
|
|||||||
zprop_attr_t attr, int objset_types, const char *colname)
|
zprop_attr_t attr, int objset_types, const char *colname)
|
||||||
{
|
{
|
||||||
zprop_register_impl(prop, name, type, 0, NULL, attr,
|
zprop_register_impl(prop, name, type, 0, NULL, attr,
|
||||||
objset_types, NULL, colname, B_FALSE, B_FALSE, NULL);
|
objset_types, NULL, colname,
|
||||||
|
type == PROP_TYPE_NUMBER, B_FALSE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Portions Copyright 2010 Robert Milkowski */
|
/* Portions Copyright 2010 Robert Milkowski */
|
||||||
@ -694,30 +695,33 @@ dmu_objset_create_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
spa_t *spa = dd->dd_pool->dp_spa;
|
spa_t *spa = dd->dd_pool->dp_spa;
|
||||||
struct oscarg *oa = arg2;
|
struct oscarg *oa = arg2;
|
||||||
uint64_t obj;
|
uint64_t obj;
|
||||||
|
dsl_dataset_t *ds;
|
||||||
|
blkptr_t *bp;
|
||||||
|
|
||||||
ASSERT(dmu_tx_is_syncing(tx));
|
ASSERT(dmu_tx_is_syncing(tx));
|
||||||
|
|
||||||
obj = dsl_dataset_create_sync(dd, oa->lastname,
|
obj = dsl_dataset_create_sync(dd, oa->lastname,
|
||||||
oa->clone_origin, oa->flags, oa->cr, tx);
|
oa->clone_origin, oa->flags, oa->cr, tx);
|
||||||
|
|
||||||
if (oa->clone_origin == NULL) {
|
VERIFY3U(0, ==, dsl_dataset_hold_obj(dd->dd_pool, obj, FTAG, &ds));
|
||||||
dsl_pool_t *dp = dd->dd_pool;
|
bp = dsl_dataset_get_blkptr(ds);
|
||||||
dsl_dataset_t *ds;
|
if (BP_IS_HOLE(bp)) {
|
||||||
blkptr_t *bp;
|
objset_t *os =
|
||||||
objset_t *os;
|
dmu_objset_create_impl(spa, ds, bp, oa->type, tx);
|
||||||
|
|
||||||
VERIFY3U(0, ==, dsl_dataset_hold_obj(dp, obj, FTAG, &ds));
|
|
||||||
bp = dsl_dataset_get_blkptr(ds);
|
|
||||||
ASSERT(BP_IS_HOLE(bp));
|
|
||||||
|
|
||||||
os = dmu_objset_create_impl(spa, ds, bp, oa->type, tx);
|
|
||||||
|
|
||||||
if (oa->userfunc)
|
if (oa->userfunc)
|
||||||
oa->userfunc(os, oa->userarg, oa->cr, tx);
|
oa->userfunc(os, oa->userarg, oa->cr, tx);
|
||||||
dsl_dataset_rele(ds, FTAG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_CREATE, spa, tx, "dataset = %llu", obj);
|
if (oa->clone_origin == NULL) {
|
||||||
|
spa_history_log_internal_ds(ds, "create", tx, "");
|
||||||
|
} else {
|
||||||
|
char namebuf[MAXNAMELEN];
|
||||||
|
dsl_dataset_name(oa->clone_origin, namebuf);
|
||||||
|
spa_history_log_internal_ds(ds, "clone", tx,
|
||||||
|
"origin=%s (%llu)", namebuf, oa->clone_origin->ds_object);
|
||||||
|
}
|
||||||
|
dsl_dataset_rele(ds, FTAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -794,34 +798,40 @@ dmu_objset_destroy(const char *name, boolean_t defer)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct snaparg {
|
typedef struct snapallarg {
|
||||||
dsl_sync_task_group_t *dstg;
|
dsl_sync_task_group_t *saa_dstg;
|
||||||
char *snapname;
|
boolean_t saa_needsuspend;
|
||||||
char *htag;
|
nvlist_t *saa_props;
|
||||||
char failed[MAXPATHLEN];
|
|
||||||
boolean_t recursive;
|
/* the following are used only if 'temporary' is set: */
|
||||||
boolean_t needsuspend;
|
boolean_t saa_temporary;
|
||||||
boolean_t temporary;
|
const char *saa_htag;
|
||||||
nvlist_t *props;
|
struct dsl_ds_holdarg *saa_ha;
|
||||||
struct dsl_ds_holdarg *ha; /* only needed in the temporary case */
|
dsl_dataset_t *saa_newds;
|
||||||
dsl_dataset_t *newds;
|
} snapallarg_t;
|
||||||
};
|
|
||||||
|
typedef struct snaponearg {
|
||||||
|
const char *soa_longname; /* long snap name */
|
||||||
|
const char *soa_snapname; /* short snap name */
|
||||||
|
snapallarg_t *soa_saa;
|
||||||
|
} snaponearg_t;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
objset_t *os = arg1;
|
objset_t *os = arg1;
|
||||||
struct snaparg *sn = arg2;
|
snaponearg_t *soa = arg2;
|
||||||
|
snapallarg_t *saa = soa->soa_saa;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* The props have already been checked by zfs_check_userprops(). */
|
/* The props have already been checked by zfs_check_userprops(). */
|
||||||
|
|
||||||
error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
|
error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
|
||||||
sn->snapname, tx);
|
soa->soa_snapname, tx);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
if (sn->temporary) {
|
if (saa->saa_temporary) {
|
||||||
/*
|
/*
|
||||||
* Ideally we would just call
|
* Ideally we would just call
|
||||||
* dsl_dataset_user_hold_check() and
|
* dsl_dataset_user_hold_check() and
|
||||||
@ -839,12 +849,13 @@ snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
* Not checking number of tags because the tag will be
|
* Not checking number of tags because the tag will be
|
||||||
* unique, as it will be the only tag.
|
* unique, as it will be the only tag.
|
||||||
*/
|
*/
|
||||||
if (strlen(sn->htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
|
if (strlen(saa->saa_htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
|
||||||
return (E2BIG);
|
return (E2BIG);
|
||||||
|
|
||||||
sn->ha = kmem_alloc(sizeof (struct dsl_ds_holdarg), KM_SLEEP);
|
saa->saa_ha = kmem_alloc(sizeof (struct dsl_ds_holdarg),
|
||||||
sn->ha->temphold = B_TRUE;
|
KM_SLEEP);
|
||||||
sn->ha->htag = sn->htag;
|
saa->saa_ha->temphold = B_TRUE;
|
||||||
|
saa->saa_ha->htag = saa->saa_htag;
|
||||||
}
|
}
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -854,24 +865,25 @@ snapshot_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
{
|
{
|
||||||
objset_t *os = arg1;
|
objset_t *os = arg1;
|
||||||
dsl_dataset_t *ds = os->os_dsl_dataset;
|
dsl_dataset_t *ds = os->os_dsl_dataset;
|
||||||
struct snaparg *sn = arg2;
|
snaponearg_t *soa = arg2;
|
||||||
|
snapallarg_t *saa = soa->soa_saa;
|
||||||
|
|
||||||
dsl_dataset_snapshot_sync(ds, sn->snapname, tx);
|
dsl_dataset_snapshot_sync(ds, soa->soa_snapname, tx);
|
||||||
|
|
||||||
if (sn->props) {
|
if (saa->saa_props != NULL) {
|
||||||
dsl_props_arg_t pa;
|
dsl_props_arg_t pa;
|
||||||
pa.pa_props = sn->props;
|
pa.pa_props = saa->saa_props;
|
||||||
pa.pa_source = ZPROP_SRC_LOCAL;
|
pa.pa_source = ZPROP_SRC_LOCAL;
|
||||||
dsl_props_set_sync(ds->ds_prev, &pa, tx);
|
dsl_props_set_sync(ds->ds_prev, &pa, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sn->temporary) {
|
if (saa->saa_temporary) {
|
||||||
struct dsl_ds_destroyarg da;
|
struct dsl_ds_destroyarg da;
|
||||||
|
|
||||||
dsl_dataset_user_hold_sync(ds->ds_prev, sn->ha, tx);
|
dsl_dataset_user_hold_sync(ds->ds_prev, saa->saa_ha, tx);
|
||||||
kmem_free(sn->ha, sizeof (struct dsl_ds_holdarg));
|
kmem_free(saa->saa_ha, sizeof (struct dsl_ds_holdarg));
|
||||||
sn->ha = NULL;
|
saa->saa_ha = NULL;
|
||||||
sn->newds = ds->ds_prev;
|
saa->saa_newds = ds->ds_prev;
|
||||||
|
|
||||||
da.ds = ds->ds_prev;
|
da.ds = ds->ds_prev;
|
||||||
da.defer = B_TRUE;
|
da.defer = B_TRUE;
|
||||||
@ -880,118 +892,169 @@ snapshot_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dmu_objset_snapshot_one(const char *name, void *arg)
|
snapshot_one_impl(const char *snapname, void *arg)
|
||||||
{
|
{
|
||||||
struct snaparg *sn = arg;
|
char fsname[MAXPATHLEN];
|
||||||
|
snapallarg_t *saa = arg;
|
||||||
|
snaponearg_t *soa;
|
||||||
objset_t *os;
|
objset_t *os;
|
||||||
int err;
|
int err;
|
||||||
char *cp;
|
|
||||||
|
|
||||||
/*
|
(void) strlcpy(fsname, snapname, sizeof (fsname));
|
||||||
* If the objset starts with a '%', then ignore it unless it was
|
strchr(fsname, '@')[0] = '\0';
|
||||||
* explicitly named (ie, not recursive). These hidden datasets
|
|
||||||
* are always inconsistent, and by not opening them here, we can
|
|
||||||
* avoid a race with dsl_dir_destroy_check().
|
|
||||||
*/
|
|
||||||
cp = strrchr(name, '/');
|
|
||||||
if (cp && cp[1] == '%' && sn->recursive)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
(void) strcpy(sn->failed, name);
|
err = dmu_objset_hold(fsname, saa, &os);
|
||||||
|
|
||||||
/*
|
|
||||||
* Check permissions if we are doing a recursive snapshot. The
|
|
||||||
* permission checks for the starting dataset have already been
|
|
||||||
* performed in zfs_secpolicy_snapshot()
|
|
||||||
*/
|
|
||||||
if (sn->recursive && (err = zfs_secpolicy_snapshot_perms(name, CRED())))
|
|
||||||
return (err);
|
|
||||||
|
|
||||||
err = dmu_objset_hold(name, sn, &os);
|
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return (err);
|
return (err);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the objset is in an inconsistent state (eg, in the process
|
* If the objset is in an inconsistent state (eg, in the process
|
||||||
* of being destroyed), don't snapshot it. As with %hidden
|
* of being destroyed), don't snapshot it.
|
||||||
* datasets, we return EBUSY if this name was explicitly
|
|
||||||
* requested (ie, not recursive), and otherwise ignore it.
|
|
||||||
*/
|
*/
|
||||||
if (os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) {
|
if (os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) {
|
||||||
dmu_objset_rele(os, sn);
|
dmu_objset_rele(os, saa);
|
||||||
return (sn->recursive ? 0 : EBUSY);
|
return (EBUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sn->needsuspend) {
|
if (saa->saa_needsuspend) {
|
||||||
err = zil_suspend(dmu_objset_zil(os));
|
err = zil_suspend(dmu_objset_zil(os));
|
||||||
if (err) {
|
if (err) {
|
||||||
dmu_objset_rele(os, sn);
|
dmu_objset_rele(os, saa);
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dsl_sync_task_create(sn->dstg, snapshot_check, snapshot_sync,
|
|
||||||
os, sn, 3);
|
soa = kmem_zalloc(sizeof (*soa), KM_SLEEP);
|
||||||
|
soa->soa_saa = saa;
|
||||||
|
soa->soa_longname = snapname;
|
||||||
|
soa->soa_snapname = strchr(snapname, '@') + 1;
|
||||||
|
|
||||||
|
dsl_sync_task_create(saa->saa_dstg, snapshot_check, snapshot_sync,
|
||||||
|
os, soa, 3);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The snapshots must all be in the same pool.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
dmu_objset_snapshot(char *fsname, char *snapname, char *tag,
|
dmu_objset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
|
||||||
nvlist_t *props, boolean_t recursive, boolean_t temporary, int cleanup_fd)
|
|
||||||
{
|
{
|
||||||
dsl_sync_task_t *dst;
|
dsl_sync_task_t *dst;
|
||||||
struct snaparg sn;
|
snapallarg_t saa = { 0 };
|
||||||
|
spa_t *spa;
|
||||||
|
int rv = 0;
|
||||||
|
int err;
|
||||||
|
nvpair_t *pair;
|
||||||
|
|
||||||
|
pair = nvlist_next_nvpair(snaps, NULL);
|
||||||
|
if (pair == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
err = spa_open(nvpair_name(pair), &spa, FTAG);
|
||||||
|
if (err)
|
||||||
|
return (err);
|
||||||
|
saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
|
||||||
|
saa.saa_props = props;
|
||||||
|
saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
|
||||||
|
|
||||||
|
for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
|
||||||
|
pair = nvlist_next_nvpair(snaps, pair)) {
|
||||||
|
err = snapshot_one_impl(nvpair_name(pair), &saa);
|
||||||
|
if (err != 0) {
|
||||||
|
if (errors != NULL) {
|
||||||
|
fnvlist_add_int32(errors,
|
||||||
|
nvpair_name(pair), err);
|
||||||
|
}
|
||||||
|
rv = err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If any call to snapshot_one_impl() failed, don't execute the
|
||||||
|
* sync task. The error handling code below will clean up the
|
||||||
|
* snaponearg_t from any successful calls to
|
||||||
|
* snapshot_one_impl().
|
||||||
|
*/
|
||||||
|
if (rv == 0)
|
||||||
|
err = dsl_sync_task_group_wait(saa.saa_dstg);
|
||||||
|
if (err != 0)
|
||||||
|
rv = err;
|
||||||
|
|
||||||
|
for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
|
||||||
|
dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
|
||||||
|
objset_t *os = dst->dst_arg1;
|
||||||
|
snaponearg_t *soa = dst->dst_arg2;
|
||||||
|
if (dst->dst_err != 0) {
|
||||||
|
if (errors != NULL) {
|
||||||
|
fnvlist_add_int32(errors,
|
||||||
|
soa->soa_longname, dst->dst_err);
|
||||||
|
}
|
||||||
|
rv = dst->dst_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saa.saa_needsuspend)
|
||||||
|
zil_resume(dmu_objset_zil(os));
|
||||||
|
dmu_objset_rele(os, &saa);
|
||||||
|
kmem_free(soa, sizeof (*soa));
|
||||||
|
}
|
||||||
|
|
||||||
|
dsl_sync_task_group_destroy(saa.saa_dstg);
|
||||||
|
spa_close(spa, FTAG);
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dmu_objset_snapshot_one(const char *fsname, const char *snapname)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
char *longsnap = kmem_asprintf("%s@%s", fsname, snapname);
|
||||||
|
nvlist_t *snaps = fnvlist_alloc();
|
||||||
|
|
||||||
|
fnvlist_add_boolean(snaps, longsnap);
|
||||||
|
err = dmu_objset_snapshot(snaps, NULL, NULL);
|
||||||
|
fnvlist_free(snaps);
|
||||||
|
strfree(longsnap);
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dmu_objset_snapshot_tmp(const char *snapname, const char *tag, int cleanup_fd)
|
||||||
|
{
|
||||||
|
dsl_sync_task_t *dst;
|
||||||
|
snapallarg_t saa = { 0 };
|
||||||
spa_t *spa;
|
spa_t *spa;
|
||||||
minor_t minor;
|
minor_t minor;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
(void) strcpy(sn.failed, fsname);
|
err = spa_open(snapname, &spa, FTAG);
|
||||||
|
|
||||||
err = spa_open(fsname, &spa, FTAG);
|
|
||||||
if (err)
|
if (err)
|
||||||
return (err);
|
return (err);
|
||||||
|
saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
|
||||||
|
saa.saa_htag = tag;
|
||||||
|
saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
|
||||||
|
saa.saa_temporary = B_TRUE;
|
||||||
|
|
||||||
if (temporary) {
|
if (cleanup_fd < 0) {
|
||||||
if (cleanup_fd < 0) {
|
spa_close(spa, FTAG);
|
||||||
spa_close(spa, FTAG);
|
return (EINVAL);
|
||||||
return (EINVAL);
|
}
|
||||||
}
|
if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
|
||||||
if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
|
spa_close(spa, FTAG);
|
||||||
spa_close(spa, FTAG);
|
return (err);
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
|
err = snapshot_one_impl(snapname, &saa);
|
||||||
sn.snapname = snapname;
|
|
||||||
sn.htag = tag;
|
|
||||||
sn.props = props;
|
|
||||||
sn.recursive = recursive;
|
|
||||||
sn.needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
|
|
||||||
sn.temporary = temporary;
|
|
||||||
sn.ha = NULL;
|
|
||||||
sn.newds = NULL;
|
|
||||||
|
|
||||||
if (recursive) {
|
|
||||||
err = dmu_objset_find(fsname,
|
|
||||||
dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN);
|
|
||||||
} else {
|
|
||||||
err = dmu_objset_snapshot_one(fsname, &sn);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
err = dsl_sync_task_group_wait(sn.dstg);
|
err = dsl_sync_task_group_wait(saa.saa_dstg);
|
||||||
|
|
||||||
for (dst = list_head(&sn.dstg->dstg_tasks); dst;
|
for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
|
||||||
dst = list_next(&sn.dstg->dstg_tasks, dst)) {
|
dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
|
||||||
objset_t *os = dst->dst_arg1;
|
objset_t *os = dst->dst_arg1;
|
||||||
dsl_dataset_t *ds = os->os_dsl_dataset;
|
dsl_register_onexit_hold_cleanup(saa.saa_newds, tag, minor);
|
||||||
if (dst->dst_err) {
|
if (saa.saa_needsuspend)
|
||||||
dsl_dataset_name(ds, sn.failed);
|
|
||||||
} else if (temporary) {
|
|
||||||
dsl_register_onexit_hold_cleanup(sn.newds, tag, minor);
|
|
||||||
}
|
|
||||||
if (sn.needsuspend)
|
|
||||||
zil_resume(dmu_objset_zil(os));
|
zil_resume(dmu_objset_zil(os));
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
@ -1005,18 +1068,16 @@ dmu_objset_snapshot(char *fsname, char *snapname, char *tag,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
dmu_objset_rele(os, &sn);
|
dmu_objset_rele(os, &saa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err)
|
zfs_onexit_fd_rele(cleanup_fd);
|
||||||
(void) strcpy(fsname, sn.failed);
|
dsl_sync_task_group_destroy(saa.saa_dstg);
|
||||||
if (temporary)
|
|
||||||
zfs_onexit_fd_rele(cleanup_fd);
|
|
||||||
dsl_sync_task_group_destroy(sn.dstg);
|
|
||||||
spa_close(spa, FTAG);
|
spa_close(spa, FTAG);
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dmu_objset_sync_dnodes(list_t *list, list_t *newlist, dmu_tx_t *tx)
|
dmu_objset_sync_dnodes(list_t *list, list_t *newlist, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
|
@ -403,9 +403,48 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
|||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE if 'earlier' is an earlier snapshot in 'later's timeline.
|
||||||
|
* For example, they could both be snapshots of the same filesystem, and
|
||||||
|
* 'earlier' is before 'later'. Or 'earlier' could be the origin of
|
||||||
|
* 'later's filesystem. Or 'earlier' could be an older snapshot in the origin's
|
||||||
|
* filesystem. Or 'earlier' could be the origin's origin.
|
||||||
|
*/
|
||||||
|
static boolean_t
|
||||||
|
is_before(dsl_dataset_t *later, dsl_dataset_t *earlier)
|
||||||
|
{
|
||||||
|
dsl_pool_t *dp = later->ds_dir->dd_pool;
|
||||||
|
int error;
|
||||||
|
boolean_t ret;
|
||||||
|
dsl_dataset_t *origin;
|
||||||
|
|
||||||
|
if (earlier->ds_phys->ds_creation_txg >=
|
||||||
|
later->ds_phys->ds_creation_txg)
|
||||||
|
return (B_FALSE);
|
||||||
|
|
||||||
|
if (later->ds_dir == earlier->ds_dir)
|
||||||
|
return (B_TRUE);
|
||||||
|
if (!dsl_dir_is_clone(later->ds_dir))
|
||||||
|
return (B_FALSE);
|
||||||
|
|
||||||
|
rw_enter(&dp->dp_config_rwlock, RW_READER);
|
||||||
|
if (later->ds_dir->dd_phys->dd_origin_obj == earlier->ds_object) {
|
||||||
|
rw_exit(&dp->dp_config_rwlock);
|
||||||
|
return (B_TRUE);
|
||||||
|
}
|
||||||
|
error = dsl_dataset_hold_obj(dp,
|
||||||
|
later->ds_dir->dd_phys->dd_origin_obj, FTAG, &origin);
|
||||||
|
rw_exit(&dp->dp_config_rwlock);
|
||||||
|
if (error != 0)
|
||||||
|
return (B_FALSE);
|
||||||
|
ret = is_before(origin, earlier);
|
||||||
|
dsl_dataset_rele(origin, FTAG);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dmu_send(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
|
dmu_send(objset_t *tosnap, objset_t *fromsnap, int outfd, struct file *fp,
|
||||||
int outfd, struct file *fp, offset_t *off)
|
offset_t *off)
|
||||||
{
|
{
|
||||||
dsl_dataset_t *ds = tosnap->os_dsl_dataset;
|
dsl_dataset_t *ds = tosnap->os_dsl_dataset;
|
||||||
dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
|
dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
|
||||||
@ -418,30 +457,13 @@ dmu_send(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
|
|||||||
if (ds->ds_phys->ds_next_snap_obj == 0)
|
if (ds->ds_phys->ds_next_snap_obj == 0)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
/* fromsnap must be an earlier snapshot from the same fs as tosnap */
|
/*
|
||||||
if (fromds && (ds->ds_dir != fromds->ds_dir ||
|
* fromsnap must be an earlier snapshot from the same fs as tosnap,
|
||||||
fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg))
|
* or the origin's fs.
|
||||||
|
*/
|
||||||
|
if (fromds != NULL && !is_before(ds, fromds))
|
||||||
return (EXDEV);
|
return (EXDEV);
|
||||||
|
|
||||||
if (fromorigin) {
|
|
||||||
dsl_pool_t *dp = ds->ds_dir->dd_pool;
|
|
||||||
|
|
||||||
if (fromsnap)
|
|
||||||
return (EINVAL);
|
|
||||||
|
|
||||||
if (dsl_dir_is_clone(ds->ds_dir)) {
|
|
||||||
rw_enter(&dp->dp_config_rwlock, RW_READER);
|
|
||||||
err = dsl_dataset_hold_obj(dp,
|
|
||||||
ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &fromds);
|
|
||||||
rw_exit(&dp->dp_config_rwlock);
|
|
||||||
if (err)
|
|
||||||
return (err);
|
|
||||||
} else {
|
|
||||||
fromorigin = B_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP);
|
drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP);
|
||||||
drr->drr_type = DRR_BEGIN;
|
drr->drr_type = DRR_BEGIN;
|
||||||
drr->drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
|
drr->drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
|
||||||
@ -466,7 +488,7 @@ dmu_send(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
|
|||||||
drr->drr_u.drr_begin.drr_creation_time =
|
drr->drr_u.drr_begin.drr_creation_time =
|
||||||
ds->ds_phys->ds_creation_time;
|
ds->ds_phys->ds_creation_time;
|
||||||
drr->drr_u.drr_begin.drr_type = tosnap->os_phys->os_type;
|
drr->drr_u.drr_begin.drr_type = tosnap->os_phys->os_type;
|
||||||
if (fromorigin)
|
if (fromds != NULL && ds->ds_dir != fromds->ds_dir)
|
||||||
drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE;
|
drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE;
|
||||||
drr->drr_u.drr_begin.drr_toguid = ds->ds_phys->ds_guid;
|
drr->drr_u.drr_begin.drr_toguid = ds->ds_phys->ds_guid;
|
||||||
if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET)
|
if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET)
|
||||||
@ -478,8 +500,6 @@ dmu_send(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
|
|||||||
|
|
||||||
if (fromds)
|
if (fromds)
|
||||||
fromtxg = fromds->ds_phys->ds_creation_txg;
|
fromtxg = fromds->ds_phys->ds_creation_txg;
|
||||||
if (fromorigin)
|
|
||||||
dsl_dataset_rele(fromds, FTAG);
|
|
||||||
|
|
||||||
dsp = kmem_zalloc(sizeof (dmu_sendarg_t), KM_SLEEP);
|
dsp = kmem_zalloc(sizeof (dmu_sendarg_t), KM_SLEEP);
|
||||||
|
|
||||||
@ -538,8 +558,7 @@ dmu_send(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
|
dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, uint64_t *sizep)
|
||||||
uint64_t *sizep)
|
|
||||||
{
|
{
|
||||||
dsl_dataset_t *ds = tosnap->os_dsl_dataset;
|
dsl_dataset_t *ds = tosnap->os_dsl_dataset;
|
||||||
dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
|
dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
|
||||||
@ -551,27 +570,13 @@ dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
|
|||||||
if (ds->ds_phys->ds_next_snap_obj == 0)
|
if (ds->ds_phys->ds_next_snap_obj == 0)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
/* fromsnap must be an earlier snapshot from the same fs as tosnap */
|
/*
|
||||||
if (fromds && (ds->ds_dir != fromds->ds_dir ||
|
* fromsnap must be an earlier snapshot from the same fs as tosnap,
|
||||||
fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg))
|
* or the origin's fs.
|
||||||
|
*/
|
||||||
|
if (fromds != NULL && !is_before(ds, fromds))
|
||||||
return (EXDEV);
|
return (EXDEV);
|
||||||
|
|
||||||
if (fromorigin) {
|
|
||||||
if (fromsnap)
|
|
||||||
return (EINVAL);
|
|
||||||
|
|
||||||
if (dsl_dir_is_clone(ds->ds_dir)) {
|
|
||||||
rw_enter(&dp->dp_config_rwlock, RW_READER);
|
|
||||||
err = dsl_dataset_hold_obj(dp,
|
|
||||||
ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &fromds);
|
|
||||||
rw_exit(&dp->dp_config_rwlock);
|
|
||||||
if (err)
|
|
||||||
return (err);
|
|
||||||
} else {
|
|
||||||
fromorigin = B_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get uncompressed size estimate of changed data. */
|
/* Get uncompressed size estimate of changed data. */
|
||||||
if (fromds == NULL) {
|
if (fromds == NULL) {
|
||||||
size = ds->ds_phys->ds_uncompressed_bytes;
|
size = ds->ds_phys->ds_uncompressed_bytes;
|
||||||
@ -579,8 +584,6 @@ dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
|
|||||||
uint64_t used, comp;
|
uint64_t used, comp;
|
||||||
err = dsl_dataset_space_written(fromds, ds,
|
err = dsl_dataset_space_written(fromds, ds,
|
||||||
&used, &comp, &size);
|
&used, &comp, &size);
|
||||||
if (fromorigin)
|
|
||||||
dsl_dataset_rele(fromds, FTAG);
|
|
||||||
if (err)
|
if (err)
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
@ -679,8 +682,7 @@ recv_new_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
rbsa->ds, &rbsa->ds->ds_phys->ds_bp, rbsa->type, tx);
|
rbsa->ds, &rbsa->ds->ds_phys->ds_bp, rbsa->type, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_REPLAY_FULL_SYNC,
|
spa_history_log_internal_ds(rbsa->ds, "receive new", tx, "");
|
||||||
dd->dd_pool->dp_spa, tx, "dataset = %lld", dsobj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
@ -781,8 +783,7 @@ recv_existing_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
|
|
||||||
rbsa->ds = cds;
|
rbsa->ds = cds;
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_REPLAY_INC_SYNC,
|
spa_history_log_internal_ds(cds, "receive over existing", tx, "");
|
||||||
dp->dp_spa, tx, "dataset = %lld", dsobj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean_t
|
static boolean_t
|
||||||
@ -1616,6 +1617,7 @@ recv_end_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
|
|
||||||
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
||||||
ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
|
ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
|
||||||
|
spa_history_log_internal_ds(ds, "finished receiving", tx, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -48,7 +48,7 @@ dmu_tx_create_dd(dsl_dir_t *dd)
|
|||||||
{
|
{
|
||||||
dmu_tx_t *tx = kmem_zalloc(sizeof (dmu_tx_t), KM_SLEEP);
|
dmu_tx_t *tx = kmem_zalloc(sizeof (dmu_tx_t), KM_SLEEP);
|
||||||
tx->tx_dir = dd;
|
tx->tx_dir = dd;
|
||||||
if (dd)
|
if (dd != NULL)
|
||||||
tx->tx_pool = dd->dd_pool;
|
tx->tx_pool = dd->dd_pool;
|
||||||
list_create(&tx->tx_holds, sizeof (dmu_tx_hold_t),
|
list_create(&tx->tx_holds, sizeof (dmu_tx_hold_t),
|
||||||
offsetof(dmu_tx_hold_t, txh_node));
|
offsetof(dmu_tx_hold_t, txh_node));
|
||||||
|
@ -947,7 +947,8 @@ dmu_get_recursive_snaps_nvl(const char *fsname, const char *snapname,
|
|||||||
* The snapshots must all be in the same pool.
|
* The snapshots must all be in the same pool.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
dmu_snapshots_destroy_nvl(nvlist_t *snaps, boolean_t defer, char *failed)
|
dmu_snapshots_destroy_nvl(nvlist_t *snaps, boolean_t defer,
|
||||||
|
nvlist_t *errlist)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
dsl_sync_task_t *dst;
|
dsl_sync_task_t *dst;
|
||||||
@ -982,7 +983,7 @@ dmu_snapshots_destroy_nvl(nvlist_t *snaps, boolean_t defer, char *failed)
|
|||||||
} else if (err == ENOENT) {
|
} else if (err == ENOENT) {
|
||||||
err = 0;
|
err = 0;
|
||||||
} else {
|
} else {
|
||||||
(void) strcpy(failed, nvpair_name(pair));
|
fnvlist_add_int32(errlist, nvpair_name(pair), err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -996,10 +997,12 @@ dmu_snapshots_destroy_nvl(nvlist_t *snaps, boolean_t defer, char *failed)
|
|||||||
dsl_dataset_t *ds = dsda->ds;
|
dsl_dataset_t *ds = dsda->ds;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the file system name that triggered the error
|
* Return the snapshots that triggered the error.
|
||||||
*/
|
*/
|
||||||
if (dst->dst_err) {
|
if (dst->dst_err != 0) {
|
||||||
dsl_dataset_name(ds, failed);
|
char name[ZFS_MAXNAMELEN];
|
||||||
|
dsl_dataset_name(ds, name);
|
||||||
|
fnvlist_add_int32(errlist, name, dst->dst_err);
|
||||||
}
|
}
|
||||||
ASSERT3P(dsda->rm_origin, ==, NULL);
|
ASSERT3P(dsda->rm_origin, ==, NULL);
|
||||||
dsl_dataset_disown(ds, dstg);
|
dsl_dataset_disown(ds, dstg);
|
||||||
@ -1078,7 +1081,6 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer)
|
|||||||
dsl_dir_t *dd;
|
dsl_dir_t *dd;
|
||||||
uint64_t obj;
|
uint64_t obj;
|
||||||
struct dsl_ds_destroyarg dsda = { 0 };
|
struct dsl_ds_destroyarg dsda = { 0 };
|
||||||
dsl_dataset_t dummy_ds = { 0 };
|
|
||||||
|
|
||||||
dsda.ds = ds;
|
dsda.ds = ds;
|
||||||
|
|
||||||
@ -1098,8 +1100,6 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dd = ds->ds_dir;
|
dd = ds->ds_dir;
|
||||||
dummy_ds.ds_dir = dd;
|
|
||||||
dummy_ds.ds_object = ds->ds_object;
|
|
||||||
|
|
||||||
if (!spa_feature_is_enabled(dsl_dataset_get_spa(ds),
|
if (!spa_feature_is_enabled(dsl_dataset_get_spa(ds),
|
||||||
&spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
|
&spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
|
||||||
@ -1181,7 +1181,7 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer)
|
|||||||
dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
|
dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
|
||||||
dsl_dataset_destroy_sync, &dsda, tag, 0);
|
dsl_dataset_destroy_sync, &dsda, tag, 0);
|
||||||
dsl_sync_task_create(dstg, dsl_dir_destroy_check,
|
dsl_sync_task_create(dstg, dsl_dir_destroy_check,
|
||||||
dsl_dir_destroy_sync, &dummy_ds, FTAG, 0);
|
dsl_dir_destroy_sync, dd, FTAG, 0);
|
||||||
err = dsl_sync_task_group_wait(dstg);
|
err = dsl_sync_task_group_wait(dstg);
|
||||||
dsl_sync_task_group_destroy(dstg);
|
dsl_sync_task_group_destroy(dstg);
|
||||||
|
|
||||||
@ -1367,14 +1367,12 @@ static void
|
|||||||
dsl_dataset_destroy_begin_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
dsl_dataset_destroy_begin_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_dataset_t *ds = arg1;
|
dsl_dataset_t *ds = arg1;
|
||||||
dsl_pool_t *dp = ds->ds_dir->dd_pool;
|
|
||||||
|
|
||||||
/* Mark it as inconsistent on-disk, in case we crash */
|
/* Mark it as inconsistent on-disk, in case we crash */
|
||||||
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
||||||
ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
|
ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_DESTROY_BEGIN, dp->dp_spa, tx,
|
spa_history_log_internal_ds(ds, "destroy begin", tx, "");
|
||||||
"dataset = %llu", ds->ds_object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1700,9 +1698,13 @@ dsl_dataset_destroy_sync(void *arg1, void *tag, dmu_tx_t *tx)
|
|||||||
ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
|
ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
|
||||||
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
||||||
ds->ds_phys->ds_flags |= DS_FLAG_DEFER_DESTROY;
|
ds->ds_phys->ds_flags |= DS_FLAG_DEFER_DESTROY;
|
||||||
|
spa_history_log_internal_ds(ds, "defer_destroy", tx, "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We need to log before removing it from the namespace. */
|
||||||
|
spa_history_log_internal_ds(ds, "destroy", tx, "");
|
||||||
|
|
||||||
/* signal any waiters that this dataset is going away */
|
/* signal any waiters that this dataset is going away */
|
||||||
mutex_enter(&ds->ds_lock);
|
mutex_enter(&ds->ds_lock);
|
||||||
ds->ds_owner = dsl_reaper;
|
ds->ds_owner = dsl_reaper;
|
||||||
@ -2000,8 +2002,6 @@ dsl_dataset_destroy_sync(void *arg1, void *tag, dmu_tx_t *tx)
|
|||||||
dsl_dataset_rele(ds_prev, FTAG);
|
dsl_dataset_rele(ds_prev, FTAG);
|
||||||
|
|
||||||
spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
|
spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
|
||||||
spa_history_log_internal(LOG_DS_DESTROY, dp->dp_spa, tx,
|
|
||||||
"dataset = %llu", ds->ds_object);
|
|
||||||
|
|
||||||
if (ds->ds_phys->ds_next_clones_obj != 0) {
|
if (ds->ds_phys->ds_next_clones_obj != 0) {
|
||||||
uint64_t count;
|
uint64_t count;
|
||||||
@ -2049,7 +2049,7 @@ dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx)
|
|||||||
return (ENOSPC);
|
return (ENOSPC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Propogate any reserved space for this snapshot to other
|
* Propagate any reserved space for this snapshot to other
|
||||||
* snapshot checks in this sync group.
|
* snapshot checks in this sync group.
|
||||||
*/
|
*/
|
||||||
if (asize > 0)
|
if (asize > 0)
|
||||||
@ -2059,10 +2059,9 @@ dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dsl_dataset_snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
dsl_dataset_snapshot_check(dsl_dataset_t *ds, const char *snapname,
|
||||||
|
dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_dataset_t *ds = arg1;
|
|
||||||
const char *snapname = arg2;
|
|
||||||
int err;
|
int err;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
|
|
||||||
@ -2074,7 +2073,7 @@ dsl_dataset_snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
return (EAGAIN);
|
return (EAGAIN);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for conflicting name snapshot name.
|
* Check for conflicting snapshot name.
|
||||||
*/
|
*/
|
||||||
err = dsl_dataset_snap_lookup(ds, snapname, &value);
|
err = dsl_dataset_snap_lookup(ds, snapname, &value);
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
@ -2098,10 +2097,9 @@ dsl_dataset_snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dsl_dataset_snapshot_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *snapname,
|
||||||
|
dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_dataset_t *ds = arg1;
|
|
||||||
const char *snapname = arg2;
|
|
||||||
dsl_pool_t *dp = ds->ds_dir->dd_pool;
|
dsl_pool_t *dp = ds->ds_dir->dd_pool;
|
||||||
dmu_buf_t *dbuf;
|
dmu_buf_t *dbuf;
|
||||||
dsl_dataset_phys_t *dsphys;
|
dsl_dataset_phys_t *dsphys;
|
||||||
@ -2209,8 +2207,7 @@ dsl_dataset_snapshot_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
|
|
||||||
dsl_dir_snap_cmtime_update(ds->ds_dir);
|
dsl_dir_snap_cmtime_update(ds->ds_dir);
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_SNAPSHOT, dp->dp_spa, tx,
|
spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, "");
|
||||||
"dataset = %llu", dsobj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2296,7 +2293,22 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
|
|||||||
{
|
{
|
||||||
uint64_t refd, avail, uobjs, aobjs, ratio;
|
uint64_t refd, avail, uobjs, aobjs, ratio;
|
||||||
|
|
||||||
dsl_dir_stats(ds->ds_dir, nv);
|
ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 :
|
||||||
|
(ds->ds_phys->ds_uncompressed_bytes * 100 /
|
||||||
|
ds->ds_phys->ds_compressed_bytes);
|
||||||
|
|
||||||
|
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
|
||||||
|
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALREFERENCED,
|
||||||
|
ds->ds_phys->ds_uncompressed_bytes);
|
||||||
|
|
||||||
|
if (dsl_dataset_is_snapshot(ds)) {
|
||||||
|
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio);
|
||||||
|
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
|
||||||
|
ds->ds_phys->ds_unique_bytes);
|
||||||
|
get_clones_stat(ds, nv);
|
||||||
|
} else {
|
||||||
|
dsl_dir_stats(ds->ds_dir, nv);
|
||||||
|
}
|
||||||
|
|
||||||
dsl_dataset_space(ds, &refd, &avail, &uobjs, &aobjs);
|
dsl_dataset_space(ds, &refd, &avail, &uobjs, &aobjs);
|
||||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_AVAILABLE, avail);
|
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_AVAILABLE, avail);
|
||||||
@ -2340,24 +2352,6 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 :
|
|
||||||
(ds->ds_phys->ds_uncompressed_bytes * 100 /
|
|
||||||
ds->ds_phys->ds_compressed_bytes);
|
|
||||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
|
|
||||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALREFERENCED,
|
|
||||||
ds->ds_phys->ds_uncompressed_bytes);
|
|
||||||
|
|
||||||
if (ds->ds_phys->ds_next_snap_obj) {
|
|
||||||
/*
|
|
||||||
* This is a snapshot; override the dd's space used with
|
|
||||||
* our unique space and compression ratio.
|
|
||||||
*/
|
|
||||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
|
|
||||||
ds->ds_phys->ds_unique_bytes);
|
|
||||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio);
|
|
||||||
|
|
||||||
get_clones_stat(ds, nv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2366,27 +2360,25 @@ dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_stats_t *stat)
|
|||||||
stat->dds_creation_txg = ds->ds_phys->ds_creation_txg;
|
stat->dds_creation_txg = ds->ds_phys->ds_creation_txg;
|
||||||
stat->dds_inconsistent = ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT;
|
stat->dds_inconsistent = ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT;
|
||||||
stat->dds_guid = ds->ds_phys->ds_guid;
|
stat->dds_guid = ds->ds_phys->ds_guid;
|
||||||
if (ds->ds_phys->ds_next_snap_obj) {
|
stat->dds_origin[0] = '\0';
|
||||||
|
if (dsl_dataset_is_snapshot(ds)) {
|
||||||
stat->dds_is_snapshot = B_TRUE;
|
stat->dds_is_snapshot = B_TRUE;
|
||||||
stat->dds_num_clones = ds->ds_phys->ds_num_children - 1;
|
stat->dds_num_clones = ds->ds_phys->ds_num_children - 1;
|
||||||
} else {
|
} else {
|
||||||
stat->dds_is_snapshot = B_FALSE;
|
stat->dds_is_snapshot = B_FALSE;
|
||||||
stat->dds_num_clones = 0;
|
stat->dds_num_clones = 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* clone origin is really a dsl_dir thing... */
|
rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
|
||||||
rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
|
if (dsl_dir_is_clone(ds->ds_dir)) {
|
||||||
if (dsl_dir_is_clone(ds->ds_dir)) {
|
dsl_dataset_t *ods;
|
||||||
dsl_dataset_t *ods;
|
|
||||||
|
|
||||||
VERIFY(0 == dsl_dataset_get_ref(ds->ds_dir->dd_pool,
|
VERIFY(0 == dsl_dataset_get_ref(ds->ds_dir->dd_pool,
|
||||||
ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &ods));
|
ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &ods));
|
||||||
dsl_dataset_name(ods, stat->dds_origin);
|
dsl_dataset_name(ods, stat->dds_origin);
|
||||||
dsl_dataset_drop_ref(ods, FTAG);
|
dsl_dataset_drop_ref(ods, FTAG);
|
||||||
} else {
|
}
|
||||||
stat->dds_origin[0] = '\0';
|
rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
|
||||||
}
|
}
|
||||||
rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
@ -2509,8 +2501,8 @@ dsl_dataset_snapshot_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
zvol_rename_minors(oldname, newname);
|
zvol_rename_minors(oldname, newname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_RENAME, dd->dd_pool->dp_spa, tx,
|
spa_history_log_internal_ds(ds, "rename", tx,
|
||||||
"dataset = %llu", ds->ds_object);
|
"-> @%s", newsnapname);
|
||||||
dsl_dataset_rele(hds, FTAG);
|
dsl_dataset_rele(hds, FTAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2996,8 +2988,7 @@ dsl_dataset_promote_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
origin_ds->ds_phys->ds_unique_bytes = pa->unique;
|
origin_ds->ds_phys->ds_unique_bytes = pa->unique;
|
||||||
|
|
||||||
/* log history record */
|
/* log history record */
|
||||||
spa_history_log_internal(LOG_DS_PROMOTE, dd->dd_pool->dp_spa, tx,
|
spa_history_log_internal_ds(hds, "promote", tx, "");
|
||||||
"dataset = %llu", hds->ds_object);
|
|
||||||
|
|
||||||
dsl_dir_close(odd, FTAG);
|
dsl_dir_close(odd, FTAG);
|
||||||
}
|
}
|
||||||
@ -3355,6 +3346,9 @@ dsl_dataset_clone_swap_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
csa->ohds->ds_phys->ds_deadlist_obj);
|
csa->ohds->ds_phys->ds_deadlist_obj);
|
||||||
|
|
||||||
dsl_scan_ds_clone_swapped(csa->ohds, csa->cds, tx);
|
dsl_scan_ds_clone_swapped(csa->ohds, csa->cds, tx);
|
||||||
|
|
||||||
|
spa_history_log_internal_ds(csa->cds, "clone swap", tx,
|
||||||
|
"parent=%s", csa->ohds->ds_dir->dd_myname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3678,7 +3672,7 @@ dsl_dataset_user_hold_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
{
|
{
|
||||||
dsl_dataset_t *ds = arg1;
|
dsl_dataset_t *ds = arg1;
|
||||||
struct dsl_ds_holdarg *ha = arg2;
|
struct dsl_ds_holdarg *ha = arg2;
|
||||||
char *htag = ha->htag;
|
const char *htag = ha->htag;
|
||||||
objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
|
objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
@ -3712,7 +3706,7 @@ dsl_dataset_user_hold_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
{
|
{
|
||||||
dsl_dataset_t *ds = arg1;
|
dsl_dataset_t *ds = arg1;
|
||||||
struct dsl_ds_holdarg *ha = arg2;
|
struct dsl_ds_holdarg *ha = arg2;
|
||||||
char *htag = ha->htag;
|
const char *htag = ha->htag;
|
||||||
dsl_pool_t *dp = ds->ds_dir->dd_pool;
|
dsl_pool_t *dp = ds->ds_dir->dd_pool;
|
||||||
objset_t *mos = dp->dp_meta_objset;
|
objset_t *mos = dp->dp_meta_objset;
|
||||||
uint64_t now = gethrestime_sec();
|
uint64_t now = gethrestime_sec();
|
||||||
@ -3740,9 +3734,9 @@ dsl_dataset_user_hold_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
htag, &now, tx));
|
htag, &now, tx));
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_USER_HOLD,
|
spa_history_log_internal_ds(ds, "hold", tx,
|
||||||
dp->dp_spa, tx, "<%s> temp = %d dataset = %llu", htag,
|
"tag = %s temp = %d holds now = %llu",
|
||||||
(int)ha->temphold, ds->ds_object);
|
htag, (int)ha->temphold, ds->ds_userrefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -3949,7 +3943,6 @@ dsl_dataset_user_release_sync(void *arg1, void *tag, dmu_tx_t *tx)
|
|||||||
dsl_pool_t *dp = ds->ds_dir->dd_pool;
|
dsl_pool_t *dp = ds->ds_dir->dd_pool;
|
||||||
objset_t *mos = dp->dp_meta_objset;
|
objset_t *mos = dp->dp_meta_objset;
|
||||||
uint64_t zapobj;
|
uint64_t zapobj;
|
||||||
uint64_t dsobj = ds->ds_object;
|
|
||||||
uint64_t refs;
|
uint64_t refs;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
@ -3962,9 +3955,8 @@ dsl_dataset_user_release_sync(void *arg1, void *tag, dmu_tx_t *tx)
|
|||||||
zapobj = ds->ds_phys->ds_userrefs_obj;
|
zapobj = ds->ds_phys->ds_userrefs_obj;
|
||||||
VERIFY(0 == zap_remove(mos, zapobj, ra->htag, tx));
|
VERIFY(0 == zap_remove(mos, zapobj, ra->htag, tx));
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_USER_RELEASE,
|
spa_history_log_internal_ds(ds, "release", tx,
|
||||||
dp->dp_spa, tx, "<%s> %lld dataset = %llu",
|
"tag = %s refs now = %lld", ra->htag, (longlong_t)refs);
|
||||||
ra->htag, (longlong_t)refs, dsobj);
|
|
||||||
|
|
||||||
if (ds->ds_userrefs == 0 && ds->ds_phys->ds_num_children == 1 &&
|
if (ds->ds_userrefs == 0 && ds->ds_phys->ds_num_children == 1 &&
|
||||||
DS_IS_DEFER_DESTROY(ds)) {
|
DS_IS_DEFER_DESTROY(ds)) {
|
||||||
|
@ -181,10 +181,8 @@ dsl_deleg_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
|
|
||||||
VERIFY(zap_update(mos, jumpobj,
|
VERIFY(zap_update(mos, jumpobj,
|
||||||
perm, 8, 1, &n, tx) == 0);
|
perm, 8, 1, &n, tx) == 0);
|
||||||
spa_history_log_internal(LOG_DS_PERM_UPDATE,
|
spa_history_log_internal_dd(dd, "permission update", tx,
|
||||||
dd->dd_pool->dp_spa, tx,
|
"%s %s", whokey, perm);
|
||||||
"%s %s dataset = %llu", whokey, perm,
|
|
||||||
dd->dd_phys->dd_head_dataset_obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,10 +211,8 @@ dsl_deleg_unset_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
(void) zap_remove(mos, zapobj, whokey, tx);
|
(void) zap_remove(mos, zapobj, whokey, tx);
|
||||||
VERIFY(0 == zap_destroy(mos, jumpobj, tx));
|
VERIFY(0 == zap_destroy(mos, jumpobj, tx));
|
||||||
}
|
}
|
||||||
spa_history_log_internal(LOG_DS_PERM_WHO_REMOVE,
|
spa_history_log_internal_dd(dd, "permission who remove",
|
||||||
dd->dd_pool->dp_spa, tx,
|
tx, "%s", whokey);
|
||||||
"%s dataset = %llu", whokey,
|
|
||||||
dd->dd_phys->dd_head_dataset_obj);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,10 +230,8 @@ dsl_deleg_unset_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
VERIFY(0 == zap_destroy(mos,
|
VERIFY(0 == zap_destroy(mos,
|
||||||
jumpobj, tx));
|
jumpobj, tx));
|
||||||
}
|
}
|
||||||
spa_history_log_internal(LOG_DS_PERM_REMOVE,
|
spa_history_log_internal_dd(dd, "permission remove", tx,
|
||||||
dd->dd_pool->dp_spa, tx,
|
"%s %s", whokey, perm);
|
||||||
"%s %s dataset = %llu", whokey, perm,
|
|
||||||
dd->dd_phys->dd_head_dataset_obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -524,12 +518,10 @@ dsl_load_user_sets(objset_t *mos, uint64_t zapobj, avl_tree_t *avl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if user has requested permission. If descendent is set, must have
|
* Check if user has requested permission.
|
||||||
* descendent perms.
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
dsl_deleg_access_impl(dsl_dataset_t *ds, boolean_t descendent, const char *perm,
|
dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr)
|
||||||
cred_t *cr)
|
|
||||||
{
|
{
|
||||||
dsl_dir_t *dd;
|
dsl_dir_t *dd;
|
||||||
dsl_pool_t *dp;
|
dsl_pool_t *dp;
|
||||||
@ -550,7 +542,7 @@ dsl_deleg_access_impl(dsl_dataset_t *ds, boolean_t descendent, const char *perm,
|
|||||||
SPA_VERSION_DELEGATED_PERMS)
|
SPA_VERSION_DELEGATED_PERMS)
|
||||||
return (EPERM);
|
return (EPERM);
|
||||||
|
|
||||||
if (dsl_dataset_is_snapshot(ds) || descendent) {
|
if (dsl_dataset_is_snapshot(ds)) {
|
||||||
/*
|
/*
|
||||||
* Snapshots are treated as descendents only,
|
* Snapshots are treated as descendents only,
|
||||||
* local permissions do not apply.
|
* local permissions do not apply.
|
||||||
@ -643,7 +635,7 @@ dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
|
|||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
error = dsl_deleg_access_impl(ds, B_FALSE, perm, cr);
|
error = dsl_deleg_access_impl(ds, perm, cr);
|
||||||
dsl_dataset_rele(ds, FTAG);
|
dsl_dataset_rele(ds, FTAG);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/dmu.h>
|
#include <sys/dmu.h>
|
||||||
@ -45,8 +46,8 @@
|
|||||||
#include "zfs_namecheck.h"
|
#include "zfs_namecheck.h"
|
||||||
|
|
||||||
static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
|
static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
|
||||||
static void dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx);
|
static void dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd,
|
||||||
|
uint64_t value, dmu_tx_t *tx);
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
static void
|
static void
|
||||||
@ -452,8 +453,7 @@ dsl_dir_create_sync(dsl_pool_t *dp, dsl_dir_t *pds, const char *name,
|
|||||||
int
|
int
|
||||||
dsl_dir_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
dsl_dir_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_dataset_t *ds = arg1;
|
dsl_dir_t *dd = arg1;
|
||||||
dsl_dir_t *dd = ds->ds_dir;
|
|
||||||
dsl_pool_t *dp = dd->dd_pool;
|
dsl_pool_t *dp = dd->dd_pool;
|
||||||
objset_t *mos = dp->dp_meta_objset;
|
objset_t *mos = dp->dp_meta_objset;
|
||||||
int err;
|
int err;
|
||||||
@ -484,24 +484,19 @@ dsl_dir_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
void
|
void
|
||||||
dsl_dir_destroy_sync(void *arg1, void *tag, dmu_tx_t *tx)
|
dsl_dir_destroy_sync(void *arg1, void *tag, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_dataset_t *ds = arg1;
|
dsl_dir_t *dd = arg1;
|
||||||
dsl_dir_t *dd = ds->ds_dir;
|
|
||||||
objset_t *mos = dd->dd_pool->dp_meta_objset;
|
objset_t *mos = dd->dd_pool->dp_meta_objset;
|
||||||
dsl_prop_setarg_t psa;
|
|
||||||
uint64_t value = 0;
|
|
||||||
uint64_t obj;
|
uint64_t obj;
|
||||||
dd_used_t t;
|
dd_used_t t;
|
||||||
|
|
||||||
ASSERT(RW_WRITE_HELD(&dd->dd_pool->dp_config_rwlock));
|
ASSERT(RW_WRITE_HELD(&dd->dd_pool->dp_config_rwlock));
|
||||||
ASSERT(dd->dd_phys->dd_head_dataset_obj == 0);
|
ASSERT(dd->dd_phys->dd_head_dataset_obj == 0);
|
||||||
|
|
||||||
/* Remove our reservation. */
|
/*
|
||||||
dsl_prop_setarg_init_uint64(&psa, "reservation",
|
* Remove our reservation. The impl() routine avoids setting the
|
||||||
(ZPROP_SRC_NONE | ZPROP_SRC_LOCAL | ZPROP_SRC_RECEIVED),
|
* actual property, which would require the (already destroyed) ds.
|
||||||
&value);
|
*/
|
||||||
psa.psa_effective_value = 0; /* predict default value */
|
dsl_dir_set_reservation_sync_impl(dd, 0, tx);
|
||||||
|
|
||||||
dsl_dir_set_reservation_sync(ds, &psa, tx);
|
|
||||||
|
|
||||||
ASSERT0(dd->dd_phys->dd_used_bytes);
|
ASSERT0(dd->dd_phys->dd_used_bytes);
|
||||||
ASSERT0(dd->dd_phys->dd_reserved);
|
ASSERT0(dd->dd_phys->dd_reserved);
|
||||||
@ -1151,25 +1146,17 @@ dsl_dir_set_reservation_check(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_dataset_t *ds = arg1;
|
|
||||||
dsl_dir_t *dd = ds->ds_dir;
|
|
||||||
dsl_prop_setarg_t *psa = arg2;
|
|
||||||
uint64_t effective_value = psa->psa_effective_value;
|
|
||||||
uint64_t used;
|
uint64_t used;
|
||||||
int64_t delta;
|
int64_t delta;
|
||||||
|
|
||||||
dsl_prop_set_sync(ds, psa, tx);
|
|
||||||
DSL_PROP_CHECK_PREDICTION(dd, psa);
|
|
||||||
|
|
||||||
dmu_buf_will_dirty(dd->dd_dbuf, tx);
|
dmu_buf_will_dirty(dd->dd_dbuf, tx);
|
||||||
|
|
||||||
mutex_enter(&dd->dd_lock);
|
mutex_enter(&dd->dd_lock);
|
||||||
used = dd->dd_phys->dd_used_bytes;
|
used = dd->dd_phys->dd_used_bytes;
|
||||||
delta = MAX(used, effective_value) -
|
delta = MAX(used, value) - MAX(used, dd->dd_phys->dd_reserved);
|
||||||
MAX(used, dd->dd_phys->dd_reserved);
|
dd->dd_phys->dd_reserved = value;
|
||||||
dd->dd_phys->dd_reserved = effective_value;
|
|
||||||
|
|
||||||
if (dd->dd_parent != NULL) {
|
if (dd->dd_parent != NULL) {
|
||||||
/* Roll up this additional usage into our ancestors */
|
/* Roll up this additional usage into our ancestors */
|
||||||
@ -1179,6 +1166,23 @@ dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
mutex_exit(&dd->dd_lock);
|
mutex_exit(&dd->dd_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||||
|
{
|
||||||
|
dsl_dataset_t *ds = arg1;
|
||||||
|
dsl_dir_t *dd = ds->ds_dir;
|
||||||
|
dsl_prop_setarg_t *psa = arg2;
|
||||||
|
uint64_t value = psa->psa_effective_value;
|
||||||
|
|
||||||
|
dsl_prop_set_sync(ds, psa, tx);
|
||||||
|
DSL_PROP_CHECK_PREDICTION(dd, psa);
|
||||||
|
|
||||||
|
dsl_dir_set_reservation_sync_impl(dd, value, tx);
|
||||||
|
|
||||||
|
spa_history_log_internal_dd(dd, "set reservation", tx,
|
||||||
|
"reservation=%lld", (longlong_t)value);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
|
dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
|
||||||
uint64_t reservation)
|
uint64_t reservation)
|
||||||
@ -1302,9 +1306,15 @@ dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
dsl_pool_t *dp = dd->dd_pool;
|
dsl_pool_t *dp = dd->dd_pool;
|
||||||
objset_t *mos = dp->dp_meta_objset;
|
objset_t *mos = dp->dp_meta_objset;
|
||||||
int err;
|
int err;
|
||||||
|
char namebuf[MAXNAMELEN];
|
||||||
|
|
||||||
ASSERT(ra->allowmounted || dmu_buf_refcount(dd->dd_dbuf) <= 2);
|
ASSERT(ra->allowmounted || dmu_buf_refcount(dd->dd_dbuf) <= 2);
|
||||||
|
|
||||||
|
/* Log this before we change the name. */
|
||||||
|
dsl_dir_name(ra->newparent, namebuf);
|
||||||
|
spa_history_log_internal_dd(dd, "rename", tx,
|
||||||
|
"-> %s/%s", namebuf, ra->mynewname);
|
||||||
|
|
||||||
if (ra->newparent != dd->dd_parent) {
|
if (ra->newparent != dd->dd_parent) {
|
||||||
dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD,
|
dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD,
|
||||||
-dd->dd_phys->dd_used_bytes,
|
-dd->dd_phys->dd_used_bytes,
|
||||||
@ -1350,8 +1360,6 @@ dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
zvol_rename_minors(oldname, newname);
|
zvol_rename_minors(oldname, newname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_RENAME, dd->dd_pool->dp_spa,
|
|
||||||
tx, "dataset = %llu", dd->dd_phys->dd_head_dataset_obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/zfs_context.h>
|
#include <sys/zfs_context.h>
|
||||||
@ -702,11 +703,9 @@ dsl_prop_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_history_log_internal((source == ZPROP_SRC_NONE ||
|
spa_history_log_internal_ds(ds, (source == ZPROP_SRC_NONE ||
|
||||||
source == ZPROP_SRC_INHERITED) ? LOG_DS_INHERIT :
|
source == ZPROP_SRC_INHERITED) ? "inherit" : "set", tx,
|
||||||
LOG_DS_PROPSET, ds->ds_dir->dd_pool->dp_spa, tx,
|
"%s=%s", propname, (valstr == NULL ? "" : valstr));
|
||||||
"%s=%s dataset = %llu", propname,
|
|
||||||
(valstr == NULL ? "" : valstr), ds->ds_object);
|
|
||||||
|
|
||||||
if (tbuf != NULL)
|
if (tbuf != NULL)
|
||||||
kmem_free(tbuf, ZAP_MAXVALUELEN);
|
kmem_free(tbuf, ZAP_MAXVALUELEN);
|
||||||
@ -755,24 +754,6 @@ dsl_props_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
dsl_dir_prop_set_uint64_sync(dsl_dir_t *dd, const char *name, uint64_t val,
|
|
||||||
dmu_tx_t *tx)
|
|
||||||
{
|
|
||||||
objset_t *mos = dd->dd_pool->dp_meta_objset;
|
|
||||||
uint64_t zapobj = dd->dd_phys->dd_props_zapobj;
|
|
||||||
|
|
||||||
ASSERT(dmu_tx_is_syncing(tx));
|
|
||||||
|
|
||||||
VERIFY(0 == zap_update(mos, zapobj, name, sizeof (val), 1, &val, tx));
|
|
||||||
|
|
||||||
dsl_prop_changed_notify(dd->dd_pool, dd->dd_object, name, val, TRUE);
|
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_PROPSET, dd->dd_pool->dp_spa, tx,
|
|
||||||
"%s=%llu dataset = %llu", name, (u_longlong_t)val,
|
|
||||||
dd->dd_phys->dd_head_dataset_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
dsl_prop_set(const char *dsname, const char *propname, zprop_source_t source,
|
dsl_prop_set(const char *dsname, const char *propname, zprop_source_t source,
|
||||||
int intsz, int numints, const void *buf)
|
int intsz, int numints, const void *buf)
|
||||||
|
@ -258,7 +258,7 @@ dsl_scan_setup_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
|
|
||||||
dsl_scan_sync_state(scn, tx);
|
dsl_scan_sync_state(scn, tx);
|
||||||
|
|
||||||
spa_history_log_internal(LOG_POOL_SCAN, spa, tx,
|
spa_history_log_internal(spa, "scan setup", tx,
|
||||||
"func=%u mintxg=%llu maxtxg=%llu",
|
"func=%u mintxg=%llu maxtxg=%llu",
|
||||||
*funcp, scn->scn_phys.scn_min_txg, scn->scn_phys.scn_max_txg);
|
*funcp, scn->scn_phys.scn_min_txg, scn->scn_phys.scn_max_txg);
|
||||||
}
|
}
|
||||||
@ -307,7 +307,7 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
|
|||||||
else
|
else
|
||||||
scn->scn_phys.scn_state = DSS_CANCELED;
|
scn->scn_phys.scn_state = DSS_CANCELED;
|
||||||
|
|
||||||
spa_history_log_internal(LOG_POOL_SCAN_DONE, spa, tx,
|
spa_history_log_internal(spa, "scan done", tx,
|
||||||
"complete=%u", complete);
|
"complete=%u", complete);
|
||||||
|
|
||||||
if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
|
if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/dmu.h>
|
#include <sys/dmu.h>
|
||||||
@ -85,17 +86,17 @@ dsl_sync_task_group_wait(dsl_sync_task_group_t *dstg)
|
|||||||
|
|
||||||
/* Do a preliminary error check. */
|
/* Do a preliminary error check. */
|
||||||
dstg->dstg_err = 0;
|
dstg->dstg_err = 0;
|
||||||
|
#ifdef ZFS_DEBUG
|
||||||
|
/*
|
||||||
|
* Only check half the time, otherwise, the sync-context
|
||||||
|
* check will almost never fail.
|
||||||
|
*/
|
||||||
|
if (spa_get_random(2) == 0)
|
||||||
|
goto skip;
|
||||||
|
#endif
|
||||||
rw_enter(&dstg->dstg_pool->dp_config_rwlock, RW_READER);
|
rw_enter(&dstg->dstg_pool->dp_config_rwlock, RW_READER);
|
||||||
for (dst = list_head(&dstg->dstg_tasks); dst;
|
for (dst = list_head(&dstg->dstg_tasks); dst;
|
||||||
dst = list_next(&dstg->dstg_tasks, dst)) {
|
dst = list_next(&dstg->dstg_tasks, dst)) {
|
||||||
#ifdef ZFS_DEBUG
|
|
||||||
/*
|
|
||||||
* Only check half the time, otherwise, the sync-context
|
|
||||||
* check will almost never fail.
|
|
||||||
*/
|
|
||||||
if (spa_get_random(2) == 0)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
dst->dst_err =
|
dst->dst_err =
|
||||||
dst->dst_checkfunc(dst->dst_arg1, dst->dst_arg2, tx);
|
dst->dst_checkfunc(dst->dst_arg1, dst->dst_arg2, tx);
|
||||||
if (dst->dst_err)
|
if (dst->dst_err)
|
||||||
@ -107,6 +108,7 @@ dsl_sync_task_group_wait(dsl_sync_task_group_t *dstg)
|
|||||||
dmu_tx_commit(tx);
|
dmu_tx_commit(tx);
|
||||||
return (dstg->dstg_err);
|
return (dstg->dstg_err);
|
||||||
}
|
}
|
||||||
|
skip:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't generally have many sync tasks, so pay the price of
|
* We don't generally have many sync tasks, so pay the price of
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <sys/refcount.h>
|
#include <sys/refcount.h>
|
||||||
#include <sys/rrwlock.h>
|
#include <sys/rrwlock.h>
|
||||||
@ -262,3 +265,13 @@ rrw_held(rrwlock_t *rrl, krw_t rw)
|
|||||||
|
|
||||||
return (held);
|
return (held);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rrw_tsd_destroy(void *arg)
|
||||||
|
{
|
||||||
|
rrw_node_t *rn = arg;
|
||||||
|
if (rn != NULL) {
|
||||||
|
panic("thread %p terminating with rrw lock %p held",
|
||||||
|
(void *)curthread, (void *)rn->rn_rrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -729,17 +729,8 @@ spa_change_guid_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
vdev_config_dirty(rvd);
|
vdev_config_dirty(rvd);
|
||||||
spa_config_exit(spa, SCL_STATE, FTAG);
|
spa_config_exit(spa, SCL_STATE, FTAG);
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
spa_history_log_internal(spa, "guid change", tx, "old=%llu new=%llu",
|
||||||
/*
|
|
||||||
* TODO: until recent illumos logging changes are merged
|
|
||||||
* log reguid as pool property change
|
|
||||||
*/
|
|
||||||
spa_history_log_internal(LOG_POOL_PROPSET, spa, tx,
|
|
||||||
"guid change old=%llu new=%llu", oldguid, *newguid);
|
|
||||||
#else
|
|
||||||
spa_history_log_internal(spa, "guid change", tx, "old=%lld new=%lld",
|
|
||||||
oldguid, *newguid);
|
oldguid, *newguid);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2642,6 +2633,12 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
|
|||||||
vdev_resilver_needed(rvd, NULL, NULL))
|
vdev_resilver_needed(rvd, NULL, NULL))
|
||||||
spa_async_request(spa, SPA_ASYNC_RESILVER);
|
spa_async_request(spa, SPA_ASYNC_RESILVER);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Log the fact that we booted up (so that we can detect if
|
||||||
|
* we rebooted in the middle of an operation).
|
||||||
|
*/
|
||||||
|
spa_history_log_version(spa, "open");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete any inconsistent datasets.
|
* Delete any inconsistent datasets.
|
||||||
*/
|
*/
|
||||||
@ -3327,7 +3324,7 @@ spa_l2cache_drop(spa_t *spa)
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
||||||
const char *history_str, nvlist_t *zplprops)
|
nvlist_t *zplprops)
|
||||||
{
|
{
|
||||||
spa_t *spa;
|
spa_t *spa;
|
||||||
char *altroot = NULL;
|
char *altroot = NULL;
|
||||||
@ -3546,9 +3543,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||||||
|
|
||||||
spa_config_sync(spa, B_FALSE, B_TRUE);
|
spa_config_sync(spa, B_FALSE, B_TRUE);
|
||||||
|
|
||||||
if (version >= SPA_VERSION_ZPOOL_HISTORY && history_str != NULL)
|
spa_history_log_version(spa, "create");
|
||||||
(void) spa_history_log(spa, history_str, LOG_CMD_POOL_CREATE);
|
|
||||||
spa_history_log_version(spa, LOG_POOL_CREATE);
|
|
||||||
|
|
||||||
spa->spa_minref = refcount_count(&spa->spa_refcount);
|
spa->spa_minref = refcount_count(&spa->spa_refcount);
|
||||||
|
|
||||||
@ -3749,7 +3744,6 @@ spa_import_rootpool(char *devpath, char *devid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
spa_history_log_version(spa, LOG_POOL_IMPORT);
|
|
||||||
out:
|
out:
|
||||||
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
|
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
|
||||||
vdev_free(rvd);
|
vdev_free(rvd);
|
||||||
@ -4006,7 +4000,7 @@ spa_import(const char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
|
|||||||
spa_config_sync(spa, B_FALSE, B_TRUE);
|
spa_config_sync(spa, B_FALSE, B_TRUE);
|
||||||
|
|
||||||
mutex_exit(&spa_namespace_lock);
|
mutex_exit(&spa_namespace_lock);
|
||||||
spa_history_log_version(spa, LOG_POOL_IMPORT);
|
spa_history_log_version(spa, "import");
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -4137,7 +4131,7 @@ spa_import(const char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
|
|||||||
spa_async_request(spa, SPA_ASYNC_AUTOEXPAND);
|
spa_async_request(spa, SPA_ASYNC_AUTOEXPAND);
|
||||||
|
|
||||||
mutex_exit(&spa_namespace_lock);
|
mutex_exit(&spa_namespace_lock);
|
||||||
spa_history_log_version(spa, LOG_POOL_IMPORT);
|
spa_history_log_version(spa, "import");
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
@ -4680,7 +4674,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
|
|||||||
*/
|
*/
|
||||||
(void) spa_vdev_exit(spa, newrootvd, dtl_max_txg, 0);
|
(void) spa_vdev_exit(spa, newrootvd, dtl_max_txg, 0);
|
||||||
|
|
||||||
spa_history_log_internal(LOG_POOL_VDEV_ATTACH, spa, NULL,
|
spa_history_log_internal(spa, "vdev attach", NULL,
|
||||||
"%s vdev=%s %s vdev=%s",
|
"%s vdev=%s %s vdev=%s",
|
||||||
replacing && newvd_isspare ? "spare in" :
|
replacing && newvd_isspare ? "spare in" :
|
||||||
replacing ? "replace" : "attach", newvdpath,
|
replacing ? "replace" : "attach", newvdpath,
|
||||||
@ -4897,7 +4891,7 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
|
|||||||
|
|
||||||
error = spa_vdev_exit(spa, vd, txg, 0);
|
error = spa_vdev_exit(spa, vd, txg, 0);
|
||||||
|
|
||||||
spa_history_log_internal(LOG_POOL_VDEV_DETACH, spa, NULL,
|
spa_history_log_internal(spa, "detach", NULL,
|
||||||
"vdev=%s", vdpath);
|
"vdev=%s", vdpath);
|
||||||
spa_strfree(vdpath);
|
spa_strfree(vdpath);
|
||||||
|
|
||||||
@ -5173,9 +5167,8 @@ spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config,
|
|||||||
if (vml[c] != NULL) {
|
if (vml[c] != NULL) {
|
||||||
vdev_split(vml[c]);
|
vdev_split(vml[c]);
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
spa_history_log_internal(LOG_POOL_VDEV_DETACH,
|
spa_history_log_internal(spa, "detach", tx,
|
||||||
spa, tx, "vdev=%s",
|
"vdev=%s", vml[c]->vdev_path);
|
||||||
vml[c]->vdev_path);
|
|
||||||
vdev_free(vml[c]);
|
vdev_free(vml[c]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5190,8 +5183,8 @@ spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config,
|
|||||||
zio_handle_panic_injection(spa, FTAG, 3);
|
zio_handle_panic_injection(spa, FTAG, 3);
|
||||||
|
|
||||||
/* split is complete; log a history record */
|
/* split is complete; log a history record */
|
||||||
spa_history_log_internal(LOG_POOL_SPLIT, newspa, NULL,
|
spa_history_log_internal(newspa, "split", NULL,
|
||||||
"split new pool %s from pool %s", newname, spa_name(spa));
|
"from pool %s", spa_name(spa));
|
||||||
|
|
||||||
kmem_free(vml, children * sizeof (vdev_t *));
|
kmem_free(vml, children * sizeof (vdev_t *));
|
||||||
|
|
||||||
@ -5778,8 +5771,7 @@ spa_async_thread(void *arg)
|
|||||||
* then log an internal history event.
|
* then log an internal history event.
|
||||||
*/
|
*/
|
||||||
if (new_space != old_space) {
|
if (new_space != old_space) {
|
||||||
spa_history_log_internal(LOG_POOL_VDEV_ONLINE,
|
spa_history_log_internal(spa, "vdev online", NULL,
|
||||||
spa, NULL,
|
|
||||||
"pool '%s' size: %llu(+%llu)",
|
"pool '%s' size: %llu(+%llu)",
|
||||||
spa_name(spa), new_space, new_space - old_space);
|
spa_name(spa), new_space, new_space - old_space);
|
||||||
}
|
}
|
||||||
@ -6023,6 +6015,7 @@ spa_sync_version(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
|
|
||||||
spa->spa_uberblock.ub_version = version;
|
spa->spa_uberblock.ub_version = version;
|
||||||
vdev_config_dirty(spa->spa_root_vdev);
|
vdev_config_dirty(spa->spa_root_vdev);
|
||||||
|
spa_history_log_internal(spa, "set", tx, "version=%lld", version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6057,6 +6050,8 @@ spa_sync_props(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
VERIFY3U(0, ==, zfeature_lookup_name(fname, &feature));
|
VERIFY3U(0, ==, zfeature_lookup_name(fname, &feature));
|
||||||
|
|
||||||
spa_feature_enable(spa, feature, tx);
|
spa_feature_enable(spa, feature, tx);
|
||||||
|
spa_history_log_internal(spa, "set", tx,
|
||||||
|
"%s=enabled", nvpair_name(elem));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_PROP_VERSION:
|
case ZPOOL_PROP_VERSION:
|
||||||
@ -6096,6 +6091,8 @@ spa_sync_props(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
*/
|
*/
|
||||||
if (tx->tx_txg != TXG_INITIAL)
|
if (tx->tx_txg != TXG_INITIAL)
|
||||||
vdev_config_dirty(spa->spa_root_vdev);
|
vdev_config_dirty(spa->spa_root_vdev);
|
||||||
|
spa_history_log_internal(spa, "set", tx,
|
||||||
|
"%s=%s", nvpair_name(elem), strval);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
@ -6118,7 +6115,8 @@ spa_sync_props(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
VERIFY(zap_update(mos,
|
VERIFY(zap_update(mos,
|
||||||
spa->spa_pool_props_object, propname,
|
spa->spa_pool_props_object, propname,
|
||||||
1, strlen(strval) + 1, strval, tx) == 0);
|
1, strlen(strval) + 1, strval, tx) == 0);
|
||||||
|
spa_history_log_internal(spa, "set", tx,
|
||||||
|
"%s=%s", nvpair_name(elem), strval);
|
||||||
} else if (nvpair_type(elem) == DATA_TYPE_UINT64) {
|
} else if (nvpair_type(elem) == DATA_TYPE_UINT64) {
|
||||||
VERIFY(nvpair_value_uint64(elem, &intval) == 0);
|
VERIFY(nvpair_value_uint64(elem, &intval) == 0);
|
||||||
|
|
||||||
@ -6130,6 +6128,8 @@ spa_sync_props(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
VERIFY(zap_update(mos,
|
VERIFY(zap_update(mos,
|
||||||
spa->spa_pool_props_object, propname,
|
spa->spa_pool_props_object, propname,
|
||||||
8, 1, &intval, tx) == 0);
|
8, 1, &intval, tx) == 0);
|
||||||
|
spa_history_log_internal(spa, "set", tx,
|
||||||
|
"%s=%lld", nvpair_name(elem), intval);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(0); /* not allowed */
|
ASSERT(0); /* not allowed */
|
||||||
}
|
}
|
||||||
@ -6158,13 +6158,6 @@ spa_sync_props(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* log internal history if this is not a zpool create */
|
|
||||||
if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY &&
|
|
||||||
tx->tx_txg != TXG_INITIAL) {
|
|
||||||
spa_history_log_internal(LOG_POOL_PROPSET,
|
|
||||||
spa, tx, "%s %lld %s",
|
|
||||||
nvpair_name(elem), intval, spa_name(spa));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_exit(&spa->spa_props_lock);
|
mutex_exit(&spa->spa_props_lock);
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/spa.h>
|
#include <sys/spa.h>
|
||||||
@ -30,8 +30,11 @@
|
|||||||
#include <sys/dsl_synctask.h>
|
#include <sys/dsl_synctask.h>
|
||||||
#include <sys/dmu_tx.h>
|
#include <sys/dmu_tx.h>
|
||||||
#include <sys/dmu_objset.h>
|
#include <sys/dmu_objset.h>
|
||||||
|
#include <sys/dsl_dataset.h>
|
||||||
|
#include <sys/dsl_dir.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <sys/sunddi.h>
|
#include <sys/sunddi.h>
|
||||||
|
#include <sys/cred.h>
|
||||||
#include "zfs_comutil.h"
|
#include "zfs_comutil.h"
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
#include <sys/cmn_err.h>
|
#include <sys/cmn_err.h>
|
||||||
@ -176,14 +179,14 @@ spa_history_write(spa_t *spa, void *buf, uint64_t len, spa_history_phys_t *shpp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
spa_history_zone()
|
spa_history_zone(void)
|
||||||
{
|
{
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
/* XXX: pr_hostname can be changed by default from within a jail! */
|
/* XXX: pr_hostname can be changed by default from within a jail! */
|
||||||
if (jailed(curthread->td_ucred))
|
if (jailed(curthread->td_ucred))
|
||||||
return (curthread->td_ucred->cr_prison->pr_hostname);
|
return (curthread->td_ucred->cr_prison->pr_hostname);
|
||||||
#endif
|
#endif
|
||||||
return ("global");
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -194,14 +197,12 @@ static void
|
|||||||
spa_history_log_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
spa_history_log_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
spa_t *spa = arg1;
|
spa_t *spa = arg1;
|
||||||
history_arg_t *hap = arg2;
|
nvlist_t *nvl = arg2;
|
||||||
const char *history_str = hap->ha_history_str;
|
|
||||||
objset_t *mos = spa->spa_meta_objset;
|
objset_t *mos = spa->spa_meta_objset;
|
||||||
dmu_buf_t *dbp;
|
dmu_buf_t *dbp;
|
||||||
spa_history_phys_t *shpp;
|
spa_history_phys_t *shpp;
|
||||||
size_t reclen;
|
size_t reclen;
|
||||||
uint64_t le_len;
|
uint64_t le_len;
|
||||||
nvlist_t *nvrecord;
|
|
||||||
char *record_packed = NULL;
|
char *record_packed = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -231,46 +232,35 @@ spa_history_log_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VERIFY(nvlist_alloc(&nvrecord, NV_UNIQUE_NAME, KM_SLEEP) == 0);
|
fnvlist_add_uint64(nvl, ZPOOL_HIST_TIME, gethrestime_sec());
|
||||||
VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_TIME,
|
|
||||||
gethrestime_sec()) == 0);
|
|
||||||
VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_WHO, hap->ha_uid) == 0);
|
|
||||||
if (hap->ha_zone != NULL)
|
|
||||||
VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_ZONE,
|
|
||||||
hap->ha_zone) == 0);
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_HOST,
|
fnvlist_add_string(nvl, ZPOOL_HIST_HOST, utsname.nodename);
|
||||||
utsname.nodename) == 0);
|
|
||||||
#endif
|
#endif
|
||||||
if (hap->ha_log_type == LOG_CMD_POOL_CREATE ||
|
if (nvlist_exists(nvl, ZPOOL_HIST_CMD)) {
|
||||||
hap->ha_log_type == LOG_CMD_NORMAL) {
|
zfs_dbgmsg("command: %s",
|
||||||
VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_CMD,
|
fnvlist_lookup_string(nvl, ZPOOL_HIST_CMD));
|
||||||
history_str) == 0);
|
} else if (nvlist_exists(nvl, ZPOOL_HIST_INT_NAME)) {
|
||||||
|
if (nvlist_exists(nvl, ZPOOL_HIST_DSNAME)) {
|
||||||
zfs_dbgmsg("command: %s", history_str);
|
zfs_dbgmsg("txg %lld %s %s (id %llu) %s",
|
||||||
} else {
|
fnvlist_lookup_uint64(nvl, ZPOOL_HIST_TXG),
|
||||||
VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_INT_EVENT,
|
fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_NAME),
|
||||||
hap->ha_event) == 0);
|
fnvlist_lookup_string(nvl, ZPOOL_HIST_DSNAME),
|
||||||
VERIFY(nvlist_add_uint64(nvrecord, ZPOOL_HIST_TXG,
|
fnvlist_lookup_uint64(nvl, ZPOOL_HIST_DSID),
|
||||||
tx->tx_txg) == 0);
|
fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_STR));
|
||||||
VERIFY(nvlist_add_string(nvrecord, ZPOOL_HIST_INT_STR,
|
} else {
|
||||||
history_str) == 0);
|
zfs_dbgmsg("txg %lld %s %s",
|
||||||
|
fnvlist_lookup_uint64(nvl, ZPOOL_HIST_TXG),
|
||||||
zfs_dbgmsg("internal %s pool:%s txg:%llu %s",
|
fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_NAME),
|
||||||
zfs_history_event_names[hap->ha_event], spa_name(spa),
|
fnvlist_lookup_string(nvl, ZPOOL_HIST_INT_STR));
|
||||||
(longlong_t)tx->tx_txg, history_str);
|
}
|
||||||
|
} else if (nvlist_exists(nvl, ZPOOL_HIST_IOCTL)) {
|
||||||
|
zfs_dbgmsg("ioctl %s",
|
||||||
|
fnvlist_lookup_string(nvl, ZPOOL_HIST_IOCTL));
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY(nvlist_size(nvrecord, &reclen, NV_ENCODE_XDR) == 0);
|
record_packed = fnvlist_pack(nvl, &reclen);
|
||||||
record_packed = kmem_alloc(reclen, KM_SLEEP);
|
|
||||||
|
|
||||||
VERIFY(nvlist_pack(nvrecord, &record_packed, &reclen,
|
|
||||||
NV_ENCODE_XDR, KM_SLEEP) == 0);
|
|
||||||
|
|
||||||
mutex_enter(&spa->spa_history_lock);
|
mutex_enter(&spa->spa_history_lock);
|
||||||
if (hap->ha_log_type == LOG_CMD_POOL_CREATE)
|
|
||||||
VERIFY(shpp->sh_eof == shpp->sh_pool_create_len);
|
|
||||||
|
|
||||||
/* write out the packed length as little endian */
|
/* write out the packed length as little endian */
|
||||||
le_len = LE_64((uint64_t)reclen);
|
le_len = LE_64((uint64_t)reclen);
|
||||||
@ -278,33 +268,42 @@ spa_history_log_sync(void *arg1, void *arg2, dmu_tx_t *tx)
|
|||||||
if (!ret)
|
if (!ret)
|
||||||
ret = spa_history_write(spa, record_packed, reclen, shpp, tx);
|
ret = spa_history_write(spa, record_packed, reclen, shpp, tx);
|
||||||
|
|
||||||
if (!ret && hap->ha_log_type == LOG_CMD_POOL_CREATE) {
|
/* The first command is the create, which we keep forever */
|
||||||
shpp->sh_pool_create_len += sizeof (le_len) + reclen;
|
if (ret == 0 && shpp->sh_pool_create_len == 0 &&
|
||||||
shpp->sh_bof = shpp->sh_pool_create_len;
|
nvlist_exists(nvl, ZPOOL_HIST_CMD)) {
|
||||||
|
shpp->sh_pool_create_len = shpp->sh_bof = shpp->sh_eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_exit(&spa->spa_history_lock);
|
mutex_exit(&spa->spa_history_lock);
|
||||||
nvlist_free(nvrecord);
|
fnvlist_pack_free(record_packed, reclen);
|
||||||
kmem_free(record_packed, reclen);
|
|
||||||
dmu_buf_rele(dbp, FTAG);
|
dmu_buf_rele(dbp, FTAG);
|
||||||
|
fnvlist_free(nvl);
|
||||||
strfree(hap->ha_history_str);
|
|
||||||
if (hap->ha_zone != NULL)
|
|
||||||
strfree(hap->ha_zone);
|
|
||||||
kmem_free(hap, sizeof (history_arg_t));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write out a history event.
|
* Write out a history event.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
spa_history_log(spa_t *spa, const char *history_str, history_log_type_t what)
|
spa_history_log(spa_t *spa, const char *msg)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
nvlist_t *nvl = fnvlist_alloc();
|
||||||
|
|
||||||
|
fnvlist_add_string(nvl, ZPOOL_HIST_CMD, msg);
|
||||||
|
err = spa_history_log_nvl(spa, nvl);
|
||||||
|
fnvlist_free(nvl);
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spa_history_log_nvl(spa_t *spa, nvlist_t *nvl)
|
||||||
{
|
{
|
||||||
history_arg_t *ha;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
dmu_tx_t *tx;
|
dmu_tx_t *tx;
|
||||||
|
nvlist_t *nvarg;
|
||||||
|
|
||||||
ASSERT(what != LOG_INTERNAL);
|
if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY || !spa_writeable(spa))
|
if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY || !spa_writeable(spa))
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
@ -316,19 +315,21 @@ spa_history_log(spa_t *spa, const char *history_str, history_log_type_t what)
|
|||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
ha = kmem_alloc(sizeof (history_arg_t), KM_SLEEP);
|
nvarg = fnvlist_dup(nvl);
|
||||||
ha->ha_history_str = strdup(history_str);
|
if (spa_history_zone() != NULL) {
|
||||||
ha->ha_zone = strdup(spa_history_zone());
|
fnvlist_add_string(nvarg, ZPOOL_HIST_ZONE,
|
||||||
ha->ha_log_type = what;
|
spa_history_zone());
|
||||||
ha->ha_uid = crgetuid(CRED());
|
}
|
||||||
|
fnvlist_add_uint64(nvarg, ZPOOL_HIST_WHO, crgetruid(CRED()));
|
||||||
|
|
||||||
/* Kick this off asynchronously; errors are ignored. */
|
/* Kick this off asynchronously; errors are ignored. */
|
||||||
dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
|
dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
|
||||||
spa_history_log_sync, spa, ha, 0, tx);
|
spa_history_log_sync, spa, nvarg, 0, tx);
|
||||||
dmu_tx_commit(tx);
|
dmu_tx_commit(tx);
|
||||||
|
|
||||||
/* spa_history_log_sync will free ha and strings */
|
/* spa_history_log_sync will free nvl */
|
||||||
return (err);
|
return (err);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -345,7 +346,7 @@ spa_history_get(spa_t *spa, uint64_t *offp, uint64_t *len, char *buf)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the command history doesn't exist (older pool),
|
* If the command history doesn't exist (older pool),
|
||||||
* that's ok, just return ENOENT.
|
* that's ok, just return ENOENT.
|
||||||
*/
|
*/
|
||||||
if (!spa->spa_history)
|
if (!spa->spa_history)
|
||||||
@ -428,11 +429,14 @@ spa_history_get(spa_t *spa, uint64_t *offp, uint64_t *len, char *buf)
|
|||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The nvlist will be consumed by this call.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
log_internal(history_internal_events_t event, spa_t *spa,
|
log_internal(nvlist_t *nvl, const char *operation, spa_t *spa,
|
||||||
dmu_tx_t *tx, const char *fmt, va_list adx)
|
dmu_tx_t *tx, const char *fmt, va_list adx)
|
||||||
{
|
{
|
||||||
history_arg_t *ha;
|
char *msg;
|
||||||
va_list adx2;
|
va_list adx2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -445,30 +449,27 @@ log_internal(history_internal_events_t event, spa_t *spa,
|
|||||||
|
|
||||||
va_copy(adx2, adx);
|
va_copy(adx2, adx);
|
||||||
|
|
||||||
ha = kmem_alloc(sizeof (history_arg_t), KM_SLEEP);
|
msg = kmem_alloc(vsnprintf(NULL, 0, fmt, adx) + 1, KM_SLEEP);
|
||||||
ha->ha_history_str = kmem_alloc(vsnprintf(NULL, 0, fmt, adx2) + 1,
|
(void) vsprintf(msg, fmt, adx);
|
||||||
KM_SLEEP);
|
fnvlist_add_string(nvl, ZPOOL_HIST_INT_STR, msg);
|
||||||
|
strfree(msg);
|
||||||
|
|
||||||
va_end(adx2);
|
va_end(adx2);
|
||||||
|
|
||||||
(void) vsprintf(ha->ha_history_str, fmt, adx);
|
fnvlist_add_string(nvl, ZPOOL_HIST_INT_NAME, operation);
|
||||||
|
fnvlist_add_uint64(nvl, ZPOOL_HIST_TXG, tx->tx_txg);
|
||||||
ha->ha_log_type = LOG_INTERNAL;
|
|
||||||
ha->ha_event = event;
|
|
||||||
ha->ha_zone = NULL;
|
|
||||||
ha->ha_uid = 0;
|
|
||||||
|
|
||||||
if (dmu_tx_is_syncing(tx)) {
|
if (dmu_tx_is_syncing(tx)) {
|
||||||
spa_history_log_sync(spa, ha, tx);
|
spa_history_log_sync(spa, nvl, tx);
|
||||||
} else {
|
} else {
|
||||||
dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
|
dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
|
||||||
spa_history_log_sync, spa, ha, 0, tx);
|
spa_history_log_sync, spa, nvl, 0, tx);
|
||||||
}
|
}
|
||||||
/* spa_history_log_sync() will free ha and strings */
|
/* spa_history_log_sync() will free nvl */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
spa_history_log_internal(history_internal_events_t event, spa_t *spa,
|
spa_history_log_internal(spa_t *spa, const char *operation,
|
||||||
dmu_tx_t *tx, const char *fmt, ...)
|
dmu_tx_t *tx, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
dmu_tx_t *htx = tx;
|
dmu_tx_t *htx = tx;
|
||||||
@ -484,7 +485,7 @@ spa_history_log_internal(history_internal_events_t event, spa_t *spa,
|
|||||||
}
|
}
|
||||||
|
|
||||||
va_start(adx, fmt);
|
va_start(adx, fmt);
|
||||||
log_internal(event, spa, htx, fmt, adx);
|
log_internal(fnvlist_alloc(), operation, spa, htx, fmt, adx);
|
||||||
va_end(adx);
|
va_end(adx);
|
||||||
|
|
||||||
/* if we didn't get a tx from the caller, commit the one we made */
|
/* if we didn't get a tx from the caller, commit the one we made */
|
||||||
@ -493,22 +494,57 @@ spa_history_log_internal(history_internal_events_t event, spa_t *spa,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
spa_history_log_version(spa_t *spa, history_internal_events_t event)
|
spa_history_log_internal_ds(dsl_dataset_t *ds, const char *operation,
|
||||||
|
dmu_tx_t *tx, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list adx;
|
||||||
|
char namebuf[MAXNAMELEN];
|
||||||
|
nvlist_t *nvl = fnvlist_alloc();
|
||||||
|
|
||||||
|
ASSERT(tx != NULL);
|
||||||
|
|
||||||
|
dsl_dataset_name(ds, namebuf);
|
||||||
|
fnvlist_add_string(nvl, ZPOOL_HIST_DSNAME, namebuf);
|
||||||
|
fnvlist_add_uint64(nvl, ZPOOL_HIST_DSID, ds->ds_object);
|
||||||
|
|
||||||
|
va_start(adx, fmt);
|
||||||
|
log_internal(nvl, operation, dsl_dataset_get_spa(ds), tx, fmt, adx);
|
||||||
|
va_end(adx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spa_history_log_internal_dd(dsl_dir_t *dd, const char *operation,
|
||||||
|
dmu_tx_t *tx, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list adx;
|
||||||
|
char namebuf[MAXNAMELEN];
|
||||||
|
nvlist_t *nvl = fnvlist_alloc();
|
||||||
|
|
||||||
|
ASSERT(tx != NULL);
|
||||||
|
|
||||||
|
dsl_dir_name(dd, namebuf);
|
||||||
|
fnvlist_add_string(nvl, ZPOOL_HIST_DSNAME, namebuf);
|
||||||
|
fnvlist_add_uint64(nvl, ZPOOL_HIST_DSID,
|
||||||
|
dd->dd_phys->dd_head_dataset_obj);
|
||||||
|
|
||||||
|
va_start(adx, fmt);
|
||||||
|
log_internal(nvl, operation, dd->dd_pool->dp_spa, tx, fmt, adx);
|
||||||
|
va_end(adx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spa_history_log_version(spa_t *spa, const char *operation)
|
||||||
{
|
{
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
uint64_t current_vers = spa_version(spa);
|
uint64_t current_vers = spa_version(spa);
|
||||||
|
|
||||||
if (current_vers >= SPA_VERSION_ZPOOL_HISTORY) {
|
spa_history_log_internal(spa, operation, NULL,
|
||||||
spa_history_log_internal(event, spa, NULL,
|
"pool version %llu; software version %llu/%d; uts %s %s %s %s",
|
||||||
"pool spa %llu; zfs spa %llu; zpl %d; uts %s %s %s %s",
|
(u_longlong_t)current_vers, SPA_VERSION, ZPL_VERSION,
|
||||||
(u_longlong_t)current_vers, SPA_VERSION, ZPL_VERSION,
|
utsname.nodename, utsname.release, utsname.version,
|
||||||
utsname.nodename, utsname.release, utsname.version,
|
utsname.machine);
|
||||||
utsname.machine);
|
#ifdef illumos
|
||||||
}
|
cmn_err(CE_CONT, "!%s version %llu pool %s using %llu", operation,
|
||||||
#if 0
|
|
||||||
cmn_err(CE_CONT, "!%s version %llu pool %s using %llu",
|
|
||||||
event == LOG_POOL_IMPORT ? "imported" :
|
|
||||||
event == LOG_POOL_CREATE ? "created" : "accessed",
|
|
||||||
(u_longlong_t)current_vers, spa_name(spa), SPA_VERSION);
|
(u_longlong_t)current_vers, spa_name(spa), SPA_VERSION);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/cred.h>
|
#include <sys/cred.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/fs/zfs.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -216,16 +217,6 @@ typedef enum dmu_object_type {
|
|||||||
DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE),
|
DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE),
|
||||||
} dmu_object_type_t;
|
} dmu_object_type_t;
|
||||||
|
|
||||||
typedef enum dmu_objset_type {
|
|
||||||
DMU_OST_NONE,
|
|
||||||
DMU_OST_META,
|
|
||||||
DMU_OST_ZFS,
|
|
||||||
DMU_OST_ZVOL,
|
|
||||||
DMU_OST_OTHER, /* For testing only! */
|
|
||||||
DMU_OST_ANY, /* Be careful! */
|
|
||||||
DMU_OST_NUMTYPES
|
|
||||||
} dmu_objset_type_t;
|
|
||||||
|
|
||||||
void byteswap_uint64_array(void *buf, size_t size);
|
void byteswap_uint64_array(void *buf, size_t size);
|
||||||
void byteswap_uint32_array(void *buf, size_t size);
|
void byteswap_uint32_array(void *buf, size_t size);
|
||||||
void byteswap_uint16_array(void *buf, size_t size);
|
void byteswap_uint16_array(void *buf, size_t size);
|
||||||
@ -272,9 +263,11 @@ int dmu_objset_clone(const char *name, struct dsl_dataset *clone_origin,
|
|||||||
int dmu_objset_destroy(const char *name, boolean_t defer);
|
int dmu_objset_destroy(const char *name, boolean_t defer);
|
||||||
int dmu_get_recursive_snaps_nvl(const char *fsname, const char *snapname,
|
int dmu_get_recursive_snaps_nvl(const char *fsname, const char *snapname,
|
||||||
struct nvlist *snaps);
|
struct nvlist *snaps);
|
||||||
int dmu_snapshots_destroy_nvl(struct nvlist *snaps, boolean_t defer, char *);
|
int dmu_snapshots_destroy_nvl(struct nvlist *snaps, boolean_t defer,
|
||||||
int dmu_objset_snapshot(char *fsname, char *snapname, char *tag,
|
struct nvlist *errlist);
|
||||||
struct nvlist *props, boolean_t recursive, boolean_t temporary, int fd);
|
int dmu_objset_snapshot(struct nvlist *snaps, struct nvlist *, struct nvlist *);
|
||||||
|
int dmu_objset_snapshot_one(const char *fsname, const char *snapname);
|
||||||
|
int dmu_objset_snapshot_tmp(const char *, const char *, int);
|
||||||
int dmu_objset_rename(const char *name, const char *newname,
|
int dmu_objset_rename(const char *name, const char *newname,
|
||||||
boolean_t recursive);
|
boolean_t recursive);
|
||||||
int dmu_objset_find(const char *name, int func(const char *, void *), void *arg,
|
int dmu_objset_find(const char *name, int func(const char *, void *), void *arg,
|
||||||
@ -797,10 +790,9 @@ typedef void (*dmu_traverse_cb_t)(objset_t *os, void *arg, struct blkptr *bp,
|
|||||||
void dmu_traverse_objset(objset_t *os, uint64_t txg_start,
|
void dmu_traverse_objset(objset_t *os, uint64_t txg_start,
|
||||||
dmu_traverse_cb_t cb, void *arg);
|
dmu_traverse_cb_t cb, void *arg);
|
||||||
|
|
||||||
int dmu_send(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
|
int dmu_send(objset_t *tosnap, objset_t *fromsnap,
|
||||||
int outfd, struct file *fp, offset_t *off);
|
int outfd, struct file *fp, offset_t *off);
|
||||||
int dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap,
|
int dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, uint64_t *sizep);
|
||||||
boolean_t fromorigin, uint64_t *sizep);
|
|
||||||
|
|
||||||
typedef struct dmu_recv_cookie {
|
typedef struct dmu_recv_cookie {
|
||||||
/*
|
/*
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Portions Copyright 2010 Robert Milkowski */
|
/* Portions Copyright 2010 Robert Milkowski */
|
||||||
@ -137,24 +138,14 @@ void dmu_objset_rele(objset_t *os, void *tag);
|
|||||||
void dmu_objset_disown(objset_t *os, void *tag);
|
void dmu_objset_disown(objset_t *os, void *tag);
|
||||||
int dmu_objset_from_ds(struct dsl_dataset *ds, objset_t **osp);
|
int dmu_objset_from_ds(struct dsl_dataset *ds, objset_t **osp);
|
||||||
|
|
||||||
int dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
|
|
||||||
void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg);
|
|
||||||
int dmu_objset_clone(const char *name, struct dsl_dataset *clone_origin,
|
|
||||||
uint64_t flags);
|
|
||||||
int dmu_objset_destroy(const char *name, boolean_t defer);
|
|
||||||
int dmu_objset_snapshot(char *fsname, char *snapname, char *tag,
|
|
||||||
struct nvlist *props, boolean_t recursive, boolean_t temporary, int fd);
|
|
||||||
void dmu_objset_stats(objset_t *os, nvlist_t *nv);
|
void dmu_objset_stats(objset_t *os, nvlist_t *nv);
|
||||||
void dmu_objset_fast_stat(objset_t *os, dmu_objset_stats_t *stat);
|
void dmu_objset_fast_stat(objset_t *os, dmu_objset_stats_t *stat);
|
||||||
void dmu_objset_space(objset_t *os, uint64_t *refdbytesp, uint64_t *availbytesp,
|
void dmu_objset_space(objset_t *os, uint64_t *refdbytesp, uint64_t *availbytesp,
|
||||||
uint64_t *usedobjsp, uint64_t *availobjsp);
|
uint64_t *usedobjsp, uint64_t *availobjsp);
|
||||||
uint64_t dmu_objset_fsid_guid(objset_t *os);
|
uint64_t dmu_objset_fsid_guid(objset_t *os);
|
||||||
int dmu_objset_find(const char *name, int func(const char *, void *), void *arg,
|
|
||||||
int flags);
|
|
||||||
int dmu_objset_find_spa(spa_t *spa, const char *name,
|
int dmu_objset_find_spa(spa_t *spa, const char *name,
|
||||||
int func(spa_t *, uint64_t, const char *, void *), void *arg, int flags);
|
int func(spa_t *, uint64_t, const char *, void *), void *arg, int flags);
|
||||||
int dmu_objset_prefetch(const char *name, void *arg);
|
int dmu_objset_prefetch(const char *name, void *arg);
|
||||||
void dmu_objset_byteswap(void *buf, size_t size);
|
|
||||||
int dmu_objset_evict_dbufs(objset_t *os);
|
int dmu_objset_evict_dbufs(objset_t *os);
|
||||||
timestruc_t dmu_objset_snap_cmtime(objset_t *os);
|
timestruc_t dmu_objset_snap_cmtime(objset_t *os);
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ struct dsl_ds_destroyarg {
|
|||||||
|
|
||||||
struct dsl_ds_holdarg {
|
struct dsl_ds_holdarg {
|
||||||
dsl_sync_task_group_t *dstg;
|
dsl_sync_task_group_t *dstg;
|
||||||
char *htag;
|
const char *htag;
|
||||||
char *snapname;
|
char *snapname;
|
||||||
boolean_t recursive;
|
boolean_t recursive;
|
||||||
boolean_t gotone;
|
boolean_t gotone;
|
||||||
@ -223,12 +223,11 @@ uint64_t dsl_dataset_create_sync(dsl_dir_t *pds, const char *lastname,
|
|||||||
uint64_t dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
|
uint64_t dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
|
||||||
uint64_t flags, dmu_tx_t *tx);
|
uint64_t flags, dmu_tx_t *tx);
|
||||||
int dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer);
|
int dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer);
|
||||||
int dsl_snapshots_destroy(char *fsname, char *snapname, boolean_t defer);
|
|
||||||
dsl_checkfunc_t dsl_dataset_destroy_check;
|
dsl_checkfunc_t dsl_dataset_destroy_check;
|
||||||
dsl_syncfunc_t dsl_dataset_destroy_sync;
|
dsl_syncfunc_t dsl_dataset_destroy_sync;
|
||||||
dsl_checkfunc_t dsl_dataset_snapshot_check;
|
|
||||||
dsl_syncfunc_t dsl_dataset_snapshot_sync;
|
|
||||||
dsl_syncfunc_t dsl_dataset_user_hold_sync;
|
dsl_syncfunc_t dsl_dataset_user_hold_sync;
|
||||||
|
int dsl_dataset_snapshot_check(dsl_dataset_t *ds, const char *, dmu_tx_t *tx);
|
||||||
|
void dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *, dmu_tx_t *tx);
|
||||||
int dsl_dataset_rename(char *name, const char *newname, int flags);
|
int dsl_dataset_rename(char *name, const char *newname, int flags);
|
||||||
int dsl_dataset_promote(const char *name, char *conflsnap);
|
int dsl_dataset_promote(const char *name, char *conflsnap);
|
||||||
int dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
|
int dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_DSL_DELEG_H
|
#ifndef _SYS_DSL_DELEG_H
|
||||||
@ -65,8 +65,7 @@ extern "C" {
|
|||||||
int dsl_deleg_get(const char *ddname, nvlist_t **nvp);
|
int dsl_deleg_get(const char *ddname, nvlist_t **nvp);
|
||||||
int dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset);
|
int dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset);
|
||||||
int dsl_deleg_access(const char *ddname, const char *perm, cred_t *cr);
|
int dsl_deleg_access(const char *ddname, const char *perm, cred_t *cr);
|
||||||
int dsl_deleg_access_impl(struct dsl_dataset *ds, boolean_t descendent,
|
int dsl_deleg_access_impl(struct dsl_dataset *ds, const char *perm, cred_t *cr);
|
||||||
const char *perm, cred_t *cr);
|
|
||||||
void dsl_deleg_set_create_perms(dsl_dir_t *dd, dmu_tx_t *tx, cred_t *cr);
|
void dsl_deleg_set_create_perms(dsl_dir_t *dd, dmu_tx_t *tx, cred_t *cr);
|
||||||
int dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr);
|
int dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr);
|
||||||
int dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr);
|
int dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_DSL_PROP_H
|
#ifndef _SYS_DSL_PROP_H
|
||||||
@ -89,8 +90,6 @@ dsl_syncfunc_t dsl_props_set_sync;
|
|||||||
int dsl_prop_set(const char *ddname, const char *propname,
|
int dsl_prop_set(const char *ddname, const char *propname,
|
||||||
zprop_source_t source, int intsz, int numints, const void *buf);
|
zprop_source_t source, int intsz, int numints, const void *buf);
|
||||||
int dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *nvl);
|
int dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *nvl);
|
||||||
void dsl_dir_prop_set_uint64_sync(dsl_dir_t *dd, const char *name, uint64_t val,
|
|
||||||
dmu_tx_t *tx);
|
|
||||||
|
|
||||||
void dsl_prop_setarg_init_uint64(dsl_prop_setarg_t *psa, const char *propname,
|
void dsl_prop_setarg_init_uint64(dsl_prop_setarg_t *psa, const char *propname,
|
||||||
zprop_source_t source, uint64_t *value);
|
zprop_source_t source, uint64_t *value);
|
||||||
|
@ -22,12 +22,13 @@
|
|||||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_RR_RW_LOCK_H
|
#ifndef _SYS_RR_RW_LOCK_H
|
||||||
#define _SYS_RR_RW_LOCK_H
|
#define _SYS_RR_RW_LOCK_H
|
||||||
|
|
||||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -68,6 +69,7 @@ void rrw_destroy(rrwlock_t *rrl);
|
|||||||
void rrw_enter(rrwlock_t *rrl, krw_t rw, void *tag);
|
void rrw_enter(rrwlock_t *rrl, krw_t rw, void *tag);
|
||||||
void rrw_exit(rrwlock_t *rrl, void *tag);
|
void rrw_exit(rrwlock_t *rrl, void *tag);
|
||||||
boolean_t rrw_held(rrwlock_t *rrl, krw_t rw);
|
boolean_t rrw_held(rrwlock_t *rrl, krw_t rw);
|
||||||
|
void rrw_tsd_destroy(void *arg);
|
||||||
|
|
||||||
#define RRW_READ_HELD(x) rrw_held(x, RW_READER)
|
#define RRW_READ_HELD(x) rrw_held(x, RW_READER)
|
||||||
#define RRW_WRITE_HELD(x) rrw_held(x, RW_WRITER)
|
#define RRW_WRITE_HELD(x) rrw_held(x, RW_WRITER)
|
||||||
|
@ -52,6 +52,7 @@ typedef struct spa_aux_vdev spa_aux_vdev_t;
|
|||||||
typedef struct ddt ddt_t;
|
typedef struct ddt ddt_t;
|
||||||
typedef struct ddt_entry ddt_entry_t;
|
typedef struct ddt_entry ddt_entry_t;
|
||||||
struct dsl_pool;
|
struct dsl_pool;
|
||||||
|
struct dsl_dataset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* General-purpose 32-bit and 64-bit bitfield encodings.
|
* General-purpose 32-bit and 64-bit bitfield encodings.
|
||||||
@ -418,7 +419,7 @@ extern int spa_open_rewind(const char *pool, spa_t **, void *tag,
|
|||||||
extern int spa_get_stats(const char *pool, nvlist_t **config, char *altroot,
|
extern int spa_get_stats(const char *pool, nvlist_t **config, char *altroot,
|
||||||
size_t buflen);
|
size_t buflen);
|
||||||
extern int spa_create(const char *pool, nvlist_t *config, nvlist_t *props,
|
extern int spa_create(const char *pool, nvlist_t *config, nvlist_t *props,
|
||||||
const char *history_str, nvlist_t *zplprops);
|
nvlist_t *zplprops);
|
||||||
#if defined(sun)
|
#if defined(sun)
|
||||||
extern int spa_import_rootpool(char *devpath, char *devid);
|
extern int spa_import_rootpool(char *devpath, char *devid);
|
||||||
#else
|
#else
|
||||||
@ -630,31 +631,20 @@ extern int spa_mode(spa_t *spa);
|
|||||||
extern uint64_t zfs_strtonum(const char *str, char **nptr);
|
extern uint64_t zfs_strtonum(const char *str, char **nptr);
|
||||||
#define strtonum(str, nptr) zfs_strtonum((str), (nptr))
|
#define strtonum(str, nptr) zfs_strtonum((str), (nptr))
|
||||||
|
|
||||||
/* history logging */
|
|
||||||
typedef enum history_log_type {
|
|
||||||
LOG_CMD_POOL_CREATE,
|
|
||||||
LOG_CMD_NORMAL,
|
|
||||||
LOG_INTERNAL
|
|
||||||
} history_log_type_t;
|
|
||||||
|
|
||||||
typedef struct history_arg {
|
|
||||||
char *ha_history_str;
|
|
||||||
history_log_type_t ha_log_type;
|
|
||||||
history_internal_events_t ha_event;
|
|
||||||
char *ha_zone;
|
|
||||||
uid_t ha_uid;
|
|
||||||
} history_arg_t;
|
|
||||||
|
|
||||||
extern char *spa_his_ievent_table[];
|
extern char *spa_his_ievent_table[];
|
||||||
|
|
||||||
extern void spa_history_create_obj(spa_t *spa, dmu_tx_t *tx);
|
extern void spa_history_create_obj(spa_t *spa, dmu_tx_t *tx);
|
||||||
extern int spa_history_get(spa_t *spa, uint64_t *offset, uint64_t *len_read,
|
extern int spa_history_get(spa_t *spa, uint64_t *offset, uint64_t *len_read,
|
||||||
char *his_buf);
|
char *his_buf);
|
||||||
extern int spa_history_log(spa_t *spa, const char *his_buf,
|
extern int spa_history_log(spa_t *spa, const char *his_buf);
|
||||||
history_log_type_t what);
|
extern int spa_history_log_nvl(spa_t *spa, nvlist_t *nvl);
|
||||||
extern void spa_history_log_internal(history_internal_events_t event,
|
extern void spa_history_log_version(spa_t *spa, const char *operation);
|
||||||
spa_t *spa, dmu_tx_t *tx, const char *fmt, ...);
|
extern void spa_history_log_internal(spa_t *spa, const char *operation,
|
||||||
extern void spa_history_log_version(spa_t *spa, history_internal_events_t evt);
|
dmu_tx_t *tx, const char *fmt, ...);
|
||||||
|
extern void spa_history_log_internal_ds(struct dsl_dataset *ds, const char *op,
|
||||||
|
dmu_tx_t *tx, const char *fmt, ...);
|
||||||
|
extern void spa_history_log_internal_dd(dsl_dir_t *dd, const char *operation,
|
||||||
|
dmu_tx_t *tx, const char *fmt, ...);
|
||||||
|
|
||||||
/* error handling */
|
/* error handling */
|
||||||
struct zbookmark;
|
struct zbookmark;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_ZFS_IOCTL_H
|
#ifndef _SYS_ZFS_IOCTL_H
|
||||||
@ -40,6 +41,15 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The structures in this file are passed between userland and the
|
||||||
|
* kernel. Userland may be running a 32-bit process, while the kernel
|
||||||
|
* is 64-bit. Therefore, these structures need to compile the same in
|
||||||
|
* 32-bit and 64-bit. This means not using type "long", and adding
|
||||||
|
* explicit padding so that the 32-bit structure will not be packed more
|
||||||
|
* tightly than the 64-bit structure (which requires 64-bit alignment).
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Property values for snapdir
|
* Property values for snapdir
|
||||||
*/
|
*/
|
||||||
@ -284,22 +294,29 @@ typedef enum zfs_case {
|
|||||||
} zfs_case_t;
|
} zfs_case_t;
|
||||||
|
|
||||||
typedef struct zfs_cmd {
|
typedef struct zfs_cmd {
|
||||||
char zc_name[MAXPATHLEN];
|
char zc_name[MAXPATHLEN]; /* name of pool or dataset */
|
||||||
|
uint64_t zc_nvlist_src; /* really (char *) */
|
||||||
|
uint64_t zc_nvlist_src_size;
|
||||||
|
uint64_t zc_nvlist_dst; /* really (char *) */
|
||||||
|
uint64_t zc_nvlist_dst_size;
|
||||||
|
boolean_t zc_nvlist_dst_filled; /* put an nvlist in dst? */
|
||||||
|
int zc_pad2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following members are for legacy ioctls which haven't been
|
||||||
|
* converted to the new method.
|
||||||
|
*/
|
||||||
|
uint64_t zc_history; /* really (char *) */
|
||||||
char zc_value[MAXPATHLEN * 2];
|
char zc_value[MAXPATHLEN * 2];
|
||||||
char zc_string[MAXNAMELEN];
|
char zc_string[MAXNAMELEN];
|
||||||
char zc_top_ds[MAXPATHLEN];
|
char zc_top_ds[MAXPATHLEN];
|
||||||
uint64_t zc_guid;
|
uint64_t zc_guid;
|
||||||
uint64_t zc_nvlist_conf; /* really (char *) */
|
uint64_t zc_nvlist_conf; /* really (char *) */
|
||||||
uint64_t zc_nvlist_conf_size;
|
uint64_t zc_nvlist_conf_size;
|
||||||
uint64_t zc_nvlist_src; /* really (char *) */
|
|
||||||
uint64_t zc_nvlist_src_size;
|
|
||||||
uint64_t zc_nvlist_dst; /* really (char *) */
|
|
||||||
uint64_t zc_nvlist_dst_size;
|
|
||||||
uint64_t zc_cookie;
|
uint64_t zc_cookie;
|
||||||
uint64_t zc_objset_type;
|
uint64_t zc_objset_type;
|
||||||
uint64_t zc_perm_action;
|
uint64_t zc_perm_action;
|
||||||
uint64_t zc_history; /* really (char *) */
|
uint64_t zc_history_len;
|
||||||
uint64_t zc_history_len;
|
|
||||||
uint64_t zc_history_offset;
|
uint64_t zc_history_offset;
|
||||||
uint64_t zc_obj;
|
uint64_t zc_obj;
|
||||||
uint64_t zc_iflags; /* internal to zfs(7fs) */
|
uint64_t zc_iflags; /* internal to zfs(7fs) */
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -884,8 +885,7 @@ zfsctl_snapdir_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp,
|
|||||||
return (err);
|
return (err);
|
||||||
|
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
err = dmu_objset_snapshot(name, dirname, NULL, NULL,
|
err = dmu_objset_snapshot_one(name, dirname);
|
||||||
B_FALSE, B_FALSE, -1);
|
|
||||||
if (err)
|
if (err)
|
||||||
return (err);
|
return (err);
|
||||||
err = lookupnameat(dirname, seg, follow, NULL, vpp, dvp);
|
err = lookupnameat(dirname, seg, follow, NULL, vpp, dvp);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,6 +22,7 @@
|
|||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Portions Copyright 2010 Robert Milkowski */
|
/* Portions Copyright 2010 Robert Milkowski */
|
||||||
@ -2408,9 +2409,8 @@ zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers)
|
|||||||
sa_register_update_callback(os, zfs_sa_upgrade);
|
sa_register_update_callback(os, zfs_sa_upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_history_log_internal(LOG_DS_UPGRADE,
|
spa_history_log_internal_ds(dmu_objset_ds(os), "upgrade", tx,
|
||||||
dmu_objset_spa(os), tx, "oldver=%llu newver=%llu dataset = %llu",
|
"from %llu to %llu", zfsvfs->z_version, newvers);
|
||||||
zfsvfs->z_version, newvers, dmu_objset_id(os));
|
|
||||||
|
|
||||||
dmu_tx_commit(tx);
|
dmu_tx_commit(tx);
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
* Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Portions Copyright 2010 Robert Milkowski */
|
/* Portions Copyright 2010 Robert Milkowski */
|
||||||
@ -144,7 +145,7 @@ typedef struct zvol_state {
|
|||||||
int zvol_maxphys = DMU_MAX_ACCESS/2;
|
int zvol_maxphys = DMU_MAX_ACCESS/2;
|
||||||
|
|
||||||
extern int zfs_set_prop_nvlist(const char *, zprop_source_t,
|
extern int zfs_set_prop_nvlist(const char *, zprop_source_t,
|
||||||
nvlist_t *, nvlist_t **);
|
nvlist_t *, nvlist_t *);
|
||||||
static int zvol_remove_zv(zvol_state_t *);
|
static int zvol_remove_zv(zvol_state_t *);
|
||||||
static int zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio);
|
static int zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio);
|
||||||
static int zvol_dumpify(zvol_state_t *zv);
|
static int zvol_dumpify(zvol_state_t *zv);
|
||||||
@ -1878,7 +1879,7 @@ zvol_dumpify(zvol_state_t *zv)
|
|||||||
|
|
||||||
if (zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ, ZVOL_DUMPSIZE,
|
if (zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ, ZVOL_DUMPSIZE,
|
||||||
8, 1, &dumpsize) != 0 || dumpsize != zv->zv_volsize) {
|
8, 1, &dumpsize) != 0 || dumpsize != zv->zv_volsize) {
|
||||||
boolean_t resize = (dumpsize > 0) ? B_TRUE : B_FALSE;
|
boolean_t resize = (dumpsize > 0);
|
||||||
|
|
||||||
if ((error = zvol_dump_init(zv, resize)) != 0) {
|
if ((error = zvol_dump_init(zv, resize)) != 0) {
|
||||||
(void) zvol_dump_fini(zv);
|
(void) zvol_dump_fini(zv);
|
||||||
|
@ -27,8 +27,6 @@
|
|||||||
#ifndef _SYS_FEATURE_TESTS_H
|
#ifndef _SYS_FEATURE_TESTS_H
|
||||||
#define _SYS_FEATURE_TESTS_H
|
#define _SYS_FEATURE_TESTS_H
|
||||||
|
|
||||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
|
||||||
|
|
||||||
#include <sys/ccompile.h>
|
#include <sys/ccompile.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -366,7 +364,7 @@ extern "C" {
|
|||||||
* compiler is used. This allows for the use of single prototype
|
* compiler is used. This allows for the use of single prototype
|
||||||
* declarations regardless of compiler version.
|
* declarations regardless of compiler version.
|
||||||
*/
|
*/
|
||||||
#if (defined(__STDC__) && defined(_STDC_C99))
|
#if (defined(__STDC__) && defined(_STDC_C99)) && !defined(__cplusplus)
|
||||||
#define _RESTRICT_KYWD restrict
|
#define _RESTRICT_KYWD restrict
|
||||||
#else
|
#else
|
||||||
#define _RESTRICT_KYWD
|
#define _RESTRICT_KYWD
|
||||||
|
@ -55,6 +55,16 @@ typedef enum {
|
|||||||
ZFS_TYPE_POOL = 0x8
|
ZFS_TYPE_POOL = 0x8
|
||||||
} zfs_type_t;
|
} zfs_type_t;
|
||||||
|
|
||||||
|
typedef enum dmu_objset_type {
|
||||||
|
DMU_OST_NONE,
|
||||||
|
DMU_OST_META,
|
||||||
|
DMU_OST_ZFS,
|
||||||
|
DMU_OST_ZVOL,
|
||||||
|
DMU_OST_OTHER, /* For testing only! */
|
||||||
|
DMU_OST_ANY, /* Be careful! */
|
||||||
|
DMU_OST_NUMTYPES
|
||||||
|
} dmu_objset_type_t;
|
||||||
|
|
||||||
#define ZFS_TYPE_DATASET \
|
#define ZFS_TYPE_DATASET \
|
||||||
(ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME | ZFS_TYPE_SNAPSHOT)
|
(ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME | ZFS_TYPE_SNAPSHOT)
|
||||||
|
|
||||||
@ -750,75 +760,79 @@ typedef struct ddt_histogram {
|
|||||||
/*
|
/*
|
||||||
* /dev/zfs ioctl numbers.
|
* /dev/zfs ioctl numbers.
|
||||||
*/
|
*/
|
||||||
typedef unsigned long zfs_ioc_t;
|
typedef enum zfs_ioc {
|
||||||
|
ZFS_IOC_FIRST = 0,
|
||||||
#define ZFS_IOC(ioreq) ((ioreq) & 0xff)
|
ZFS_IOC_POOL_CREATE = ZFS_IOC_FIRST,
|
||||||
|
ZFS_IOC_POOL_DESTROY,
|
||||||
#define ZFS_IOC_POOL_CREATE _IOWR('Z', 0, struct zfs_cmd)
|
ZFS_IOC_POOL_IMPORT,
|
||||||
#define ZFS_IOC_POOL_DESTROY _IOWR('Z', 1, struct zfs_cmd)
|
ZFS_IOC_POOL_EXPORT,
|
||||||
#define ZFS_IOC_POOL_IMPORT _IOWR('Z', 2, struct zfs_cmd)
|
ZFS_IOC_POOL_CONFIGS,
|
||||||
#define ZFS_IOC_POOL_EXPORT _IOWR('Z', 3, struct zfs_cmd)
|
ZFS_IOC_POOL_STATS,
|
||||||
#define ZFS_IOC_POOL_CONFIGS _IOWR('Z', 4, struct zfs_cmd)
|
ZFS_IOC_POOL_TRYIMPORT,
|
||||||
#define ZFS_IOC_POOL_STATS _IOWR('Z', 5, struct zfs_cmd)
|
ZFS_IOC_POOL_SCAN,
|
||||||
#define ZFS_IOC_POOL_TRYIMPORT _IOWR('Z', 6, struct zfs_cmd)
|
ZFS_IOC_POOL_FREEZE,
|
||||||
#define ZFS_IOC_POOL_SCAN _IOWR('Z', 7, struct zfs_cmd)
|
ZFS_IOC_POOL_UPGRADE,
|
||||||
#define ZFS_IOC_POOL_FREEZE _IOWR('Z', 8, struct zfs_cmd)
|
ZFS_IOC_POOL_GET_HISTORY,
|
||||||
#define ZFS_IOC_POOL_UPGRADE _IOWR('Z', 9, struct zfs_cmd)
|
ZFS_IOC_VDEV_ADD,
|
||||||
#define ZFS_IOC_POOL_GET_HISTORY _IOWR('Z', 10, struct zfs_cmd)
|
ZFS_IOC_VDEV_REMOVE,
|
||||||
#define ZFS_IOC_VDEV_ADD _IOWR('Z', 11, struct zfs_cmd)
|
ZFS_IOC_VDEV_SET_STATE,
|
||||||
#define ZFS_IOC_VDEV_REMOVE _IOWR('Z', 12, struct zfs_cmd)
|
ZFS_IOC_VDEV_ATTACH,
|
||||||
#define ZFS_IOC_VDEV_SET_STATE _IOWR('Z', 13, struct zfs_cmd)
|
ZFS_IOC_VDEV_DETACH,
|
||||||
#define ZFS_IOC_VDEV_ATTACH _IOWR('Z', 14, struct zfs_cmd)
|
ZFS_IOC_VDEV_SETPATH,
|
||||||
#define ZFS_IOC_VDEV_DETACH _IOWR('Z', 15, struct zfs_cmd)
|
ZFS_IOC_VDEV_SETFRU,
|
||||||
#define ZFS_IOC_VDEV_SETPATH _IOWR('Z', 16, struct zfs_cmd)
|
ZFS_IOC_OBJSET_STATS,
|
||||||
#define ZFS_IOC_VDEV_SETFRU _IOWR('Z', 17, struct zfs_cmd)
|
ZFS_IOC_OBJSET_ZPLPROPS,
|
||||||
#define ZFS_IOC_OBJSET_STATS _IOWR('Z', 18, struct zfs_cmd)
|
ZFS_IOC_DATASET_LIST_NEXT,
|
||||||
#define ZFS_IOC_OBJSET_ZPLPROPS _IOWR('Z', 19, struct zfs_cmd)
|
ZFS_IOC_SNAPSHOT_LIST_NEXT,
|
||||||
#define ZFS_IOC_DATASET_LIST_NEXT _IOWR('Z', 20, struct zfs_cmd)
|
ZFS_IOC_SET_PROP,
|
||||||
#define ZFS_IOC_SNAPSHOT_LIST_NEXT _IOWR('Z', 21, struct zfs_cmd)
|
ZFS_IOC_CREATE,
|
||||||
#define ZFS_IOC_SET_PROP _IOWR('Z', 22, struct zfs_cmd)
|
ZFS_IOC_DESTROY,
|
||||||
#define ZFS_IOC_CREATE _IOWR('Z', 23, struct zfs_cmd)
|
ZFS_IOC_ROLLBACK,
|
||||||
#define ZFS_IOC_DESTROY _IOWR('Z', 24, struct zfs_cmd)
|
ZFS_IOC_RENAME,
|
||||||
#define ZFS_IOC_ROLLBACK _IOWR('Z', 25, struct zfs_cmd)
|
ZFS_IOC_RECV,
|
||||||
#define ZFS_IOC_RENAME _IOWR('Z', 26, struct zfs_cmd)
|
ZFS_IOC_SEND,
|
||||||
#define ZFS_IOC_RECV _IOWR('Z', 27, struct zfs_cmd)
|
ZFS_IOC_INJECT_FAULT,
|
||||||
#define ZFS_IOC_SEND _IOWR('Z', 28, struct zfs_cmd)
|
ZFS_IOC_CLEAR_FAULT,
|
||||||
#define ZFS_IOC_INJECT_FAULT _IOWR('Z', 29, struct zfs_cmd)
|
ZFS_IOC_INJECT_LIST_NEXT,
|
||||||
#define ZFS_IOC_CLEAR_FAULT _IOWR('Z', 30, struct zfs_cmd)
|
ZFS_IOC_ERROR_LOG,
|
||||||
#define ZFS_IOC_INJECT_LIST_NEXT _IOWR('Z', 31, struct zfs_cmd)
|
ZFS_IOC_CLEAR,
|
||||||
#define ZFS_IOC_ERROR_LOG _IOWR('Z', 32, struct zfs_cmd)
|
ZFS_IOC_PROMOTE,
|
||||||
#define ZFS_IOC_CLEAR _IOWR('Z', 33, struct zfs_cmd)
|
ZFS_IOC_DESTROY_SNAPS,
|
||||||
#define ZFS_IOC_PROMOTE _IOWR('Z', 34, struct zfs_cmd)
|
ZFS_IOC_SNAPSHOT,
|
||||||
#define ZFS_IOC_DESTROY_SNAPS_NVL _IOWR('Z', 35, struct zfs_cmd)
|
ZFS_IOC_DSOBJ_TO_DSNAME,
|
||||||
#define ZFS_IOC_SNAPSHOT _IOWR('Z', 36, struct zfs_cmd)
|
ZFS_IOC_OBJ_TO_PATH,
|
||||||
#define ZFS_IOC_DSOBJ_TO_DSNAME _IOWR('Z', 37, struct zfs_cmd)
|
ZFS_IOC_POOL_SET_PROPS,
|
||||||
#define ZFS_IOC_OBJ_TO_PATH _IOWR('Z', 38, struct zfs_cmd)
|
ZFS_IOC_POOL_GET_PROPS,
|
||||||
#define ZFS_IOC_POOL_SET_PROPS _IOWR('Z', 39, struct zfs_cmd)
|
ZFS_IOC_SET_FSACL,
|
||||||
#define ZFS_IOC_POOL_GET_PROPS _IOWR('Z', 40, struct zfs_cmd)
|
ZFS_IOC_GET_FSACL,
|
||||||
#define ZFS_IOC_SET_FSACL _IOWR('Z', 41, struct zfs_cmd)
|
ZFS_IOC_SHARE,
|
||||||
#define ZFS_IOC_GET_FSACL _IOWR('Z', 42, struct zfs_cmd)
|
ZFS_IOC_INHERIT_PROP,
|
||||||
#define ZFS_IOC_SHARE _IOWR('Z', 43, struct zfs_cmd)
|
ZFS_IOC_SMB_ACL,
|
||||||
#define ZFS_IOC_INHERIT_PROP _IOWR('Z', 44, struct zfs_cmd)
|
ZFS_IOC_USERSPACE_ONE,
|
||||||
#define ZFS_IOC_SMB_ACL _IOWR('Z', 45, struct zfs_cmd)
|
ZFS_IOC_USERSPACE_MANY,
|
||||||
#define ZFS_IOC_USERSPACE_ONE _IOWR('Z', 46, struct zfs_cmd)
|
ZFS_IOC_USERSPACE_UPGRADE,
|
||||||
#define ZFS_IOC_USERSPACE_MANY _IOWR('Z', 47, struct zfs_cmd)
|
ZFS_IOC_HOLD,
|
||||||
#define ZFS_IOC_USERSPACE_UPGRADE _IOWR('Z', 48, struct zfs_cmd)
|
ZFS_IOC_RELEASE,
|
||||||
#define ZFS_IOC_HOLD _IOWR('Z', 49, struct zfs_cmd)
|
ZFS_IOC_GET_HOLDS,
|
||||||
#define ZFS_IOC_RELEASE _IOWR('Z', 50, struct zfs_cmd)
|
ZFS_IOC_OBJSET_RECVD_PROPS,
|
||||||
#define ZFS_IOC_GET_HOLDS _IOWR('Z', 51, struct zfs_cmd)
|
ZFS_IOC_VDEV_SPLIT,
|
||||||
#define ZFS_IOC_OBJSET_RECVD_PROPS _IOWR('Z', 52, struct zfs_cmd)
|
ZFS_IOC_NEXT_OBJ,
|
||||||
#define ZFS_IOC_VDEV_SPLIT _IOWR('Z', 53, struct zfs_cmd)
|
ZFS_IOC_DIFF,
|
||||||
#define ZFS_IOC_NEXT_OBJ _IOWR('Z', 54, struct zfs_cmd)
|
ZFS_IOC_TMP_SNAPSHOT,
|
||||||
#define ZFS_IOC_DIFF _IOWR('Z', 55, struct zfs_cmd)
|
ZFS_IOC_OBJ_TO_STATS,
|
||||||
#define ZFS_IOC_TMP_SNAPSHOT _IOWR('Z', 56, struct zfs_cmd)
|
ZFS_IOC_JAIL,
|
||||||
#define ZFS_IOC_OBJ_TO_STATS _IOWR('Z', 57, struct zfs_cmd)
|
ZFS_IOC_UNJAIL,
|
||||||
#define ZFS_IOC_JAIL _IOWR('Z', 58, struct zfs_cmd)
|
ZFS_IOC_POOL_REGUID,
|
||||||
#define ZFS_IOC_UNJAIL _IOWR('Z', 59, struct zfs_cmd)
|
ZFS_IOC_SPACE_WRITTEN,
|
||||||
#define ZFS_IOC_POOL_REGUID _IOWR('Z', 60, struct zfs_cmd)
|
ZFS_IOC_SPACE_SNAPS,
|
||||||
#define ZFS_IOC_SPACE_WRITTEN _IOWR('Z', 61, struct zfs_cmd)
|
ZFS_IOC_SEND_PROGRESS,
|
||||||
#define ZFS_IOC_SPACE_SNAPS _IOWR('Z', 62, struct zfs_cmd)
|
ZFS_IOC_POOL_REOPEN,
|
||||||
#define ZFS_IOC_SEND_PROGRESS _IOWR('Z', 63, struct zfs_cmd)
|
ZFS_IOC_LOG_HISTORY,
|
||||||
#define ZFS_IOC_POOL_REOPEN _IOWR('Z', 64, struct zfs_cmd)
|
ZFS_IOC_SEND_NEW,
|
||||||
|
ZFS_IOC_SEND_SPACE,
|
||||||
|
ZFS_IOC_CLONE,
|
||||||
|
ZFS_IOC_LAST
|
||||||
|
} zfs_ioc_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal SPA load state. Used by FMA diagnosis engine.
|
* Internal SPA load state. Used by FMA diagnosis engine.
|
||||||
@ -854,6 +868,12 @@ typedef enum {
|
|||||||
#define ZPOOL_HIST_TXG "history txg"
|
#define ZPOOL_HIST_TXG "history txg"
|
||||||
#define ZPOOL_HIST_INT_EVENT "history internal event"
|
#define ZPOOL_HIST_INT_EVENT "history internal event"
|
||||||
#define ZPOOL_HIST_INT_STR "history internal str"
|
#define ZPOOL_HIST_INT_STR "history internal str"
|
||||||
|
#define ZPOOL_HIST_INT_NAME "internal_name"
|
||||||
|
#define ZPOOL_HIST_IOCTL "ioctl"
|
||||||
|
#define ZPOOL_HIST_INPUT_NVL "in_nvl"
|
||||||
|
#define ZPOOL_HIST_OUTPUT_NVL "out_nvl"
|
||||||
|
#define ZPOOL_HIST_DSNAME "dsname"
|
||||||
|
#define ZPOOL_HIST_DSID "dsid"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags for ZFS_IOC_VDEV_SET_STATE
|
* Flags for ZFS_IOC_VDEV_SET_STATE
|
||||||
@ -899,56 +919,6 @@ typedef enum {
|
|||||||
#define ZFS_EV_VDEV_PATH "vdev_path"
|
#define ZFS_EV_VDEV_PATH "vdev_path"
|
||||||
#define ZFS_EV_VDEV_GUID "vdev_guid"
|
#define ZFS_EV_VDEV_GUID "vdev_guid"
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: This is encoded on-disk, so new events must be added to the
|
|
||||||
* end, and unused events can not be removed. Be sure to edit
|
|
||||||
* libzfs_pool.c: hist_event_table[].
|
|
||||||
*/
|
|
||||||
typedef enum history_internal_events {
|
|
||||||
LOG_NO_EVENT = 0,
|
|
||||||
LOG_POOL_CREATE,
|
|
||||||
LOG_POOL_VDEV_ADD,
|
|
||||||
LOG_POOL_REMOVE,
|
|
||||||
LOG_POOL_DESTROY,
|
|
||||||
LOG_POOL_EXPORT,
|
|
||||||
LOG_POOL_IMPORT,
|
|
||||||
LOG_POOL_VDEV_ATTACH,
|
|
||||||
LOG_POOL_VDEV_REPLACE,
|
|
||||||
LOG_POOL_VDEV_DETACH,
|
|
||||||
LOG_POOL_VDEV_ONLINE,
|
|
||||||
LOG_POOL_VDEV_OFFLINE,
|
|
||||||
LOG_POOL_UPGRADE,
|
|
||||||
LOG_POOL_CLEAR,
|
|
||||||
LOG_POOL_SCAN,
|
|
||||||
LOG_POOL_PROPSET,
|
|
||||||
LOG_DS_CREATE,
|
|
||||||
LOG_DS_CLONE,
|
|
||||||
LOG_DS_DESTROY,
|
|
||||||
LOG_DS_DESTROY_BEGIN,
|
|
||||||
LOG_DS_INHERIT,
|
|
||||||
LOG_DS_PROPSET,
|
|
||||||
LOG_DS_QUOTA,
|
|
||||||
LOG_DS_PERM_UPDATE,
|
|
||||||
LOG_DS_PERM_REMOVE,
|
|
||||||
LOG_DS_PERM_WHO_REMOVE,
|
|
||||||
LOG_DS_PROMOTE,
|
|
||||||
LOG_DS_RECEIVE,
|
|
||||||
LOG_DS_RENAME,
|
|
||||||
LOG_DS_RESERVATION,
|
|
||||||
LOG_DS_REPLAY_INC_SYNC,
|
|
||||||
LOG_DS_REPLAY_FULL_SYNC,
|
|
||||||
LOG_DS_ROLLBACK,
|
|
||||||
LOG_DS_SNAPSHOT,
|
|
||||||
LOG_DS_UPGRADE,
|
|
||||||
LOG_DS_REFQUOTA,
|
|
||||||
LOG_DS_REFRESERV,
|
|
||||||
LOG_POOL_SCAN_DONE,
|
|
||||||
LOG_DS_USER_HOLD,
|
|
||||||
LOG_DS_USER_RELEASE,
|
|
||||||
LOG_POOL_SPLIT,
|
|
||||||
LOG_END
|
|
||||||
} history_internal_events_t;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user