| Aligning an SSD on Linux |
|
|
| Written by Markus Ewald | |||
| Thursday, December 24 2009 20:38 | |||
|
I've got a small home server with a software RAID-5 for storing my files. It also runs a few virtual machines and acts as a NAT router for internet access. Nothing expensive, just some Frankensteinian patchwork built from old hardware left over when I upgraded my workstation. Nevertheless, I granted it a brand new Intel X25-M SSD last week.
Did I mention that this server is running Gentoo Linux? I thought this would be a good time to do a fresh install and get everything right that might have gone wrong the first time. Besides, installing Linux always is an interesting (and masochistic) experience, especially when your chosen distribution has no installer :) Because getting my partitions and file systems aligned also proved to be difficult task, I thought why not make a small article out of this! Erase Block SizeSSDs always operate on entire blocks of memory. This is so because, before writing to a memory cell, flash memory needs to be erased, which requires the application of a large voltage to the memory cells, which can only happen to an entire memory cell block at once (probably because this kind of power would affect other cells around the one being erased, at least that's my guess.) Anyway, this means that if you write 1 KB of data to an SSD with an erase block size of 128 KB, the SSD needs to read 127 KB from the target block, erase the block and write the old data plus the new data back into the block. That's something one just has to accept when using an SSD. Modern SSD firmware will do its best to pre-erase blocks when it's idle and try to write new data into these pre-erased blocks (by mapping data to other locations on the drive without the knowledge of the OS.) Still, watch what happens if a file system just sees the SSD as a brick of memory and writes data at a random position:
The SSD now has to erase and write two blocks, even though one would have sufficed for the amount of data being written. To fix this, the drive's firmware would have to do data mapping on the byte level, which likely isn't going to happen (in the worst case, you would need more memory for the remapping table than the drive's capacity!) If the file system's write was aligned to a multiple of the SSD's erase block size, the result would be this:
Thus, it's generally a good idea to make sure your file system's writes are aligned to multiples of your SSD's erase block size. As I found out, this isn't quite as easy as it sounds. The first road block is already encountered when you partition a hard drive: Partition AlignmentIf the partitions of a hard drive aren't aligned to begin at multiples of 128 KiB, 256 KiB or 512 KiB (depending on the SSD used), aligning the file system is useless because everything is skewed by the start offset of the partition. Thus, the first thing you have to take care of is aligning the partitions you create.
Traditionally, hard drives were addressed by indicating the cylinder, head and sector at which data was to be read or written. These represented the radial position, the drive head (= platter and side) and the axial position of the data respectively. With LBA (logical block addressing), this is no longer the case. Instead, the entire hard drive is addressed as one continuous stream of data. Linux' fdisk, however, still uses a virtual C-H-S system where you can define any number of heads and sectors yourself (the cylinders are calculated automatically from the drive's capacity), with partitions always starting and ending at intervals of heads x cylinders. Thus, you need to choose a number of heads and sectors of which the SSD's erase block size is a multiple. I found two posts which detail this process: Aligning Filesystems to an SSD's Erase Block Size and Partition alignment for OCZ Vertex in Linux. The first one recommends 224 heads and 56 sectors, but I can't quite understand where those numbers come from, so I used the advice from the post on the OCZ forums with 32 heads and 32 sectors which means fdisk uses a cylinder size of 1024 bytes. And because fdisk partitions in units of 512 cylinders (= 512 x heads x sectors) fdisk's unit size now happens to be an SSD's maximum erase block size. Nice! To make fdisk use 32 heads and 32 sectors, remove all partitions from a hard drive and then launch fdisk with the following command line when you create the first partition: The OCZ post also recommends starting at the second 512-cylinder unit because the first partition is otherwise shifted by one track. Don't ask me why :) Here's how I partitioned my SSD in the end:
For a normal hard drive, I'd probably use 128 heads and 32 tracks now to achieve 4 KiB boundaries for my partitions. RAID Chunk SizeIf you plan on running a software RAID array, I've seen chunk sizes of 64 KiB and 128 KiB being recommended. This can be specified using the --chunk parameter for mdadm, eg. Probably the larger chunk size is more useful if you are storing large files on the RAID partition, but I haven't found any advice which included benchmarks or at least a solid explanation yet. File System AlignmentNow that the partitions have been taken care of, the file systems need to use proper alignment as well. Generally all file systems use some kind of allocation blocks, usually with a size of 4 KiB. But increasing this size to 128 KiB (or even 512 KiB) would waste a lot of space since any file would use up memory in a multiple of that number. Luckily, Linux file systems can be tweaked a lot. I'm using ext4, here the -E stride,stripe-width parameters control the alignment. The HowTos/Disk Optimization page in the CentOS wiki gives this advice:
The Linux Kernel RAID wiki offers further insight:
So these are the stride and stripe-width parameters I'd use:
Thus, I set up the file systems on the Intel SSD like this: mkfs.ext4 defaulted to 1024 byte allocation units on my boot partition, so I adjusted the stride up to 128 KiB according to the advice from the CentOS wiki. The alignment of my boot partition is probably not of any relevance because the system will read maybe 10 files from it and not modify anything, but I wanted to stay consistent :)
|




Comments
Quote:
Because the first sector (512bytes) is Master Boot Record and cannot be part of the first partition.
fdisk /dev/sda -u -c
I don't know what -c does (and neither does my fdisk ;-)), but here's fdisk -u -l /dev/sda for you:
Usage:
fdisk [options] change partition table
fdisk [options] -l list partition table(s)
fdisk -s give partition size(s) in blocks
Options:
-b sector size (512, 1024, 2048 or 4096)
-c switch off DOS-compatible mode
-h print help
-u give sizes in sectors instead of cylinders
-v print version
-C specify the number of cylinders
-H specify the number of heads
-S specify the number of sectors per track
and, AFAIK, Intel based SSDs use 128 blocks of 4KB as errase block size, so it should be 512kB, just as OCZ:
http://www.anandtech.com/show/2614/3
http://www.xbitlabs.com/articles/storage/display/intel-x25m-ssd_2.html
please, correct me if I'm wrong.
I'm quite sure that the erase block size on Intel drives is 128 KB, not 512 KB. It's one of the features used by Intel to market their SSDs as superior to others (check this: techreport.com/articles.x/15433) - they say the smaller erase block size reduces write overhead, thereby increasing the drive's longevity.
I believe the first article you linked got it a bit wrong. The graph clearly says 4 KB write requires a 128 KB erase (= write amplification of 32), but then the text from the article incorrectly states that 16 KB write would require a 512 KB erase, assuming the write amplification to be a static property of the drive. The write amplification in this case would be 8. And for a 128 KB write, it would be 1.
This is closest so far:
http://forums.anandtech.com/showthread.php?t=2069082
This is wrong, or at least misleading from what you said earlier.
Chunk size is typically reported in bytes (or kilobytes). For example, a 64 KiB chunk size.
stride is the number of blocks in a chunk size. For a block size of 4 KiB, this is 64/4 = 16.
Likewise for stripe-width, it is the number of blocks in a stripe width. This is 16*number of data disks.
I've been trying to add correct information the Linux RAID wiki: https://raid.wiki.kernel.org/index.php/RAID_setup which should be considered the authoritative source on the subject.
mkfs.ext4 -b 4096 -E stride=32 -E stripe-width=32 /dev/sda3
will give you 0 blocks stride with 32 stripe width as can be observed by the output on screen after entering the command.
The correct command I needed to enter in order to get 32 stride with 32 stripe width is:
mkfs.ext4 -b 4096 -E stride=32,stripe-width=32 /dev/sda3
@Samat Jain: Wow, I din't even didn't know the kernel team had a wiki for the raid modules. Thanks for the link. I fixed the formula and also quoted the relevant section from the kernel raid wiki.
@clesch: Whoops. That's unexpected. I changed the commands to read the way you're using (and the kernel raid wiki does, too). Thanks for the clarification!
RSS feed for comments to this post.