Date: Sun, 11 Mar 2007 08:01:43 GMT From: "Jukka A. Ukkonen"<jau@iki.fi> To: freebsd-gnats-submit@FreeBSD.org Subject: bin/110182: Inability to read and write the same format makes fdisk far less than production quality Message-ID: <200703110801.l2B81hGD041609@www.freebsd.org> Resent-Message-ID: <200703110810.l2B8A3Rv010431@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 110182 >Category: bin >Synopsis: Inability to read and write the same format makes fdisk far less than production quality >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun Mar 11 08:10:03 GMT 2007 >Closed-Date: >Last-Modified: >Originator: Jukka A. Ukkonen >Release: 6.2-STABLE >Organization: private person >Environment: FreeBSD mjolnir 6.2-STABLE FreeBSD 6.2-STABLE #1: Wed Mar 7 03:19:18 EET 2007 root@mjolnir:/usr/obj/usr/src/sys/Mjolnir i386 >Description: Fdisk being unable to read what it writes does not support true production environments' need to rebuild new equivalent slice tables to new disks. At the moment one is forced to manual setting of the correct values or forced to use locally built ad hoc scripts to convert the output from "fdisk -s". Manual setting of the correct values is slow and error prone. Scripted approach is error prone assuming fdisk might actually change one day. Proper production quality approach is to make fdisk able to read and write the same format. This allows for storing existing values on an off-line media for emergensies. This allows also dumping the slice table from an exsiting disk to a new one which could be intended e.g. as a new mirror side. A production level environment always requires ability to rebuild and replace new disks in a semi-automatic manner such that one can rely on getting exactly the same parameters as in an older model setup. Speedy recovery and speedy addition of new (homogenized) storage are core requirements for production environments. To support this I added a new command line option -p which does otherwise exactly the same as -s but in the same simple format fdisk is willing to read. See the attached patch. >How-To-Repeat: Just try to rebuild a new side for a mgirror from scratch using two slices on each disk. Use the first slice for mirrored file system area and the second slices for (interleaved) swap. Notice! Mirroring the swap area makes really no sense at all, because it only slows things down. So, to speed things up even while swap gets used one really needs to make use of the interleaved nature of swap parallelized on multiple disks. One could do this using an fdisk configuration file like... g c8942 h255 s63 p 1 0xa5 63 140504427 a 1 p 2 0xa5 140504490 3148740 But once you have this setup on one disk fdisk does not allow replicating this to another disk, because with all probability your original slice layout on the first disk was not generated using an fdisk configuration file but using sysinstall. To replicate this setup you really want to dump it out as is to be used as input for initialization of a secondary disk using fdisk. >Fix: Apply the attached patch. It adds a new option -p to fdisk. This PR cover the same issue as bin/92723, but overrides it completely by providing the patch while also boosting the priority and severity. Patch attached with submission follows: --- fdisk.c.orig Sat Mar 10 09:50:32 2007 +++ fdisk.c Sat Mar 10 10:45:45 2007 @@ -120,6 +120,7 @@ static int t_flag = 0; /* test only */ static char *f_flag = NULL; /* Read config info from file */ static int v_flag = 0; /* Be verbose */ +static int print_config_flag = 0; static struct part_type { @@ -247,7 +248,7 @@ int partition = -1; struct dos_partition *partp; - while ((c = getopt(argc, argv, "BIab:f:istuv1234")) != -1) + while ((c = getopt(argc, argv, "BIab:f:ipstuv1234")) != -1) switch (c) { case 'B': B_flag = 1; @@ -267,6 +268,9 @@ case 'i': i_flag = 1; break; + case 'p': + print_config_flag = 1; + break; case 's': s_flag = 1; break; @@ -322,11 +326,44 @@ free(mboot.bootinst); mboot.bootinst = NULL; + if (print_config_flag) { + if (read_s0()) + err(1, "read_s0"); + + printf("g c%d h%d s%d\n", dos_cyls, dos_heads, dos_sectors); + + for (i = 0; i < NDOSPART; i++) { + partp = ((struct dos_partition *) &mboot.parts) + i; + + if (partp->dp_start == 0 && partp->dp_size == 0) + continue; + + printf ("p %d 0x%02x %lu %lu\n", + i + 1, + partp->dp_typ, + (u_long) partp->dp_start, + (u_long) partp->dp_size); + + /* + * Full flags for the partition. + * + * printf ("f 0x%02x\n", + * partp->dp_flag); + */ + + if (partp->dp_flag & 0x80) { + printf ("a %d\n", i + 1); + } + } + + exit(0); + } + if (s_flag) { if (read_s0()) err(1, "read_s0"); - printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads, - dos_sectors); + printf("%s: %d cyl %d hd %d sec\n", + disk, dos_cyls, dos_heads, dos_sectors); printf("Part %11s %11s Type Flags\n", "Start", "Size"); for (i = 0; i < NDOSPART; i++) { partp = ((struct dos_partition *) &mboot.parts) + i; --- src/sbin/fdisk/fdisk.c.orig Mon Jun 26 04:18:17 2006 +++ src/sbin/fdisk/fdisk.c Sun Mar 11 08:18:26 2007 @@ -120,6 +120,7 @@ static int t_flag = 0; /* test only */ static char *f_flag = NULL; /* Read config info from file */ static int v_flag = 0; /* Be verbose */ +static int print_config_flag = 0; static struct part_type { @@ -247,7 +248,7 @@ int partition = -1; struct dos_partition *partp; - while ((c = getopt(argc, argv, "BIab:f:istuv1234")) != -1) + while ((c = getopt(argc, argv, "BIab:f:ipstuv1234")) != -1) switch (c) { case 'B': B_flag = 1; @@ -267,6 +268,9 @@ case 'i': i_flag = 1; break; + case 'p': + print_config_flag = 1; + break; case 's': s_flag = 1; break; @@ -322,11 +326,44 @@ free(mboot.bootinst); mboot.bootinst = NULL; + if (print_config_flag) { + if (read_s0()) + err(1, "read_s0"); + + printf("g c%d h%d s%d\n", dos_cyls, dos_heads, dos_sectors); + + for (i = 0; i < NDOSPART; i++) { + partp = ((struct dos_partition *) &mboot.parts) + i; + + if (partp->dp_start == 0 && partp->dp_size == 0) + continue; + + printf ("p %d 0x%02x %lu %lu\n", + i + 1, + partp->dp_typ, + (u_long) partp->dp_start, + (u_long) partp->dp_size); + + /* + * Full flags for the partition. + * + * printf ("f 0x%02x\n", + * partp->dp_flag); + */ + + if (partp->dp_flag & 0x80) { + printf ("a %d\n", i + 1); + } + } + + exit(0); + } + if (s_flag) { if (read_s0()) err(1, "read_s0"); - printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads, - dos_sectors); + printf("%s: %d cyl %d hd %d sec\n", + disk, dos_cyls, dos_heads, dos_sectors); printf("Part %11s %11s Type Flags\n", "Start", "Size"); for (i = 0; i < NDOSPART; i++) { partp = ((struct dos_partition *) &mboot.parts) + i; >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200703110801.l2B81hGD041609>