Re: [PATCH]: Many Sun label handling fixes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: David Miller <davem@xxxxxxxxxxxxx>
Date: Fri, 29 Jun 2007 15:50:21 -0700 (PDT)

> 
> While working on Sun LDOMs I had opportunity to spot many errors in
> how fdisk creates Sun disk labels compared to the reality of what
> Solaris and other systems expect.
> 
> The worst offense was not setting the version, sane, and num_partition
> fields of the disk label.
> 
> That, as well as several other issues, are fixed in the patch below.
> 
> [FDISK]: Many significant improvements and fixes to Sun label handling.
> 
> 1) Properly describe the exact layout and fields of the sun disk
>    label.  Several fields were incorrectly mentioned and others
>    wrongly sized.
> 
> 2) Properly set the version, sane, and num_partitions fields.
> 
>    Because we weren't doing this, programs such as Solaris's format
>    and the Solaris kernel itself refused to recognize our disk labels
>    as valid.
> 
> 3) Move SSWAP*() macros into fdisksunlabel.c as there is no reason
>    for them to be exposed to the rest of fdisk.
> 
> 4) Kill the sun_predefined_drives array hack and assosciated code.
> 
>    Instead size the disk and figure out the geometry properly just
>    like the SGI and MSDOS partition handling do, by means of the
>    HD_GETGEO ioctl() and disksize().
> 
> 5) If the disk label read is found to not have the proper values
>    set in version, sane, or num_partitions, fix them, recompute the
>    label checksum, dirty the disk label, and let the user know what
>    we did and that the fixed values will be written out if they 'w'.
> 
>    This gives users an easy way to fix up disk labels created by
>    disk labelling programs which had this bug.
> 
> 6) Create a sun_sys_getid() function so that fdisk.c does not need
>    to reference the sun disk label details directly, just like the
>    SGI code does.
> 
> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>

I just noticed there were some recent mildly conflicting changesets
in this area, so I've respun my patch against the current tree,
same changelog and singoff, thanks!

diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c
index c4ab6d5..292b7a8 100644
--- a/fdisk/fdisk.c
+++ b/fdisk/fdisk.c
@@ -470,7 +470,7 @@ xmenu(void) {
 static int
 get_sysid(int i) {
 	return (
-		sun_label ? sunlabel->infos[i].id :
+		sun_label ? sun_get_sysid(i) :
 		sgi_label ? sgi_get_sysid(i) :
 		ptes[i].part_table->sys_ind);
 }
@@ -1178,7 +1178,7 @@ get_partition(int warn, int max) {
 		if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
 		    || (sun_label &&
 			(!sunlabel->partitions[i].num_sectors ||
-			 !sunlabel->infos[i].id))
+			 !sunlabel->part_tags[i].tag))
 		    || (sgi_label && (!sgi_get_num_sectors(i)))
 		   )
 			fprintf(stderr,
@@ -1400,7 +1400,7 @@ change_sysid(void) {
 		}
 
                 if (sys < 256) {
-			if (sun_label && i == 2 && sys != WHOLE_DISK)
+			if (sun_label && i == 2 && sys != SUN_TAG_BACKUP)
 				printf(_("Consider leaving partition 3 "
 				       "as Whole disk (5),\n"
 				       "as SunOS/Solaris expects it and "
@@ -2614,7 +2614,7 @@ main(int argc, char **argv) {
 				toggle_active(get_partition(1, partitions));
 			else if (sun_label)
 				toggle_sunflags(get_partition(1, partitions),
-						0x01);
+						SUN_FLAG_UNMNT);
 			else if (sgi_label)
 				sgi_set_bootpartition(
 					get_partition(1, partitions));
@@ -2638,7 +2638,7 @@ main(int argc, char **argv) {
 				toggle_dos_compatibility_flag();
 			else if (sun_label)
 				toggle_sunflags(get_partition(1, partitions),
-						0x10);
+						SUN_FLAG_RONLY);
 			else if (sgi_label)
 				sgi_set_swappartition(
 						get_partition(1, partitions));
diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c
index a1994e2..248989c 100644
--- a/fdisk/fdisksunlabel.c
+++ b/fdisk/fdisksunlabel.c
@@ -36,25 +36,23 @@ static int     other_endian = 0;
 static int     scsi_disk = 0;
 static int     floppy = 0;
 
-#define LINUX_SWAP      0x82
-#define LINUX_NATIVE    0x83
-
 struct systypes sun_sys_types[] = {
-	{0, N_("Empty")},
-	{1, N_("Boot")},
-	{2, N_("SunOS root")},
-	{SUNOS_SWAP, N_("SunOS swap")},
-	{4, N_("SunOS usr")},
-	{WHOLE_DISK, N_("Whole disk")},
-	{6, N_("SunOS stand")},
-	{7, N_("SunOS var")},
-	{8, N_("SunOS home")},
-	{LINUX_SWAP, N_("Linux swap")},
-	{LINUX_NATIVE, N_("Linux native")},
-	{0x8e, N_("Linux LVM")},
-	{0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition
-					       with autodetect using
-					       persistent superblock */
+	{SUN_TAG_UNASSIGNED, N_("Unassigned")},
+	{SUN_TAG_BOOT, N_("Boot")},
+	{SUN_TAG_ROOT, N_("SunOS root")},
+	{SUN_TAG_SWAP, N_("SunOS swap")},
+	{SUN_TAG_USR, N_("SunOS usr")},
+	{SUN_TAG_BACKUP, N_("Whole disk")},
+	{SUN_TAG_STAND, N_("SunOS stand")},
+	{SUN_TAG_VAR, N_("SunOS var")},
+	{SUN_TAG_HOME, N_("SunOS home")},
+	{SUN_TAG_ALTSCTR, N_("SunOS alt sectors")},
+	{SUN_TAG_CACHE, N_("SunOS cachefs")},
+	{SUN_TAG_RESERVED, N_("SunOS reserved")},
+	{SUN_TAG_LINUX_SWAP, N_("Linux swap")},
+	{SUN_TAG_LINUX_NATIVE, N_("Linux native")},
+	{SUN_TAG_LINUX_LVM, N_("Linux LVM")},
+	{SUN_TAG_LINUX_RAID, N_("Linux raid autodetect")},
 	{ 0, NULL }
 };
 
@@ -65,10 +63,10 @@ static inline __u32 __swap32(__u32 x) {
         return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24);
 }
 
-int
-get_num_sectors(struct sun_partition p) {
-	return SSWAP32(p.num_sectors);
-}
+#define SSWAP16(x) (other_endian ? __swap16(x) \
+				 : (__u16)(x))
+#define SSWAP32(x) (other_endian ? __swap32(x) \
+				 : (__u32)(x))
 
 #ifndef IDE0_MAJOR
 #define IDE0_MAJOR 3
@@ -76,7 +74,8 @@ get_num_sectors(struct sun_partition p) {
 #ifndef IDE1_MAJOR
 #define IDE1_MAJOR 22
 #endif
-void guess_device_type(int fd) {
+void guess_device_type(int fd)
+{
 	struct stat bootstat;
 
 	if (fstat (fd, &bootstat) < 0) {
@@ -97,9 +96,10 @@ void guess_device_type(int fd) {
 	}
 }
 
-static void
-set_sun_partition(int i, unsigned int start, unsigned int stop, int sysid) {
-	sunlabel->infos[i].id = sysid;
+static void set_sun_partition(int i, __u32 start, __u32 stop, __u16 sysid)
+{
+	sunlabel->part_tags[i].tag = SSWAP16(sysid);
+	sunlabel->part_tags[i].flag = SSWAP16(0);
 	sunlabel->partitions[i].start_cylinder =
 		SSWAP32(start / (heads * sectors));
 	sunlabel->partitions[i].num_sectors =
@@ -107,15 +107,15 @@ set_sun_partition(int i, unsigned int start, unsigned int stop, int sysid) {
 	set_changed(i);
 }
 
-void
-sun_nolabel(void) {
+void sun_nolabel(void)
+{
 	sun_label = 0;
 	sunlabel->magic = 0;
 	partitions = 4;
 }
 
-int
-check_sun_label(void) {
+int check_sun_label(void)
+{
 	unsigned short *ush;
 	int csum;
 
@@ -126,133 +126,67 @@ check_sun_label(void) {
 		return 0;
 	}
 	other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
+
 	ush = ((unsigned short *) (sunlabel + 1)) - 1;
-	for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
+	for (csum = 0; ush >= (unsigned short *)sunlabel;)
+		csum ^= *ush--;
+
 	if (csum) {
 		fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
 				"Probably you'll have to set all the values,\n"
 				"e.g. heads, sectors, cylinders and partitions\n"
 				"or force a fresh label (s command in main menu)\n"));
 	} else {
-		heads = SSWAP16(sunlabel->ntrks);
+		int need_fixing = 0;
+
+		heads = SSWAP16(sunlabel->nhead);
 		cylinders = SSWAP16(sunlabel->ncyl);
 		sectors = SSWAP16(sunlabel->nsect);
+
+		if (sunlabel->version != SSWAP32(SUN_LABEL_VERSION)) {
+			fprintf(stderr,_("Detected sun disklabel with wrong version [0x%08x].\n"),
+				sunlabel->version);
+			need_fixing = 1;
+		}
+		if (sunlabel->sanity != SSWAP32(SUN_LABEL_SANE)) {
+			fprintf(stderr,_("Detected sun disklabel with wrong sanity [0x%08x].\n"),
+				sunlabel->sanity);
+			need_fixing = 1;
+		}
+		if (sunlabel->num_partitions != SSWAP16(SUN_NUM_PARTITIONS)) {
+			fprintf(stderr,_("Detected sun disklabel with wrong num_partitions [%u].\n"),
+				sunlabel->num_partitions);
+			need_fixing = 1;
+		}
+		if (need_fixing) {
+			fprintf(stderr, _("Warning: Wrong values need to be "
+					  "fixed up and will be corrected "
+					  "by w(rite)\n"));
+			sunlabel->version = SSWAP32(SUN_LABEL_VERSION);
+			sunlabel->sanity = SSWAP32(SUN_LABEL_SANE);
+			sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
+
+			ush = (unsigned short *)sunlabel;
+			csum = 0;
+			while(ush < (unsigned short *)(&sunlabel->cksum))
+				csum ^= *ush++;
+			sunlabel->cksum = csum;
+
+			set_changed(0);
+		}
 	}
 	update_units();
 	sun_label = 1;
-	partitions = 8;
+	partitions = SUN_NUM_PARTITIONS;
 	return 1;
 }
 
-struct sun_predefined_drives {
-	char *vendor;
-	char *model;
-	unsigned short sparecyl;
-	unsigned short ncyl;
-	unsigned short nacyl;
-	unsigned short pcylcount;
-	unsigned short ntrks;
-	unsigned short nsect;
-	unsigned short rspeed;
-} sun_drives[] = {
-{"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
-{"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
-{"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
-{"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
-{"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
-{"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
-{"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
-{"","SUN0104",1,974,2,1019,6,35,3662},
-{"","SUN0207",4,1254,2,1272,9,36,3600},
-{"","SUN0327",3,1545,2,1549,9,46,3600},
-{"","SUN0340",0,1538,2,1544,6,72,4200},
-{"","SUN0424",2,1151,2,2500,9,80,4400},
-{"","SUN0535",0,1866,2,2500,7,80,5400},
-{"","SUN0669",5,1614,2,1632,15,54,3600},
-{"","SUN1.0G",5,1703,2,1931,15,80,3597},
-{"","SUN1.05",0,2036,2,2038,14,72,5400},
-{"","SUN1.3G",6,1965,2,3500,17,80,5400},
-{"","SUN2.1G",0,2733,2,3500,19,80,5400},
-{"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
-};
-
-static struct sun_predefined_drives *
-sun_autoconfigure_scsi(void) {
-    struct sun_predefined_drives *p = NULL;
-
-#ifdef SCSI_IOCTL_GET_IDLUN
-    unsigned int id[2];
-    char buffer[2048];
-    char buffer2[2048];
-    FILE *pfd;
-    char *vendor;
-    char *model;
-    char *q;
-    int i;
-
-    if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
-        sprintf(buffer,
-            "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
-#if 0                    
-            ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
-#else
-            /* This is very wrong (works only if you have one HBA),
-               but I haven't found a way how to get hostno
-               from the current kernel */
-            0,
-#endif                        
-            (id[0]>>16)&0xff,
-            id[0]&0xff,
-            (id[0]>>8)&0xff);
-        pfd = fopen("/proc/scsi/scsi","r");
-        if (pfd) {
-            while (fgets(buffer2,2048,pfd)) {
-		if (!strcmp(buffer, buffer2)) {
-                    if (fgets(buffer2,2048,pfd)) {
-                        q = strstr(buffer2,"Vendor: ");
-                        if (q) {
-                            q += 8;
-                            vendor = q;
-			    q = strstr(q," ");
-			    *q++ = 0;	/* truncate vendor name */
-                            q = strstr(q,"Model: ");
-                            if (q) {
-                                *q = 0;
-                                q += 7;
-                                model = q;
-                                q = strstr(q," Rev: ");
-                                if (q) {
-                                    *q = 0;
-                                    for (i = 0; i < SIZE(sun_drives); i++) {
-                                        if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
-                                            continue;
-                                        if (!strstr(model, sun_drives[i].model))
-                                            continue;
-                                        printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
-                                        p = sun_drives + i;
-                                        break;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    break;
-                }
-            }
-            fclose(pfd);
-        }
-    }
-#endif
-    return p;
-}
-
 void create_sunlabel(void)
 {
 	struct hd_geometry geometry;
+	unsigned long long llsectors, llcyls;
 	unsigned int ndiv;
-	int i;
-	unsigned char c;
-	struct sun_predefined_drives *p = NULL;
+	int res, sec_fac;
 
 	fprintf(stderr,
 	_("Building a new sun disklabel. Changes will remain in memory only,\n"
@@ -265,116 +199,70 @@ void create_sunlabel(void)
 #endif
 	memset(MBRbuffer, 0, sizeof(MBRbuffer));
 	sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC);
-	if (!floppy) {
-	    puts(_("Drive type\n"
-	         "   ?   auto configure\n"
-	         "   0   custom (with hardware detected defaults)"));
-	    for (i = 0; i < SIZE(sun_drives); i++) {
-	        printf("   %c   %s%s%s\n",
-		       i + 'a', sun_drives[i].vendor,
-		       (*sun_drives[i].vendor) ? " " : "",
-		       sun_drives[i].model);
-	    }
-	    for (;;) {
-	        c = read_char(_("Select type (? for auto, 0 for custom): "));
-	        if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
-	     	    p = sun_drives + c - 'a';
-	     	    break;
-	        } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
-	            p = sun_drives + c - 'A';
-	            break;
-	        } else if (c == '0') {
-	            break;
-	        } else if (c == '?' && scsi_disk) {
-		    p = sun_autoconfigure_scsi();
-	            if (!p)
-	                printf(_("Autoconfigure failed.\n"));
-	            else
-	                break;
-	        }
-	    }
-	}
-	if (!p || floppy) {
-	    if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+	sunlabel->sanity = SSWAP32(SUN_LABEL_SANE);
+	sunlabel->version = SSWAP32(SUN_LABEL_VERSION);
+	sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
+
+	res = disksize(fd, &llsectors);
+	sec_fac = sector_size / 512;
+
+	if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
 	        heads = geometry.heads;
 	        sectors = geometry.sectors;
-	        cylinders = geometry.cylinders;
-	    } else {
-	        heads = 0;
-	        sectors = 0;
-	        cylinders = 0;
-	    }
-	    if (floppy) {
-	        sunlabel->nacyl = 0;
-	        sunlabel->pcylcount = SSWAP16(cylinders);
-	        sunlabel->rspeed = SSWAP16(300);
-	        sunlabel->ilfact = SSWAP16(1);
-	        sunlabel->sparecyl = 0;
-	    } else {
-	        heads = read_int(1,heads,1024,0,_("Heads"));
-		sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
-	        if (cylinders)
-	            cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
-	        else
-	            cylinders = read_int(1,0,65535,0,_("Cylinders"));
-	        sunlabel->nacyl =
-			SSWAP16(read_int(0,2,65535,0,
-					 _("Alternate cylinders")));
-	        sunlabel->pcylcount =
-			SSWAP16(read_int(0,cylinders+SSWAP16(sunlabel->nacyl),
-					 65535,0,_("Physical cylinders")));
-	        sunlabel->rspeed =
-			SSWAP16(read_int(1,5400,100000,0,
-					 _("Rotation speed (rpm)")));
-	        sunlabel->ilfact =
-			SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
-	        sunlabel->sparecyl =
-			SSWAP16(read_int(0,0,sectors,0,
-					 _("Extra sectors per cylinder")));
-	    }
+		if (res == 0) {
+			llcyls = llsectors / (heads * sectors * sec_fac);
+			cylinders = llcyls;
+			if (cylinders != llcyls)
+				cylinders = ~0;
+		} else {
+			cylinders = geometry.cylinders;
+			fprintf(stderr,
+				_("Warning:  BLKGETSIZE ioctl failed on %s.  "
+				  "Using geometry cylinder value of %d.\n"
+				  "This value may be truncated for devices"
+				  " > 33.8 GB.\n"), disk_device, cylinders);
+		}
 	} else {
-	    sunlabel->sparecyl = SSWAP16(p->sparecyl);
-	    sunlabel->ncyl = SSWAP16(p->ncyl);
-	    sunlabel->nacyl = SSWAP16(p->nacyl);
-	    sunlabel->pcylcount = SSWAP16(p->pcylcount);
-	    sunlabel->ntrks = SSWAP16(p->ntrks);
-	    sunlabel->nsect = SSWAP16(p->nsect);
-	    sunlabel->rspeed = SSWAP16(p->rspeed);
-	    sunlabel->ilfact = SSWAP16(1);
-	    cylinders = p->ncyl;
-	    heads = p->ntrks;
-	    sectors = p->nsect;
-	    puts(_("You may change all the disk params from the x menu"));
+	        heads = read_int(1,1,1024,0,_("Heads"));
+		sectors = read_int(1,1,1024,0,_("Sectors/track"));
+		cylinders = read_int(1,1,65535,0,_("Cylinders"));
 	}
 
-	snprintf(sunlabel->info, sizeof(sunlabel->info),
-		 "%s%s%s cyl %d alt %d hd %d sec %llu",
-		 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
-		 p ? p->model
-		   : (floppy ? _("3,5\" floppy") : _("Linux custom")),
-		cylinders, SSWAP16(sunlabel->nacyl), heads, sectors);
+	sunlabel->acyl   = SSWAP16(2);
+	sunlabel->pcyl   = SSWAP16(cylinders);
+	sunlabel->ncyl   = SSWAP16(cylinders - 2);
+	sunlabel->rpm    = SSWAP16(5400);
+	sunlabel->intrlv = SSWAP16(1);
+	sunlabel->apc    = SSWAP16(0);
 
-	sunlabel->ntrks = SSWAP16(heads);
+	sunlabel->nhead = SSWAP16(heads);
 	sunlabel->nsect = SSWAP16(sectors);
 	sunlabel->ncyl = SSWAP16(cylinders);
-	if (floppy)
-	    set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
-	else {
-	    if (cylinders * heads * sectors >= 150 * 2048) {
+
+	snprintf(sunlabel->label_id, sizeof(sunlabel->label_id),
+		 "Linux cyl %d alt %d hd %d sec %llu",
+		 cylinders, SSWAP16(sunlabel->acyl), heads, sectors);
+
+	if (cylinders * heads * sectors >= 150 * 2048) {
 	        ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
-	    } else
+	} else
 	        ndiv = cylinders * 2 / 3;
-	    set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
-	    set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
-	    sunlabel->infos[1].flags |= 0x01; /* Not mountable */
-	}
-	set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
+
+	set_sun_partition(0, 0, ndiv * heads * sectors,
+			  SUN_TAG_LINUX_NATIVE);
+	set_sun_partition(1, ndiv * heads * sectors,
+			  cylinders * heads * sectors,
+			  SUN_TAG_LINUX_SWAP);
+	sunlabel->part_tags[1].flag |= SSWAP16(SUN_FLAG_UNMNT);
+
+	set_sun_partition(2, 0, cylinders * heads * sectors, SUN_TAG_BACKUP);
+
 	{
 		unsigned short *ush = (unsigned short *)sunlabel;
 		unsigned short csum = 0;
-		while(ush < (unsigned short *)(&sunlabel->csum))
+		while(ush < (unsigned short *)(&sunlabel->cksum))
 			csum ^= *ush++;
-		sunlabel->csum = csum;
+		sunlabel->cksum = csum;
 	}
 
 	set_all_unchanged();
@@ -382,24 +270,32 @@ void create_sunlabel(void)
 	set_changed(0);
 }
 
-void
-toggle_sunflags(int i, unsigned char mask) {
-	if (sunlabel->infos[i].flags & mask)
-		sunlabel->infos[i].flags &= ~mask;
-	else sunlabel->infos[i].flags |= mask;
+void toggle_sunflags(int i, __u16 mask)
+{
+	struct sun_tag_flag *p = &sunlabel->part_tags[i];
+
+	p->flag ^= SSWAP16(mask);
+
 	set_changed(i);
 }
 
-static void
-fetch_sun(unsigned int *starts, unsigned int *lens, unsigned int *start, unsigned int *stop) {
+static void fetch_sun(__u32 *starts, __u32 *lens, __u32 *start, __u32 *stop)
+{
 	int i, continuous = 1;
-	*start = 0; *stop = cylinders * heads * sectors;
+
+	*start = 0;
+	*stop = cylinders * heads * sectors;
+
 	for (i = 0; i < partitions; i++) {
-		if (sunlabel->partitions[i].num_sectors
-		    && sunlabel->infos[i].id
-		    && sunlabel->infos[i].id != WHOLE_DISK) {
-			starts[i] = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
-			lens[i] = SSWAP32(sunlabel->partitions[i].num_sectors);
+		struct sun_partition *part = &sunlabel->partitions[i];
+		struct sun_tag_flag *tag = &sunlabel->part_tags[i];
+
+		if (part->num_sectors &&
+		    tag->tag != SSWAP16(SUN_TAG_UNASSIGNED) &&
+		    tag->tag != SSWAP16(SUN_TAG_BACKUP)) {
+			starts[i] = (SSWAP32(part->start_cylinder) *
+				     heads * sectors);
+			lens[i] = SSWAP32(part->num_sectors);
 			if (continuous) {
 				if (starts[i] == *start)
 					*start += lens[i];
@@ -419,24 +315,29 @@ fetch_sun(unsigned int *starts, unsigned int *lens, unsigned int *start, unsigne
 
 static unsigned int *verify_sun_starts;
 
-static int
-verify_sun_cmp(int *a, int *b) {
-    if (*a == -1) return 1;
-    if (*b == -1) return -1;
-    if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
+static int verify_sun_cmp(int *a, int *b)
+{
+    if (*a == -1)
+	    return 1;
+    if (*b == -1)
+	    return -1;
+    if (verify_sun_starts[*a] > verify_sun_starts[*b])
+	    return 1;
     return -1;
 }
 
-void
-verify_sun(void) {
-    unsigned int starts[8], lens[8], start, stop;
+void verify_sun(void)
+{
+    __u32 starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS], start, stop;
     int i,j,k,starto,endo;
-    int array[8];
+    int array[SUN_NUM_PARTITIONS];
 
     verify_sun_starts = starts;
-    fetch_sun(starts,lens,&start,&stop);
+
+    fetch_sun(starts, lens, &start, &stop);
+
     for (k = 0; k < 7; k++) {
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < SUN_NUM_PARTITIONS; i++) {
 	    if (k && (lens[i] % (heads * sectors))) {
 	        printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
 	    }
@@ -466,7 +367,7 @@ verify_sun(void) {
 	    }
 	}
     }
-    for (i = 0; i < 8; i++) {
+    for (i = 0; i < SUN_NUM_PARTITIONS; i++) {
         if (lens[i])
             array[i] = i;
         else
@@ -480,31 +381,35 @@ verify_sun(void) {
     }
     stop = cylinders * heads * sectors;
     if (starts[array[0]])
-        printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
+        printf(_("Unused gap - sectors 0-%d\n"), starts[array[0]]);
     for (i = 0; i < 7 && array[i+1] != -1; i++) {
-        printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
+        printf(_("Unused gap - sectors %d-%d\n"),
+	       (starts[array[i]] + lens[array[i]]),
+	       starts[array[i+1]]);
     }
-    start = starts[array[i]]+lens[array[i]];
+    start = (starts[array[i]] + lens[array[i]]);
     if (start < stop)
-        printf(_("Unused gap - sectors %d-%d\n"),start,stop);
+        printf(_("Unused gap - sectors %d-%d\n"), start, stop);
 }
 
-void
-add_sun_partition(int n, int sys) {
-	unsigned int start, stop, stop2;
-	unsigned int starts[8], lens[8];
+void add_sun_partition(int n, int sys)
+{
+	__u32 starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS];
+	struct sun_partition *part = &sunlabel->partitions[n];
+	struct sun_tag_flag *tag = &sunlabel->part_tags[n];
+	__u32 start, stop, stop2;
 	int whole_disk = 0;
 		
 	char mesg[256];
 	int i, first, last;
 
-	if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
+	if (part->num_sectors && tag->tag != SSWAP16(SUN_TAG_UNASSIGNED)) {
 		printf(_("Partition %d is already defined.  Delete "
 			"it before re-adding it.\n"), n + 1);
 		return;
 	}
 	
-	fetch_sun(starts,lens,&start,&stop);
+	fetch_sun(starts, lens, &start, &stop);
 	if (stop <= start) {
 		if (n == 2)
 			whole_disk = 1;
@@ -600,29 +505,37 @@ and is of type `Whole disk'\n");
 	} else if (!whole_disk && last > stop)
 		last = stop;
 
-	if (whole_disk) sys = WHOLE_DISK;
+	if (whole_disk)
+		sys = SUN_TAG_BACKUP;
+
 	set_sun_partition(n, first, last, sys);
 }
 
-void
-sun_delete_partition(int i) {
+void sun_delete_partition(int i)
+{
+	struct sun_partition *part = &sunlabel->partitions[i];
+	struct sun_tag_flag *tag = &sunlabel->part_tags[i];
 	unsigned int nsec;
 
-	if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK && 
-	    !sunlabel->partitions[i].start_cylinder && 
-	    (nsec = SSWAP32(sunlabel->partitions[i].num_sectors))
+	if (i == 2 &&
+	    tag->tag == SSWAP16(SUN_TAG_BACKUP) && 
+	    !part->start_cylinder && 
+	    (nsec = SSWAP32(part->num_sectors))
 	      == heads * sectors * cylinders)
 		printf(_("If you want to maintain SunOS/Solaris compatibility, "
 		       "consider leaving this\n"
 		       "partition as Whole disk (5), starting at 0, with %u "
 		       "sectors\n"), nsec);
-	sunlabel->infos[i].id = 0;
-	sunlabel->partitions[i].num_sectors = 0;
+	tag->tag = SSWAP16(SUN_TAG_UNASSIGNED);
+	part->num_sectors = 0;
 }
 
-void
-sun_change_sysid(int i, int sys) {
-	if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
+void sun_change_sysid(int i, __u16 sys)
+{
+	struct sun_partition *part = &sunlabel->partitions[i];
+	struct sun_tag_flag *tag = &sunlabel->part_tags[i];
+
+	if (sys == SUN_TAG_LINUX_SWAP && !part->start_cylinder) {
 	    read_chars(
 	      _("It is highly recommended that the partition at offset 0\n"
 	      "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
@@ -633,22 +546,22 @@ sun_change_sysid(int i, int sys) {
 		    return;
 	}
 	switch (sys) {
-	case SUNOS_SWAP:
-	case LINUX_SWAP:
+	case SUN_TAG_SWAP:
+	case SUN_TAG_LINUX_SWAP:
 		/* swaps are not mountable by default */
-		sunlabel->infos[i].flags |= 0x01;
+		tag->flag |= SSWAP16(SUN_FLAG_UNMNT);
 		break;
 	default:
 		/* assume other types are mountable;
 		   user can change it anyway */
-		sunlabel->infos[i].flags &= ~0x01;
+		tag->flag &= ~SSWAP16(SUN_FLAG_UNMNT);
 		break;
 	}
-	sunlabel->infos[i].id = sys;
+	tag->tag = SSWAP16(sys);
 }
 
-void
-sun_list_table(int xtra) {
+void sun_list_table(int xtra)
+{
 	int i, w;
 	char *type;
 
@@ -658,14 +571,16 @@ sun_list_table(int xtra) {
 		_("\nDisk %s (Sun disk label): %d heads, %llu sectors, %d rpm\n"
 		"%d cylinders, %d alternate cylinders, %d physical cylinders\n"
 		"%d extra sects/cyl, interleave %d:1\n"
-		"%s\n"
+		"Label ID: %s\n"
+		"Volume ID: %s\n"
 		"Units = %s of %d * 512 bytes\n\n"),
-		       disk_device, heads, sectors, SSWAP16(sunlabel->rspeed),
-		       cylinders, SSWAP16(sunlabel->nacyl),
-		       SSWAP16(sunlabel->pcylcount),
-		       SSWAP16(sunlabel->sparecyl),
-		       SSWAP16(sunlabel->ilfact),
-		       (char *)sunlabel,
+		       disk_device, heads, sectors, SSWAP16(sunlabel->rpm),
+		       cylinders, SSWAP16(sunlabel->acyl),
+		       SSWAP16(sunlabel->pcyl),
+		       SSWAP16(sunlabel->apc),
+		       SSWAP16(sunlabel->intrlv),
+		       sunlabel->label_id,
+		       sunlabel->volume_id,
 		       str_units(PLURAL), units_per_sector);
 	else
 		printf(
@@ -677,74 +592,82 @@ sun_list_table(int xtra) {
 	printf(_("%*s Flag    Start       End    Blocks   Id  System\n"),
 	       w + 1, _("Device"));
 	for (i = 0 ; i < partitions; i++) {
-		if (sunlabel->partitions[i].num_sectors) {
-			__u32 start = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
-			__u32 len = SSWAP32(sunlabel->partitions[i].num_sectors);
+		struct sun_partition *part = &sunlabel->partitions[i];
+		struct sun_tag_flag *tag = &sunlabel->part_tags[i];
+
+		if (part->num_sectors) {
+			__u32 start = SSWAP32(part->start_cylinder) * heads * sectors;
+			__u32 len = SSWAP32(part->num_sectors);
 			printf(
 			    "%s %c%c %9ld %9ld %9ld%c  %2x  %s\n",
 /* device */		  partname(disk_device, i+1, w),
-/* flags */		  (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
-			  (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
+/* flags */		  (tag->flag & SSWAP16(SUN_FLAG_UNMNT)) ? 'u' : ' ',
+			  (tag->flag & SSWAP16(SUN_FLAG_RONLY)) ? 'r' : ' ',
 /* start */		  (long) scround(start),
 /* end */		  (long) scround(start+len),
 /* odd flag on end */	  (long) len / 2, len & 1 ? '+' : ' ',
-/* type id */		  sunlabel->infos[i].id,
-/* type name */		  (type = partition_type(sunlabel->infos[i].id))
+/* type id */		  SSWAP16(tag->tag),
+/* type name */		  (type = partition_type(SSWAP16(tag->tag)))
 			        ? type : _("Unknown"));
 		}
 	}
 }
 
-void
-sun_set_alt_cyl(void) {
-	sunlabel->nacyl =
-		SSWAP16(read_int(0,SSWAP16(sunlabel->nacyl), 65535, 0,
+void sun_set_alt_cyl(void)
+{
+	sunlabel->acyl =
+		SSWAP16(read_int(0,SSWAP16(sunlabel->acyl), 65535, 0,
 				 _("Number of alternate cylinders")));
 }
 
-void
-sun_set_ncyl(int cyl) {
+void sun_set_ncyl(int cyl)
+{
 	sunlabel->ncyl = SSWAP16(cyl);
 }
 
-void
-sun_set_xcyl(void) {
-	sunlabel->sparecyl =
-		SSWAP16(read_int(0, SSWAP16(sunlabel->sparecyl), sectors, 0,
+void sun_set_xcyl(void)
+{
+	sunlabel->apc =
+		SSWAP16(read_int(0, SSWAP16(sunlabel->apc), sectors, 0,
 				 _("Extra sectors per cylinder")));
 }
 
-void
-sun_set_ilfact(void) {
-	sunlabel->ilfact =
-		SSWAP16(read_int(1, SSWAP16(sunlabel->ilfact), 32, 0,
+void sun_set_ilfact(void)
+{
+	sunlabel->intrlv =
+		SSWAP16(read_int(1, SSWAP16(sunlabel->intrlv), 32, 0,
 				 _("Interleave factor")));
 }
 
-void
-sun_set_rspeed(void) {
-	sunlabel->rspeed =
-		SSWAP16(read_int(1, SSWAP16(sunlabel->rspeed), 100000, 0,
+void sun_set_rspeed(void)
+{
+	sunlabel->rpm =
+		SSWAP16(read_int(1, SSWAP16(sunlabel->rpm), 100000, 0,
 				 _("Rotation speed (rpm)")));
 }
 
-void
-sun_set_pcylcount(void) {
-	sunlabel->pcylcount =
-		SSWAP16(read_int(0, SSWAP16(sunlabel->pcylcount), 65535, 0,
+void sun_set_pcylcount(void)
+{
+	sunlabel->pcyl =
+		SSWAP16(read_int(0, SSWAP16(sunlabel->pcyl), 65535, 0,
 				 _("Number of physical cylinders")));
 }
 
-void
-sun_write_table(void) {
+void sun_write_table(void)
+{
 	unsigned short *ush = (unsigned short *)sunlabel;
 	unsigned short csum = 0;
 
-	while(ush < (unsigned short *)(&sunlabel->csum))
+	while(ush < (unsigned short *)(&sunlabel->cksum))
 		csum ^= *ush++;
-	sunlabel->csum = csum;
+	sunlabel->cksum = csum;
 	if (lseek(fd, 0, SEEK_SET) < 0)
 		fatal(unable_to_seek);
 	if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
 		fatal(unable_to_write);
 }
+
+int sun_get_sysid(int i)
+{
+	return SSWAP16(sunlabel->part_tags[i].tag);
+}
diff --git a/fdisk/fdisksunlabel.h b/fdisk/fdisksunlabel.h
index e322e66..c8e0698 100644
--- a/fdisk/fdisksunlabel.h
+++ b/fdisk/fdisksunlabel.h
@@ -3,53 +3,86 @@
 
 #include <linux/types.h>   /* for __u16, __u32 */
 
-typedef struct {
-	unsigned char info[128];   /* Informative text string */
-	unsigned char spare0[14];
-	struct sun_info {
-		unsigned char spare1;
-		unsigned char id;
-		unsigned char spare2;
-		unsigned char flags;
-	} infos[8];
-	unsigned char spare1[246]; /* Boot information etc. */
-	unsigned short rspeed;     /* Disk rotational speed */
-	unsigned short pcylcount;  /* Physical cylinder count */
-	unsigned short sparecyl;   /* extra sects per cylinder */
-	unsigned char spare2[4];   /* More magic... */
-	unsigned short ilfact;     /* Interleave factor */
-	unsigned short ncyl;       /* Data cylinder count */
-	unsigned short nacyl;      /* Alt. cylinder count */
-	unsigned short ntrks;      /* Tracks per cylinder */
-	unsigned short nsect;      /* Sectors per track */
-	unsigned char spare3[4];   /* Even more magic... */
-	struct sun_partition {
-		__u32 start_cylinder;
-		__u32 num_sectors;
-	} partitions[8];
-	unsigned short magic;      /* Magic number */
-	unsigned short csum;       /* Label xor'd checksum */
-} sun_partition;
+struct sun_partition {
+	__u32	start_cylinder;
+	__u32	num_sectors;
+};
 
-#define SUN_LABEL_MAGIC          0xDABE
-#define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
-#define sunlabel ((sun_partition *)MBRbuffer)
-#define SSWAP16(x) (other_endian ? __swap16(x) \
-				 : (__u16)(x))
-#define SSWAP32(x) (other_endian ? __swap32(x) \
-				 : (__u32)(x))
-/* fdisksunlabel.c */
-#define SUNOS_SWAP 3
-#define WHOLE_DISK 5
+struct sun_tag_flag {
+	__u16	tag;
+#define SUN_TAG_UNASSIGNED	0x00	/* Unassigned partition */
+#define SUN_TAG_BOOT		0x01	/* Boot partition	*/
+#define SUN_TAG_ROOT		0x02	/* Root filesystem	*/
+#define SUN_TAG_SWAP		0x03	/* Swap partition	*/
+#define SUN_TAG_USR		0x04	/* /usr filesystem	*/
+#define SUN_TAG_BACKUP		0x05	/* Full-disk slice	*/
+#define SUN_TAG_STAND		0x06	/* Stand partition	*/
+#define SUN_TAG_VAR		0x07	/* /var filesystem	*/
+#define SUN_TAG_HOME		0x08	/* /home filesystem	*/
+#define SUN_TAG_ALTSCTR		0x09	/* Alt sector partition	*/
+#define SUN_TAG_CACHE		0x0a	/* Cachefs partition	*/
+#define SUN_TAG_RESERVED	0x0b	/* SMI reserved data	*/
+#define SUN_TAG_LINUX_SWAP	0x82	/* Linux SWAP		*/
+#define SUN_TAG_LINUX_NATIVE	0x83	/* Linux filesystem	*/
+#define SUN_TAG_LINUX_LVM	0x8e	/* Linux LVM		*/
+#define SUN_TAG_LINUX_RAID	0xfd	/* LInux RAID		*/
+
+	__u16	flag;
+#define SUN_FLAG_UNMNT		0x01	/* Unmountable partition*/
+#define SUN_FLAG_RONLY		0x10	/* Read only		*/
+};
+
+#define SUN_LABEL_SIZE		512
+
+#define SUN_LABEL_ID_SIZE	128
+#define SUN_VOLUME_ID_SIZE	8
 
+#define SUN_LABEL_VERSION	0x00000001
+#define SUN_LABEL_SANE		0x600ddeee
+#define SUN_NUM_PARTITIONS	8
+
+struct sun_disk_label {
+	char			label_id[SUN_LABEL_ID_SIZE];
+	__u32			version;
+	char			volume_id[SUN_VOLUME_ID_SIZE];
+	__u16			num_partitions;
+	struct sun_tag_flag	part_tags[SUN_NUM_PARTITIONS];
+	__u32			bootinfo[3];
+	__u32			sanity;
+	__u32			resv[10];
+	__u32			part_timestamps[SUN_NUM_PARTITIONS];
+	__u32			write_reinstruct;
+	__u32			read_reinstruct;
+	__u8			pad[148];
+	__u16			rpm;
+	__u16			pcyl;
+	__u16			apc;
+	__u16			resv1;
+	__u16			resv2;
+	__u16			intrlv;
+	__u16			ncyl;
+	__u16			acyl;
+	__u16			nhead;
+	__u16			nsect;
+	__u16			resv3;
+	__u16			resv4;
+	struct sun_partition	partitions[SUN_NUM_PARTITIONS];
+	__u16			magic;
+	__u16			cksum;
+};
+
+#define SUN_LABEL_MAGIC		0xDABE
+#define SUN_LABEL_MAGIC_SWAPPED	0xBEDA
+#define sunlabel ((struct sun_disk_label *)MBRbuffer)
+
+/* fdisksunlabel.c */
 extern struct systypes sun_sys_types[];
-extern int get_num_sectors(struct sun_partition p);
 extern void guess_device_type(int fd);
 extern int check_sun_label(void);
 extern void sun_nolabel(void);
 extern void create_sunlabel(void);
 extern void sun_delete_partition(int i);
-extern void sun_change_sysid(int i, int sys);
+extern void sun_change_sysid(int i, __u16 sys);
 extern void sun_list_table(int xtra);
 extern void verify_sun(void);
 extern void add_sun_partition(int n, int sys);
@@ -60,6 +93,7 @@ extern void sun_set_xcyl(void);
 extern void sun_set_ilfact(void);
 extern void sun_set_rspeed(void);
 extern void sun_set_pcylcount(void);
-extern void toggle_sunflags(int i, unsigned char mask);
+extern void toggle_sunflags(int i, __u16 mask);
+extern int sun_get_sysid(int i);
 
 #endif /* FDISK_SUN_LABEL_H */
-
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux