socsvn commit: r329241 - soc2017/kneitinger/libbe-head/lib/libbe
allanjude at FreeBSD.org
allanjude at FreeBSD.org
Thu Nov 9 16:07:44 UTC 2017
Author: allanjude
Date: Thu Nov 9 16:07:42 2017
New Revision: 329241
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=329241
Log:
Add the deep cloning feature, with smart property copying
Modified:
soc2017/kneitinger/libbe-head/lib/libbe/be.c
soc2017/kneitinger/libbe-head/lib/libbe/be_impl.h
Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.c
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be.c Thu Nov 9 16:03:18 2017 (r329240)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be.c Thu Nov 9 16:07:42 2017 (r329241)
@@ -245,46 +245,87 @@
}
-/*
- * Create the boot environment from pre-existing snapshot
- */
-int
-be_create_from_existing_snap(libbe_handle_t *lbh, char *name, char *snap)
+static int
+be_deep_clone_prop(int prop, void *cb)
{
int err;
- char be_path[BE_MAXPATHLEN];
- char snap_path[BE_MAXPATHLEN];
- zfs_handle_t *snap_hdl;
- nvlist_t *props;
-
- if (err = be_validate_name(lbh, name)) {
- return (set_error(lbh, err));
+ struct libbe_dccb *dccb = cb;
+ zprop_source_t src;
+ char pval[BE_MAXPATHLEN];
+ char source[BE_MAXPATHLEN];
+
+ /* Skip some properties we don't want to touch */
+ switch (prop) {
+ case ZFS_PROP_CANMOUNT:
+ return (ZPROP_CONT);
+ break;
}
- if (err = be_root_concat(lbh, snap, snap_path)) {
- return (set_error(lbh, err));
+ /* Don't copy readonly properties */
+ if (zfs_prop_readonly(prop)) {
+ return (ZPROP_CONT);
}
- if (err = be_validate_snap(lbh, snap_path)) {
- return (set_error(lbh, err));
+ if ((err = zfs_prop_get(dccb->zhp, prop, (char *)&pval,
+ sizeof(pval), &src, (char *)&source, sizeof(source), false))) {
+ /* Just continue if we fail to read a property */
+ return (ZPROP_CONT);
+ }
+ /* Only copy locally defined properties */
+ if (src != ZPROP_SRC_LOCAL) {
+ return (ZPROP_CONT);
}
- if (err = be_root_concat(lbh, name, be_path)) {
- return (set_error(lbh, err));
+ nvlist_add_string(dccb->props, zfs_prop_to_name(prop), (char *)pval);
+
+ return (ZPROP_CONT);
+}
+
+static int
+be_deep_clone(zfs_handle_t *ds, void *data)
+{
+ int err;
+ char be_path[BE_MAXPATHLEN];
+ char snap_path[BE_MAXPATHLEN];
+ char mp[BE_MAXPATHLEN];
+ const char *dspath;
+ char *dsname;
+ zfs_handle_t *snap_hdl;
+ nvlist_t *props;
+ struct libbe_deep_clone sdc;
+ struct libbe_deep_clone *isdc = (struct libbe_deep_clone *)data;
+ struct libbe_dccb dccb;
+
+ dspath = zfs_get_name(ds);
+ if ((dsname = strrchr(dspath, '/')) == NULL) {
+ return (BE_ERR_UNKNOWN);
+ }
+ dsname++;
+ if (isdc->bename == NULL) {
+ snprintf(be_path, sizeof(be_path), "%s/%s", isdc->be_root, dsname);
+ } else {
+ snprintf(be_path, sizeof(be_path), "%s/%s", isdc->be_root, isdc->bename);
}
+ snprintf(snap_path, sizeof(snap_path), "%s@%s", dspath, isdc->snapname);
- if (zfs_dataset_exists(lbh->lzh, be_path, ZFS_TYPE_DATASET)) {
- return (set_error(lbh, BE_ERR_EXISTS));
+ if (zfs_dataset_exists(isdc->lbh->lzh, be_path, ZFS_TYPE_DATASET)) {
+ return (set_error(isdc->lbh, BE_ERR_EXISTS));
}
if ((snap_hdl =
- zfs_open(lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT)) == NULL) {
- return (set_error(lbh, BE_ERR_ZFSOPEN));
+ zfs_open(isdc->lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT)) == NULL) {
+ return (set_error(isdc->lbh, BE_ERR_ZFSOPEN));
}
nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
nvlist_add_string(props, "canmount", "noauto");
- nvlist_add_string(props, "mountpoint", "/");
+
+ dccb.zhp = ds;
+ dccb.props = props;
+ if (zprop_iter(be_deep_clone_prop, &dccb, B_FALSE, B_FALSE,
+ ZFS_TYPE_FILESYSTEM) == ZPROP_INVAL) {
+ return (-1);
+ }
if (err = zfs_clone(snap_hdl, be_path, props)) {
switch (err) {
@@ -300,6 +341,70 @@
nvlist_free(props);
zfs_close(snap_hdl);
+ sdc.lbh = isdc->lbh;
+ sdc.bename = NULL;
+ sdc.snapname = isdc->snapname;
+ sdc.be_root = (char *)&be_path;
+
+ err = zfs_iter_filesystems(ds, be_deep_clone, &sdc);
+
+ return (err);
+}
+
+/*
+ * Create the boot environment from pre-existing snapshot
+ */
+int
+be_create_from_existing_snap(libbe_handle_t *lbh, char *name, char *snap)
+{
+ int err;
+ char be_path[BE_MAXPATHLEN];
+ char snap_path[BE_MAXPATHLEN];
+ char *parentname, *bename, *snapname;
+ zfs_handle_t *parent_hdl;
+ struct libbe_deep_clone sdc;
+
+ if (err = be_validate_name(lbh, name)) {
+ return (set_error(lbh, err));
+ }
+
+ if (err = be_root_concat(lbh, snap, snap_path)) {
+ return (set_error(lbh, err));
+ }
+
+ if (err = be_validate_snap(lbh, snap_path)) {
+ return (set_error(lbh, err));
+ }
+
+ if (err = be_root_concat(lbh, name, be_path)) {
+ return (set_error(lbh, err));
+ }
+
+ if ((bename = strrchr(name, '/')) == NULL) {
+ bename = name;
+ } else {
+ bename++;
+ }
+ if ((parentname = strdup(snap_path)) == NULL) {
+ err = BE_ERR_UNKNOWN;
+ return (set_error(lbh, err));
+ }
+ snapname = strchr(parentname, '@');
+ if (snapname == NULL) {
+ err = BE_ERR_UNKNOWN;
+ return (set_error(lbh, err));
+ }
+ *snapname = '\0';
+ snapname++;
+
+ sdc.lbh = lbh;
+ sdc.bename = bename;
+ sdc.snapname = snapname;
+ sdc.be_root = lbh->root;
+
+ parent_hdl = zfs_open(lbh->lzh, parentname, ZFS_TYPE_DATASET);
+ err = be_deep_clone(parent_hdl, &sdc);
+
return (set_error(lbh, err));
}
Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_impl.h
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be_impl.h Thu Nov 9 16:03:18 2017 (r329240)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be_impl.h Thu Nov 9 16:07:42 2017 (r329241)
@@ -42,6 +42,18 @@
bool print_on_err;
};
+struct libbe_deep_clone {
+ libbe_handle_t *lbh;
+ char *bename;
+ char *snapname;
+ char *be_root;
+};
+
+struct libbe_dccb {
+ zfs_handle_t *zhp;
+ nvlist_t *props;
+};
+
int set_error(libbe_handle_t *, be_error_t);
#endif /* _LIBBE_IMPL_H */
More information about the svn-soc-all
mailing list