changeset 4082:2e3825fd8bb5

6372011 libdiskmgt needs to build appropriate .po file 6533990 zpool create in-use check fails on svm swap device
author mmusante
date Fri, 20 Apr 2007 17:46:13 -0700
parents d68a788b1ca0
children 08c82bb85ef2
files usr/src/cmd/zpool/zpool_vdev.c usr/src/lib/Makefile usr/src/lib/libdiskmgt/Makefile usr/src/lib/libdiskmgt/common/entry.c usr/src/lib/libdiskmgt/common/inuse_mnt.c usr/src/lib/libdiskmgt/common/libdiskmgt.h usr/src/lib/libdiskmgt/common/mapfile-vers
diffstat 7 files changed, 213 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/zpool/zpool_vdev.c	Fri Apr 20 14:52:21 2007 -0700
+++ b/usr/src/cmd/zpool/zpool_vdev.c	Fri Apr 20 17:46:13 2007 -0700
@@ -137,7 +137,6 @@
 {
 	char *msg;
 	int error = 0;
-	int ret = 0;
 
 	if (dm_inuse((char *)path, &msg, isspare ? DM_WHO_ZPOOL_SPARE :
 	    (force ? DM_WHO_ZPOOL_FORCE : DM_WHO_ZPOOL), &error) || error) {
@@ -147,9 +146,8 @@
 		} else {
 			vdev_error("%s", msg);
 			free(msg);
-			ret = -1;
+			return (-1);
 		}
-
 	}
 
 	/*
@@ -159,18 +157,19 @@
 	error = 0;
 	if (!wholedisk && !force &&
 	    (dm_isoverlapping((char *)path, &msg, &error) || error)) {
-		if (error != 0) {
+		if (error == 0) {
+			/* dm_isoverlapping returned -1 */
+			vdev_error(gettext("%s overlaps with %s\n"), path, msg);
+			free(msg);
+			return (-1);
+		} else if (error != ENODEV) {
+			/* libdiskmgt's devcache only handles physical drives */
 			libdiskmgt_error(error);
 			return (0);
-		} else {
-			vdev_error("%s overlaps with %s\n", path, msg);
-			free(msg);
 		}
-
-		ret = -1;
 	}
 
-	return (ret);
+	return (0);
 }
 
 /*
@@ -273,7 +272,7 @@
 
 /*
  * Check that a file is valid.  All we can do in this case is check that it's
- * not in use by another pool.
+ * not in use by another pool, and not in use by swap.
  */
 int
 check_file(const char *file, boolean_t force, boolean_t isspare)
@@ -281,9 +280,19 @@
 	char  *name;
 	int fd;
 	int ret = 0;
+	int err;
 	pool_state_t state;
 	boolean_t inuse;
 
+	if (dm_inuse_swap(file, &err)) {
+		if (err)
+			libdiskmgt_error(err);
+		else
+			vdev_error(gettext("%s is currently used by swap. "
+			    "Please see swap(1M).\n"), file);
+		return (-1);
+	}
+
 	if ((fd = open(file, O_RDONLY)) < 0)
 		return (0);
 
--- a/usr/src/lib/Makefile	Fri Apr 20 14:52:21 2007 -0700
+++ b/usr/src/lib/Makefile	Fri Apr 20 17:46:13 2007 -0700
@@ -273,6 +273,7 @@
 	libdhcpsvc 	\
 	libdhcputil	\
 	libipsecutil	\
+	libdiskmgt	\
 	libdladm	\
 	libgss		\
 	libinetcfg	\
--- a/usr/src/lib/libdiskmgt/Makefile	Fri Apr 20 14:52:21 2007 -0700
+++ b/usr/src/lib/libdiskmgt/Makefile	Fri Apr 20 17:46:13 2007 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -46,15 +46,20 @@
 lint :=		TARGET = lint
 install_h:=	TARGET = install_h
 
+POFILE =        libdiskmgt.po
+MSGFILES =      `$(GREP) -l gettext common/*.[ch]`
+
 .KEEP_STATE:
 
 all clean clobber install lint: $(SUBDIRS)
 
+$(POFILE):      pofile_MSGFILES
+
 install_h: $(ROOTHDRS)
 
 check:		$(CHECKHDRS)
 
-$(POFILE):
+_msg: $(MSGDOMAINPOFILE)
 
 $(SUBDIRS):	FRC
 	@cd $@; pwd; $(MAKE) $(TARGET)
@@ -62,3 +67,4 @@
 FRC:
 
 include ../Makefile.targ
+include ../../Makefile.msg.targ
--- a/usr/src/lib/libdiskmgt/common/entry.c	Fri Apr 20 14:52:21 2007 -0700
+++ b/usr/src/lib/libdiskmgt/common/entry.c	Fri Apr 20 17:46:13 2007 -0700
@@ -36,14 +36,21 @@
 #include <libintl.h>
 #include <locale.h>
 #include <sys/debug.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/swap.h>
 
 #include "libdiskmgt.h"
 #include "disks_private.h"
 #include "partition.h"
 
+#define	ANY_ZPOOL_USE(who) \
+	(((who) == DM_WHO_ZPOOL_FORCE) || \
+	((who) == DM_WHO_ZPOOL) || \
+	((who) == DM_WHO_ZPOOL_SPARE))
+
 extern	char	*getfullblkname();
 
-
 extern dm_desc_type_t drive_assoc_types[];
 extern dm_desc_type_t bus_assoc_types[];
 extern dm_desc_type_t controller_assoc_types[];
@@ -727,6 +734,113 @@
 }
 
 /*
+ * Get the full list of swap entries.  Returns -1 on error, or >= 0 to
+ * indicate the number of entries in the list.  Callers are responsible
+ * for calling dm_free_swapentries() to deallocate memory.  If this
+ * returns 0, the swaptbl_t still needs to be freed.
+ */
+int
+dm_get_swapentries(swaptbl_t **stp, int *errp)
+{
+	int count, i;
+	swaptbl_t *tbl;
+	char *ptr;
+
+	*stp = NULL;
+
+	/* get number of swap entries */
+	if ((count = swapctl(SC_GETNSWP, NULL)) < 0) {
+		*errp = errno;
+		return (-1);
+	}
+
+	if (count == 0) {
+		return (0);
+	}
+
+	/* allocate space */
+	tbl = calloc(1, sizeof (int) + count * sizeof (swapent_t));
+	if (tbl == NULL) {
+		*errp = ENOMEM;
+		return (-1);
+	}
+
+	ptr = calloc(1, count * MAXPATHLEN);
+	if (ptr == NULL) {
+		*errp = ENOMEM;
+		free(tbl);
+		return (-1);
+	}
+
+	/* set up pointers to the pathnames */
+	tbl->swt_n = count;
+	for (i = 0; i < count; i++) {
+		tbl->swt_ent[i].ste_path = ptr;
+		ptr += MAXPATHLEN;
+	}
+
+	/* get list of swap paths */
+	count = swapctl(SC_LIST, tbl);
+	if (count < 0) {
+		*errp = errno;
+		free(ptr);
+		free(tbl);
+		return (-1);
+	}
+
+	*stp = tbl;
+	return (count);
+}
+
+/* ARGSUSED */
+void
+dm_free_swapentries(swaptbl_t *stp)
+{
+	ASSERT(stp != NULL);
+
+	free(stp->swt_ent[0].ste_path);
+	free(stp);
+}
+
+/*
+ * Check a slice to see if it's being used by swap.
+ */
+int
+dm_inuse_swap(const char *dev_name, int *errp)
+{
+	int count;
+	int found;
+	swaptbl_t *tbl = NULL;
+
+	*errp = 0;
+
+	count = dm_get_swapentries(&tbl, errp);
+	if (count < 0 || *errp) {
+		if (tbl)
+			dm_free_swapentries(tbl);
+		return (-1);
+	}
+
+	/* if there are no swap entries, we're done */
+	if (!count) {
+		return (0);
+	}
+
+	ASSERT(tbl != NULL);
+
+	found = 0;
+	while (count--) {
+		if (strcmp(dev_name, tbl->swt_ent[count].ste_path) == 0) {
+			found = 1;
+			break;
+		}
+	}
+
+	dm_free_swapentries(tbl);
+	return (found);
+}
+
+/*
  * Returns 'in use' details, if found, about a specific dev_name,
  * based on the caller(who). It is important to note that it is possible
  * for there to be more than one 'in use' statistic regarding a dev_name.
@@ -741,6 +855,7 @@
 	nvpair_t *nvwhat = NULL;
 	nvpair_t *nvdesc = NULL;
 	int	found = 0;
+	int	err;
 	char	*dname = NULL;
 
 	*errp = 0;
@@ -762,6 +877,31 @@
 		return (found);
 	}
 
+	/*
+	 * Slice stats for swap devices are only returned if mounted
+	 * (e.g. /tmp).  Other devices or files being used for swap
+	 * are ignored, so we add a special check here to use swapctl(2)
+	 * to perform in-use checking.
+	 */
+	if (ANY_ZPOOL_USE(who) && (err = dm_inuse_swap(dname, errp))) {
+
+		/* on error, dm_inuse_swap sets errp */
+		if (err < 0) {
+			free(dname);
+			return (err);
+		}
+
+		/* simulate a mounted swap device */
+		(void) build_usage_string(dname, DM_USE_MOUNT, "swap", msg,
+		    &found, errp);
+
+		/* if this fails, dm_get_usage_string changed */
+		ASSERT(found == 1);
+
+		free(dname);
+		return (found);
+	}
+
 	dm_get_slice_stats(dname, &dev_stats, errp);
 	if (dev_stats == NULL) {
 		/*
--- a/usr/src/lib/libdiskmgt/common/inuse_mnt.c	Fri Apr 20 14:52:21 2007 -0700
+++ b/usr/src/lib/libdiskmgt/common/inuse_mnt.c	Fri Apr 20 17:46:13 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -207,6 +206,10 @@
 	struct mntpnt_list	*headp;
 	int			num;
 	struct mntpnt_list	*prevp;
+	struct swaptable	*st;
+	struct swapent		*swapent;
+	int			err;
+	int			i;
 
 	headp = NULL;
 	prevp = NULL;
@@ -276,94 +279,61 @@
 	}
 
 	/* get the swap entries */
-	if ((num = swapctl(SC_GETNSWP, NULL)) > -1) {
-
-	    struct swaptable 	*st;
-	    struct swapent	*swapent;
-	    int			i;
-	    char		*path;
-	    char		*pathstart;
-	    char		fullpath[MAXPATHLEN+1];
-
-	    st = malloc((size_t)((num * sizeof (swapent_t)) + sizeof (int)));
-	    if (st == NULL) {
-		/* out of memory, free what we have and return */
-		free_mnttab(headp);
-		return (ENOMEM);
-	    }
-
-	    path = malloc(num * MAXPATHLEN);
-	    if (path == NULL) {
-		/* out of memory, free what we have and return */
-		free(st);
+	num = dm_get_swapentries(&st, &err);
+	if (num < 0) {
 		free_mnttab(headp);
 		return (ENOMEM);
-	    }
-	    pathstart = path;
+	}
 
-	    swapent = st->swt_ent;
-	    for (i = 0; i < num; i++, swapent++) {
-		swapent->ste_path = path;
-		path += MAXPATHLEN;
-	    }
+	for (i = 0, swapent = st->swt_ent; i < num; i++, swapent++) {
+		char		fullpath[MAXPATHLEN+1];
 
-	    st->swt_n = num;
-	    if ((num = swapctl(SC_LIST, st)) >= 0) {
-		swapent = st->swt_ent;
-		for (i = 0; i < num; i++, swapent++) {
+		currp = (struct mntpnt_list *)
+		    calloc((size_t)1, (size_t)sizeof (struct mntpnt_list));
 
-		    currp = (struct mntpnt_list *)
-			calloc((size_t)1, (size_t)sizeof (struct mntpnt_list));
-
-		    if (currp == NULL) {
+		if (currp == NULL) {
 			/* out of memory, free what we have and return */
-			free((void *)st);
-			free((void *)pathstart);
+			dm_free_swapentries(st);
 			free_mnttab(headp);
 			return (ENOMEM);
-		    }
+		}
 
-		    if (headp == NULL) {
+		if (headp == NULL) {
 			headp = currp;
-		    } else {
+		} else {
 			prevp->next = currp;
-		    }
+		}
 
-		    currp->next = NULL;
+		currp->next = NULL;
 
-		    if (*swapent->ste_path != '/') {
+		if (*swapent->ste_path != '/') {
 			(void) snprintf(fullpath, sizeof (fullpath), "/dev/%s",
 			    swapent->ste_path);
-		    } else {
+		} else {
 			(void) strlcpy(fullpath, swapent->ste_path,
 			    sizeof (fullpath));
-		    }
+		}
 
-		    currp->special = strdup(fullpath);
-		    if (currp->special == NULL) {
+		currp->special = strdup(fullpath);
+		if (currp->special == NULL) {
 			/* out of memory, free what we have and return */
-			free(st);
-			free(pathstart);
+			dm_free_swapentries(st);
 			free_mnttab(headp);
 			return (ENOMEM);
-		    }
+		}
 
-		    currp->mountp = strdup("swap");
-		    if (currp->mountp == NULL) {
+		currp->mountp = strdup("swap");
+		if (currp->mountp == NULL) {
 			/* out of memory, free what we have and return */
-			free(st);
-			free(pathstart);
+			dm_free_swapentries(st);
 			free_mnttab(headp);
 			return (ENOMEM);
-		    }
+		}
 
-		    prevp = currp;
-		}
-	    }
-
-	    free(st);
-	    free(pathstart);
+		prevp = currp;
 	}
+	if (num)
+		dm_free_swapentries(st);
 
 	/* note that we unlock the mutex in both paths of this if statement */
 	(void) rw_wrlock(&mntpoint_lock);
--- a/usr/src/lib/libdiskmgt/common/libdiskmgt.h	Fri Apr 20 14:52:21 2007 -0700
+++ b/usr/src/lib/libdiskmgt/common/libdiskmgt.h	Fri Apr 20 17:46:13 2007 -0700
@@ -33,7 +33,7 @@
 #endif
 
 #include <libnvpair.h>
-
+#include <sys/swap.h>
 
 
 /*
@@ -235,6 +235,7 @@
 void			dm_free_descriptors(dm_descriptor_t *desc_list);
 void			dm_free_descriptor(dm_descriptor_t desc);
 void			dm_free_name(char *name);
+void			dm_free_swapentries(swaptbl_t *);
 
 dm_descriptor_t		*dm_get_descriptors(dm_desc_type_t type, int filter[],
 			    int *errp);
@@ -255,9 +256,11 @@
 			    int *errp);
 void			dm_get_slice_stats(char *slice, nvlist_t **dev_stats,
 			    int *errp);
+int			dm_get_swapentries(swaptbl_t **, int *);
 void			dm_get_usage_string(char *who, char *data, char **msg);
 int			dm_inuse(char *dev_name, char **msg, dm_who_type_t who,
 			    int *errp);
+int			dm_inuse_swap(const char *dev_name, int *errp);
 int			dm_isoverlapping(char *dev_name, char **msg, int *errp);
 
 #ifdef __cplusplus
--- a/usr/src/lib/libdiskmgt/common/mapfile-vers	Fri Apr 20 14:52:21 2007 -0700
+++ b/usr/src/lib/libdiskmgt/common/mapfile-vers	Fri Apr 20 17:46:13 2007 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -30,6 +30,7 @@
 	dm_free_descriptor;
 	dm_free_descriptors;
 	dm_free_name;
+	dm_free_swapentries;
 	dm_get_associated_descriptors;
 	dm_get_associated_types;
 	dm_get_attributes;
@@ -40,9 +41,11 @@
 	dm_get_slices;
 	dm_get_slice_stats;
 	dm_get_stats;
+	dm_get_swapentries;
 	dm_get_type;
 	dm_init_event_queue;
 	dm_inuse;
+	dm_inuse_swap;
 	dm_isoverlapping;
     local:
 	*;