libbe(3): simplify import, allow replication streams
Previously, we directly used libzfs_core's lzc_receive to import to a temporary snapshot, then cloned the snapshot and setup the properties. This failed when attempting to import replication streams with questionable error. libzfs's zfs_receive is a much better fit here, so we now use it instead with the destination dataset and let libzfs take care of the dirty details. be_import is greatly simplified as a result. Reported by: Marie Helene Kvello-Aune <freebsd@mhka.no> MFC after: 1 week
This commit is contained in:
parent
20694769bd
commit
16ac070581
@ -649,32 +649,14 @@ int
|
||||
be_import(libbe_handle_t *lbh, const char *bootenv, int fd)
|
||||
{
|
||||
char buf[BE_MAXPATHLEN];
|
||||
time_t rawtime;
|
||||
nvlist_t *props;
|
||||
zfs_handle_t *zfs;
|
||||
int err, len;
|
||||
char nbuf[24];
|
||||
recvflags_t flags = { .nomount = 1 };
|
||||
int err;
|
||||
|
||||
/*
|
||||
* We don't need this to be incredibly random, just unique enough that
|
||||
* it won't conflict with an existing dataset name. Chopping time
|
||||
* down to 32 bits is probably good enough for this.
|
||||
*/
|
||||
snprintf(nbuf, 24, "tmp%u",
|
||||
(uint32_t)(time(NULL) & 0xFFFFFFFF));
|
||||
if ((err = be_root_concat(lbh, nbuf, buf)) != 0)
|
||||
/*
|
||||
* Technically this is our problem, but we try to use short
|
||||
* enough names that we won't run into problems except in
|
||||
* worst-case BE root approaching MAXPATHLEN.
|
||||
*/
|
||||
return (set_error(lbh, BE_ERR_PATHLEN));
|
||||
be_root_concat(lbh, bootenv, buf);
|
||||
|
||||
time(&rawtime);
|
||||
len = strlen(buf);
|
||||
strftime(buf + len, sizeof(buf) - len, "@%F-%T", localtime(&rawtime));
|
||||
|
||||
if ((err = lzc_receive(buf, NULL, NULL, false, fd)) != 0) {
|
||||
if ((err = zfs_receive(lbh->lzh, buf, NULL, &flags, fd, NULL)) != 0) {
|
||||
switch (err) {
|
||||
case EINVAL:
|
||||
return (set_error(lbh, BE_ERR_NOORIGIN));
|
||||
@ -687,39 +669,22 @@ be_import(libbe_handle_t *lbh, const char *bootenv, int fd)
|
||||
}
|
||||
}
|
||||
|
||||
if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_SNAPSHOT)) == NULL)
|
||||
if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_FILESYSTEM)) == NULL)
|
||||
return (set_error(lbh, BE_ERR_ZFSOPEN));
|
||||
|
||||
nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
|
||||
nvlist_add_string(props, "canmount", "noauto");
|
||||
nvlist_add_string(props, "mountpoint", "/");
|
||||
|
||||
be_root_concat(lbh, bootenv, buf);
|
||||
|
||||
err = zfs_clone(zfs, buf, props);
|
||||
zfs_close(zfs);
|
||||
err = zfs_prop_set_list(zfs, props);
|
||||
nvlist_free(props);
|
||||
|
||||
if (err != 0)
|
||||
return (set_error(lbh, BE_ERR_UNKNOWN));
|
||||
|
||||
/*
|
||||
* Finally, we open up the dataset we just cloned the snapshot so that
|
||||
* we may promote it. This is necessary in order to clean up the ghost
|
||||
* snapshot that doesn't need to be seen after the operation is
|
||||
* complete.
|
||||
*/
|
||||
if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL)
|
||||
return (set_error(lbh, BE_ERR_ZFSOPEN));
|
||||
|
||||
err = zfs_promote(zfs);
|
||||
zfs_close(zfs);
|
||||
|
||||
if (err != 0)
|
||||
return (set_error(lbh, BE_ERR_UNKNOWN));
|
||||
|
||||
/* Clean up the temporary snapshot */
|
||||
return (be_destroy(lbh, nbuf, 0));
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if SOON
|
||||
|
Loading…
Reference in New Issue
Block a user