mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	OpenZFS 8264 - want support for promoting datasets in libzfs_core
Authored by: Andrew Stormont <astormont@racktopsystems.com> 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> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Ported-by: Giuseppe Di Natale <dinatale2@llnl.gov> OpenZFS-issue: https://www.illumos.org/issues/8264 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/a4b8c9a Closes #6254
This commit is contained in:
		
							parent
							
								
									7517376f93
								
							
						
					
					
						commit
						d12f91fde3
					
				| @ -22,6 +22,7 @@ | ||||
| /*
 | ||||
|  * Copyright (c) 2012, 2014 by Delphix. All rights reserved. | ||||
|  * Copyright (c) 2017 Datto Inc. | ||||
|  * Copyright 2017 RackTop Systems. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef	_LIBZFS_CORE_H | ||||
| @ -50,6 +51,7 @@ enum lzc_dataset_type { | ||||
| int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **); | ||||
| int lzc_create(const char *, enum lzc_dataset_type, 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_bookmark(nvlist_t *, nvlist_t **); | ||||
| int lzc_get_bookmarks(const char *, nvlist_t *, nvlist_t **); | ||||
|  | ||||
| @ -29,6 +29,7 @@ | ||||
|  * Copyright (c) 2013 Steven Hartland. All rights reserved. | ||||
|  * Copyright 2016 Nexenta Systems, Inc. | ||||
|  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> | ||||
|  * Copyright 2017 RackTop Systems. | ||||
|  */ | ||||
| 
 | ||||
| #include <ctype.h> | ||||
| @ -3731,8 +3732,7 @@ int | ||||
| zfs_promote(zfs_handle_t *zhp) | ||||
| { | ||||
| 	libzfs_handle_t *hdl = zhp->zfs_hdl; | ||||
| 	zfs_cmd_t zc = {"\0"}; | ||||
| 	char parent[MAXPATHLEN]; | ||||
| 	char snapname[ZFS_MAX_DATASET_NAME_LEN]; | ||||
| 	int ret; | ||||
| 	char errbuf[1024]; | ||||
| 
 | ||||
| @ -3745,31 +3745,25 @@ zfs_promote(zfs_handle_t *zhp) | ||||
| 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); | ||||
| 	} | ||||
| 
 | ||||
| 	(void) strlcpy(parent, zhp->zfs_dmustats.dds_origin, sizeof (parent)); | ||||
| 	if (parent[0] == '\0') { | ||||
| 	if (zhp->zfs_dmustats.dds_origin[0] == '\0') { | ||||
| 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | ||||
| 		    "not a cloned filesystem")); | ||||
| 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); | ||||
| 	} | ||||
| 
 | ||||
| 	(void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_origin, | ||||
| 	    sizeof (zc.zc_value)); | ||||
| 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); | ||||
| 	ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc); | ||||
| 	ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname)); | ||||
| 
 | ||||
| 	if (ret != 0) { | ||||
| 		int save_errno = errno; | ||||
| 
 | ||||
| 		switch (save_errno) { | ||||
| 		switch (ret) { | ||||
| 		case EEXIST: | ||||
| 			/* There is a conflicting snapshot name. */ | ||||
| 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | ||||
| 			    "conflicting snapshot '%s' from parent '%s'"), | ||||
| 			    zc.zc_string, parent); | ||||
| 			    snapname, zhp->zfs_dmustats.dds_origin); | ||||
| 			return (zfs_error(hdl, EZFS_EXISTS, errbuf)); | ||||
| 
 | ||||
| 		default: | ||||
| 			return (zfs_standard_error(hdl, save_errno, errbuf)); | ||||
| 			return (zfs_standard_error(hdl, ret, errbuf)); | ||||
| 		} | ||||
| 	} | ||||
| 	return (ret); | ||||
|  | ||||
| @ -23,6 +23,7 @@ | ||||
|  * Copyright (c) 2012, 2014 by Delphix. All rights reserved. | ||||
|  * Copyright (c) 2013 Steven Hartland. All rights reserved. | ||||
|  * Copyright (c) 2017 Datto Inc. | ||||
|  * Copyright 2017 RackTop Systems. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
| @ -206,6 +207,28 @@ lzc_clone(const char *fsname, const char *origin, | ||||
| 	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. | ||||
|  * | ||||
| @ -333,7 +356,7 @@ lzc_exists(const char *dataset) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * 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"}; | ||||
| 
 | ||||
|  | ||||
| @ -35,6 +35,7 @@ | ||||
|  * Copyright (c) 2016 Actifio, Inc. All rights reserved. | ||||
|  * Copyright (c) 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved. | ||||
|  * Copyright (c) 2017 Datto Inc. | ||||
|  * Copyright 2017 RackTop Systems. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
| @ -4963,7 +4964,6 @@ zfs_ioc_pool_reopen(zfs_cmd_t *zc) | ||||
| /*
 | ||||
|  * inputs: | ||||
|  * zc_name	name of filesystem | ||||
|  * zc_value	name of origin snapshot | ||||
|  * | ||||
|  * outputs: | ||||
|  * zc_string	name of conflicting snapshot, if there is one | ||||
| @ -4971,16 +4971,49 @@ zfs_ioc_pool_reopen(zfs_cmd_t *zc) | ||||
| static int | ||||
| 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; | ||||
| 	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 | ||||
| 	 * it's easier. | ||||
| 	 */ | ||||
| 	cp = strchr(zc->zc_value, '@'); | ||||
| 	cp = strchr(origin, '@'); | ||||
| 	if (cp) | ||||
| 		*cp = '\0'; | ||||
| 	(void) dmu_objset_find(zc->zc_value, | ||||
| 	(void) dmu_objset_find(origin, | ||||
| 	    zfs_unmount_snap_cb, NULL, DS_FIND_SNAPSHOTS); | ||||
| 	return (dsl_dataset_promote(zc->zc_name, zc->zc_string)); | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Giuseppe Di Natale
						Giuseppe Di Natale