From 5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3 Mon Sep 17 00:00:00 2001 From: Alexander Eremin Date: Thu, 17 Nov 2011 14:34:33 +0300 Subject: [PATCH] 1699 beadm destroy complains "device busy" if hampered by snapshots Reviewed by: Richard Lowe Reviewed by: Garrett D'Amore Reviewed by: Gordon Ross Approved by: Richard Lowe --- usr/src/cmd/beadm/beadm.c | 5 +++++ usr/src/lib/libbe/common/be_create.c | 38 ++++++++++++++++++++++++++++++++++++ usr/src/man/man1m/beadm.1m | 14 +++++++++++-- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/usr/src/cmd/beadm/beadm.c b/usr/src/cmd/beadm/beadm.c index 7918e00b55..5be10c10d7 100644 --- a/usr/src/cmd/beadm/beadm.c +++ b/usr/src/cmd/beadm/beadm.c @@ -1046,6 +1046,11 @@ be_do_destroy(int argc, char **argv) (void) fprintf(stderr, _("You have insufficient privileges to " "execute this command.\n")); break; + case BE_ERR_SS_EXISTS: + (void) fprintf(stderr, _("Unable to destroy %s: " + "BE has snapshots.\nUse 'beadm destroy -s %s' or " + "'zfs -r destroy '.\n"), be_name, be_name); + break; default: (void) fprintf(stderr, _("Unable to destroy %s.\n"), be_name); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); diff --git a/usr/src/lib/libbe/common/be_create.c b/usr/src/lib/libbe/common/be_create.c index 3e4202c369..48bf4ec6bf 100644 --- a/usr/src/lib/libbe/common/be_create.c +++ b/usr/src/lib/libbe/common/be_create.c @@ -65,6 +65,7 @@ static int be_destroy_callback(zfs_handle_t *, void *); static int be_send_fs_callback(zfs_handle_t *, void *); static int be_demote_callback(zfs_handle_t *, void *); static int be_demote_find_clone_callback(zfs_handle_t *, void *); +static int be_has_snapshot_callback(zfs_handle_t *, void *); static int be_demote_get_one_clone(zfs_handle_t *, void *); static int be_get_snap(char *, char **); static int be_prep_clone_send_fs(zfs_handle_t *, be_transaction_data_t *, @@ -386,6 +387,7 @@ be_destroy(nvlist_t *be_attrs) be_destroy_data_t dd = { 0 }; int ret = BE_SUCCESS; uint16_t flags = 0; + boolean_t bs_found = B_FALSE; int zret; char obe_root_ds[MAXPATHLEN]; char *mp = NULL; @@ -469,6 +471,16 @@ be_destroy(nvlist_t *be_attrs) return (zfs_err_to_be_err(g_zfs)); } + /* + * Check if BE has snapshots and BE_DESTROY_FLAG_SNAPSHOTS + * is not set. + */ + (void) zfs_iter_snapshots(zhp, be_has_snapshot_callback, &bs_found); + if (!dd.destroy_snaps && bs_found) { + ZFS_CLOSE(zhp); + return (BE_ERR_SS_EXISTS); + } + /* Get the UUID of the global BE */ if (be_get_uuid(zfs_get_name(zhp), &dd.gz_be_uuid) != BE_SUCCESS) { be_print_err(gettext("be_destroy: BE has no UUID (%s)\n"), @@ -1232,6 +1244,32 @@ be_exists_callback(zpool_handle_t *zlp, void *data) } /* + * Function: be_has_snapshots_callback + * Description: Callback function used to find out if a BE has snapshots. + * Parameters: + * zlp - zpool_handle_t pointer to the current pool being + * looked at. + * data - be_snap_found_t pointer. + * Return: + * 1 - BE has no snapshots. + * 0 - BE has snapshots. + * Scope: + * Private + */ +static int +be_has_snapshot_callback(zfs_handle_t *zhp, void *data) +{ + boolean_t *bs = data; + if (zfs_get_name(zhp) == NULL) { + zfs_close(zhp); + return (1); + } + *bs = B_TRUE; + zfs_close(zhp); + return (0); +} + +/* * Function: be_set_uuid * Description: This function generates a uuid, unparses it into * string representation, and sets that string into diff --git a/usr/src/man/man1m/beadm.1m b/usr/src/man/man1m/beadm.1m index ded01aa60b..d5747d3c4f 100644 --- a/usr/src/man/man1m/beadm.1m +++ b/usr/src/man/man1m/beadm.1m @@ -18,7 +18,7 @@ beadm \- utility for managing zfs boot environments .LP .nf -\fBbeadm\fR \fBdestroy\fR [\fB-fF\fR] \fIbeName\fR | \fIbeName@snapshot\fR +\fBbeadm\fR \fBdestroy\fR [\fB-fFs\fR] \fIbeName\fR | \fIbeName@snapshot\fR .fi .LP @@ -254,7 +254,7 @@ Creates a snapshot of the existing BE named beName. .sp .ne 2 .na -\fBbeadm\fR \fBdestroy\fR [\fB-fF\fR] \fIbeName\fR | \fIbeName@snapshot\fR +\fBbeadm\fR \fBdestroy\fR [\fB-fFs\fR] \fIbeName\fR | \fIbeName@snapshot\fR .ad .sp .6 .RS 4n @@ -284,6 +284,16 @@ Forcefully unmount the boot environment if it is currently mounted. Force the action without prompting to verify the destruction of the boot environment. .RE +.sp +.ne 2 +.na +\fB-s\fR +.ad +.sp .6 +.RS 4n +Destroy all snapshots of the boot +environment. +.RE .RE .sp -- 2.11.4.GIT