~pr0gg3d/ubuntu/oneiric/util-linux/bug-805886

« back to all changes in this revision

Viewing changes to fdisk/fdisk.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2010-03-22 17:35:40 UTC
  • mfrom: (1.6.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100322173540-sm083tdtvne1wa5w
Tags: 2.17.2-0ubuntu1
* Merge from Debian experimental, remaining changes:
  - Since udev is required in Ubuntu, the hwclock.sh init script is
    not called on startup and the hwclockfirst.sh init script is
    removed.
  - Use wildcards for symbols file, since they use versioned symbols
    properly.
  - Remove /etc/adjtime on upgrade if it was not used.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - No lsb_release call in mount.preinst since we'd need Pre-Depends
    (LP: #383697).
  - Do not install initramfs hook, since our initramfs already handles
    including blkid.
  - Mention mountall(8) in fstab(5) manpages, along with its special
    options.

* For the case where mount is called with a directory to mount, look
  that directory up in mountall's /lib/init/fstab if we couldn't find
  it mentioned anywhere else.  This means "mount /proc", "mount /sys",
  etc. work.

Show diffs side-by-side

added added

removed removed

Lines of Context:
222
222
        display_in_cyl_units = 1;
223
223
 
224
224
unsigned long long total_number_of_sectors;     /* (!) 512-byte sectors */
225
 
unsigned long io_size, alignment_offset;
 
225
unsigned long grain = DEFAULT_SECTOR_SIZE,
 
226
              io_size = DEFAULT_SECTOR_SIZE,
 
227
              min_io_size = DEFAULT_SECTOR_SIZE,
 
228
              phy_sector_size = DEFAULT_SECTOR_SIZE,
 
229
              alignment_offset;
 
230
int has_topology;
226
231
 
227
232
#define dos_label (!sun_label && !sgi_label && !aix_label && !mac_label && !osf_label)
228
233
int     sun_label = 0;                  /* looking at sun disklabel */
237
242
void fatal(enum failure why) {
238
243
        char    error[LINE_LENGTH],
239
244
                *message = error;
 
245
        int     rc = EXIT_FAILURE;
240
246
 
241
247
        if (listing) {
242
248
                close(fd);
244
250
        }
245
251
 
246
252
        switch (why) {
 
253
                case help:
 
254
                        rc = EXIT_SUCCESS;
247
255
                case usage: message = _(
248
 
"Usage: fdisk [-b SSZ] [-u] DISK     Change partition table\n"
249
 
"       fdisk -l [-b SSZ] [-u] DISK  List partition table(s)\n"
250
 
"       fdisk -s PARTITION           Give partition size(s) in blocks\n"
251
 
"       fdisk -v                     Give fdisk version\n"
252
 
"Here DISK is something like /dev/hdb or /dev/sda\n"
253
 
"and PARTITION is something like /dev/hda7\n"
254
 
"-u: give Start and End in sector (instead of cylinder) units\n"
255
 
"-b 2048: (for certain MO disks) use 2048-byte sectors\n");
256
 
                        break;
257
 
                case usage2:
258
 
                  /* msg in cases where fdisk used to probe */
259
 
                        message = _(
260
 
"Usage: fdisk [-l] [-b SSZ] [-u] device\n"
261
 
"E.g.: fdisk /dev/hda  (for the first IDE disk)\n"
262
 
"  or: fdisk /dev/sdc  (for the third SCSI disk)\n"
263
 
"  or: fdisk /dev/eda  (for the first PS/2 ESDI drive)\n"
264
 
"  or: fdisk /dev/rd/c0d0  or: fdisk /dev/ida/c0d0  (for RAID devices)\n"
265
 
"  ...\n");
 
256
"Usage:\n"
 
257
" fdisk [options] <disk>    change partition table\n"
 
258
" fdisk [options] -l <disk> list partition table(s)\n"
 
259
" fdisk -s <partition>      give partition size(s) in blocks\n"
 
260
"\nOptions:\n"
 
261
" -b <size>                 sector size (512, 1024, 2048 or 4096)\n"
 
262
" -c                        switch off DOS-compatible mode\n"
 
263
" -h                        print help\n"
 
264
" -u <size>                 give sizes in sectors instead of cylinders\n"
 
265
" -v                        print version\n"
 
266
" -C <number>               specify the number of cylinders\n"
 
267
" -H <number>               specify the number of heads\n"
 
268
" -S <number>               specify the number of sectors per track\n"
 
269
"\n");
266
270
                        break;
267
271
                case unable_to_open:
268
272
                        snprintf(error, sizeof(error),
294
298
 
295
299
        fputc('\n', stderr);
296
300
        fputs(message, stderr);
297
 
        exit(1);
 
301
        exit(rc);
298
302
}
299
303
 
300
304
static void
637
641
        return val;
638
642
}
639
643
 
640
 
#define alignment_required      (io_size != sector_size)
 
644
#define alignment_required      (grain != sector_size)
641
645
 
642
646
static int
643
647
lba_is_aligned(unsigned long long lba)
644
648
{
645
 
        unsigned long long bytes, phy_sectors;
646
 
 
647
 
        bytes = lba * sector_size;
648
 
        phy_sectors = bytes / io_size;
649
 
 
650
 
        return (alignment_offset + (phy_sectors * io_size) == bytes);
 
649
        unsigned int granularity = max(phy_sector_size, min_io_size);
 
650
        unsigned long long offset = (lba << 9) & (granularity - 1);
 
651
 
 
652
        return !((granularity + alignment_offset - offset) & (granularity - 1));
651
653
}
652
654
 
653
655
#define ALIGN_UP        1
657
659
static unsigned long long
658
660
align_lba(unsigned long long lba, int direction)
659
661
{
660
 
        unsigned long long sects_in_phy, res;
 
662
        unsigned long long res;
661
663
 
662
664
        if (lba_is_aligned(lba))
663
 
                return lba;
664
 
 
665
 
        sects_in_phy = io_size / sector_size;
666
 
 
667
 
        if (lba < sects_in_phy)
668
 
                /* align to the first physical sector */
669
 
                res = sects_in_phy;
670
 
 
671
 
        else if (direction == ALIGN_UP)
672
 
                res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy;
673
 
 
674
 
        else if (direction == ALIGN_DOWN)
675
 
                res = (lba / sects_in_phy) * sects_in_phy;
676
 
 
677
 
        else /* ALIGN_NEAREST */
678
 
                res = ((lba + sects_in_phy/2) / sects_in_phy) * sects_in_phy;
679
 
 
680
 
        if (alignment_offset)
681
 
                /*
682
 
                 * apply alignment_offset
683
 
                 *
684
 
                 * On disk with alignment compensation physical blocks start
685
 
                 * at LBA < 0 (usually LBA -1). It means we have to move LBA
686
 
                 * according the offset to be on the physical boundary.
687
 
                 */
688
 
                res -= (io_size - alignment_offset) / sector_size;
689
 
 
690
 
        /* fprintf(stderr, "LBA %llu -align-> %llu (%s)\n", lba, res,
691
 
         *                      lba_is_aligned(res) ? "OK" : "FALSE");
692
 
         */
 
665
                res = lba;
 
666
        else {
 
667
                unsigned long long sects_in_phy = grain / sector_size;
 
668
 
 
669
                if (lba < sector_offset)
 
670
                        res = sector_offset;
 
671
 
 
672
                else if (direction == ALIGN_UP)
 
673
                        res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy;
 
674
 
 
675
                else if (direction == ALIGN_DOWN)
 
676
                        res = (lba / sects_in_phy) * sects_in_phy;
 
677
 
 
678
                else /* ALIGN_NEAREST */
 
679
                        res = ((lba + sects_in_phy / 2) / sects_in_phy) * sects_in_phy;
 
680
 
 
681
                if (alignment_offset && !lba_is_aligned(res) &&
 
682
                    res > alignment_offset / sector_size) {
 
683
                        /*
 
684
                         * apply alignment_offset
 
685
                         *
 
686
                         * On disk with alignment compensation physical blocks starts
 
687
                         * at LBA < 0 (usually LBA -1). It means we have to move LBA
 
688
                         * according the offset to be on the physical boundary.
 
689
                         */
 
690
                        /* fprintf(stderr, "LBA: %llu apply alignment_offset\n", res); */
 
691
                        res -= (max(phy_sector_size, min_io_size) -
 
692
                                        alignment_offset) / sector_size;
 
693
 
 
694
                        if (direction == ALIGN_UP && res < lba)
 
695
                                res += sects_in_phy;
 
696
                }
 
697
        }
 
698
 
 
699
        /***
 
700
         fprintf(stderr, "LBA %llu (%s) --align-(%s)--> %llu (%s)\n",
 
701
                                lba,
 
702
                                lba_is_aligned(lba) ? "OK" : "FALSE",
 
703
                                direction == ALIGN_UP ?   "UP     " :
 
704
                                direction == ALIGN_DOWN ? "DOWN   " : "NEAREST",
 
705
                                res,
 
706
                                lba_is_aligned(res) ? "OK" : "FALSE");
 
707
        ***/
693
708
        return res;
694
709
}
695
710
 
742
757
}
743
758
 
744
759
static void
745
 
warn_cylinders(void) {
746
 
        if (dos_label && cylinders > 1024 && !nowarn)
747
 
                fprintf(stderr, _("\n"
748
 
"The number of cylinders for this disk is set to %d.\n"
749
 
"There is nothing wrong with that, but this is larger than 1024,\n"
750
 
"and could in certain setups cause problems with:\n"
751
 
"1) software that runs at boot time (e.g., old versions of LILO)\n"
752
 
"2) booting and partitioning software from other OSs\n"
753
 
"   (e.g., DOS FDISK, OS/2 FDISK)\n"),
754
 
                        cylinders);
755
 
}
756
 
 
757
 
static void
758
760
warn_limits(void) {
759
761
        if (total_number_of_sectors > UINT_MAX && !nowarn) {
760
762
                int giga = (total_number_of_sectors << 9) / 1000000000;
774
776
 
775
777
static void
776
778
warn_alignment(void) {
777
 
        if (nowarn || !alignment_required)
 
779
        if (nowarn)
778
780
                return;
779
781
 
780
 
        fprintf(stderr, _("\n"
 
782
        if (sector_size != phy_sector_size)
 
783
                fprintf(stderr, _("\n"
781
784
"The device presents a logical sector size that is smaller than\n"
782
 
"the optimal I/O size (often physical sector size). Aligning to a optimal\n"
783
 
"I/O size boundary is recommended, or performance may be impacted.\n\n"));
784
 
 
785
 
        /*
786
 
         * Print warning when sector_offset is not aligned for DOS mode
787
 
         */
788
 
        if (alignment_offset == 0 && dos_compatible_flag &&
789
 
            !lba_is_aligned(sector_offset))
790
 
 
791
 
                fprintf(stderr, _(
792
 
"WARNING: The device does not provide compensation (alignment_offset)\n"
793
 
"for DOS-compatible partitioning, but DOS-compatible mode is enabled.\n"
794
 
"Use command 'c' to switch-off DOS mode.\n\n"));
795
 
 
796
 
        if (display_in_cyl_units)
797
 
                fprintf(stderr, _(
798
 
"It's recommended to change display units to sectors (command 'u').\n\n"));
 
785
"the physical sector size. Aligning to a physical sector (or optimal\n"
 
786
"I/O) size boundary is recommended, or performance may be impacted.\n"));
 
787
 
 
788
        if (dos_compatible_flag) {
 
789
                fprintf(stderr, _("\n"
 
790
"WARNING: DOS-compatible mode is deprecated. It's strongly recommended to\n"
 
791
"         switch off the mode (command 'c')"));
 
792
 
 
793
                if (display_in_cyl_units)
 
794
                        fprintf(stderr, _(" and change display units to\n"
 
795
"         sectors (command 'u').\n"));
 
796
                else
 
797
                        fprintf(stderr, ".\n");
 
798
 
 
799
         } else if (display_in_cyl_units)
 
800
                fprintf(stderr, _("\n"
 
801
"WARNING: cylinders as display units are deprecated. Use command 'u' to\n"
 
802
"         change units to sectors.\n"));
799
803
 
800
804
}
801
805
 
961
965
#ifdef HAVE_LIBBLKID_INTERNAL
962
966
        blkid_probe pr;
963
967
 
964
 
        if (user_set_sector_size)
965
 
                return;
966
968
        pr = blkid_new_probe();
967
969
        if (pr && blkid_probe_set_device(pr, fd, 0, 0) == 0) {
968
970
                blkid_topology tp = blkid_probe_get_topology(pr);
969
971
 
970
972
                if (tp) {
 
973
                        min_io_size = blkid_topology_get_minimum_io_size(tp);
971
974
                        io_size = blkid_topology_get_optimal_io_size(tp);
 
975
                        phy_sector_size = blkid_topology_get_physical_sector_size(tp);
 
976
                        alignment_offset = blkid_topology_get_alignment_offset(tp);
 
977
 
 
978
                        /* We assume that the device provides topology info if
 
979
                         * optimal_io_size is set or alignment_offset is set or
 
980
                         * minimum_io_size is not power of 2.
 
981
                         *
 
982
                         * See also update_sector_offset().
 
983
                         */
 
984
                        if (io_size || alignment_offset ||
 
985
                            (min_io_size & (min_io_size - 1)))
 
986
                                has_topology = 1;
972
987
                        if (!io_size)
973
 
                                io_size = blkid_topology_get_minimum_io_size(tp);
974
 
                        alignment_offset = blkid_topology_get_alignment_offset(tp);
 
988
                                /* optimal IO is optional, default to minimum IO */
 
989
                                io_size = min_io_size;
975
990
                }
976
991
        }
977
992
        blkid_free_probe(pr);
978
993
#endif
979
994
 
980
995
        if (user_set_sector_size)
981
 
                ;
982
 
        else if (blkdev_get_sector_size(fd, &arg) == 0)
 
996
                /* fdisk since 2.17 differentiate between logical and physical
 
997
                 * sectors size. For backward compatibility the
 
998
                 *    fdisk -b <sectorsize>
 
999
                 * changes both, logical and physical sector size.
 
1000
                 */
 
1001
                phy_sector_size = sector_size;
 
1002
 
 
1003
        else if (blkdev_get_sector_size(fd, &arg) == 0) {
983
1004
                sector_size = arg;
984
1005
 
 
1006
                if (!phy_sector_size)
 
1007
                        phy_sector_size = sector_size;
 
1008
        }
 
1009
 
 
1010
        if (!min_io_size)
 
1011
                min_io_size = phy_sector_size;
985
1012
        if (!io_size)
986
 
                io_size = sector_size;
 
1013
                io_size = min_io_size;
987
1014
 
988
1015
        if (sector_size != DEFAULT_SECTOR_SIZE)
989
1016
                printf(_("Note: sector size is %d (not %d)\n"),
1041
1068
void
1042
1069
update_sector_offset(void)
1043
1070
{
1044
 
        if (dos_compatible_flag) {
1045
 
                /* usually 63 sectors for classic geometry */
1046
 
                sector_offset = sectors;
 
1071
        grain = io_size;
1047
1072
 
1048
 
                /* On the disks with alignment_offset the default geo.sectors
1049
 
                 * has to be aligned to physical block boundary. Check it!
1050
 
                 */
1051
 
                if (sectors && alignment_offset && !lba_is_aligned(sectors))
1052
 
                        fprintf(stderr, _(
1053
 
                "\nWARNING: the device provides alignment_offset, but the offset does not\n"
1054
 
                "match with device geometry.\n\n"));
1055
 
        } else {
 
1073
        if (dos_compatible_flag)
 
1074
                sector_offset = sectors;        /* usually 63 sectors */
 
1075
        else {
1056
1076
                /*
1057
 
                 * Align the begin of the first partition to the physical block
 
1077
                 * Align the begin of partitions to:
 
1078
                 *
 
1079
                 * a) topology
 
1080
                 *  a2) alignment offset
 
1081
                 *  a1) or physical sector (minimal_io_size, aka "grain")
 
1082
                 *
 
1083
                 * b) or default to 1MiB (2048 sectrors, Windows Vista default)
 
1084
                 *
 
1085
                 * c) or for very small devices use 1 phy.sector
1058
1086
                 */
1059
 
                unsigned long long  x = io_size / sector_size;
1060
 
 
1061
 
                sector_offset = align_lba(x, ALIGN_UP);
 
1087
                unsigned long long x = 0;
 
1088
 
 
1089
                if (has_topology) {
 
1090
                        if (alignment_offset)
 
1091
                                x = alignment_offset;
 
1092
                        else if (io_size > 2048 * 512)
 
1093
                                x = io_size;
 
1094
                }
 
1095
                /* default to 1MiB */
 
1096
                if (!x)
 
1097
                        x = 2048 * 512;
 
1098
 
 
1099
                sector_offset = x / sector_size;
 
1100
 
 
1101
                /* don't use huge offset on small devices */
 
1102
                if (total_number_of_sectors <= sector_offset * 4)
 
1103
                        sector_offset = phy_sector_size / sector_size;
 
1104
 
 
1105
                /* use 1MiB grain always when possible */
 
1106
                if (grain < 2048 * 512)
 
1107
                        grain = 2048 * 512;
 
1108
 
 
1109
                /* don't use huge grain on small devices */
 
1110
                if (total_number_of_sectors <= (grain * 4 / sector_size))
 
1111
                        grain = phy_sector_size;
1062
1112
        }
1063
1113
}
1064
1114
 
1249
1299
                }
1250
1300
        }
1251
1301
 
1252
 
        warn_cylinders();
1253
1302
        warn_geometry();
1254
1303
        warn_limits();
1255
1304
        warn_alignment();
1751
1800
        unsigned int lbc, lbh, lbs;     /* logical beginning c, h, s */
1752
1801
        unsigned int lec, leh, les;     /* logical ending c, h, s */
1753
1802
 
 
1803
        if (!dos_compatible_flag)
 
1804
                return;
 
1805
 
1754
1806
        if (!heads || !sectors || (partition >= 4))
1755
1807
                return;         /* do not check extended partitions */
1756
1808
 
1809
1861
}
1810
1862
 
1811
1863
static void
1812
 
check_alignment(struct partition *p, int partition)
 
1864
check_alignment(unsigned long long lba, int partition)
1813
1865
{
1814
 
        if (!lba_is_aligned(get_start_sect(p)))
1815
 
                printf(_("Partition %i does not start on optimal I/O size boundary.\n"),
 
1866
        if (!lba_is_aligned(lba))
 
1867
                printf(_("Partition %i does not start on physical sector boundary.\n"),
1816
1868
                        partition + 1);
1817
1869
}
1818
1870
 
1839
1891
               str_units(PLURAL),
1840
1892
               units_per_sector, sector_size, units_per_sector * sector_size);
1841
1893
 
1842
 
        printf(_("Sector size (logical / optimal IO): %u bytes / %lu bytes\n"),
1843
 
                                sector_size, io_size);
 
1894
        printf(_("Sector size (logical/physical): %u bytes / %lu bytes\n"),
 
1895
                                sector_size, phy_sector_size);
 
1896
        printf(_("I/O size (minimum/optimal): %lu bytes / %lu bytes\n"),
 
1897
                                min_io_size, io_size);
1844
1898
        if (alignment_offset)
1845
1899
                printf(_("Alignment offset: %lu bytes\n"), alignment_offset);
1846
1900
        if (dos_label)
2051
2105
/* type name */         (type = partition_type(p->sys_ind)) ?
2052
2106
                        type : _("Unknown"));
2053
2107
                        check_consistency(p, i);
2054
 
                        check_alignment(p, i);
 
2108
                        check_alignment(get_partition_start(pe), i);
2055
2109
                }
2056
2110
        }
2057
2111
 
2086
2140
                                (unsigned long) get_nr_sects(p), p->sys_ind);
2087
2141
                        if (p->sys_ind) {
2088
2142
                                check_consistency(p, i);
2089
 
                                check_alignment(p, i);
 
2143
                                check_alignment(get_partition_start(pe), i);
2090
2144
                        }
2091
2145
                }
2092
2146
        }
2164
2218
                p = pe->part_table;
2165
2219
                if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
2166
2220
                        check_consistency(p, i);
2167
 
                        check_alignment(p, i);
 
2221
                        check_alignment(get_partition_start(pe), i);
2168
2222
                        if (get_partition_start(pe) < first[i])
2169
2223
                                printf(_("Warning: bad start-of-data in "
2170
2224
                                        "partition %d\n"), i + 1);
2273
2327
 
2274
2328
        snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2275
2329
        do {
2276
 
                unsigned long long dflt, dflt_tmp;
 
2330
                unsigned long long dflt, aligned;
2277
2331
 
2278
2332
                temp = start;
2279
 
 
2280
2333
                dflt = start = get_unused_start(n, start, first, last);
2281
2334
 
2282
2335
                /* the default sector should be aligned and unused */
2283
2336
                do {
2284
 
                        dflt_tmp = align_lba_in_range(dflt, start, limit);
2285
 
                        dflt = get_unused_start(n, dflt_tmp, first, last);
2286
 
                } while (dflt != dflt_tmp && dflt > dflt_tmp && dflt < limit);
 
2337
                        aligned = align_lba_in_range(dflt, dflt, limit);
 
2338
                        dflt = get_unused_start(n, aligned, first, last);
 
2339
                } while (dflt != aligned && dflt > aligned && dflt < limit);
2287
2340
 
2288
2341
                if (dflt >= limit)
2289
2342
                        dflt = start;
2632
2685
                                         _("Number of cylinders"));
2633
2686
                        if (sun_label)
2634
2687
                                sun_set_ncyl(cylinders);
2635
 
                        if (dos_label)
2636
 
                                warn_cylinders();
2637
2688
                        break;
2638
2689
                case 'd':
2639
2690
                        print_raw();
2830
2881
        bindtextdomain(PACKAGE, LOCALEDIR);
2831
2882
        textdomain(PACKAGE);
2832
2883
 
2833
 
        /*
2834
 
         * Calls:
2835
 
         *  fdisk -v
2836
 
         *  fdisk -l [-b sectorsize] [-u] device ...
2837
 
         *  fdisk -s [partition] ...
2838
 
         *  fdisk [-b sectorsize] [-u] device
2839
 
         *
2840
 
         * Options -C, -H, -S set the geometry.
2841
 
         *
2842
 
         */
2843
 
        while ((c = getopt(argc, argv, "b:C:H:lsS:uvV")) != -1) {
 
2884
        while ((c = getopt(argc, argv, "b:cC:hH:lsS:uvV")) != -1) {
2844
2885
                switch (c) {
2845
2886
                case 'b':
2846
2887
                        /* Ugly: this sector size is really per device,
2857
2898
                case 'C':
2858
2899
                        user_cylinders = atoi(optarg);
2859
2900
                        break;
 
2901
                case 'c':
 
2902
                        dos_compatible_flag = 0;
 
2903
                        break;
 
2904
                case 'h':
 
2905
                        fatal(help);
 
2906
                        break;
2860
2907
                case 'H':
2861
2908
                        user_heads = atoi(optarg);
2862
2909
                        if (user_heads <= 0 || user_heads > 256)
2942
2989
 
2943
2990
        if (argc-optind == 1)
2944
2991
                disk_device = argv[optind];
2945
 
        else if (argc-optind != 0)
 
2992
        else
2946
2993
                fatal(usage);
2947
 
        else
2948
 
                fatal(usage2);
2949
2994
 
2950
2995
        gpt_warning(disk_device);
2951
2996
        get_boot(fdisk);