An assortment of indigestible things

How to align partitions for best performance using parted

Some nicely aligned macaronsThere are two common problems when creating partitions in Linux on big storage arrays. The first is easy, and the warning message from fdisk is a bit of a giveaway:

WARNING: The size of this disk is 8.0 TB (7970004230144 bytes).
DOS partition table format can not be used on drives for volumes
larger than (2199023255040 bytes) for 512-byte sectors. Use parted(1) and GUID 
partition table format (GPT).

The answer: use parted. Don’t have it? Install it!

The second problem is this warning from parted:

(parted) mklabel gpt
(parted) mkpart primary 0 100%
Warning: The resulting partition is not properly aligned for best performance.
Ignore/Cancel?

…and no matter what combination of numbers you use, the message just keeps coming back. It’s tempting to ignore it, but don’t.

There are a few posts on the subject, but this one from HP really gets to the guts of the problem.

Here’s a quick step-by-step guide to aligning partitions properly. It’s just an abstraction of the HP post, but hopefully easier to follow. This will work for most arrays (in fact it works for all the arrays that I’ve seen); there are more options in HP’s post, but I’ve included the most common configuration here.

  1. Get the alignment parameters for your array (remember to replace sdb with the name of your device as seen by the kernel).
    # cat /sys/block/sdb/queue/optimal_io_size
    1048576
    # cat /sys/block/sdb/queue/minimum_io_size
    262144
    # cat /sys/block/sdb/alignment_offset
    0
    # cat /sys/block/sdb/queue/physical_block_size
    512
  2. Add optimal_io_size to alignment_offset and divide the result by physical_block_size. In my case this was (1048576 + 0) / 512 = 2048.
  3. This number is the sector at which the partition should start. Your new parted command should look like
    mkpart primary 2048s 100%

    The trailing ‘s’ is important: it tells parted that you’re talking about sectors, not bytes or megabytes.

  4. If all went well, the partition will have been created with no warnings. You can check the alignment thusly (replacing ‘1’ with the partition number if necessary):
    (parted) align-check optimal 1                                            
    1 aligned

As I alluded to before, there are cases where this won’t work: if optimal_io_size is zero, for example, there are other rules to follow. Of course it would be nice if parted could do this—the values are all available as ioctls, after all—but then what would I write about? 🙂

Previous

If the Church of England wants to be sexist, it should walk away from the Lords

Next

Another reason to dislike my MP (as if I needed one)

50 Comments

  1. This should be forwarded to the parted mailing list a a simple and effective way of calculating if there is a more user friendly suggestion that the ones parted currently makes.

  2. F2

    Very well done – thanks for doing this.

    One question: alignment offset should be in sectors according to my docs (never seen the value being other than 0) – that changes where the offset fits in your formula, does it not?

    (1048576 + 0) / 512 = 2048 should be
    1048576 / 512 + 0 = 2048
    Or did I get something wrong?

    Thanks for the excellent article! -F

    • jcg

      According to http://www.linuxtopia.org/online_books/rhel6/rhel_6_storage_admin/rhel_6_storage_newstorage-iolimits.html,
      alignment_offset = “Tthe number of BYTES that the beginning of the Linux block device (partition/MD/LVM device) is offset from the underlying physical alignment” (emphasis added)
      so his (1048576 + 0)/512 version should be correct.

      • F2

        According to
        http://www.novell.com/support/kb/doc.php?id=7007193
        if the drive reports any alignment offset, the Linux kernel in SLE11-SP1 (or later) will report this via the attribute /sys/block/$DEV/alignment_offset (in sectors).

        Reading the HP doc it looks like bytes as well. Kernel diving time!

        • jcg

          2 paragraphs down in the Novell doc, they link to a python script for calculating partition offsets – looking over the script, it appears to expect bytes as input from the alignment_offset file, but then it — the python script– reports the offset in sectors, so… reasonable probability that Novell just typo’ed in the main doc.

          Kernel diving, as you say, possibly the only way to really pin it down.

  3. Roger Dahl

    Apparently, using % causes parted to automatically align the sectors for best performance:

    (parted) mkpart primary ext4 0% 100%

  4. More information about parted available from redhat: http://people.redhat.com/msnitzer/docs/io-limits.txt

  5. Modeler

    Thanks for this. Agree with Roger Dahl about parted working it out for you. Here’s an awk one-liner that does the same:

    awk -v x=$(cat /sys/block/sdb/queue/optimal_io_size) -v y=$(cat /sys/block/sdb/alignment_offset) -v z=$(cat /sys/block/sdb/queue/physical_block_size) ‘BEGIN { print ( x + y ) / z }’

  6. steve-bc

    That is just what I was looking for. Thank you.

  7. Peter Knight

    parted has an alignment option
    -a optimal 1
    parted -s -a optimal /dev/sda mkpart primary 1 20000
    Gives the message not aligned etc but when I check
    align-check optimal 1
    I get aligned
    Why do I get the message and why does it have to be so complicatd ?
    Peter

    • The optimal feature only works when you’re using inexact units. By default parted uses Megabytes which is an inexact unit but that only allows +/- 500 KB of adjustment. On my system proper alignment requires over 1MB of adjustment. So using the default of ‘Compact’ or ‘MB’ will always throw an aliment warning. Specifying a larger unit also specifies a larger adjustment range I.E. ‘GB’ allows +/- 500 MB of adjustment. The percentage unit, by it’s nature, will always have enough range to allow proper adjustment

      If you use ‘”mkpart primary 0% 20GB” that should work.

  8. Excellent tip, thank you so much.

    I put it into a little python script if anyone is interested:
    https://raw.githubusercontent.com/MikeDacre/mike_tools/master/bin/get_optimum_drive_size.py

    Does the same thing as Modeler’s suggestion, but you can provide the device ID as an argument and it spits out the starting sector, e.g. `get_optimum_drive_size.py sbd`

    Thanks again!

  9. Prasad

    Gr8 document. Thanks for sharing

    Also checkout following site

    http://www.thomas-krenn.com/en/wiki/Partition_Alignment#Linux

  10. Nathan

    Unfortunately here are my results:
    optimal_io_size = 0
    minimum_io_size = 512
    alignment_offset = 0
    physical_block_size = 512

    So then the formula is 0 / something. Guessing this isn’t right. XenServer vm.

  11. anon

    Heh, I have the same problem as Nathan. Rackspace VM. Using “parted -a optimal” and “mkpart primary ext4 0% 100%” got me what I wanted.

  12. When I run the following command (as shown below), the result from optimal_io_size and alignment_offset are both 0 (zero) while the result from minimum_io_size and physical_block_size are both 512. This is for a new empty 128GB mSSD drive. The only thing that ended up working using the parted command was to use a starting sector of 2048s like you above. I’m confused though because my results differed so I’m still not sure why this is and why it worked – any additional insight would be much appreciated. I initially tried using a starting sector of 512s and 1024s but I still got errors with those so then I tried 2048s and only then was I able to run it without and errors.

    # cat /sys/block/sdb/queue/optimal_io_size 0 # cat /sys/block/sdb/queue/minimum_io_size 512 # cat /sys/block/sdb/alignment_offset 0 # cat /sys/block/sdb/queue/physical_block_size 512

  13. bill

    hello

    try this:

    parted < parted.txt

    # — parted.txt
    mktable gpt

    unit mib

    mkpart primary 1 3
    name 1 grub
    set 1 bios_grub on
    print

    mkpart primary 3 131
    name 2 boot

    mkpart logical 131 643
    name 3 swap

    mkpart logical 643 15643
    name 4 gentoo

    mkpart logical 15643 -1
    name 5 dat

    print
    quit

  14. Confirming that the math didn’t work out for me either.

    $ awk -v x=$(cat /sys/block/sdb/queue/optimal_io_size) -v y=$(cat /sys/block/sdb/alignment_offset) -v z=$(cat /sys/block/sdb/queue/physical_block_size) ‘BEGIN { print ( x + y ) / z }’
    0

    However when I used percentages it worked just fine.

    $ parted /dev/sde –script — mkpart primary 0% 100%
    $ parted /dev/sde –script — print
    Model: DELL PERC H710 (scsi)
    Disk /dev/sde: 600GB
    Sector size (logical/physical): 512B/512B
    Partition Table: msdos
    Disk Flags:

    Number Start End Size Type File system Flags
    1 1049kB 600GB 600GB primary

  15. me

    parted -a opt /dev/sdb mktable gpt
    parted -a opt /dev/sdb mkpart primary 0% 100%

    worked for me.

  16. Joe

    Hi,
    Anyways expand gpt disk (from VMWARE) without having to reboot to the (rhel)server?
    I am able to expand msdos partition tables without having to reboot (rhel)server

  17. hi, thanks for great article.

    unfortunately on a new Seagate external USB with 5TB size it didn’t work. actually cat /sys/block/sde/queue/optimal_io_size reported 33553920 which divided by 4096 yielded 8191,875!!

    i tried many things until i simply used optimal_io_size directly:

    mkpart ext4 33553920s 98%

    and this worked!! it resulted with a start sector at 17,2GB into the disk, but with 5TB this is managable.

    • John Drake

      My 1TB HGST external drive had the same parameters. My first assumption was to round up to a nice 8192 sector partition boundary, but parted was having none of that. Calling parted with the ‘-a optimal’ parameter and specifying a mkpart partition start of 0% resulted in parted starting the first partition at sector 65535.

      Although it seems odd that this isn’t a whole number of MiB, it is the first integer value arrived at when multiplying 8191.875 by 2, 3, 4 etc. So with a little luck you may be able to move the start of your first partition left and regain some of that wasted 17 Gb.

      Personally, I don’t like having to sacrifice even 30MiB to parted’s notion of optimal alignment. Gdisk is happy to align the same drive on 8-sector boundaries, which only satisfy parted’s minimal alignment check.

      • Rob

        Thanks, your answer helped proper alignment for my 1TB WD Blue (with 8GB SSHD) in an external USB3 connected enclosure. Starting on 65535s (33.6MB) was required and for setting the other partitions I had to use percentages in the (parted) mkpart command. This disc has to replace my internal one; I wonder whether after such a move things will change….

    • boothsama

      Thank you deViator.. ran into the same issue with the same drive. You saved me.

      mkpart xfs 524280s 100%

      Also works

      • Antus

        I hit the same values on a WD PURX 4T surveillance drive WDC WD40 PURX-78GVNY0

        # cat /sys/block/sda/queue/optimal_io_size
        33553920
        # cat /sys/block/sda/queue/minimum_io_size
        4096
        # cat /sys/block/sda/alignment_offset
        0
        # cat /sys/block/sda/queue/physical_block_size
        4096

        33553920/4096 = 8191.875. The awk script also rounds slightly, but the value is not usable anyway (neither is 8192 or 8191).

        What worked was:
        # parted -a opt /dev/sda mktable gpt
        # parted -a opt /dev/sda mkpart primary 0% 100%
        # parted /dev/sda align-check optimal 1
        1 aligned

  18. Daniel

    The link in the article is broken thanks to HP’s wonderful handling of their separation (into HP and HPE).

    This is probably the originally linked support article: http://h20564.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c03479326&DocLang=en&docLocale=en_US&jumpid=reg_r11944_uken_c-001_title_r0001

  19. boistordu

    I can’t apply what you said. the first line is 0 for me and it still says to me that I’m not aligned

  20. I’ve got a new 8TB drive, and have run into a situation where the optimal alignment calculated by parted doesn’t satisfy the minimal alignment tests, so various other tools that only check minimal alignment throw errors. Maybe I’m overthinking it, but it seems that if it doesn’t meet the minimal alignment it can’t really be the optimal alignment.

    — 8< —
    $ cat /sys/block/sdi/queue/optimal_io_size
    33553920
    $ cat /sys/block/sdi/queue/minimum_io_size
    4096
    $ cat /sys/block/sdi/queue/physical_block_size
    4096
    $ cat /sys/block/sdi/queue/logical_block_size
    512
    $ cat /sys/block/sdi/alignment_offset
    0
    — 8< —

    Parted calculates optimal alignment to 65535s, apparently aligning on logical blocks rather than physical blocks:

    — 8< —
    $ sudo parted /dev/sdi mkpart 8tb ext4 0% 100% unit s p free align-check min 1 align-check opt 1
    Model: Seagate Expansion Desk (scsi)
    Disk /dev/sdi: 15628053167s
    Sector size (logical/physical): 512B/4096B
    Partition Table: gpt
    Disk Flags:

    Number Start End Size File system Name Flags
    34s 65534s 65501s Free Space
    1 65535s 15628000379s 15627934845s ext4 8tb
    15628000380s 15628053133s 52754s Free Space

    1 not aligned
    1 aligned
    — 8< —

    Asking for minimal alignment, parted starts that partition on sector 40, which obviously doesn't pass align-check opt. Fdisk uses sector 2048, which passes parted's min check, but not opt. Frustrated at this point, I scale the 65535 parted calculated with 512b sectors to 4k sectors and make a partition starting at 524280s, which satisfies both of parted's alignment checks, and stops all the other tools complaining, at a cost of a few hundred MiB storage:

    — 8< —
    $ sudo parted /dev/sdi mkpart 8tb ext4 524280s 100% unit MiB p free align-check min 1 align-check opt 1
    Model: Seagate Expansion Desk (scsi)
    Disk /dev/sdi: 7630885MiB
    Sector size (logical/physical): 512B/4096B
    Partition Table: gpt
    Disk Flags:

    Number Start End Size File system Name Flags
    0.02MiB 256MiB 256MiB Free Space
    1 256MiB 7630860MiB 7630604MiB ext4 8tb
    7630860MiB 7630885MiB 25.8MiB Free Space

    1 aligned
    1 aligned
    — 8< —

    Now, certainly losing ~300MiB out of ~7.3TiB isn't an issue, but I wonder:

    a) was this exercise of any value,
    b) if so, is there a better way to solve for a starting sector that will satisfy both constraints, and
    c) if so, how hard is it going to be for me to patch parted to do the right thing here?

    Thoughts?

    • @Volta X comment is was in 2016. It is now 2022 and the problem still exists. parted uses one set and fdisk uses another set of criterial. I solved it like he did by giving up 524280 sectors.

  21. itengineer

    Thank you! I have been looking for this type of answer for quite sometime!!

  22. trs

    Thanks for this post, I’ve been here a number of times and looked this up.
    Today I was lazy and tried out a number of obvious values (1024s, 2048s, … up to 8 MiB) and kept getting “Warning: The resulting partition is not properly aligned for best performance.” from parted.
    Found this post again, did the maths and had to go all the way up to 65535s to get optimal alignment on my Samsung T5 SSD. That is 32MiB!
    Any updates here, is that still the correct way to calculate the minimum optimal offset?

  23. adsf

    Doesn’t work with drives in USB or other enclosures. Also if you remove the drive from the enclosure to get the proper drive info, and put the drive back in the enclosure and use parted with the right sector number, you’ll get an error message. Whereas if you use 0% and 100% while in the enclosure, parted will not throw an error. But then mkfs.ext4 will throw an error. Because parted isn’t smart enough to figure out that a usb drive enclosure lies.

    • peter9477

      I can confirm what adsf says, that with USB which can lie (not always… depends which hub/port/controller it’s on), either parted complains or mkfs complains. You probably can’t get them both to agree, at least with either the optimal/physical/etc math or with using percentages. In my case optimal_io_size is the bogus 33553920 as well, and with physical_block_size supposedly 4096 that results in 8191.875 sectors for the optimal alignment, an obvious impossibility. For now I’m telling parted to shut up (echo i | parted) and assuming mkfs knows what it’s doing better than parted does, but really I don’t know if anyone can know for such a case.

  24. I used “-a optimal mkpart primary ext4 0% 100%” and got this result. Any good ideas?

    Warning: You requested a partition from 0.00B to 4001GB (sectors
    0..7814037167).
    The closest location we can manage is 17.4kB to 1048kB (sectors 34..2047).
    Is this still acceptable to you?
    Yes/No? y
    Warning: The resulting partition is not properly aligned for best performance.
    Ignore/Cancel?

  25. Olivier LAHAYE

    Maybe a little bit out of date, but I’m hitting a problem.
    optimal_io_size = 262144
    aligment_offset = 0
    physical_block_size = 4096
    (262144 – 0) / 4096 = 64.

    If I use 64 as a start sector, parted complain. I must use 2048 to bypass this prolem.

    What I’m missing?

    PS: HP Links down.

  26. Lee

    In my case, I’m adding new virtual disks to a Photon OS VM and attempting to partition the newly-added VMDK. I get the “The resulting partition is not properly aligned for best performance.” warning, and arrived here trying to decide how critical the warning actually is. My optimal_io_size is 0, so I clicked your link to “there are other rules to follow”, and just thought I’d let you know that link appears to be dead.

    Other than that, thanks for the informative article. I’m still not done working through the warning, but you’ve been a helpful step in the process.

  27. Lee

    I took some time to read through the comments here, and I found what appears to be my solution. Thanks first to Roger Dahl and Peter Knight, my situation was similar to described by several people here who have a 0 optimal size (seems to be common with virtualization).

    I added “-a optimal” and learned that I could in fact use 0% 100% ranges instead of finding my exact start/stop values, and I no longer get this error. Thanks all, and hopefully this is also helpful to someone in the future.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Powered by WordPress & Theme by Anders Norén