MFV r319945,r319946: 8264 want support for promoting datasets in libzfs_core
illumos/illumos-gate@a4b8c9aa65
a4b8c9aa65
https://www.illumos.org/issues/8264
Oddly there is a lzc_clone function, but no lzc_promote function.
Reviewed by: Andriy Gapon <avg@FreeBSD.org>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Dan McDonald <danmcd@kebe.com>
Approved by: Dan McDonald <danmcd@kebe.com>
Author: Andrew Stormont <astormont@racktopsystems.com>
MFC after: 1 week
This commit is contained in:
commit
b8d341fe26
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=319947
@ -30,6 +30,7 @@
|
|||||||
* Copyright (c) 2014 Integros [integros.com]
|
* Copyright (c) 2014 Integros [integros.com]
|
||||||
* Copyright 2016 Nexenta Systems, Inc.
|
* Copyright 2016 Nexenta Systems, Inc.
|
||||||
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
|
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
|
||||||
|
* Copyright 2017 RackTop Systems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -3675,8 +3676,7 @@ int
|
|||||||
zfs_promote(zfs_handle_t *zhp)
|
zfs_promote(zfs_handle_t *zhp)
|
||||||
{
|
{
|
||||||
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
||||||
zfs_cmd_t zc = { 0 };
|
char snapname[ZFS_MAX_DATASET_NAME_LEN];
|
||||||
char parent[MAXPATHLEN];
|
|
||||||
int ret;
|
int ret;
|
||||||
char errbuf[1024];
|
char errbuf[1024];
|
||||||
|
|
||||||
@ -3689,31 +3689,25 @@ zfs_promote(zfs_handle_t *zhp)
|
|||||||
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
|
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) strlcpy(parent, zhp->zfs_dmustats.dds_origin, sizeof (parent));
|
if (zhp->zfs_dmustats.dds_origin[0] == '\0') {
|
||||||
if (parent[0] == '\0') {
|
|
||||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||||
"not a cloned filesystem"));
|
"not a cloned filesystem"));
|
||||||
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
|
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_origin,
|
ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname));
|
||||||
sizeof (zc.zc_value));
|
|
||||||
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
|
|
||||||
ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
|
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
int save_errno = errno;
|
switch (ret) {
|
||||||
|
|
||||||
switch (save_errno) {
|
|
||||||
case EEXIST:
|
case EEXIST:
|
||||||
/* There is a conflicting snapshot name. */
|
/* There is a conflicting snapshot name. */
|
||||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||||
"conflicting snapshot '%s' from parent '%s'"),
|
"conflicting snapshot '%s' from parent '%s'"),
|
||||||
zc.zc_string, parent);
|
snapname, zhp->zfs_dmustats.dds_origin);
|
||||||
return (zfs_error(hdl, EZFS_EXISTS, errbuf));
|
return (zfs_error(hdl, EZFS_EXISTS, errbuf));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return (zfs_standard_error(hdl, save_errno, errbuf));
|
return (zfs_standard_error(hdl, ret, errbuf));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||||
* Copyright (c) 2014 Integros [integros.com]
|
* Copyright (c) 2014 Integros [integros.com]
|
||||||
|
* Copyright 2017 RackTop Systems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -244,6 +245,28 @@ lzc_clone(const char *fsname, const char *origin,
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lzc_promote(const char *fsname, char *snapnamebuf, int snapnamelen)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The promote ioctl is still legacy, so we need to construct our
|
||||||
|
* own zfs_cmd_t rather than using lzc_ioctl().
|
||||||
|
*/
|
||||||
|
zfs_cmd_t zc = { 0 };
|
||||||
|
|
||||||
|
ASSERT3S(g_refcount, >, 0);
|
||||||
|
VERIFY3S(g_fd, !=, -1);
|
||||||
|
|
||||||
|
(void) strlcpy(zc.zc_name, fsname, sizeof (zc.zc_name));
|
||||||
|
if (ioctl(g_fd, ZFS_IOC_PROMOTE, &zc) != 0) {
|
||||||
|
int error = errno;
|
||||||
|
if (error == EEXIST && snapnamebuf != NULL)
|
||||||
|
(void) strlcpy(snapnamebuf, zc.zc_string, snapnamelen);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates snapshots.
|
* Creates snapshots.
|
||||||
*
|
*
|
||||||
@ -371,7 +394,7 @@ lzc_exists(const char *dataset)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The objset_stats ioctl is still legacy, so we need to construct our
|
* The objset_stats ioctl is still legacy, so we need to construct our
|
||||||
* own zfs_cmd_t rather than using zfsc_ioctl().
|
* own zfs_cmd_t rather than using lzc_ioctl().
|
||||||
*/
|
*/
|
||||||
zfs_cmd_t zc = { 0 };
|
zfs_cmd_t zc = { 0 };
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 by Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
* Copyright (c) 2013 by Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||||
|
* Copyright 2017 RackTop Systems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LIBZFS_CORE_H
|
#ifndef _LIBZFS_CORE_H
|
||||||
@ -49,6 +50,7 @@ enum lzc_dataset_type {
|
|||||||
int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
|
int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
|
||||||
int lzc_create(const char *, enum lzc_dataset_type, nvlist_t *);
|
int lzc_create(const char *, enum lzc_dataset_type, nvlist_t *);
|
||||||
int lzc_clone(const char *, const char *, nvlist_t *);
|
int lzc_clone(const char *, const char *, nvlist_t *);
|
||||||
|
int lzc_promote(const char *, char *, int);
|
||||||
int lzc_destroy_snaps(nvlist_t *, boolean_t, nvlist_t **);
|
int lzc_destroy_snaps(nvlist_t *, boolean_t, nvlist_t **);
|
||||||
int lzc_bookmark(nvlist_t *, nvlist_t **);
|
int lzc_bookmark(nvlist_t *, nvlist_t **);
|
||||||
int lzc_get_bookmarks(const char *, nvlist_t *, nvlist_t **);
|
int lzc_get_bookmarks(const char *, nvlist_t *, nvlist_t **);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||||
* Copyright (c) 2014 Integros [integros.com]
|
* Copyright (c) 2014 Integros [integros.com]
|
||||||
* Copyright 2016 Toomas Soome <tsoome@me.com>
|
* Copyright 2016 Toomas Soome <tsoome@me.com>
|
||||||
|
* Copyright 2017 RackTop Systems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4884,7 +4885,6 @@ zfs_ioc_pool_reopen(zfs_cmd_t *zc)
|
|||||||
/*
|
/*
|
||||||
* inputs:
|
* inputs:
|
||||||
* zc_name name of filesystem
|
* zc_name name of filesystem
|
||||||
* zc_value name of origin snapshot
|
|
||||||
*
|
*
|
||||||
* outputs:
|
* outputs:
|
||||||
* zc_string name of conflicting snapshot, if there is one
|
* zc_string name of conflicting snapshot, if there is one
|
||||||
@ -4892,16 +4892,49 @@ zfs_ioc_pool_reopen(zfs_cmd_t *zc)
|
|||||||
static int
|
static int
|
||||||
zfs_ioc_promote(zfs_cmd_t *zc)
|
zfs_ioc_promote(zfs_cmd_t *zc)
|
||||||
{
|
{
|
||||||
|
dsl_pool_t *dp;
|
||||||
|
dsl_dataset_t *ds, *ods;
|
||||||
|
char origin[ZFS_MAX_DATASET_NAME_LEN];
|
||||||
char *cp;
|
char *cp;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
error = dsl_dataset_hold(dp, zc->zc_name, FTAG, &ds);
|
||||||
|
if (error != 0) {
|
||||||
|
dsl_pool_rele(dp, FTAG);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dsl_dir_is_clone(ds->ds_dir)) {
|
||||||
|
dsl_dataset_rele(ds, FTAG);
|
||||||
|
dsl_pool_rele(dp, FTAG);
|
||||||
|
return (SET_ERROR(EINVAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
error = dsl_dataset_hold_obj(dp,
|
||||||
|
dsl_dir_phys(ds->ds_dir)->dd_origin_obj, FTAG, &ods);
|
||||||
|
if (error != 0) {
|
||||||
|
dsl_dataset_rele(ds, FTAG);
|
||||||
|
dsl_pool_rele(dp, FTAG);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
dsl_dataset_name(ods, origin);
|
||||||
|
dsl_dataset_rele(ods, FTAG);
|
||||||
|
dsl_dataset_rele(ds, FTAG);
|
||||||
|
dsl_pool_rele(dp, FTAG);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't need to unmount *all* the origin fs's snapshots, but
|
* We don't need to unmount *all* the origin fs's snapshots, but
|
||||||
* it's easier.
|
* it's easier.
|
||||||
*/
|
*/
|
||||||
cp = strchr(zc->zc_value, '@');
|
cp = strchr(origin, '@');
|
||||||
if (cp)
|
if (cp)
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
(void) dmu_objset_find(zc->zc_value,
|
(void) dmu_objset_find(origin,
|
||||||
zfs_unmount_snap_cb, NULL, DS_FIND_SNAPSHOTS);
|
zfs_unmount_snap_cb, NULL, DS_FIND_SNAPSHOTS);
|
||||||
return (dsl_dataset_promote(zc->zc_name, zc->zc_string));
|
return (dsl_dataset_promote(zc->zc_name, zc->zc_string));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user