summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/boot/bootadm/bootadm.c125
-rw-r--r--usr/src/cmd/boot/bootadm/bootadm.h7
-rw-r--r--usr/src/cmd/boot/scripts/update_grub.ksh55
-rw-r--r--usr/src/cmd/dumpadm/Makefile4
-rw-r--r--usr/src/cmd/dumpadm/dconf.c11
-rw-r--r--usr/src/cmd/power/Makefile4
-rw-r--r--usr/src/cmd/power/handlers.c171
-rw-r--r--usr/src/cmd/power/svc-power13
-rw-r--r--usr/src/cmd/svc/milestone/fs-minimal2
-rw-r--r--usr/src/cmd/svc/milestone/fs-usr35
-rw-r--r--usr/src/cmd/svc/shell/fs_include.sh13
-rw-r--r--usr/src/cmd/swap/swap.c16
-rw-r--r--usr/src/cmd/zdb/zdb.c3
13 files changed, 410 insertions, 49 deletions
diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c
index d1ae66bbcb..a0647e0b0e 100644
--- a/usr/src/cmd/boot/bootadm/bootadm.c
+++ b/usr/src/cmd/boot/bootadm/bootadm.c
@@ -54,6 +54,7 @@
#include <sys/systeminfo.h>
#include <sys/dktp/fdisk.h>
#include <sys/param.h>
+#include <sys/sysmacros.h>
#if !defined(_OPB)
#include <sys/ucode.h>
@@ -197,6 +198,7 @@ static int bam_argc;
static int bam_check;
static int bam_smf_check;
static int bam_lock_fd = -1;
+static int bam_zfs;
static char rootbuf[PATH_MAX] = "/";
static int bam_update_all;
static int bam_alt_platform;
@@ -242,6 +244,7 @@ static int s_fputs(char *, FILE *);
static char *s_strdup(char *);
static int is_readonly(char *);
+static int is_zfs(char *, char **);
static int is_amd64(void);
static int is_sun4u(void);
static int is_sun4v(void);
@@ -419,7 +422,7 @@ parse_args_internal(int argc, char *argv[])
opterr = 0;
error = 0;
- while ((c = getopt(argc, argv, "a:d:fm:no:vCR:p:")) != -1) {
+ while ((c = getopt(argc, argv, "a:d:fm:no:vCR:p:Z")) != -1) {
switch (c) {
case 'a':
if (bam_cmd) {
@@ -500,6 +503,9 @@ parse_args_internal(int argc, char *argv[])
bam_error(INVALID_PLAT, bam_platform);
}
break;
+ case 'Z':
+ bam_zfs = 1;
+ break;
case '?':
error = 1;
bam_error(BAD_OPT, optopt);
@@ -893,8 +899,9 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[])
error_t ret;
char menu_path[PATH_MAX];
char path[PATH_MAX];
+ char full_menu_root[PATH_MAX];
menu_t *menu;
- char *mntpt, *menu_root, *logslice, *fstype;
+ char *mntpt, *menu_root, *logslice, *fstype, *grubSLICEpool, *pool;
struct stat sb;
int mnted; /* set if we did a mount */
error_t (*f)(menu_t *mp, char *menu_path, char *opt);
@@ -919,7 +926,7 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[])
mntpt = NULL;
mnted = 0;
- logslice = fstype = NULL;
+ logslice = fstype = grubSLICEpool = pool = NULL;
/*
* Check for the menu.list file:
@@ -931,10 +938,18 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[])
* 4. Use /
*/
if (bam_alt_root) {
- (void) snprintf(path, sizeof (path), "%s%s", bam_root,
- GRUB_slice);
+ if (is_zfs(bam_root, &grubSLICEpool))
+ (void) snprintf(path, sizeof (path), "%s/%s%s",
+ bam_root, grubSLICEpool, GRUB_slice);
+ else
+ (void) snprintf(path, sizeof (path), "%s%s",
+ bam_root, GRUB_slice);
} else {
- (void) snprintf(path, sizeof (path), "%s", GRUB_slice);
+ if (is_zfs(bam_root, &grubSLICEpool))
+ (void) snprintf(path, sizeof (path), "/%s%s",
+ grubSLICEpool, GRUB_slice);
+ else
+ (void) snprintf(path, sizeof (path), "%s", GRUB_slice);
}
if (stat(path, &sb) == 0) {
@@ -953,7 +968,25 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[])
return (BAM_ERROR);
}
- elide_trailing_slash(menu_root, menu_path, sizeof (menu_path));
+ /*
+ * menu_root is the root file system of the boot environment being
+ * operated on.
+ * full_menu_root is the location of the /boot/grub directory.
+ * With a ufs root, this is simply menu_root. With a zfs
+ * root, it's <menu_root>/<poolname>
+ */
+ elide_trailing_slash(menu_root, full_menu_root,
+ sizeof (full_menu_root));
+
+ if (is_zfs(menu_root, &pool)) {
+ (void) strlcat(full_menu_root, "/", sizeof (full_menu_root));
+ (void) strlcat(full_menu_root, pool, sizeof (full_menu_root));
+ }
+
+ /*
+ * menu_path is the directory that contains the menu.lst file
+ */
+ (void) strlcpy(menu_path, full_menu_root, sizeof (menu_path));
(void) strlcat(menu_path, GRUB_MENU, sizeof (menu_path));
/*
@@ -999,13 +1032,17 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[])
else
ret = f(menu, menu_path, opt);
if (ret == BAM_WRITE) {
- ret = menu_write(menu_root, menu);
+ ret = menu_write(full_menu_root, menu);
}
menu_free(menu);
umount_grub_slice(mnted, mntpt, NULL, logslice, fstype);
+ if (grubSLICEpool)
+ free(grubSLICEpool);
+ if (pool)
+ free(pool);
return (ret);
}
@@ -2093,6 +2130,65 @@ is_readonly(char *root)
return (0);
}
+static int
+is_zfs(char *root, char **poolname)
+{
+ struct statvfs64 vfs;
+ FILE *fp;
+ struct extmnttab mnt;
+ dev_t devicenum;
+ char *special = NULL;
+ char *cp;
+
+ /* poolname can be null */
+ if (poolname)
+ *poolname = NULL;
+
+ if (statvfs64(root, &vfs) != 0) {
+ if (bam_verbose)
+ bam_error(STATVFS_FAIL, root, strerror(errno));
+ return (0);
+ }
+
+ if (strncmp(vfs.f_basetype, "zfs", strlen("zfs")) != 0)
+ return (0);
+
+ if (poolname == NULL)
+ return (1);
+
+ /*
+ * Now find the mnttab entry so that we can extract the
+ * pool name from the special device field.
+ */
+ fp = fopen(MNTTAB, "r");
+ if (fp == NULL) {
+ bam_error(OPEN_FAIL, MNTTAB, strerror(errno));
+ return (0);
+ }
+
+ resetmnttab(fp);
+
+ while (getextmntent(fp, &mnt, sizeof (mnt)) == 0) {
+ devicenum = makedevice(mnt.mnt_major, mnt.mnt_minor);
+ if (devicenum == vfs.f_fsid) {
+ special = s_strdup(mnt.mnt_special);
+ if ((cp = strchr(special, '/')) != NULL)
+ *cp = '\0';
+ *poolname = s_strdup(special);
+ break;
+ }
+ }
+
+ (void) fclose(fp);
+
+ if (special) {
+ free(special);
+ return (1);
+ }
+
+ return (0);
+}
+
static error_t
update_archive(char *root, char *opt)
{
@@ -3480,12 +3576,13 @@ update_entry(menu_t *mp, char *menu_root, char *opt)
/* add the entry for normal Solaris */
if (bam_direct == BAM_DIRECT_DBOOT) {
entry = update_boot_entry(mp, title, grubdisk,
- DIRECT_BOOT_KERNEL, NULL, DIRECT_BOOT_ARCHIVE,
- osroot == menu_root);
+ (bam_zfs ? DIRECT_BOOT_KERNEL_ZFS : DIRECT_BOOT_KERNEL),
+ NULL, DIRECT_BOOT_ARCHIVE, osroot == menu_root);
if ((entry != BAM_ERROR) && (bam_is_hv == BAM_HV_PRESENT)) {
(void) update_boot_entry(mp, NEW_HV_ENTRY, grubdisk,
- XEN_MENU, KERNEL_MODULE_LINE, DIRECT_BOOT_ARCHIVE,
- osroot == menu_root);
+ XEN_MENU, (bam_zfs ?
+ KERNEL_MODULE_LINE_ZFS : KERNEL_MODULE_LINE),
+ DIRECT_BOOT_ARCHIVE, osroot == menu_root);
}
} else {
entry = update_boot_entry(mp, title, grubdisk, MULTI_BOOT,
@@ -3503,7 +3600,9 @@ update_entry(menu_t *mp, char *menu_root, char *opt)
(void) snprintf(failsafe, sizeof (failsafe), "%s%s", osroot,
DIRECT_BOOT_FAILSAFE_KERNEL);
if (stat(failsafe, &sbuf) == 0) {
- failsafe_kernel = DIRECT_BOOT_FAILSAFE_LINE;
+ failsafe_kernel =
+ (bam_zfs ? DIRECT_BOOT_FAILSAFE_LINE_ZFS :
+ DIRECT_BOOT_FAILSAFE_LINE);
} else {
(void) snprintf(failsafe, sizeof (failsafe), "%s%s",
osroot, MULTI_BOOT_FAILSAFE);
diff --git a/usr/src/cmd/boot/bootadm/bootadm.h b/usr/src/cmd/boot/bootadm/bootadm.h
index f29071d1d0..a4a606e845 100644
--- a/usr/src/cmd/boot/bootadm/bootadm.h
+++ b/usr/src/cmd/boot/bootadm/bootadm.h
@@ -174,6 +174,9 @@ extern int is_grub(const char *);
/* Title used for hv entries */
#define NEW_HV_ENTRY "Solaris xVM"
+/* ZFS boot option */
+#define ZFS_BOOT "-B $ZFS-BOOTFS"
+
/* multiboot */
#define MULTI_BOOT "/platform/i86pc/multiboot"
#define MULTI_BOOT_FAILSAFE "/boot/multiboot"
@@ -186,6 +189,8 @@ extern int is_grub(const char *);
#define DIRECT_BOOT_KERNEL "/platform/i86pc/kernel/$ISADIR/unix"
#define DIRECT_BOOT_FAILSAFE_KERNEL "/boot/platform/i86pc/kernel/unix"
#define DIRECT_BOOT_FAILSAFE_LINE DIRECT_BOOT_FAILSAFE_KERNEL " -s"
+#define DIRECT_BOOT_KERNEL_ZFS DIRECT_BOOT_KERNEL " " ZFS_BOOT
+#define DIRECT_BOOT_FAILSAFE_LINE_ZFS DIRECT_BOOT_FAILSAFE_LINE " " ZFS_BOOT
/* Boot archives */
#define SUN4U_ARCHIVE "/platform/sun4u/boot_archive"
@@ -202,6 +207,8 @@ extern int is_grub(const char *);
#define XEN_MENU "/boot/$ISADIR/xen.gz"
#define HYPERVISOR_KERNEL "/platform/i86xpv/kernel/$ISADIR/unix"
#define KERNEL_MODULE_LINE HYPERVISOR_KERNEL " " HYPERVISOR_KERNEL
+#define KERNEL_MODULE_LINE_ZFS \
+ HYPERVISOR_KERNEL " " HYPERVISOR_KERNEL " " ZFS_BOOT
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/boot/scripts/update_grub.ksh b/usr/src/cmd/boot/scripts/update_grub.ksh
index 86a2ee65c8..d824afd5d1 100644
--- a/usr/src/cmd/boot/scripts/update_grub.ksh
+++ b/usr/src/cmd/boot/scripts/update_grub.ksh
@@ -21,7 +21,7 @@
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -43,6 +43,7 @@ done
ARCH=`uname -p`
is_pcfs_boot=yes
+is_zfs_boot=no
check_pcfs_boot()
{
@@ -53,13 +54,42 @@ check_pcfs_boot()
fi
}
+check_zfs_boot()
+{
+ if [ -f "$ALT_ROOT"/etc/lu/GRUB_slice ]; then
+ dev=`grep '^PHYS_SLICE=' "$ALT_ROOT"/etc/lu/GRUB_slice |
+ cut -d= -f2`
+ if [ "`fstyp $dev`" = "zfs" ]; then
+ is_zfs_boot=yes
+ fi
+ else
+ rootfstype=`df -n ${ALT_ROOT:-/} | awk '{print $3}'`
+ if [ "$rootfstype" = "zfs" ]; then
+ is_zfs_boot=yes
+ fi
+
+ fi
+}
+
#
# Detect SVM root and return the list of raw devices under the mirror
#
get_rootdev_list()
{
if [ -f "$ALT_ROOT"/etc/lu/GRUB_slice ]; then
- grep '^PHYS_SLICE' "$ALT_ROOT"/etc/lu/GRUB_slice | cut -d= -f2
+ dev=`grep '^PHYS_SLICE' "$ALT_ROOT"/etc/lu/GRUB_slice |
+ cut -d= -f2`
+ if [ "$is_zfs_boot" = "yes" ]; then
+ fstyp -a "$dev" | grep 'path: ' | grep -v phys_path: |
+ cut -d"'" -f2 | sed 's+/dsk/+/rdsk/+'
+ else
+ echo "$dev"
+ fi
+ return
+ elif [ "$is_zfs_boot" = "yes" ]; then
+ rootpool=`df -k ${ALT_ROOT:-/} | tail +2 | cut -d/ -f1`
+ rootdevlist=`zpool iostat -v "$rootpool" | tail +5 |
+ grep -v mirror | sed -n -e '/--/q' -e p | awk '{print $1}'`
else
metadev=`grep -v "^#" "$ALT_ROOT"/etc/vfstab | \
grep "[ ]/[ ]" | nawk '{print $2}'`
@@ -70,11 +100,11 @@ get_rootdev_list()
rootdevlist=`metastat -p $metavol |\
grep -v "^$metavol[ ]" | nawk '{print $4}'`
fi
- for rootdev in $rootdevlist
- do
- echo /dev/rdsk/$rootdev
- done
fi
+ for rootdev in $rootdevlist
+ do
+ echo /dev/rdsk/$rootdev
+ done
}
#
@@ -101,16 +131,22 @@ install_grub()
fi
fi
- get_rootdev_list | while read rootdev
+ grubdevlist=`get_rootdev_list`
+ zfsarg=""
+ if [ "$is_zfs_boot" = "yes" ]; then
+ zfsarg="-Z"
+ fi
+
+ for rootdev in $grubdevlist
do
if [ X"$rpcfsdev" != X ]; then
echo "create GRUB menu in "$ALT_ROOT"/stubboot"
- "$ALT_ROOT"/sbin/bootadm update-menu \
+ "$ALT_ROOT"/sbin/bootadm update-menu $zfsarg\
-R "$ALT_ROOT"/stubboot -o $rootdev,"$ALT_ROOT"
else
echo "Creating GRUB menu in ${ALT_ROOT:-/}"
$ALT_ROOT/sbin/bootadm update-menu -R ${ALT_ROOT:-/} \
- -o $rootdev
+ $zfsarg -o $rootdev
fi
print "Installing grub on $rootdev"
"$ALT_ROOT"/sbin/installgrub $STAGE1 $STAGE2 $rootdev
@@ -119,6 +155,7 @@ install_grub()
if [ -f "$ALT_ROOT"/platform/i86pc/multiboot -a "$ARCH" = i386 ] ; then
check_pcfs_boot
+ check_zfs_boot
install_grub
fi
diff --git a/usr/src/cmd/dumpadm/Makefile b/usr/src/cmd/dumpadm/Makefile
index 406f5dc3a0..fac14347df 100644
--- a/usr/src/cmd/dumpadm/Makefile
+++ b/usr/src/cmd/dumpadm/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -44,7 +44,7 @@ GROUP = bin
ROOTMANIFESTDIR = $(ROOTSVCSYSTEM)
-LDLIBS += -ldiskmgt
+LDLIBS += -ldiskmgt -lzfs
.KEEP_STATE:
diff --git a/usr/src/cmd/dumpadm/dconf.c b/usr/src/cmd/dumpadm/dconf.c
index 1fb9216765..3cd5b725da 100644
--- a/usr/src/cmd/dumpadm/dconf.c
+++ b/usr/src/cmd/dumpadm/dconf.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,6 +38,7 @@
#include <fcntl.h>
#include <errno.h>
#include <libdiskmgt.h>
+#include <libzfs.h>
#include "dconf.h"
#include "minfree.h"
@@ -343,6 +344,11 @@ dconf_dev_ioctl(dumpconf_t *dcp, int cmd)
case EBUSY:
warn(gettext("device %s is already in use\n"), dcp->dc_device);
break;
+ case EBADR:
+ /* ZFS pool is too fragmented to support a dump device */
+ warn(gettext("device %s is too fragmented to be used as "
+ "a dump device\n"), dcp->dc_device);
+ break;
default:
/*
* NOTE: The stmsboot(1M) command's boot-up script parses this
@@ -447,6 +453,9 @@ dconf_update(dumpconf_t *dcp, int checkinuse)
goto err;
}
+ if ((error = zvol_check_dump_config(
+ dcp->dc_device)) > 0)
+ goto err;
if (ioctl(dcp->dc_dump_fd, DIOCGETDUMPSIZE, &d) == -1) {
warn(gettext("failed to get kernel dump size"));
goto err;
diff --git a/usr/src/cmd/power/Makefile b/usr/src/cmd/power/Makefile
index 6fc647efc5..0af61cb3fb 100644
--- a/usr/src/cmd/power/Makefile
+++ b/usr/src/cmd/power/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -60,7 +60,7 @@ POFILES= $(PMCFG_SRCS:%.c=%.po)
OPOFILES= sysidpm.po
# pmconfig only needs libdevinfo on sparc
-sparc_LDEVINFO= -ldevinfo
+sparc_LDEVINFO= -ldevinfo -lefi -ladm -lzfs -lnvpair
i386_LDEVINFO=
LDEVINFO= -ldevinfo
diff --git a/usr/src/cmd/power/handlers.c b/usr/src/cmd/power/handlers.c
index 3440d56389..f5fa621c0c 100644
--- a/usr/src/cmd/power/handlers.c
+++ b/usr/src/cmd/power/handlers.c
@@ -30,11 +30,14 @@
#include <sys/syslog.h>
#include <sys/openpromio.h>
#include <sys/mnttab.h>
+#include <sys/vtoc.h>
+#include <sys/efi_partition.h>
#include <syslog.h>
#include <stdlib.h>
#include <sys/pm.h>
#include <kstat.h>
#include <sys/smbios.h>
+#include <libzfs.h>
#define STRCPYLIM(dst, src, str) strcpy_limit(dst, src, sizeof (dst), str)
@@ -824,7 +827,6 @@ nfsreq(void)
return (scan_int(LINEARG(1), &new_cc.nfsreqs_thold));
}
-
#ifdef sparc
static char open_fmt[] = "cannot open \"%s\", %s\n";
@@ -838,6 +840,8 @@ check_mount(char *sfile, dev_t sfdev, int ufs)
{
char *src, *err_fmt = NULL, *mnttab = MNTTAB;
int rgent, match = 0;
+ struct mnttab zroot = { 0 };
+ struct mnttab entry;
struct extmnttab ent;
FILE *fp;
@@ -846,6 +850,18 @@ check_mount(char *sfile, dev_t sfdev, int ufs)
return (1);
}
+ if (ufs) {
+ zroot.mnt_mountp = "/";
+ zroot.mnt_fstype = "zfs";
+ if (getmntany(fp, &entry, &zroot) == 0) {
+ err_fmt = "ufs statefile with zfs root is not"
+ " supported\n";
+ mesg(MERR, err_fmt, sfile);
+ fclose(fp);
+ return (1);
+ }
+ resetmnttab(fp);
+ }
/*
* Search for a matching dev_t;
* ignore non-ufs filesystems for a regular statefile.
@@ -862,14 +878,13 @@ check_mount(char *sfile, dev_t sfdev, int ufs)
break;
}
}
- (void) fclose(fp);
/*
* No match is needed for a block device statefile,
* a match is needed for a regular statefile.
*/
if (match == 0) {
- if (new_cc.cf_type == CFT_SPEC)
+ if (new_cc.cf_type != CFT_UFS)
STRCPYLIM(new_cc.cf_devfs, sfile, "block statefile");
else
err_fmt = "cannot find ufs mount point for \"%s\"\n";
@@ -882,6 +897,7 @@ check_mount(char *sfile, dev_t sfdev, int ufs)
STRCPYLIM(new_cc.cf_path, src, "statefile path");
} else
err_fmt = "statefile device \"%s\" is a mounted filesystem\n";
+ (void) fclose(fp);
if (err_fmt)
mesg(MERR, err_fmt, sfile);
return (err_fmt != NULL);
@@ -893,7 +909,7 @@ check_mount(char *sfile, dev_t sfdev, int ufs)
* log any ioctl/conversion error.
*/
static int
-utop(void)
+utop(char *fs_name, char *prom_name)
{
union obpbuf {
char buf[OBP_MAXPATHLEN + sizeof (uint_t)];
@@ -911,23 +927,132 @@ utop(void)
opp = &oppbuf.oppio;
opp->oprom_size = OBP_MAXPATHLEN;
- strcpy_limit(opp->oprom_array, new_cc.cf_devfs,
+ strcpy_limit(opp->oprom_array, fs_name,
OBP_MAXPATHLEN, "statefile device");
upval = ioctl(fd, OPROMDEV2PROMNAME, opp);
(void) close(fd);
- if (upval == OKUP)
- STRCPYLIM(new_cc.cf_dev_prom, opp->oprom_array, "prom device");
- else {
+ if (upval == OKUP) {
+ strcpy_limit(prom_name, opp->oprom_array, OBP_MAXPATHLEN,
+ "prom device");
+ } else {
openlog("pmconfig", 0, LOG_DAEMON);
syslog(LOG_NOTICE,
gettext("cannot convert \"%s\" to prom device"),
- new_cc.cf_devfs);
+ fs_name);
closelog();
}
return (upval);
}
+/*
+ * given the path to a zvol, return the cXtYdZ name
+ * returns < 0 on error, 0 if it isn't a zvol, > 1 on success
+ */
+static int
+ztop(char *arg, char *diskname)
+{
+ zpool_handle_t *zpool_handle;
+ nvlist_t *config, *nvroot;
+ nvlist_t **child;
+ uint_t children;
+ libzfs_handle_t *lzfs;
+ char *vname;
+ char *p;
+ char pool_name[MAXPATHLEN];
+
+ if (strncmp(arg, "/dev/zvol/dsk/", 14)) {
+ return (0);
+ }
+ arg += 14;
+ strncpy(pool_name, arg, MAXPATHLEN);
+ if (p = strchr(pool_name, '/'))
+ *p = '\0';
+ STRCPYLIM(new_cc.cf_fs, p + 1, "statefile path");
+
+ if ((lzfs = libzfs_init()) == NULL) {
+ mesg(MERR, "failed to initialize ZFS library\n");
+ return (-1);
+ }
+ if ((zpool_handle = zpool_open(lzfs, pool_name)) == NULL) {
+ mesg(MERR, "couldn't open pool '%s'\n", pool_name);
+ libzfs_fini(lzfs);
+ return (-1);
+ }
+ config = zpool_get_config(zpool_handle, NULL);
+ if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
+ &nvroot) != 0) {
+ zpool_close(zpool_handle);
+ libzfs_fini(lzfs);
+ return (-1);
+ }
+ verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
+ &child, &children) == 0);
+ if (children != 1) {
+ mesg(MERR, "expected one vdev, got %d\n", children);
+ zpool_close(zpool_handle);
+ libzfs_fini(lzfs);
+ return (-1);
+ }
+ vname = zpool_vdev_name(lzfs, zpool_handle, child[0]);
+ if (vname == NULL) {
+ mesg(MERR, "couldn't determine vdev name\n");
+ zpool_close(zpool_handle);
+ libzfs_fini(lzfs);
+ return (-1);
+ }
+ strcpy(diskname, "/dev/dsk/");
+ strcat(diskname, vname);
+ free(vname);
+ zpool_close(zpool_handle);
+ libzfs_fini(lzfs);
+ return (1);
+}
+
+/*
+ * returns NULL if the slice is good (e.g. does not start at block
+ * zero, or a string describing the error if it doesn't
+ */
+static boolean_t
+is_good_slice(char *sfile, char **err)
+{
+ int fd, rc;
+ struct vtoc vtoc;
+ dk_gpt_t *gpt;
+ char rdskname[MAXPATHLEN];
+ char *x, *y;
+
+ *err = NULL;
+ /* convert from dsk to rdsk */
+ STRCPYLIM(rdskname, sfile, "disk name");
+ x = strstr(rdskname, "dsk/");
+ y = strstr(sfile, "dsk/");
+ if (x != NULL) {
+ *x++ = 'r';
+ strcpy(x, y);
+ }
+
+ if ((fd = open(rdskname, O_RDONLY)) == -1) {
+ *err = "could not open '%s'\n";
+ } else if ((rc = read_vtoc(fd, &vtoc)) >= 0) {
+ /*
+ * we got a slice number; now check the block
+ * number where the slice starts
+ */
+ if (vtoc.v_part[rc].p_start < 2)
+ *err = "using '%s' would clobber the disk label\n";
+ close(fd);
+ return (*err ? B_FALSE : B_TRUE);
+ } else if ((rc == VT_ENOTSUP) &&
+ (efi_alloc_and_read(fd, &gpt)) >= 0) {
+ /* EFI slices don't clobber the disk label */
+ free(gpt);
+ close(fd);
+ return (B_TRUE);
+ } else
+ *err = "could not read partition table from '%s'\n";
+ return (B_FALSE);
+}
/*
* Check for a valid statefile pathname, inode and mount status.
@@ -938,6 +1063,7 @@ sfpath(void)
static int statefile;
char *err_fmt = NULL;
char *sfile, *sp, ch;
+ char diskname[256];
struct stat stbuf;
int dir = 0;
dev_t dev;
@@ -991,12 +1117,20 @@ sfpath(void)
new_cc.cf_type = CFT_UFS;
dev = stbuf.st_dev;
} else if (S_ISBLK(stbuf.st_mode)) {
- if (minor(stbuf.st_rdev) != 2) {
- new_cc.cf_type = CFT_SPEC;
+ if (is_good_slice(sfile, &err_fmt)) {
+ switch (ztop(sfile, diskname)) {
+ case 1:
+ new_cc.cf_type = CFT_ZVOL;
+ break;
+ case 0:
+ new_cc.cf_type = CFT_SPEC;
+ break;
+ case -1:
+ default:
+ return (NOUP);
+ }
dev = stbuf.st_rdev;
- } else
- err_fmt = "statefile device cannot be slice 2 (%s)\n"
- "would clobber the disk label and boot-block\n";
+ }
} else
err_fmt = "bad file type for \"%s\"\n"
"statefile must be a regular file or block device\n";
@@ -1004,9 +1138,14 @@ sfpath(void)
mesg(MERR, err_fmt, sfile);
return (NOUP);
}
-
- if (check_mount(sfile, dev, (new_cc.cf_type == CFT_UFS)) || utop())
+ if (check_mount(sfile, dev, (new_cc.cf_type == CFT_UFS)))
return (NOUP);
+ if (new_cc.cf_type == CFT_ZVOL) {
+ if (utop(diskname, new_cc.cf_dev_prom))
+ return (NOUP);
+ } else if (utop(new_cc.cf_devfs, new_cc.cf_dev_prom)) {
+ return (NOUP);
+ }
new_cc.cf_magic = CPR_CONFIG_MAGIC;
statefile = 1;
return (OKUP);
diff --git a/usr/src/cmd/power/svc-power b/usr/src/cmd/power/svc-power
index 5fabb0b67f..bfef70d7e9 100644
--- a/usr/src/cmd/power/svc-power
+++ b/usr/src/cmd/power/svc-power
@@ -66,6 +66,19 @@ init_statefile_entry() {
return
)
+ if [ $max_avail -eq 0 ]; then
+ if [ X`df -n / | awk '{print $3}'` != "Xzfs" ] ; then
+ return
+ fi
+ rootpool=`zfs mount | grep ' \/$' | awk '{print $1 }' |\
+ sed 's/\/.*$//'`
+ if [ X$rootpool = "X" ] || \
+ [ ! -L /dev/zvol/dsk/$rootpool/dump ]; then
+ return
+ fi
+ echo "statefile /dev/zvol/dsk/$rootpool/dump" \
+ >> /etc/power.conf
+ fi
}
case "$1" in
diff --git a/usr/src/cmd/svc/milestone/fs-minimal b/usr/src/cmd/svc/milestone/fs-minimal
index 6a7141fa1a..ff7cea8a20 100644
--- a/usr/src/cmd/svc/milestone/fs-minimal
+++ b/usr/src/cmd/svc/milestone/fs-minimal
@@ -58,7 +58,7 @@ for fs in /var /var/adm /tmp; do
mountpt=`zfs get -H -o value mountpoint $be$fs 2>/dev/null`
if [ $? = 0 ] ; then
if [ "x$mountpt" = "x$fs" ] ; then
- /sbin/zfs mount $be$fs
+ /sbin/zfs mount -O $be$fs
fi
fi
fi
diff --git a/usr/src/cmd/svc/milestone/fs-usr b/usr/src/cmd/svc/milestone/fs-usr
index f4a75e08f9..72f906e82e 100644
--- a/usr/src/cmd/svc/milestone/fs-usr
+++ b/usr/src/cmd/svc/milestone/fs-usr
@@ -33,18 +33,49 @@
. /lib/svc/share/fs_include.sh
#
-# Add physical swap.
+# Once root is read/write we can enable the dedicated dumpdevice if it exists
+# locally. This is an optimization as svc-dumpadm will attempt do this later.
#
-/sbin/swapadd -1
+dump_setup()
+{
+ [ -r /etc/dumpadm.conf ] && . /etc/dumpadm.conf
+
+ readswapdev $DUMPADM_DEVICE < $vfstab
+
+ #
+ # If we have a dedicated dump device, then go ahead and configure it.
+ #
+ if [ "x$special" != "x$DUMPADM_DEVICE" ]; then
+ if [ -x /usr/sbin/zfs ]; then
+ dataset=`echo $DUMPADM_DEVICE | cut -d'/' -f5-`
+ [ -n "$dataset" ] && \
+ /usr/sbin/zfs list -t volume $dataset > \
+ /dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ /usr/sbin/zfs volinit
+ fi
+ fi
+
+ if [ -x /usr/sbin/dumpadm -a -b $DUMPADM_DEVICE ]; then
+ /usr/sbin/dumpadm -u || exit $SMF_EXIT_ERR_CONFIG
+ fi
+ fi
+}
rootiszfs=0
# get the fstype of root
readmnttab / </etc/mnttab
if [ "$fstype" = zfs ] ; then
rootiszfs=1
+ dump_setup
fi
#
+# Add physical swap.
+#
+/sbin/swapadd -1
+
+#
# Check and remount the / (root) file system.
# For NFS mounts, force the llock option on.
#
diff --git a/usr/src/cmd/svc/shell/fs_include.sh b/usr/src/cmd/svc/shell/fs_include.sh
index 7ab7dfdd3e..99810383cc 100644
--- a/usr/src/cmd/svc/shell/fs_include.sh
+++ b/usr/src/cmd/svc/shell/fs_include.sh
@@ -72,6 +72,19 @@ readvfstab() {
done
}
+readswapdev() {
+ while read special fsckdev mountp fstype fsckpass automnt mntopts; do
+ # Ignore comments, empty lines, and no-action lines
+ case "$special" in
+ '#'* | '' | '-') continue;;
+ esac
+
+ [ "$fstype" != swap ] && continue
+
+ [ "x$special" = "x$1" ] && break
+ done
+}
+
#
# readmnttab mount_point
# -> (special, mountp, fstype, mntopts, mnttime)
diff --git a/usr/src/cmd/swap/swap.c b/usr/src/cmd/swap/swap.c
index a38897f70c..91cecd5cb4 100644
--- a/usr/src/cmd/swap/swap.c
+++ b/usr/src/cmd/swap/swap.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -63,6 +63,7 @@
#include <locale.h>
#include <libintl.h>
#include <libdiskmgt.h>
+#include <sys/fs/zfs.h>
#define LFLAG 0x01 /* swap -l (list swap devices) */
#define DFLAG 0x02 /* swap -d (delete swap device) */
@@ -645,6 +646,19 @@ add(char *path, off_t offset, off_t cnt, int flags)
(void) close(fd);
+ /*
+ * zvols cannot act as both a swap device and dump device.
+ */
+ if (strncmp(dumpdev, ZVOL_FULL_DEV_DIR,
+ strlen(ZVOL_FULL_DEV_DIR)) == 0) {
+ if (strcmp(dumpdev, path) == 0) {
+ (void) fprintf(stderr, gettext("%s: zvol "
+ "cannot be used as a swap device and a "
+ "dump device\n"), path);
+ return (2);
+ }
+ }
+
} else if (!(flags & P1FLAG))
dumpadm_err(gettext("Warning: failed to open /dev/dump"));
diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c
index 7108c36883..139aa5dd0d 100644
--- a/usr/src/cmd/zdb/zdb.c
+++ b/usr/src/cmd/zdb/zdb.c
@@ -95,7 +95,7 @@ usage(void)
"dataset [object...]\n"
" %s -C [pool]\n"
" %s -l dev\n"
- " %s -R vdev:offset:size:flags\n"
+ " %s -R pool:vdev:offset:size:flags\n"
" %s [-p path_to_vdev_dir]\n"
" %s -e pool | GUID | devid ...\n",
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
@@ -1117,7 +1117,6 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
static char *objset_types[DMU_OST_NUMTYPES] = {
"NONE", "META", "ZPL", "ZVOL", "OTHER", "ANY" };
-/*ARGSUSED*/
static void
dump_dir(objset_t *os)
{