Skip to content

Commit 46ba1e5

Browse files
ahrensbehlendorf
authored andcommitted
Illumos #3996
3996 want a libzfs_core API to rollback to latest snapshot Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Andy Stormont <andyjstormont@gmail.com> Approved by: Richard Lowe <richlowe@richlowe.net> References: https://www.illumos.org/issues/3996 illumos/illumos-gate@a7027df Ported-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Issue #1775
1 parent 5d1f7fb commit 46ba1e5

File tree

6 files changed

+57
-26
lines changed

6 files changed

+57
-26
lines changed

include/libzfs_core.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
*/
2121

2222
/*
23-
* Copyright (c) 2012 by Delphix. All rights reserved.
23+
* Copyright (c) 2013 by Delphix. All rights reserved.
2424
*/
2525

2626
#ifndef _LIBZFS_CORE_H
@@ -58,6 +58,7 @@ int lzc_send_space(const char *snapname, const char *fromsnap,
5858

5959
boolean_t lzc_exists(const char *dataset);
6060

61+
int lzc_rollback(const char *fsname, char *snapnamebuf, int snapnamelen);
6162

6263
#ifdef __cplusplus
6364
}

include/sys/dsl_dataset.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ int dsl_dataset_snap_lookup(dsl_dataset_t *ds, const char *name,
265265
int dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx);
266266
void dsl_dataset_set_refreservation_sync_impl(dsl_dataset_t *ds,
267267
zprop_source_t source, uint64_t value, dmu_tx_t *tx);
268-
int dsl_dataset_rollback(const char *fsname, void *owner);
268+
int dsl_dataset_rollback(const char *fsname, void *owner, nvlist_t *result);
269269

270270
#ifdef ZFS_DEBUG
271271
#define dprintf_ds(ds, fmt, ...) do { \

lib/libzfs/libzfs_dataset.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3732,7 +3732,6 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
37323732
{
37333733
rollback_data_t cb = { 0 };
37343734
int err;
3735-
zfs_cmd_t zc = {"\0"};
37363735
boolean_t restore_resv = 0;
37373736
uint64_t old_volsize = 0, new_volsize;
37383737
zfs_prop_t resv_prop = { 0 };
@@ -3766,22 +3765,15 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
37663765
(old_volsize == zfs_prop_get_int(zhp, resv_prop));
37673766
}
37683767

3769-
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3770-
3771-
if (ZFS_IS_VOLUME(zhp))
3772-
zc.zc_objset_type = DMU_OST_ZVOL;
3773-
else
3774-
zc.zc_objset_type = DMU_OST_ZFS;
3775-
37763768
/*
37773769
* We rely on zfs_iter_children() to verify that there are no
37783770
* newer snapshots for the given dataset. Therefore, we can
37793771
* simply pass the name on to the ioctl() call. There is still
37803772
* an unlikely race condition where the user has taken a
37813773
* snapshot since we verified that this was the most recent.
3782-
*
37833774
*/
3784-
if ((err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_ROLLBACK, &zc)) != 0) {
3775+
err = lzc_rollback(zhp->zfs_name, NULL, 0);
3776+
if (err != 0) {
37853777
(void) zfs_standard_error_fmt(zhp->zfs_hdl, errno,
37863778
dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
37873779
zhp->zfs_name);

lib/libzfs_core/libzfs_core.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
*/
2121

2222
/*
23-
* Copyright (c) 2012 by Delphix. All rights reserved.
23+
* Copyright (c) 2013 by Delphix. All rights reserved.
2424
* Copyright (c) 2013 Steven Hartland. All rights reserved.
2525
*/
2626

@@ -581,3 +581,27 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
581581
free((void*)(uintptr_t)zc.zc_nvlist_dst);
582582
return (error);
583583
}
584+
585+
/*
586+
* Roll back this filesystem or volume to its most recent snapshot.
587+
* If snapnamebuf is not NULL, it will be filled in with the name
588+
* of the most recent snapshot.
589+
*
590+
* Return 0 on success or an errno on failure.
591+
*/
592+
int
593+
lzc_rollback(const char *fsname, char *snapnamebuf, int snapnamelen)
594+
{
595+
nvlist_t *args;
596+
nvlist_t *result;
597+
int err;
598+
599+
args = fnvlist_alloc();
600+
err = lzc_ioctl(ZFS_IOC_ROLLBACK, fsname, args, &result);
601+
nvlist_free(args);
602+
if (err == 0 && snapnamebuf != NULL) {
603+
const char *snapname = fnvlist_lookup_string(result, "target");
604+
(void) strlcpy(snapnamebuf, snapname, snapnamelen);
605+
}
606+
return (err);
607+
}

module/zfs/dsl_dataset.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,7 @@ dsl_dataset_handoff_check(dsl_dataset_t *ds, void *owner, dmu_tx_t *tx)
17031703
typedef struct dsl_dataset_rollback_arg {
17041704
const char *ddra_fsname;
17051705
void *ddra_owner;
1706+
nvlist_t *ddra_result;
17061707
} dsl_dataset_rollback_arg_t;
17071708

17081709
static int
@@ -1774,9 +1775,13 @@ dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx)
17741775
dsl_pool_t *dp = dmu_tx_pool(tx);
17751776
dsl_dataset_t *ds, *clone;
17761777
uint64_t cloneobj;
1778+
char namebuf[ZFS_MAXNAMELEN];
17771779

17781780
VERIFY0(dsl_dataset_hold(dp, ddra->ddra_fsname, FTAG, &ds));
17791781

1782+
dsl_dataset_name(ds->ds_prev, namebuf);
1783+
fnvlist_add_string(ddra->ddra_result, "target", namebuf);
1784+
17801785
cloneobj = dsl_dataset_create_sync(ds->ds_dir, "%rollback",
17811786
ds->ds_prev, DS_CREATE_FLAG_NODIRTY, kcred, tx);
17821787

@@ -1792,8 +1797,11 @@ dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx)
17921797
}
17931798

17941799
/*
1795-
* If owner != NULL:
1800+
* Rolls back the given filesystem or volume to the most recent snapshot.
1801+
* The name of the most recent snapshot will be returned under key "target"
1802+
* in the result nvlist.
17961803
*
1804+
* If owner != NULL:
17971805
* - The existing dataset MUST be owned by the specified owner at entry
17981806
* - Upon return, dataset will still be held by the same owner, whether we
17991807
* succeed or not.
@@ -1802,15 +1810,16 @@ dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx)
18021810
* notes above zfs_suspend_fs() for further details.
18031811
*/
18041812
int
1805-
dsl_dataset_rollback(const char *fsname, void *owner)
1813+
dsl_dataset_rollback(const char *fsname, void *owner, nvlist_t *result)
18061814
{
18071815
dsl_dataset_rollback_arg_t ddra;
18081816

18091817
ddra.ddra_fsname = fsname;
18101818
ddra.ddra_owner = owner;
1819+
ddra.ddra_result = result;
18111820

18121821
return (dsl_sync_task(fsname, dsl_dataset_rollback_check,
1813-
dsl_dataset_rollback_sync, (void *)&ddra, 1));
1822+
dsl_dataset_rollback_sync, &ddra, 1));
18141823
}
18151824

18161825
struct promotenode {

module/zfs/zfs_ioctl.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3488,29 +3488,32 @@ zfs_ioc_destroy(zfs_cmd_t *zc)
34883488
}
34893489

34903490
/*
3491-
* inputs:
3492-
* zc_name name of dataset to rollback (to most recent snapshot)
3491+
* fsname is name of dataset to rollback (to most recent snapshot)
34933492
*
3494-
* outputs: none
3493+
* innvl is not used.
3494+
*
3495+
* outnvl: "target" -> name of most recent snapshot
3496+
* }
34953497
*/
3498+
/* ARGSUSED */
34963499
static int
3497-
zfs_ioc_rollback(zfs_cmd_t *zc)
3500+
zfs_ioc_rollback(const char *fsname, nvlist_t *args, nvlist_t *outnvl)
34983501
{
34993502
zfs_sb_t *zsb;
35003503
int error;
35013504

3502-
if (get_zfs_sb(zc->zc_name, &zsb) == 0) {
3505+
if (get_zfs_sb(fsname, &zsb) == 0) {
35033506
error = zfs_suspend_fs(zsb);
35043507
if (error == 0) {
35053508
int resume_err;
35063509

3507-
error = dsl_dataset_rollback(zc->zc_name, zsb);
3508-
resume_err = zfs_resume_fs(zsb, zc->zc_name);
3510+
error = dsl_dataset_rollback(fsname, zsb, outnvl);
3511+
resume_err = zfs_resume_fs(zsb, fsname);
35093512
error = error ? error : resume_err;
35103513
}
35113514
deactivate_super(zsb->z_sb);
35123515
} else {
3513-
error = dsl_dataset_rollback(zc->zc_name, NULL);
3516+
error = dsl_dataset_rollback(fsname, NULL, outnvl);
35143517
}
35153518
return (error);
35163519
}
@@ -5273,6 +5276,10 @@ zfs_ioctl_init(void)
52735276
zfs_ioc_get_holds, zfs_secpolicy_read, DATASET_NAME,
52745277
POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE);
52755278

5279+
zfs_ioctl_register("rollback", ZFS_IOC_ROLLBACK,
5280+
zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME,
5281+
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_TRUE);
5282+
52765283
/* IOCTLS that use the legacy function signature */
52775284

52785285
zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
@@ -5384,8 +5391,6 @@ zfs_ioctl_init(void)
53845391
zfs_secpolicy_none);
53855392
zfs_ioctl_register_dataset_modify(ZFS_IOC_DESTROY, zfs_ioc_destroy,
53865393
zfs_secpolicy_destroy);
5387-
zfs_ioctl_register_dataset_modify(ZFS_IOC_ROLLBACK, zfs_ioc_rollback,
5388-
zfs_secpolicy_rollback);
53895394
zfs_ioctl_register_dataset_modify(ZFS_IOC_RENAME, zfs_ioc_rename,
53905395
zfs_secpolicy_rename);
53915396
zfs_ioctl_register_dataset_modify(ZFS_IOC_RECV, zfs_ioc_recv,

0 commit comments

Comments
 (0)