diff options
| author | Prasad Singamsetty <Prasad.Singamsetty@Sun.COM> | 2008-09-11 18:00:50 -0700 |
|---|---|---|
| committer | Prasad Singamsetty <Prasad.Singamsetty@Sun.COM> | 2008-09-11 18:00:50 -0700 |
| commit | 342440ec94087b8c751c580ab9ed6c693d31d418 (patch) | |
| tree | 87195f6bee2bb52c9f592f1ce57636b3de75b7d7 /usr/src/lib/libadm/common | |
| parent | 7ddfa2acf3cfb8a6397a0fb7b4dcd2ce701cc293 (diff) | |
| download | illumos-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-vers | 10 | ||||
| -rw-r--r-- | usr/src/lib/libadm/common/rdwr_vtoc.c | 211 |
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); } |
