Skip to content

Commit

Permalink
Add libzfs_core and create new Makefile.am for it.
Browse files Browse the repository at this point in the history
Update the zfs man page to document concurrent snapshots.

Updates to libzfs.h.
  • Loading branch information
dweeezil committed May 21, 2013
1 parent 0377189 commit 028f8a6
Show file tree
Hide file tree
Showing 7 changed files with 650 additions and 40 deletions.
101 changes: 78 additions & 23 deletions cmd/zfs/zfs_main.c
Original file line number Diff line number Diff line change
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 @@ -71,6 +72,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 @@ -260,7 +262,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 @@ -891,9 +893,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 @@ -1007,11 +1009,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 @@ -1026,12 +1030,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 @@ -1048,13 +1052,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 @@ -1907,9 +1911,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 @@ -6388,8 +6441,7 @@ main(int argc, char **argv)
if ((g_zfs = libzfs_init()) == NULL)
return (1);

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 @@ -6414,6 +6466,9 @@ main(int argc, char **argv)

(void) fclose(mnttab_file);

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
23 changes: 12 additions & 11 deletions include/libzfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ extern char *zpool_default_import_path[DEFAULT_IMPORT_PATH_SIZE];
/*
* libzfs errors
*/
enum {
typedef enum zfs_error {
EZFS_SUCCESS = 0, /* no error -- success */
EZFS_NOMEM = 2000, /* out of memory */
EZFS_BADPROP, /* invalid property value */
EZFS_PROPREADONLY, /* cannot set readonly property */
Expand Down Expand Up @@ -135,7 +136,7 @@ enum {
EZFS_DIFFDATA, /* bad zfs diff data */
EZFS_POOLREADONLY, /* pool is in read-only mode */
EZFS_UNKNOWN
};
} zfs_error_t;

/*
* The following data structures are all part
Expand Down Expand Up @@ -191,6 +192,9 @@ extern libzfs_handle_t *zfs_get_handle(zfs_handle_t *);

extern void libzfs_print_on_error(libzfs_handle_t *, boolean_t);

extern void zfs_save_arguments(int argc, char **, char *, int);
extern int zpool_log_history(libzfs_handle_t *, const char *);

extern int libzfs_errno(libzfs_handle_t *);
extern const char *libzfs_error_action(libzfs_handle_t *);
extern const char *libzfs_error_description(libzfs_handle_t *);
Expand Down Expand Up @@ -225,7 +229,7 @@ extern int zpool_iter(libzfs_handle_t *, zpool_iter_f, void *);
*/
extern int zpool_create(libzfs_handle_t *, const char *, nvlist_t *,
nvlist_t *, nvlist_t *);
extern int zpool_destroy(zpool_handle_t *);
extern int zpool_destroy(zpool_handle_t *, const char *);
extern int zpool_add(zpool_handle_t *, nvlist_t *);

typedef struct splitflags {
Expand Down Expand Up @@ -349,8 +353,8 @@ extern int zpool_get_errlog(zpool_handle_t *, nvlist_t **);
/*
* Import and export functions
*/
extern int zpool_export(zpool_handle_t *, boolean_t);
extern int zpool_export_force(zpool_handle_t *);
extern int zpool_export(zpool_handle_t *, boolean_t, const char *);
extern int zpool_export_force(zpool_handle_t *, const char *);
extern int zpool_import(libzfs_handle_t *, nvlist_t *, const char *,
char *altroot);
extern int zpool_import_props(libzfs_handle_t *, nvlist_t *, const char *,
Expand Down Expand Up @@ -384,17 +388,14 @@ extern nvlist_t *zpool_find_import_cached(libzfs_handle_t *, const char *,
*/
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 *,
boolean_t verbose);
extern int zpool_upgrade(zpool_handle_t *, uint64_t);
extern int zpool_get_history(zpool_handle_t *, nvlist_t **);
extern int zpool_history_unpack(char *, uint64_t, uint64_t *,
nvlist_t ***, uint_t *);
extern void zpool_set_history_str(const char *subcommand, int argc,
char **argv, char *history_str);
extern int zpool_stage_history(libzfs_handle_t *, const char *);
extern int zpool_events_next(libzfs_handle_t *, nvlist_t **, int *, int, int);
extern int zpool_events_clear(libzfs_handle_t *, int *);
extern void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *,
Expand Down Expand Up @@ -449,8 +450,6 @@ extern int zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
char *propbuf, int proplen, boolean_t literal);
extern int zfs_prop_get_feature(zfs_handle_t *zhp, const char *propname,
char *buf, size_t len);
extern int zfs_get_snapused_int(zfs_handle_t *firstsnap, zfs_handle_t *lastsnap,
uint64_t *usedp);
extern uint64_t getprop_uint64(zfs_handle_t *, zfs_prop_t, char **);
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);
Expand Down Expand Up @@ -566,6 +565,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_clone(zfs_handle_t *, const char *, nvlist_t *);
extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *);
extern int zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps,
nvlist_t *props);
extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t);
extern int zfs_rename(zfs_handle_t *, const char *, boolean_t, boolean_t);

Expand Down
62 changes: 62 additions & 0 deletions include/libzfs_core.h
Original file line number Diff line number Diff line change
@@ -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 */
2 changes: 1 addition & 1 deletion lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ SUBDIRS = libspl libavl libefi libshare libunicode

# These four libraries, which are installed as the final build product,
# incorporate the five convenience libraries given above.
SUBDIRS += libuutil libnvpair libzpool libzfs
SUBDIRS += libuutil libnvpair libzpool libzfs libzfs_core
15 changes: 15 additions & 0 deletions lib/libzfs_core/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
include $(top_srcdir)/config/Rules.am

DEFAULT_INCLUDES += \
-I$(top_srcdir)/include \
-I$(top_srcdir)/lib/libspl/include

lib_LTLIBRARIES = libzfs_core.la

libzfs_core_la_SOURCES = \
$(top_srcdir)/lib/libzfs_core/libzfs_core.c

libzfs_core_la_LIBADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la

libzfs_core_la_LDFLAGS = -pthread -version-info 1:1:0
Loading

0 comments on commit 028f8a6

Please sign in to comment.