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