changeset 13967:92bec6d87f59

3557 dumpvp_size is not updated correctly when a dump zvol's size is changed 3558 setting the volsize on a dump device does not return back ENOSPC 3559 setting a volsize larger than the space available sometimes succeeds 3560 dumpadm should be able to remove a dump device Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Approved by: Albert Lee <trisk@nexenta.com>
author George Wilson <george.wilson@delphix.com>
date Wed, 20 Feb 2013 22:50:16 -0800
parents 0e1d84ebb004
children e4988c7d0403
files usr/src/cmd/dumpadm/dconf.c usr/src/cmd/zfs/zfs_main.c usr/src/lib/libzfs/common/libzfs_dataset.c usr/src/lib/libzfs/common/mapfile-vers usr/src/man/man1m/dumpadm.1m usr/src/uts/common/fs/zfs/sys/zvol.h usr/src/uts/common/fs/zfs/zfs_ioctl.c usr/src/uts/common/fs/zfs/zvol.c usr/src/uts/common/io/dump.c usr/src/uts/common/sys/dumpadm.h
diffstat 10 files changed, 120 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/dumpadm/dconf.c	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/cmd/dumpadm/dconf.c	Wed Feb 20 22:50:16 2013 -0800
@@ -70,6 +70,7 @@
 static const char DC_STR_YES[] = "yes";		/* Enable on string */
 static const char DC_STR_NO[] = "no";		/* Enable off string */
 static const char DC_STR_SWAP[] = "swap";	/* Default dump device */
+static const char DC_STR_NONE[] = "none";
 
 /* The pages included in the dump */
 static const char DC_STR_KERNEL[] = "kernel";	/* Kernel only */
@@ -367,7 +368,7 @@
 int
 dconf_update(dumpconf_t *dcp, int checkinuse)
 {
-	int 		oconf;
+	int		oconf;
 	int		error;
 	char		*msg;
 
@@ -438,6 +439,11 @@
 		}
 		free(swt);
 
+	} else if (strcmp(dcp->dc_device, DC_STR_NONE) == 0) {
+		if (ioctl(dcp->dc_dump_fd, DIOCRMDEV, NULL) == -1) {
+			warn(gettext("failed to remove dump device"));
+			return (-1);
+		}
 	} else if (dcp->dc_device[0] != '\0') {
 		/*
 		 * If we're not in forcible update mode, then fail the change
@@ -564,6 +570,11 @@
 		return (0);
 	}
 
+	if (strcasecmp(buf, DC_STR_NONE) == 0) {
+		(void) strcpy(dcp->dc_device, DC_STR_NONE);
+		return (0);
+	}
+
 	if (valid_abspath(buf)) {
 		(void) strcpy(dcp->dc_device, buf);
 		return (0);
--- a/usr/src/cmd/zfs/zfs_main.c	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/cmd/zfs/zfs_main.c	Wed Feb 20 22:50:16 2013 -0800
@@ -775,10 +775,12 @@
 
 	if (type == ZFS_TYPE_VOLUME && !noreserve) {
 		zpool_handle_t *zpool_handle;
+		nvlist_t *real_props;
 		uint64_t spa_version;
 		char *p;
 		zfs_prop_t resv_prop;
 		char *strval;
+		char msg[1024];
 
 		if (p = strchr(argv[0], '/'))
 			*p = '\0';
@@ -794,7 +796,15 @@
 			resv_prop = ZFS_PROP_REFRESERVATION;
 		else
 			resv_prop = ZFS_PROP_RESERVATION;
-		volsize = zvol_volsize_to_reservation(volsize, props);
+
+		(void) snprintf(msg, sizeof (msg),
+		    gettext("cannot create '%s'"), argv[0]);
+		if (props && (real_props = zfs_valid_proplist(g_zfs, type,
+		    props, 0, NULL, msg)) == NULL)
+			goto error;
+
+		volsize = zvol_volsize_to_reservation(volsize, real_props);
+		nvlist_free(real_props);
 
 		if (nvlist_lookup_string(props, zfs_prop_to_name(resv_prop),
 		    &strval) != 0) {
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Wed Feb 20 22:50:16 2013 -0800
@@ -1283,6 +1283,7 @@
 	uint64_t old_reservation;
 	uint64_t new_reservation;
 	zfs_prop_t resv_prop;
+	nvlist_t *props;
 
 	/*
 	 * If this is an existing volume, and someone is setting the volsize,
@@ -1292,16 +1293,25 @@
 	if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
 		return (-1);
 	old_reservation = zfs_prop_get_int(zhp, resv_prop);
-	if ((zvol_volsize_to_reservation(old_volsize, zhp->zfs_props) !=
-	    old_reservation) || nvlist_lookup_uint64(nvl,
-	    zfs_prop_to_name(resv_prop), &new_reservation) != ENOENT) {
+
+	props = fnvlist_alloc();
+	fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
+	    zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
+
+	if ((zvol_volsize_to_reservation(old_volsize, props) !=
+	    old_reservation) || nvlist_exists(nvl,
+	    zfs_prop_to_name(resv_prop))) {
+		fnvlist_free(props);
 		return (0);
 	}
 	if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
-	    &new_volsize) != 0)
+	    &new_volsize) != 0) {
+		fnvlist_free(props);
 		return (-1);
-	new_reservation = zvol_volsize_to_reservation(new_volsize,
-	    zhp->zfs_props);
+	}
+	new_reservation = zvol_volsize_to_reservation(new_volsize, props);
+	fnvlist_free(props);
+
 	if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
 	    new_reservation) != 0) {
 		(void) no_memory(zhp->zfs_hdl);
--- a/usr/src/lib/libzfs/common/mapfile-vers	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/lib/libzfs/common/mapfile-vers	Wed Feb 20 22:50:16 2013 -0800
@@ -158,6 +158,7 @@
 	zfs_unshareall_nfs;
 	zfs_unshareall_smb;
 	zfs_userspace;
+	zfs_valid_proplist;
 	zfs_get_fsacl;
 	zfs_set_fsacl;
 	zfs_userquota_prop_prefixes;
--- a/usr/src/man/man1m/dumpadm.1m	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/man/man1m/dumpadm.1m	Wed Feb 20 22:50:16 2013 -0800
@@ -1,10 +1,11 @@
 '\" te
-.\"  Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved
+.\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved
 .\" Copyright 2013 Nexenta Systems, Inc.  All Rights Reserved.
+.\" Copyright (c) 2013 by Delphix. All rights reserved.
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH DUMPADM 1M "Jan 30, 2013"
+.TH DUMPADM 1M "Feb 15, 2013"
 .SH NAME
 dumpadm \- configure operating system crash dump
 .SH SYNOPSIS
@@ -172,6 +173,17 @@
 device.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fBnone\fR\fR
+.ad
+.sp .6
+.RS 4n
+If the special token \fBnone\fR is specified, the active dump device is removed
+and crash dumps are disabled.
+.RE
+
 .RE
 
 .sp
--- a/usr/src/uts/common/fs/zfs/sys/zvol.h	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zvol.h	Wed Feb 20 22:50:16 2013 -0800
@@ -43,7 +43,7 @@
 extern int zvol_create_minor(const char *);
 extern int zvol_remove_minor(const char *);
 extern void zvol_remove_minors(const char *);
-extern int zvol_set_volsize(const char *, major_t, uint64_t);
+extern int zvol_set_volsize(const char *, uint64_t);
 
 extern int zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr);
 extern int zvol_dump(dev_t dev, caddr_t addr, daddr_t offset, int nblocks);
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Wed Feb 20 22:50:16 2013 -0800
@@ -2368,8 +2368,7 @@
 		err = dsl_dataset_set_reservation(dsname, source, intval);
 		break;
 	case ZFS_PROP_VOLSIZE:
-		err = zvol_set_volsize(dsname, ddi_driver_major(zfs_dip),
-		    intval);
+		err = zvol_set_volsize(dsname, intval);
 		break;
 	case ZFS_PROP_VERSION:
 	{
--- a/usr/src/uts/common/fs/zfs/zvol.c	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/uts/common/fs/zfs/zvol.c	Wed Feb 20 22:50:16 2013 -0800
@@ -145,10 +145,11 @@
 static int zvol_dump_init(zvol_state_t *zv, boolean_t resize);
 
 static void
-zvol_size_changed(uint64_t volsize, major_t maj, minor_t min)
+zvol_size_changed(zvol_state_t *zv, uint64_t volsize)
 {
-	dev_t dev = makedevice(maj, min);
+	dev_t dev = makedevice(ddi_driver_major(zfs_dip), zv->zv_minor);
 
+	zv->zv_volsize = volsize;
 	VERIFY(ddi_prop_update_int64(dev, zfs_dip,
 	    "Size", volsize) == DDI_SUCCESS);
 	VERIFY(ddi_prop_update_int64(dev, zfs_dip,
@@ -610,22 +611,22 @@
 	if (error)
 		return (error);
 
+	zv->zv_objset = os;
 	error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
 	if (error) {
 		ASSERT(error == 0);
 		dmu_objset_disown(os, zvol_tag);
 		return (error);
 	}
-	zv->zv_objset = os;
+
 	error = dmu_bonus_hold(os, ZVOL_OBJ, zvol_tag, &zv->zv_dbuf);
 	if (error) {
 		dmu_objset_disown(os, zvol_tag);
 		return (error);
 	}
-	zv->zv_volsize = volsize;
+
+	zvol_size_changed(zv, volsize);
 	zv->zv_zilog = zil_open(os, zvol_get_data);
-	zvol_size_changed(zv->zv_volsize, ddi_driver_major(zfs_dip),
-	    zv->zv_minor);
 
 	VERIFY(dsl_prop_get_integer(zv->zv_name, "readonly", &readonly,
 	    NULL) == 0);
@@ -747,56 +748,37 @@
 	mutex_exit(&zfsdev_state_lock);
 }
 
-int
-zvol_set_volsize(const char *name, major_t maj, uint64_t volsize)
+static int
+zvol_set_volsize_impl(objset_t *os, zvol_state_t *zv, uint64_t volsize)
 {
-	zvol_state_t *zv = NULL;
-	objset_t *os;
+	uint64_t old_volsize = 0ULL;
 	int error;
-	dmu_object_info_t doi;
-	uint64_t old_volsize = 0ULL;
-	uint64_t readonly;
 
-	mutex_enter(&zfsdev_state_lock);
-	zv = zvol_minor_lookup(name);
-	if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) {
-		mutex_exit(&zfsdev_state_lock);
-		return (error);
-	}
+	ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+	error = zvol_update_volsize(os, volsize);
 
-	if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 ||
-	    (error = zvol_check_volsize(volsize,
-	    doi.doi_data_block_size)) != 0)
-		goto out;
-
-	VERIFY(dsl_prop_get_integer(name, "readonly", &readonly,
-	    NULL) == 0);
-	if (readonly) {
-		error = EROFS;
-		goto out;
-	}
-
-	error = zvol_update_volsize(os, volsize);
 	/*
 	 * Reinitialize the dump area to the new size. If we
 	 * failed to resize the dump area then restore it back to
-	 * its original size.
+	 * its original size.  We must set the new volsize prior
+	 * to calling dumpvp_resize() to ensure that the devices'
+	 * size(9P) is not visible by the dump subsystem.
 	 */
 	if (zv && error == 0) {
+		old_volsize = zv->zv_volsize;
+		zvol_size_changed(zv, volsize);
+
 		if (zv->zv_flags & ZVOL_DUMPIFIED) {
-			old_volsize = zv->zv_volsize;
-			zv->zv_volsize = volsize;
 			if ((error = zvol_dumpify(zv)) != 0 ||
 			    (error = dumpvp_resize()) != 0) {
+				int dumpify_error;
+
 				(void) zvol_update_volsize(os, old_volsize);
-				zv->zv_volsize = old_volsize;
-				error = zvol_dumpify(zv);
+				zvol_size_changed(zv, old_volsize);
+				dumpify_error = zvol_dumpify(zv);
+				error = dumpify_error ? dumpify_error : error;
 			}
 		}
-		if (error == 0) {
-			zv->zv_volsize = volsize;
-			zvol_size_changed(volsize, maj, zv->zv_minor);
-		}
 	}
 
 	/*
@@ -819,12 +801,41 @@
 		nvlist_free(attr);
 		kmem_free(physpath, MAXPATHLEN);
 	}
+	return (error);
+}
 
+int
+zvol_set_volsize(const char *name, uint64_t volsize)
+{
+	zvol_state_t *zv = NULL;
+	objset_t *os;
+	int error;
+	dmu_object_info_t doi;
+	uint64_t readonly;
+
+	mutex_enter(&zfsdev_state_lock);
+	zv = zvol_minor_lookup(name);
+	if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) {
+		mutex_exit(&zfsdev_state_lock);
+		return (error);
+	}
+
+	if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 ||
+	    (error = zvol_check_volsize(volsize,
+	    doi.doi_data_block_size)) != 0)
+		goto out;
+
+	VERIFY3U(dsl_prop_get_integer(name,
+	    zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL), ==, 0);
+	if (readonly) {
+		error = EROFS;
+		goto out;
+	}
+
+	error = zvol_set_volsize_impl(os, zv, volsize);
 out:
 	dmu_objset_rele(os, FTAG);
-
 	mutex_exit(&zfsdev_state_lock);
-
 	return (error);
 }
 
--- a/usr/src/uts/common/io/dump.c	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/uts/common/io/dump.c	Wed Feb 20 22:50:16 2013 -0800
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Delphix (c) 2012 by Delphix. All rights reserved.
  */
 
 
@@ -208,6 +209,13 @@
 		error = copyoutstr(dump_get_uuid(), (void *)arg, 37, NULL);
 		break;
 
+	case DIOCRMDEV:
+		mutex_enter(&dump_lock);
+		if (dumpvp != NULL)
+			dumpfini();
+		mutex_exit(&dump_lock);
+		break;
+
 	default:
 		error = ENXIO;
 	}
--- a/usr/src/uts/common/sys/dumpadm.h	Wed Feb 20 13:30:36 2013 -0800
+++ b/usr/src/uts/common/sys/dumpadm.h	Wed Feb 20 22:50:16 2013 -0800
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #ifndef	_SYS_DUMPADM_H
@@ -42,6 +43,7 @@
 #define	DIOCDUMP	(DDIOC | 0x16)
 #define	DIOCSETUUID	(DDIOC | 0x17)
 #define	DIOCGETUUID	(DDIOC | 0x18)
+#define	DIOCRMDEV	(DDIOC | 0x19)
 
 /*
  * Kernel-controlled dump state flags for dump_conflags