summaryrefslogtreecommitdiff
path: root/usr/src/lib/libadm/common
diff options
context:
space:
mode:
authorPrasad Singamsetty <Prasad.Singamsetty@Sun.COM>2008-09-11 18:00:50 -0700
committerPrasad Singamsetty <Prasad.Singamsetty@Sun.COM>2008-09-11 18:00:50 -0700
commit342440ec94087b8c751c580ab9ed6c693d31d418 (patch)
tree87195f6bee2bb52c9f592f1ce57636b3de75b7d7 /usr/src/lib/libadm/common
parent7ddfa2acf3cfb8a6397a0fb7b4dcd2ce701cc293 (diff)
downloadillumos-joyent-342440ec94087b8c751c580ab9ed6c693d31d418.tar.gz
PSARC/2008/336 Extended VTOC
6708609 Support booting on disks > 1TB (phase 1) 6672960 cmlb: default minor nodes for disks > 1TB is not EFI/GPT style 6727240 When a fat32 partition created in the part of the disk after 1TB, block I/O and umount fail
Diffstat (limited to 'usr/src/lib/libadm/common')
-rw-r--r--usr/src/lib/libadm/common/mapfile-vers10
-rw-r--r--usr/src/lib/libadm/common/rdwr_vtoc.c211
2 files changed, 211 insertions, 10 deletions
diff --git a/usr/src/lib/libadm/common/mapfile-vers b/usr/src/lib/libadm/common/mapfile-vers
index 3ae4aa1166..b42d7d67e8 100644
--- a/usr/src/lib/libadm/common/mapfile-vers
+++ b/usr/src/lib/libadm/common/mapfile-vers
@@ -19,11 +19,15 @@
# 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"
-#
+
+SUNW_1.2 {
+ global:
+ read_extvtoc;
+ write_extvtoc;
+} SUNW_1.1;
# Due to mistakes made early in the history of this library, there are
# no SUNW_1.1 symbols, but the version is now kept as a placeholder.
diff --git a/usr/src/lib/libadm/common/rdwr_vtoc.c b/usr/src/lib/libadm/common/rdwr_vtoc.c
index b662bded7c..0e3d36ca01 100644
--- a/usr/src/lib/libadm/common/rdwr_vtoc.c
+++ b/usr/src/lib/libadm/common/rdwr_vtoc.c
@@ -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.
@@ -19,13 +18,12 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 1991-1997,2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*LINTLIBRARY*/
@@ -37,6 +35,44 @@
#include <sys/param.h>
#include <sys/dkio.h>
#include <sys/vtoc.h>
+#include <strings.h>
+#include <limits.h>
+
+/*
+ * To copy each field of vtoc individually for copying extvtoc
+ * to 32 bit vtoc and vs.
+ * Currently bootinfo and timestamp are not really supported.
+ */
+
+#define libadm_vtoc_copy(vs, vd) \
+ { \
+ int i; \
+ vd->v_bootinfo[0] = (unsigned)vs->v_bootinfo[0]; \
+ vd->v_bootinfo[1] = (unsigned)vs->v_bootinfo[1]; \
+ vd->v_bootinfo[2] = (unsigned)vs->v_bootinfo[2]; \
+ vd->v_sanity = (unsigned)vs->v_sanity; \
+ vd->v_version = (unsigned)vs->v_version; \
+ bcopy(vs->v_volume, vd->v_volume, LEN_DKL_VVOL); \
+ vd->v_sectorsz = vs->v_sectorsz; \
+ vd->v_nparts = vs->v_nparts; \
+ vd->v_version = (unsigned)vs->v_version; \
+ for (i = 0; i < 10; i++) \
+ vd->v_reserved[i] = (unsigned)vs->v_reserved[i];\
+ for (i = 0; i < V_NUMPAR; i++) { \
+ vd->v_part[i].p_tag = vs->v_part[i].p_tag; \
+ vd->v_part[i].p_flag = vs->v_part[i].p_flag; \
+ vd->v_part[i].p_start = (unsigned)vs->v_part[i].p_start;\
+ vd->v_part[i].p_size = (unsigned)vs->v_part[i].p_size; \
+ } \
+ for (i = 0; i < V_NUMPAR; i++) \
+ if ((sizeof (vd->timestamp[i]) != sizeof (vs->timestamp[i])) &&\
+ (vs->timestamp[i] > INT32_MAX)) \
+ vd->timestamp[i] = INT32_MAX; \
+ else \
+ vd->timestamp[i] = (unsigned)vs->timestamp[i]; \
+ bcopy(vs->v_asciilabel, vd->v_asciilabel, LEN_DKL_ASCII); \
+ }
+
/*
* Read VTOC - return partition number.
@@ -55,9 +91,11 @@ read_vtoc(int fd, struct vtoc *vtoc)
return (VT_EIO);
case EINVAL:
return (VT_EINVAL);
- /* for disks > 1TB */
case ENOTSUP:
+ /* GPT labeled or disk > 1TB with no extvtoc support */
return (VT_ENOTSUP);
+ case EOVERFLOW:
+ return (VT_EOVERFLOW);
default:
return (VT_ERROR);
}
@@ -151,12 +189,171 @@ write_vtoc(int fd, struct vtoc *vtoc)
return (VT_EIO);
case EINVAL:
return (VT_EINVAL);
+ case ENOTSUP:
+ /* GPT labeled or disk > 1TB with no extvtoc support */
+ return (VT_ENOTSUP);
+ case EOVERFLOW:
+ return (VT_EOVERFLOW);
+ default:
+ return (VT_ERROR);
+ }
+ }
+ return (0);
+}
+
+int
+read_extvtoc(int fd, struct extvtoc *extvtoc)
+{
+ struct dk_cinfo dki_info;
+ struct vtoc oldvtoc;
+ struct vtoc *oldvtocp = &oldvtoc;
+ int ret;
+
+ /*
+ * Read the vtoc.
+ */
+ if (ioctl(fd, DKIOCGEXTVTOC, (caddr_t)extvtoc) == -1) {
+ switch (errno) {
+ case EIO:
+ return (VT_EIO);
+ case EINVAL:
+ return (VT_EINVAL);
/* for disks > 1TB */
case ENOTSUP:
return (VT_ENOTSUP);
+ case EOVERFLOW:
+ return (VT_EOVERFLOW);
+ case ENOTTY:
+
+ if ((ret = read_vtoc(fd, oldvtocp)) < 0)
+ return (ret);
+
+#ifdef _LP64
+ /*
+ * 64-bit vtoc and extvtoc have the same field sizes
+ * and offsets.
+ */
+ bcopy(oldvtocp, extvtoc, sizeof (struct extvtoc));
+#else
+ bzero(extvtoc, sizeof (struct extvtoc));
+ libadm_vtoc_copy(oldvtocp, extvtoc);
+#endif
+ return (ret);
+
+
default:
return (VT_ERROR);
}
}
+
+ /*
+ * Sanity-check the vtoc.
+ */
+ if (extvtoc->v_sanity != VTOC_SANE) {
+ return (VT_EINVAL);
+ }
+
+ switch (extvtoc->v_version) {
+ case 0:
+ /*
+ * For pre-version 1 vtoc keep same functionality
+ * as read_vtoc.
+ */
+
+ extvtoc->v_version = V_VERSION;
+ if (extvtoc->v_nparts == 0)
+ extvtoc->v_nparts = V_NUMPAR;
+ if (extvtoc->v_sectorsz == 0)
+ extvtoc->v_sectorsz = DEV_BSIZE;
+
+ break;
+
+ case V_VERSION:
+ break;
+
+ default:
+ return (VT_EINVAL);
+ }
+
+ /*
+ * Return partition number for this file descriptor.
+ */
+ if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) {
+ switch (errno) {
+ case EIO:
+ return (VT_EIO);
+ case EINVAL:
+ return (VT_EINVAL);
+ default:
+ return (VT_ERROR);
+ }
+ }
+ if (dki_info.dki_partition > V_NUMPAR) {
+ return (VT_EINVAL);
+ }
+ return ((int)dki_info.dki_partition);
+}
+
+/*
+ * Write ext VTOC.
+ */
+int
+write_extvtoc(int fd, struct extvtoc *extvtoc)
+{
+ int i;
+ struct vtoc oldvtoc;
+ struct vtoc *oldvtocp = &oldvtoc;
+ /*
+ * Sanity-check the vtoc
+ */
+ if (extvtoc->v_sanity != VTOC_SANE || extvtoc->v_nparts > V_NUMPAR) {
+ return (-1);
+ }
+
+ /*
+ * since many drivers won't allow opening a device make sure
+ * all partitions aren't being set to zero. If all are zero then
+ * we have no way to set them to something else
+ */
+
+ for (i = 0; i < (int)extvtoc->v_nparts; i++)
+ if (extvtoc->v_part[i].p_size > 0)
+ break;
+ if (i == (int)extvtoc->v_nparts)
+ return (-1);
+
+ /*
+ * Write the extvtoc
+ */
+ if (ioctl(fd, DKIOCSEXTVTOC, (caddr_t)extvtoc) == -1) {
+ switch (errno) {
+ case EIO:
+ return (VT_EIO);
+ case EINVAL:
+ return (VT_EINVAL);
+ /* for disks > 1TB */
+ case ENOTSUP:
+ return (VT_ENOTSUP);
+ case EOVERFLOW:
+ return (VT_EOVERFLOW);
+ case ENOTTY:
+#ifdef _LP64
+ /*
+ * 64-bit vtoc and extvtoc have the same field sizes
+ * and offsets.
+ */
+ bcopy(extvtoc, oldvtocp, sizeof (struct vtoc));
+#else
+ bzero(oldvtocp, sizeof (struct vtoc));
+ libadm_vtoc_copy(extvtoc, oldvtocp);
+
+#endif
+ return (write_vtoc(fd, &oldvtoc));
+
+ default:
+ return (VT_ERROR);
+ }
+ }
+
return (0);
}