Skip to content

Commit

Permalink
Illumos #2882, #2883, #2900
Browse files Browse the repository at this point in the history
2882 implement libzfs_core
2883 changing "canmount" property to "on" should not always remount dataset
2900 "zfs snapshot" should be able to create multiple, arbitrary snapshots at once

Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Chris Siden <christopher.siden@delphix.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Bill Pijewski <wdp@joyent.com>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Approved by: Eric Schrock <Eric.Schrock@delphix.com>

References:
  https://www.illumos.org/issues/2882
  https://www.illumos.org/issues/2883
  https://www.illumos.org/issues/2900
  illumos/illumos-gate@4445fff

Ported-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #1293

Porting notes:

WARNING: This patch changes the user/kernel ABI.  That means that
the zfs/zpool utilities built from master are NOT compatible with
the 0.6.2 kernel modules.  Ensure you load the matching kernel
modules from master after updating the utilities.  Otherwise the
zfs/zpool commands will be unable to interact with your pool and
you will see errors similar to the following:

  $ zpool list
  failed to read pool configuration: bad address
  no pools available

  $ zfs list
  no datasets available

Add zvol minor device creation to the new zfs_snapshot_nvl function.

Remove the logging of the "release" operation in
dsl_dataset_user_release_sync().  The logging caused a null dereference
because ds->ds_dir is zeroed in dsl_dataset_destroy_sync() and the
logging functions try to get the ds name via the dsl_dataset_name()
function. I've got no idea why this particular code would have worked
in Illumos.  This code has subsequently been completely reworked in
Illumos commit 3b2aab1 (3464 zfs synctask code needs restructuring).

Squash some "may be used uninitialized" warning/erorrs.

Fix some printf format warnings for %lld and %llu.

Apply a few spa_writeable() changes that were made to Illumos in
illumos/illumos-gate.git@cd1c8b8 as part of the 3112, 3113, 3114 and
3115 fixes.

Add a missing call to fnvlist_free(nvl) in log_internal() that was added
in Illumos to fix issue 3085 but couldn't be ported to ZoL at the time
(9e11c73) because it depended on future work.
  • Loading branch information
ahrens authored and behlendorf committed Sep 4, 2013
1 parent 0c28fb4 commit 6f1ffb0
Show file tree
Hide file tree
Showing 56 changed files with 2,873 additions and 1,514 deletions.
41 changes: 36 additions & 5 deletions cmd/zdb/zdb.c
Expand Up @@ -57,6 +57,7 @@
#include <sys/arc.h>
#include <sys/ddt.h>
#include <sys/zfeature.h>
#include <zfs_comutil.h>
#undef ZFS_MAXNAMELEN
#include <libzfs.h>

Expand Down Expand Up @@ -209,6 +210,27 @@ dump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
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
zdb_nicenum(uint64_t num, char *buf)
{
Expand Down Expand Up @@ -869,21 +891,22 @@ dump_history(spa_t *spa)
for (i = 0; i < num; i++) {
uint64_t time, txg, ievent;
char *cmd, *intstr;
boolean_t printed = B_FALSE;

if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME,
&time) != 0)
continue;
goto next;
if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD,
&cmd) != 0) {
if (nvlist_lookup_uint64(events[i],
ZPOOL_HIST_INT_EVENT, &ievent) != 0)
continue;
goto next;
verify(nvlist_lookup_uint64(events[i],
ZPOOL_HIST_TXG, &txg) == 0);
verify(nvlist_lookup_string(events[i],
ZPOOL_HIST_INT_STR, &intstr) == 0);
if (ievent >= LOG_END)
continue;
if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS)
goto next;

(void) snprintf(internalstr,
sizeof (internalstr),
Expand All @@ -896,6 +919,14 @@ dump_history(spa_t *spa)
(void) localtime_r(&tsec, &t);
(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
(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);
}
}
}

Expand Down Expand Up @@ -1529,7 +1560,7 @@ static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
dump_zap, /* other ZAP */
dump_zap, /* persistent error log */
dump_uint8, /* SPA history */
dump_uint64, /* SPA history offsets */
dump_history_offsets, /* SPA history offsets */
dump_zap, /* Pool properties */
dump_zap, /* DSL permissions */
dump_acl, /* ZFS ACL */
Expand Down
3 changes: 2 additions & 1 deletion cmd/zfs/Makefile.am
Expand Up @@ -16,6 +16,7 @@ zfs_LDADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la \
$(top_builddir)/lib/libuutil/libuutil.la \
$(top_builddir)/lib/libzpool/libzpool.la \
$(top_builddir)/lib/libzfs/libzfs.la
$(top_builddir)/lib/libzfs/libzfs.la \
$(top_builddir)/lib/libzfs_core/libzfs_core.la

zfs_LDFLAGS = -pthread -lm $(ZLIB) -lrt -ldl $(LIBUUID) $(LIBBLKID)
101 changes: 78 additions & 23 deletions cmd/zfs/zfs_main.c
Expand Up @@ -55,6 +55,7 @@
#include <time.h>

#include <libzfs.h>
#include <libzfs_core.h>
#include <zfs_prop.h>
#include <zfs_deleg.h>
#include <libuutil.h>
Expand All @@ -72,6 +73,7 @@ libzfs_handle_t *g_zfs;

static FILE *mnttab_file;
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_create(int argc, char **argv);
Expand Down Expand Up @@ -261,7 +263,7 @@ get_usage(zfs_help_t idx)
return (gettext("\tshare <-a | filesystem>\n"));
case HELP_SNAPSHOT:
return (gettext("\tsnapshot|snap [-r] [-o property=value] ... "
"<filesystem@snapname|volume@snapname>\n"));
"<filesystem@snapname|volume@snapname> ...\n"));
case HELP_UNMOUNT:
return (gettext("\tunmount [-f] "
"<-a | filesystem|mountpoint>\n"));
Expand Down Expand Up @@ -892,9 +894,9 @@ typedef struct destroy_cbdata {
nvlist_t *cb_nvl;

/* first snap in contiguous run */
zfs_handle_t *cb_firstsnap;
char *cb_firstsnap;
/* previous snap in contiguous run */
zfs_handle_t *cb_prevsnap;
char *cb_prevsnap;
int64_t cb_snapused;
char *cb_snapspec;
} destroy_cbdata_t;
Expand Down Expand Up @@ -1008,11 +1010,13 @@ destroy_print_cb(zfs_handle_t *zhp, void *arg)

if (nvlist_exists(cb->cb_nvl, name)) {
if (cb->cb_firstsnap == NULL)
cb->cb_firstsnap = zfs_handle_dup(zhp);
cb->cb_firstsnap = strdup(name);
if (cb->cb_prevsnap != NULL)
zfs_close(cb->cb_prevsnap);
free(cb->cb_prevsnap);
/* 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_parsable) {
(void) printf("destroy\t%s\n", name);
Expand All @@ -1027,12 +1031,12 @@ destroy_print_cb(zfs_handle_t *zhp, void *arg)
} else if (cb->cb_firstsnap != NULL) {
/* end of this range */
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_snapused += used;
zfs_close(cb->cb_firstsnap);
free(cb->cb_firstsnap);
cb->cb_firstsnap = NULL;
zfs_close(cb->cb_prevsnap);
free(cb->cb_prevsnap);
cb->cb_prevsnap = NULL;
}
zfs_close(zhp);
Expand All @@ -1049,13 +1053,13 @@ destroy_print_snapshots(zfs_handle_t *fs_zhp, destroy_cbdata_t *cb)
if (cb->cb_firstsnap != NULL) {
uint64_t used = 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_snapused += used;
zfs_close(cb->cb_firstsnap);
free(cb->cb_firstsnap);
cb->cb_firstsnap = NULL;
zfs_close(cb->cb_prevsnap);
free(cb->cb_prevsnap);
cb->cb_prevsnap = NULL;
}
return (err);
Expand Down Expand Up @@ -1908,9 +1912,11 @@ upgrade_set_callback(zfs_handle_t *zhp, void *data)
/*
* If they did "zfs upgrade -a", then we could
* 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)
cb->cb_numupgraded++;
Expand Down Expand Up @@ -3422,6 +3428,32 @@ zfs_do_set(int argc, char **argv)
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>
*
Expand All @@ -3431,13 +3463,16 @@ zfs_do_set(int argc, char **argv)
static int
zfs_do_snapshot(int argc, char **argv)
{
boolean_t recursive = B_FALSE;
int ret = 0;
signed char c;
nvlist_t *props;
snap_cbdata_t sd = { 0 };
boolean_t multiple_snaps = B_FALSE;

if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
nomem();
if (nvlist_alloc(&sd.sd_nvl, NV_UNIQUE_NAME, 0) != 0)
nomem();

/* check options */
while ((c = getopt(argc, argv, "ro:")) != -1) {
Expand All @@ -3447,7 +3482,8 @@ zfs_do_snapshot(int argc, char **argv)
return (1);
break;
case 'r':
recursive = B_TRUE;
sd.sd_recursive = B_TRUE;
multiple_snaps = B_TRUE;
break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
Expand All @@ -3464,18 +3500,35 @@ zfs_do_snapshot(int argc, char **argv)
(void) fprintf(stderr, gettext("missing snapshot argument\n"));
goto usage;
}
if (argc > 1) {
(void) fprintf(stderr, gettext("too many arguments\n"));
goto usage;

if (argc > 1)
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);
if (ret && recursive)
if (ret != 0 && multiple_snaps)
(void) fprintf(stderr, gettext("no snapshots were created\n"));
return (ret != 0);

usage:
nvlist_free(sd.sd_nvl);
nvlist_free(props);
usage(B_FALSE);
return (-1);
Expand Down Expand Up @@ -6384,8 +6437,7 @@ main(int argc, char **argv)

mnttab_file = g_zfs->libzfs_mnttab;

zpool_set_history_str("zfs", argc, argv, history_str);
verify(zpool_stage_history(g_zfs, history_str) == 0);
zfs_save_arguments(argc, argv, history_str, sizeof (history_str));

libzfs_print_on_error(g_zfs, B_TRUE);

Expand All @@ -6408,6 +6460,9 @@ main(int argc, char **argv)
}
libzfs_fini(g_zfs);

if (ret == 0 && log_history)
(void) zpool_log_history(g_zfs, history_str);

/*
* The 'ZFS_ABORT' environment variable causes us to dump core on exit
* for the purposes of running ::findleaks.
Expand Down
7 changes: 7 additions & 0 deletions cmd/zhack/zhack.c
Expand Up @@ -279,6 +279,9 @@ feature_enable_sync(void *arg1, void *arg2, dmu_tx_t *tx)
zfeature_info_t *feature = arg2;

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
Expand Down Expand Up @@ -356,6 +359,8 @@ feature_incr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
zfeature_info_t *feature = arg2;

spa_feature_incr(spa, feature, tx);
spa_history_log_internal(spa, "zhack feature incr", tx,
"name=%s", feature->fi_guid);
}

static void
Expand All @@ -365,6 +370,8 @@ feature_decr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
zfeature_info_t *feature = arg2;

spa_feature_decr(spa, feature, tx);
spa_history_log_internal(spa, "zhack feature decr", tx,
"name=%s", feature->fi_guid);
}

static void
Expand Down

0 comments on commit 6f1ffb0

Please sign in to comment.