From owner-svn-soc-all@freebsd.org Thu Nov 9 16:07:44 2017 Return-Path: Delivered-To: svn-soc-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 24D2EE54CE1 for ; Thu, 9 Nov 2017 16:07:44 +0000 (UTC) (envelope-from allanjude@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0B4FB6D9A6 for ; Thu, 9 Nov 2017 16:07:44 +0000 (UTC) (envelope-from allanjude@FreeBSD.org) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.15.2/8.15.2) with ESMTP id vA9G7huX047290 for ; Thu, 9 Nov 2017 16:07:43 GMT (envelope-from allanjude@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.15.2/8.15.2/Submit) id vA9G7hWN047249 for svn-soc-all@FreeBSD.org; Thu, 9 Nov 2017 16:07:43 GMT (envelope-from allanjude@FreeBSD.org) Date: Thu, 9 Nov 2017 16:07:43 GMT Message-Id: <201711091607.vA9G7hWN047249@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to allanjude@FreeBSD.org using -f From: allanjude@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r329241 - soc2017/kneitinger/libbe-head/lib/libbe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Nov 2017 16:07:44 -0000 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 */