changeset 10682:4c75f60a2704 onnv_125

6868033 Solaris installed via legacy installer on a Linux Swap partition does not boot 6871541 libfdisk should not be using off_t type 6879157 bootadm update-menu support for x86 extended/logical partitions 6880174 Calling 'fdisk -W' and prtvtoc(1M) caused remapping VTOC to Linux swap partition 6885084 fdisk allows more than one extended partition
author Sheshadri Vasudevan <Sheshadri.Vasudevan@Sun.COM>
date Mon, 28 Sep 2009 23:04:06 +0530
parents 39bfab5e595b
children aa7fcc69a786
files usr/src/cmd/boot/bootadm/Makefile usr/src/cmd/boot/bootadm/bootadm.c usr/src/cmd/fdisk/fdisk.c usr/src/cmd/format/menu_fdisk.c usr/src/lib/libfdisk/i386/Makefile usr/src/lib/libfdisk/i386/libfdisk.c usr/src/lib/libfdisk/i386/libfdisk.h usr/src/uts/common/io/cmlb.c
diffstat 8 files changed, 203 insertions(+), 207 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/boot/bootadm/Makefile	Mon Sep 28 21:34:36 2009 -0700
+++ b/usr/src/cmd/boot/bootadm/Makefile	Mon Sep 28 23:04:06 2009 +0530
@@ -35,7 +35,8 @@
 
 .KEEP_STATE:
 
-LDLIBS +=	-lnvpair -lgen -ladm -lefi -lscf -lz
+LDLIBS_i386= -lfdisk
+LDLIBS +=	-lnvpair -lgen -ladm -lefi -lscf -lz $(LDLIBS_$(MACH))
 
 # Writing into string literals is incorrect.  We need to match gcc's
 # behavior, which causes us to take SIGSEGV on such a write.
@@ -45,6 +46,7 @@
 
 LINTFLAGS += -erroff=E_INCONS_ARG_DECL2
 LINTFLAGS += -erroff=E_INCONS_VAL_TYPE_DECL2
+LINTFLAGS += -erroff=E_NAME_DEF_NOT_USED2
 
 all: $(PROG)
 
--- a/usr/src/cmd/boot/bootadm/bootadm.c	Mon Sep 28 21:34:36 2009 -0700
+++ b/usr/src/cmd/boot/bootadm/bootadm.c	Mon Sep 28 23:04:06 2009 +0530
@@ -63,6 +63,9 @@
 #include <zlib.h>
 #include <sys/lockfs.h>
 #include <sys/filio.h>
+#ifdef i386
+#include <libfdisk.h>
+#endif
 
 #if !defined(_OPB)
 #include <sys/ucode.h>
@@ -4869,6 +4872,11 @@
 	struct mboot *mboot;
 	char boot_sect[SECTOR_SIZE];
 	char *wholedisk, *slice;
+#ifdef i386
+	ext_part_t *epp;
+	uint32_t secnum, numsec;
+	int rval, pno;
+#endif
 
 	/* form whole disk (p0) */
 	slice = device + strlen(device) - 2;
@@ -4882,12 +4890,34 @@
 
 	/* read boot sector */
 	fd = open(wholedisk, O_RDONLY);
-	free(wholedisk);
 	if (fd == -1 || read(fd, boot_sect, SECTOR_SIZE) != SECTOR_SIZE) {
 		return (partno);
 	}
 	(void) close(fd);
 
+#ifdef i386
+	/* Read/Initialize extended partition information */
+	if ((rval = libfdisk_init(&epp, wholedisk, NULL, FDISK_READ_DISK))
+	    != FDISK_SUCCESS) {
+		switch (rval) {
+			/*
+			 * FDISK_EBADLOGDRIVE and FDISK_ENOLOGDRIVE can
+			 * be considered as soft errors and hence
+			 * we do not return
+			 */
+			case FDISK_EBADLOGDRIVE:
+				break;
+			case FDISK_ENOLOGDRIVE:
+				break;
+			default:
+				free(wholedisk);
+				return (partno);
+				break;
+		}
+	}
+#endif
+	free(wholedisk);
+
 	/* parse fdisk table */
 	mboot = (struct mboot *)((void *)boot_sect);
 	for (i = 0; i < FD_NUMPART; i++) {
@@ -4898,14 +4928,32 @@
 				partno = i;
 				break;
 			}
+#ifdef i386
+		} else if (fdisk_is_dos_extended(part->systid)) {
+			rval = fdisk_get_solaris_part(epp, &pno, &secnum,
+			    &numsec);
+			if (rval == FDISK_SUCCESS) {
+				partno = pno - 1;
+				break;
+			}
+#endif
 		} else {	/* look for solaris partition, old and new */
+#ifdef i386
+			if ((part->systid == SUNIXOS &&
+			    (fdisk_is_linux_swap(epp, part->relsect,
+			    NULL) != 0)) || part->systid == SUNIXOS2) {
+#else
 			if (part->systid == SUNIXOS ||
 			    part->systid == SUNIXOS2) {
+#endif
 				partno = i;
 				break;
 			}
 		}
 	}
+#ifdef i386
+	libfdisk_fini(&epp);
+#endif
 	return (partno);
 }
 
@@ -7226,7 +7274,7 @@
 		if (strncmp(lp->line, "/dev/dsk/", strlen("/dev/dsk/")) != 0 &&
 		    strncmp(lp->line, "/dev/rdsk/",
 		    strlen("/dev/rdsk/")) != 0)  {
-			(void) snprintf(dsk, sizeof (dsk), "/dev/dsk/%s",
+			(void) snprintf(dsk, sizeof (dsk), "/dev/rdsk/%s",
 			    lp->line);
 		} else {
 			(void) strlcpy(dsk, lp->line, sizeof (dsk));
--- a/usr/src/cmd/fdisk/fdisk.c	Mon Sep 28 21:34:36 2009 -0700
+++ b/usr/src/cmd/fdisk/fdisk.c	Mon Sep 28 23:04:06 2009 +0530
@@ -253,6 +253,7 @@
 static char QNX2str[] = "QNX part 2";
 static char QNX3str[] = "QNX part 3";
 static char LINNATstr[] = "Linux native";
+static char LINSWAPstr[] = "Linux swap";
 static char NTFSVOL1str[] = "NT volset 1";
 static char NTFSVOL2str[] = "NT volset 2";
 static char BSDstr[] = "BSD OS";
@@ -695,7 +696,6 @@
 static int ext_read_valid_partition_start(uint32_t *begsec);
 static void ext_read_valid_partition_size(uint32_t begsec, uint32_t *endsec);
 static void ext_part_menu();
-static int is_linux_swap(uint32_t part_start, off_t *lsm_offset);
 static void add_logical_drive();
 static void delete_logical_drive();
 static void ext_print_help_menu();
@@ -1431,57 +1431,6 @@
 		    Table[new_pt].systid != SUNIXOS2)
 			continue;
 
-#ifdef i386
-
-		/*
-		 * Check if a solaris old partition is there in the new table.
-		 * If so, this could potentially have been a linux swap.
-		 * Check to see if the linux swap magic is there, and destroy
-		 * the magic if there is one.
-		 */
-		if (Table[new_pt].systid == SUNIXOS) {
-			off_t lsmo;
-			char *lsm_buf;
-
-			if ((lsm_buf = calloc(1, sectsiz)) == NULL) {
-				fprintf(stderr, "Could not allocate memory\n");
-				exit(1);
-			}
-
-			if (is_linux_swap(Table[new_pt].relsect, &lsmo) == 0) {
-				if (lseek(Dev, lsmo, SEEK_SET) < 0) {
-					fprintf(stderr, "Error seeking on "
-					    "%s\n", Dfltdev);
-					exit(1);
-				}
-
-				if (read(Dev, lsm_buf, sectsiz) < sectsiz) {
-					fprintf(stderr, "Error reading on "
-					    "%s\n", Dfltdev);
-					exit(1);
-				}
-
-				bzero(lsm_buf + sectsiz -
-				    LINUX_SWAP_MAGIC_LENGTH,
-				    LINUX_SWAP_MAGIC_LENGTH);
-
-				if (lseek(Dev, lsmo, SEEK_SET) < 0) {
-					fprintf(stderr, "Error seeking on "
-					    "%s\n", Dfltdev);
-					exit(1);
-				}
-
-				if (write(Dev, lsm_buf, sectsiz) < sectsiz) {
-					fprintf(stderr, "Error writing on "
-					    "%s\n", Dfltdev);
-					exit(1);
-				}
-			}
-			free(lsm_buf);
-		}
-
-#endif
-
 		/* Does the old table have an exact entry for the new entry? */
 		for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
 
@@ -2262,6 +2211,11 @@
 				fdisk_add_logical_drive(epp, begsec, endsec,
 				    id);
 				return;
+			} else {
+				(void) fprintf(stderr,
+				    "fdisk: Invalid entry could not be "
+				    "inserted:\n        \"%s\"\n", file);
+				exit(1);
 			}
 		}
 #endif
@@ -2971,6 +2925,17 @@
 			break;
 		case 'e':	/* Extended partition, need extended int13 */
 		case 'E':
+#ifdef i386
+			if (ext_part_present) {
+				printf(Q_LINE);
+				printf(E_LINE);
+				fprintf(stderr,
+				    "Extended partition already exists\n");
+				fprintf(stderr, "Press enter to continue\n");
+				ext_read_input(s);
+				continue;
+			}
+#endif
 			tsystid = FDISK_EXTLBA;
 			break;
 		case 'f':
@@ -3718,6 +3683,11 @@
 			break;
 		case SUNIXOS:
 			type = SUstr;
+#ifdef i386
+			if (fdisk_is_linux_swap(epp, Table[i].relsect,
+			    NULL) == 0)
+				type = LINSWAPstr;
+#endif
 			break;
 		case SUNIXOS2:
 			type = SU2str;
@@ -5469,6 +5439,7 @@
 	int sysid;
 	unsigned int startcyl, endcyl, length, percent, remainder;
 	logical_drive_t *temp;
+	uint32_t part_start;
 	struct ipart *fpart;
 	char namebuff[255];
 	int numcyl = fdisk_get_disk_geom(epp, PHYSGEOM, NCYL);
@@ -5500,7 +5471,22 @@
 		/* Print the logical drive details */
 		fpart = &temp->parts[0];
 		sysid = fpart->systid;
-		id_to_name(sysid, namebuff);
+		/*
+		 * Check if partition id 0x82 is Solaris
+		 * or a Linux swap. Print the string
+		 * accordingly.
+		 */
+		if (sysid == SUNIXOS) {
+			part_start = temp->abs_secnum +
+			    temp->logdrive_offset;
+			if (fdisk_is_linux_swap(epp, part_start,
+			    NULL) == 0)
+				strcpy(namebuff, LINSWAPstr);
+			else
+				strcpy(namebuff, SUstr);
+		} else {
+			id_to_name(sysid, namebuff);
+		}
 		startcyl = temp->begcyl;
 		endcyl = temp->endcyl;
 		if (startcyl == endcyl) {
@@ -5604,59 +5590,3 @@
 	}
 }
 #endif
-
-#ifdef i386
-
-static int
-is_linux_swap(uint32_t part_start, off_t *lsm_offset)
-{
-	int		i;
-	int		rval = -1;
-	off_t		seek_offset;
-	uint32_t	linux_pg_size;
-	char		*buf, *linux_swap_magic;
-	/*
-	 * Known linux kernel page sizes
-	 * The linux swap magic is found as the last 10 bytes of a disk chunk
-	 * at the beginning of the linux swap partition whose size is that of
-	 * kernel page size.
-	 */
-	uint32_t	linux_pg_size_arr[] = {4096, };
-
-	if ((buf = calloc(1, sectsiz)) == NULL) {
-		return (ENOMEM);
-	}
-
-	linux_swap_magic = buf + sectsiz - LINUX_SWAP_MAGIC_LENGTH;
-
-	for (i = 0; i < sizeof (linux_pg_size_arr)/sizeof (uint32_t); i++) {
-		linux_pg_size = linux_pg_size_arr[i];
-		seek_offset = linux_pg_size/sectsiz - 1;
-		seek_offset += part_start;
-		seek_offset *= sectsiz;
-
-		if ((rval = lseek(Dev, seek_offset, SEEK_SET)) < 0) {
-			break;
-		}
-
-		if ((rval = read(Dev, buf, sectsiz)) < sectsiz) {
-			rval = EIO;
-			break;
-		}
-
-		if ((strncmp(linux_swap_magic, "SWAP-SPACE",
-		    LINUX_SWAP_MAGIC_LENGTH) == 0) ||
-		    (strncmp(linux_swap_magic, "SWAPSPACE2",
-		    LINUX_SWAP_MAGIC_LENGTH) == 0)) {
-			/* Found a linux swap */
-			rval = 0;
-			*lsm_offset = seek_offset;
-			break;
-		}
-	}
-
-	free(buf);
-	return (rval);
-}
-
-#endif
--- a/usr/src/cmd/format/menu_fdisk.c	Mon Sep 28 21:34:36 2009 -0700
+++ b/usr/src/cmd/format/menu_fdisk.c	Mon Sep 28 23:04:06 2009 +0530
@@ -478,6 +478,9 @@
 	(void) memcpy(&boot_sec, mbr, sizeof (struct mboot));
 	free(mbr);
 
+#ifdef i386
+	(void) extpart_init(&epp);
+#endif
 	for (i = 0; i < FD_NUMPART; i++) {
 		int	ipc;
 
@@ -491,7 +494,6 @@
 		if (fdisk_is_dos_extended(ip.systid) && (ext_part_found == 0)) {
 			/* We support only one extended partition per disk */
 			ext_part_found = 1;
-			(void) extpart_init(&epp);
 			rval = fdisk_get_solaris_part(epp, &pno, &relsec,
 			    &numsec);
 			if (rval == FDISK_SUCCESS) {
@@ -517,7 +519,6 @@
 				    sizeof (struct ipart));
 				bcopy(&ip, ipart, sizeof (struct ipart));
 			}
-			libfdisk_fini(&epp);
 			continue;
 		}
 #endif
@@ -525,9 +526,16 @@
 		/*
 		 * we are interested in Solaris and EFI partition types
 		 */
+#ifdef i386
+		if ((ip.systid == SUNIXOS &&
+		    (fdisk_is_linux_swap(epp, lel(ip.relsect), NULL) != 0)) ||
+		    ip.systid == SUNIXOS2 ||
+		    ip.systid == EFI_PMBR) {
+#else
 		if (ip.systid == SUNIXOS ||
 		    ip.systid == SUNIXOS2 ||
 		    ip.systid == EFI_PMBR) {
+#endif
 			/*
 			 * if the disk has an EFI label, nhead and nsect may
 			 * be zero.  This test protects us from FPE's, and
@@ -551,6 +559,10 @@
 		}
 	}
 
+#ifdef i386
+	libfdisk_fini(&epp);
+#endif
+
 	if (!found) {
 		err_print("Solaris fdisk partition not found\n");
 		return (-1);
@@ -686,6 +698,9 @@
 
 	(void) memcpy(&mboot, mbr, sizeof (struct mboot));
 
+#ifdef i386
+	(void) extpart_init(&epp);
+#endif
 	for (i = 0; i < FD_NUMPART; i++) {
 		int	ipc;
 
@@ -699,7 +714,6 @@
 		if (fdisk_is_dos_extended(ip.systid) && (ext_part_found == 0)) {
 			/* We support only one extended partition per disk */
 			ext_part_found = 1;
-			(void) extpart_init(&epp);
 			rval = fdisk_get_solaris_part(epp, &pno, &relsec,
 			    &numsec);
 			if (rval == FDISK_SUCCESS) {
@@ -720,14 +734,21 @@
 				ip.numsect = numsec;
 				bcopy(&ip, ipart, sizeof (struct ipart));
 			}
-			libfdisk_fini(&epp);
 			continue;
 		}
 #endif
 
+
+#ifdef i386
+		if ((ip.systid == SUNIXOS &&
+		    (fdisk_is_linux_swap(epp, lel(ip.relsect), NULL) != 0)) ||
+		    ip.systid == SUNIXOS2 ||
+		    ip.systid == EFI_PMBR) {
+#else
 		if (ip.systid == SUNIXOS ||
 		    ip.systid == SUNIXOS2 ||
 		    ip.systid == EFI_PMBR) {
+#endif
 			solaris_offset = lel(ip.relsect);
 			bcopy(&ip, ipart, sizeof (struct ipart));
 
@@ -751,6 +772,9 @@
 			break;
 		}
 	}
+#ifdef i386
+	libfdisk_fini(&epp);
+#endif
 
 	(void) close(fd);
 	free(mbr);
@@ -799,6 +823,9 @@
 
 	(void) memcpy(&mboot, mbr, sizeof (struct mboot));
 
+#ifdef i386
+	(void) extpart_init(&epp);
+#endif
 	for (i = 0; i < FD_NUMPART; i++) {
 		int	ipc;
 
@@ -812,7 +839,6 @@
 		if (fdisk_is_dos_extended(ip.systid) && (ext_part_found == 0)) {
 			/* We support only one extended partition per disk */
 			ext_part_found = 1;
-			(void) extpart_init(&epp);
 			rval = fdisk_get_solaris_part(epp, &pno, &relsec,
 			    &numsec);
 			if (rval == FDISK_SUCCESS) {
@@ -830,7 +856,6 @@
 				}
 				solaris_offset = relsec;
 			}
-			libfdisk_fini(&epp);
 			continue;
 		}
 #endif
@@ -840,9 +865,18 @@
 		 * the label may be zero.  This protects us from FPE's, and
 		 * format still seems to work happily
 		 */
+
+
+#ifdef i386
+		if ((ip.systid == SUNIXOS &&
+		    (fdisk_is_linux_swap(epp, lel(ip.relsect), NULL) != 0)) ||
+		    ip.systid == SUNIXOS2 ||
+		    ip.systid == EFI_PMBR) {
+#else
 		if (ip.systid == SUNIXOS ||
 		    ip.systid == SUNIXOS2 ||
 		    ip.systid == EFI_PMBR) {
+#endif
 			if ((label->dkl_nhead != 0) &&
 			    (label->dkl_nsect != 0)) {
 				label->dkl_pcyl = lel(ip.numsect) /
@@ -866,6 +900,9 @@
 		}
 	}
 
+#ifdef i386
+	libfdisk_fini(&epp);
+#endif
 	(void) close(fd);
 	free(mbr);
 	return (0);
--- a/usr/src/lib/libfdisk/i386/Makefile	Mon Sep 28 21:34:36 2009 -0700
+++ b/usr/src/lib/libfdisk/i386/Makefile	Mon Sep 28 23:04:06 2009 +0530
@@ -68,6 +68,8 @@
 i386_CFLAGS += -D_LARGEFILE64_SOURCE
 i386_CFLAGS += -D_FILE_OFFSET_BITS=64
 
+LINTFLAGS +=	-erroff=E_BAD_PTR_CAST_ALIGN
+
 .KEEP_STATE:
 
 LIBS=	$(DYNLIB) $(LINTLIB)
--- a/usr/src/lib/libfdisk/i386/libfdisk.c	Mon Sep 28 21:34:36 2009 -0700
+++ b/usr/src/lib/libfdisk/i386/libfdisk.c	Mon Sep 28 23:04:06 2009 +0530
@@ -235,7 +235,7 @@
 }
 
 int
-fdisk_is_linux_swap(ext_part_t *epp, uint32_t part_start, off_t *lsm_offset)
+fdisk_is_linux_swap(ext_part_t *epp, uint32_t part_start, uint64_t *lsm_offset)
 {
 	int		i;
 	int		rval = -1;
@@ -243,6 +243,8 @@
 	uint32_t	linux_pg_size;
 	char		*buf, *linux_swap_magic;
 	int		sec_sz = fdisk_get_disk_geom(epp, PHYSGEOM, SSIZE);
+	off_t		label_offset;
+
 	/*
 	 * Known linux kernel page sizes
 	 * The linux swap magic is found as the last 10 bytes of a disk chunk
@@ -255,6 +257,28 @@
 		return (ENOMEM);
 	}
 
+	/*
+	 * Check if there is a sane Solaris VTOC
+	 * If there is a valid vtoc, no need to lookup
+	 * for the linux swap signature.
+	 */
+	label_offset = (part_start + DK_LABEL_LOC) * sec_sz;
+	if ((rval = lseek(epp->dev_fd, label_offset, SEEK_SET)) < 0)
+		goto done;
+
+	if ((rval = read(epp->dev_fd, buf, sec_sz)) < sec_sz) {
+		rval = EIO;
+		goto done;
+	}
+
+
+	if ((((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) &&
+	    (((struct dk_label *)buf)->dkl_vtoc.v_sanity == VTOC_SANE)) {
+		rval = -1;
+		goto done;
+	}
+
+	/* No valid vtoc, so check for linux swap signature */
 	linux_swap_magic = buf + sec_sz - LINUX_SWAP_MAGIC_LENGTH;
 
 	for (i = 0; i < sizeof (linux_pg_size_arr)/sizeof (uint32_t); i++) {
@@ -278,11 +302,13 @@
 		    LINUX_SWAP_MAGIC_LENGTH) == 0)) {
 			/* Found a linux swap */
 			rval = 0;
-			*lsm_offset = seek_offset;
+			if (lsm_offset != NULL)
+				*lsm_offset = (uint64_t)seek_offset;
 			break;
 		}
 	}
 
+done:
 	free(buf);
 	return (rval);
 }
@@ -295,12 +321,13 @@
 	uint32_t part_start;
 	int pno;
 	int rval = -1;
-	off_t lsmo = 0;
 
 	for (pno = 5; temp != NULL; temp = temp->next, pno++) {
 		if (fdisk_is_solaris_part(LE_8(temp->parts[0].systid))) {
 			part_start = temp->abs_secnum + temp->logdrive_offset;
-			if (fdisk_is_linux_swap(epp, part_start, &lsmo) == 0) {
+			if ((temp->parts[0].systid == SUNIXOS) &&
+			    (fdisk_is_linux_swap(epp, part_start,
+			    NULL) == 0)) {
 				continue;
 			}
 			*pnum = pno;
@@ -1112,15 +1139,10 @@
 	int ld_count;
 	uint32_t abs_secnum;
 	int check_mounts = 0;
-	off_t lsmo;
-	char *lsm_buf;
 
 	if ((ebr_buf = (unsigned char *)malloc(sectsize)) == NULL) {
 		return (ENOMEM);
 	}
-	if ((lsm_buf = calloc(1, sectsize)) == NULL) {
-		return (ENOMEM);
-	}
 
 	if (epp->first_ebr_is_null) {
 		/*
@@ -1162,9 +1184,6 @@
 		if (ebr_buf) {
 			free(ebr_buf);
 		}
-		if (lsm_buf) {
-			free(lsm_buf);
-		}
 		return (rval);
 	}
 
@@ -1189,9 +1208,6 @@
 			if (ebr_buf) {
 				free(ebr_buf);
 			}
-			if (lsm_buf) {
-				free(lsm_buf);
-			}
 			return (FDISK_SUCCESS);
 		}
 
@@ -1202,56 +1218,6 @@
 		 */
 		for (temp = epp->ld_head, ld_count = 0; temp != NULL;
 		    temp = temp->next, ld_count++) {
-			/*
-			 * Check if the current partition is a solaris old
-			 * partition. In that case, check if it was previously
-			 * a linux swap. If so, overwrite the linux swap magic.
-			 */
-			if (temp->parts[0].systid == SUNIXOS) {
-				uint32_t secnum = temp->abs_secnum +
-				    temp->logdrive_offset;
-				if (fdisk_is_linux_swap(epp, secnum,
-				    &lsmo) == 0) {
-					if ((rval = lseek(epp->dev_fd, lsmo,
-					    SEEK_SET)) < 0) {
-						if (ld_count) {
-							break;
-						}
-						goto error;
-					}
-
-					if (read(epp->dev_fd, lsm_buf,
-					    sectsize) < sectsize) {
-						rval = EIO;
-						if (ld_count) {
-							break;
-						}
-						goto error;
-					}
-
-					bzero(lsm_buf + sectsize -
-					    LINUX_SWAP_MAGIC_LENGTH,
-					    LINUX_SWAP_MAGIC_LENGTH);
-
-					if ((rval = lseek(epp->dev_fd, lsmo,
-					    SEEK_SET)) < 0) {
-						if (ld_count) {
-							break;
-						}
-						goto error;
-					}
-
-					if ((rval = write(epp->dev_fd, lsm_buf,
-					    sectsize)) < sectsize) {
-						rval = EIO;
-						if (ld_count) {
-							break;
-						}
-						goto error;
-					}
-				}
-			}
-
 			if (ld_count == 0) {
 				abs_secnum = epp->ext_beg_sec;
 			} else {
@@ -1293,9 +1259,6 @@
 	if (ebr_buf) {
 		free(ebr_buf);
 	}
-	if (lsm_buf) {
-		free(lsm_buf);
-	}
 	return (rval);
 }
 
--- a/usr/src/lib/libfdisk/i386/libfdisk.h	Mon Sep 28 21:34:36 2009 -0700
+++ b/usr/src/lib/libfdisk/i386/libfdisk.h	Mon Sep 28 23:04:06 2009 +0530
@@ -268,7 +268,7 @@
 #define	fdisk_is_dos_extended(id) (((id) == EXTDOS) || ((id) == FDISK_EXTLBA))
 
 extern int fdisk_is_linux_swap(ext_part_t *epp, uint32_t part_start,
-    off_t *lsm_offset);
+    uint64_t *lsm_offset);
 extern int libfdisk_init(ext_part_t **epp, char *devstr, struct ipart *parttab,
     int opflag);
 extern int libfdisk_reset(ext_part_t *epp);
--- a/usr/src/uts/common/io/cmlb.c	Mon Sep 28 21:34:36 2009 -0700
+++ b/usr/src/uts/common/io/cmlb.c	Mon Sep 28 23:04:06 2009 +0530
@@ -2251,6 +2251,30 @@
 		return (ENOMEM);
 	}
 
+	/*
+	 * Check if there is a sane Solaris VTOC
+	 * If there is a valid vtoc, no need to lookup
+	 * for the linux swap signature.
+	 */
+	mutex_exit(CMLB_MUTEX(cl));
+	rval = DK_TG_READ(cl, buf, part_start + DK_LABEL_LOC,
+	    sec_sz, tg_cookie);
+	mutex_enter(CMLB_MUTEX(cl));
+	if (rval != 0) {
+		cmlb_dbg(CMLB_ERROR,  cl,
+		    "cmlb_is_linux_swap: disk vtoc read err\n");
+		rval = EIO;
+		goto done;
+	}
+
+	if ((((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) &&
+	    (((struct dk_label *)buf)->dkl_vtoc.v_sanity == VTOC_SANE)) {
+		rval = -1;
+		goto done;
+	}
+
+
+	/* No valid vtoc, so check for linux swap signature */
 	linux_swap_magic = buf + sec_sz - 10;
 
 	for (i = 0; i < sizeof (linux_pg_size_arr)/sizeof (uint32_t); i++) {
@@ -2279,6 +2303,7 @@
 		}
 	}
 
+done:
 	kmem_free(buf, sec_sz);
 	return (rval);
 }
@@ -2331,7 +2356,6 @@
 	struct ipart	*efdp2 = &eparts[1];
 	int		ext_part_exists = 0;
 	int		ld_count = 0;
-	int		is_linux_swap;
 #endif
 
 	ASSERT(cl != NULL);
@@ -2536,17 +2560,11 @@
 				cl->cl_fmap[j].fmap_systid = systid;
 				ld_count++;
 
-				is_linux_swap = 0;
-				if (efdp1->systid == SUNIXOS) {
-					if (cmlb_is_linux_swap(cl, abs_secnum,
-					    tg_cookie) == 0) {
-						is_linux_swap = 1;
-					}
-				}
-
-				if ((efdp1->systid == SUNIXOS) ||
-				    (efdp1->systid == SUNIXOS2)) {
-					if ((uidx == -1) && (!is_linux_swap)) {
+				if ((efdp1->systid == SUNIXOS &&
+				    (cmlb_is_linux_swap(cl, abs_secnum,
+				    tg_cookie) != 0)) ||
+				    efdp1->systid == SUNIXOS2) {
+					if (uidx == -1) {
 						uidx = 0;
 						solaris_offset = abs_secnum;
 						solaris_size = ext_numsect;
@@ -2575,14 +2593,10 @@
 		 */
 		if ((uidx == -1) || (fdp->bootid == ACTIVE)) {
 #if defined(__i386) || defined(__amd64)
-			is_linux_swap = 0;
-			if (fdp->systid == SUNIXOS) {
-				if (cmlb_is_linux_swap(cl, relsect,
-				    tg_cookie) == 0) {
-					is_linux_swap = 1;
-				}
-			}
-			if (!is_linux_swap) {
+			if (fdp->systid != SUNIXOS ||
+			    (fdp->systid == SUNIXOS &&
+			    (cmlb_is_linux_swap(cl, relsect,
+			    tg_cookie) != 0))) {
 #endif
 				uidx = i;
 				solaris_offset = relsect;