Update 10-14-2011: I should add a note that as Arch Linux is rolling release and constantly changing, these instructions are likely out of date. I do not know for sure, as I have not had a need to re-install my machine. As a silver-lining to this though, I can attest that this setup has been quite stable and reliable–even despite a few mistakes with my battery meter…

Update 4-2-2011: I just got through following my own guide to setup my desktop with a btrfs root, and noticed a few things here that needed updating or were wrong, or missing, and such. This should be more accurate now.

I was recently gifted with a 40GB Intel X25-V SSD (one of those things I really wanted, but wouldn’t buy for myself) and after sitting on it for a month, pouring over blogs and wiki articles about SSD’s, trying to determine how I wanted to set it up, I finally got around to it over the past few days. My two main sources of info are the very informative Arch Linux wiki page on SSD optimizations, along with a blog post on GPT booting. I also referenced this wiki page, but ended up doing some things differently. I decided I wanted to partition it with GPT, and use btrfs as the main filesystem, despite it’s “unstable” status. I wanted GPT because it’s more “modern” than the legacy MBR scheme, but mostly I went with it because it was the default mode for gdisk, which also aligned my partitions to that magic multiple of 1MB. (I realize fdisk can do this, but didn’t want to deal with wacky sector math :P) I wanted btrfs because it too was more “modern.” What really grabbed me, and ultimately made me switch to using it in place of ext4, was the subvolume feature. Instead of separate partitions for major directories, I could use subvolumes with disk quotas. This would allow me to just let btrfs consume the whole disk, and let the filesystem and SSD handle the rest (mostly because I have no clue how the SSD wear protection routines handles multiple partitions, I decided to take them out of the equation :P) This setup does present a few problems, namely that GPT partitions need a protective MBR workaround to boot from legacy BIOS based computers–which describes every computer I own. Legacy Grub (the Arch Linux default) doesn’t support booting from GPT in this manner, and on top of that, only syslinux supports booting from a btrfs filesystem. Even then, it cannot handle subvolumes very well. Luckily, my setup didn’t need the more interesting uses of subvolumes/snapshots.

Preparation

If you’re doing this from the Arch Linux install disk like me, don’t forget to setup up your network (partial-configure-network) and uncomment a mirror in /etc/pacman.d/mirrorlist. You may also want to set the clock and proper timezone to be sure the dates are accurate.

Preparing the Disk

Make sure gptfdisk and btrfs-progs are installed (note, gptfdisk used to be called gdisk)

# pacman -Sy gptfdisk btrfs-progs-unstable

Partitioning

Now we’ll run gdisk and partition the drive

# gdisk /dev/sda GPT fdisk (gdisk) version 0.6.14 Partition table scan: MBR: not present BSD: not present APM: not present GPT: not present Creating new GPT entries. Command (? for help):

Now, create a new empty GPT partition table using ‘o’

Command (? for help): o This option deletes all partitions and creates a new protective MBR. Proceed? (Y/N): y

Now add partitions with ‘n’, entering the necessary info when prompted. For my setup I did a 1 MiB “BIOS boot” partition at the beginning, followed by another consuming the rest of the disk. This is necessary for GRUB2 to boot a GPT disk on a legacy BIOS system, and I left it here just in case GRUB2 supports btrfs sometime soon and (for whatever reason) I decide to switch. If you do decide to use GRUB2, you’ll need a separate /boot partition with a non-btrfs filesystem also.

Command (? for help): n Partition number (1-128, default 1): 1 First sector (34-78165360, default = 34) or {+-}size{KMGTP}: 34 Information: Moved requested sector from 34 to 2048 in order to align on 2048-sector boundaries. Use 'l' on the experts' menu to adjust alignment Last sector (2048-78165360, default = 78165360) or {+-}size{KMGTP}: +1M Current type is 'Linux/Windows data' Hex code or GUID (L to show codes, Enter = 0700): ef02 Changed type of partition to 'BIOS boot partition' Command (? for help): n Partition number (2-128, default 2): 2 First sector (4096-78165360, default = 4096) or {+-}size{KMGTP}: 4096 Last sector (4096-78165360, default = 78165360) or {+-}size{KMGTP}: 78165360 Information: Moved requested sector from 78165360 to 78165326 in order to align on 2048-sector boundaries. Use 'l' on the experts' menu to adjust alignment Current type is 'Linux/Windows data' Hex code or GUID (L to show codes, Enter = 0700): 0700 Changed type of partition to 'Linux/Windows data'

Now, the other thing we need to do is set the “legacy BIOS bootable” flag on our root partition, which we can do in gdisk by first entering expert mode with ‘x’, then edit attributes with ‘a’

Command (? for help): x Expert command (? for help): a Partition number (1-2): 2 Known attributes are: 0 - system partition 1 - hide from EFI 2 - legacy BIOS bootable 60 - read-only 62 - hidden 63 - do not automount Attribute value is 0000000000000000. Set fields are: No Fields Set Toggle which attribute field (0-63, 64 to exit): 2 Have enabled the 'legacy BIOS bootable' attribute. Attribute value is 0000000000000004. Set fields are: 2 (legacy BIOS bootable) Toggle which attribute field (0-63, 64 or <Enter> to exit):

Then write the partition table with ‘w’ and exit. If you’re like me and didn’t realize the legacy BIOS boot flag was necessary, you can apply the attribute using sgdisk (part of gptfdisk).

# sgdisk -A N:set:2 /dev/sdX

where N is your partition number (2 in my case) and X is your disk. See sgdisk man page for more info.

Formatting

You can now go ahead and format your disk in the usual manner

# mkfs.btrfs -L ArchSSD /dev/sda2

Normally, this is where you’d mount this to /mnt and go about the usual manual Arch Linux installation, but there is a better option. We can make a subvolume called ‘__active’ to function as our actual root directory. This allows us to snapshot our entire ‘/’ for backup purposes. Aside: The mkinitcpio-btrfs hook (available in the AUR) looks for a subvolume called ‘__active’ for some of it’s more advanced features, such as rollback support. Naming your subvolume this way allows you to use these features if you wish. To do so, first mount this filesystem to a temporary directory, then use the btrfs command to make a new subvolume and mount that to /mnt. The mount options I use are good defaults for a SSD: discard enables TRIM support (if your drive supports it) and ssd enables optimized operations for SSD (btrfs can autodetect this, but I ere on the thorough side :P)

# mkdir /broot && mount -o defaults,noatime,discard,ssd /dev/sda2 /broot # btrfs subvolume create /broot/__active # mount -o subvol=__active /dev/sda2 /mnt

Remember how I said syslinux doesn’t handle subvolumes well? Turns out syslinux cannot read in a subvolume to find /boot, so we need to make our /boot at the very root of the filesystem, and that means we need to bind it under our ‘__active’ subvolume, so that it appears in the expected place once the system is booted.

# mkdir /broot/boot /mnt/boot && mount --bind /broot/boot /mnt/boot

At this point, go ahead and add subvolumes for any directories you’d traditionally put on a separate partition. For me this was /home, /usr, and /var.

# btrfs subvolume create /broot/__active/home # btrfs subvolume create /broot/__active/usr # btrfs subvolume create /broot/__active/var

Due to the fact these are subvolumes under ‘__active’, as long as ‘__active’ is mounted there is no need to mount these subvolumes. This is because the people behind btrfs have designed subvolumes to be navigable as simple sub-directories (as long as you have btrfs-progs installed). The default permissions of the subvolumes is 0700, but the system should/pacman installs the filesystem with 0755, so you may want to change these now so it doens’t complain later.

# chmod -R 0755 /broot/__active

Installation

The next part is your typical manual Arch Linux installation (which will be familiar to those who have ever made their system unbootable and had to rollback an upgrade).

Installing the base system

The first step is to setup our /mnt as a working root directory in order to allow us to chroot into it. This involves making a /proc and /sys filesystem, as well as binding /dev.

# mkdir /mnt/proc /mnt/dev /mnt/sys # mount -o bind /dev /mnt/dev # mount -t sysfs none /mnt/sys # mount -t proc none /mnt/proc

With our chroot setup, we can now install the base packages, along with our bootloader and our filesystem utils.

# mkdir -p /mnt/var/lib/pacman # pacman -r /mnt -Sy base syslinux btrfs-progs-unstable --ignore grub

The -r option tells pacman to use a different root directory when performing operations. Note: For whatever reason, the ignore directive was not working for me, but grub can be uninstalled later. I realized this was a feature that had been removed, but now with pacman 3.5, it’s back and working as expected :]

Installing the bootloader

Installing syslinux is simple, as follows:

# mkdir /mnt/boot/syslinux (newer versions of the syslinux package include this directory) # chroot /mnt extlinux -i /boot/syslinux

The next step is copying the boot code into the MBR. Notice we use a special GPT mbr in this case.

# cat /mnt/usr/lib/syslinux/gptmbr.bin > /dev/sda

The last thing to do for the bootloader is to write the configuration file. Mine is a simple barebones config, but it is possible to do fancier ones with syslinux if you desire.

# nano /mnt/syslinux/extlinux.conf PROMPT 0 TIMEOUT 0 DEFAULT arch LABEL arch KERNEL /boot/vmlinuz26 INITRD /boot/kernel26.img APPEND root=/dev/sda2 rootflags=subvol=__active ro elevator=noop

This is pretty much a standard “no-frills” boot configuration. The only interesting things to note are the rootflags argument, telling it to mount the subvolume ‘__active’ as root, and the elevator argument is to switch the disk I/O scheduler, a small tweak for SSD performace. If you have other non-SSD drives then check out the SSD page on the Arch Linux wiki for more info about setting only certain drives.

Configuration

Almost done, now we just need to configure some of the base system to allow us to boot into our new system. First we need to write our /etc/fstab. For this part, I followed the wiki guide and had an entry to mount the filesystem’s root to /var/lib/(btrfs label) in order to be able to bind the /boot under our ‘/’ root. Just like before, we also mount our ‘__active’ subvolume as our filesystem ‘/’. The only other unique thing I do is to mount a new tmpfs to /tmp, in order to reduce some writes to the SSD. My final fstab follows:

devpts /dev/pts devpts defaults 0 0 shm /dev/shm tmpfs nodev,nosuid 0 0 /dev/sda2 / btrfs defaults,noatime,discard,ssd,subvol=__active 0 0 /dev/sda2 /var/lib/ArchSSD btrfs defaults,noatime,discard,ssd 0 0 /var/lib/ArchSSD/boot /boot none rw,bind 0 0 none /tmp tmpfs nodev,nosuid,noatime,noexec,mode=1777 0 0

Notice I have no swap partition, (swap on an SSD would kill it if it got used often) and for the moment I have no plans to add one; this laptop has 2 GB of ram, and I’ve barely scratched that with the normal day-to-day activities. I’ve contemplated setting up Compcache and/or using a sacrificial SD card, but as I run a majority of lightweight software, I doubt this will be necessary anytime soon. Lastly, edit your rc.conf (filling in timezone data in the very least), set your root password, and perhaps perform any special edits to mkinitcpio.conf or modprobe.conf. After that you’re ready to reboot and try out that new SSD.

# cd / # umount /mnt/{dev,proc,sys,boot} # umount /mnt # reboot

Other Configurations

I have also moved my browser caches into a tmpfs. The method I did this is not too different from the “Speed-up Firefox with tmpfs” page on the Arch wiki. Although, I usually use Chromium which places it’s cache in ~/.cache/chromium (the XDG standard location). As I could not find a setting to change this, I changed the directory :P I decided to put the whole ~/.cache into the tmpfs, and I did this by simply changing XDG_CACHE_HOME. To do so, just place something like this in your .bash_profile (or your other login shell’s profile)

export XDG_CACHE_HOME=/dev/shm/username/.cache if [ ! -f $XDG_CACHE_HOME ]; then mkdir -p -m 0700 $XDG_CACHE_HOME fi

The one problem with this, of course, is that this directory will be cleared once the computer is shutdown; ~/.cache is intended for non-persistent data, but if you have thumbnail caches and such you like to keep between shutdowns, you may want to either setup a syncing script similar to the one on the wiki page, or limit it to just the chromium subdirectory. Logout then log back in for the changes to take effect. Note, the directory pointed to by XDG_CACHE_HOME will probably be regenerated as needed by any [good] xdg compliant program, but just in case it isn’t, and also to make sure it has proper permissions (as it is in a globally accessible directory), we make it ourselves with the proper permissions.

The Result

Just a qualitative result, but I definitely notice an increase in boot speed and when starting X. Even though this particular drive has relatively “low” read/write speeds compared to other SSD (and my drive isn’t even hitting that limit, as I only have SATA I on this laptop). When starting X, all my autostart applications not only startup faster, but seem to start more concurrently, where as before they seemed to startup one after the other. This could just be the smaller delay between loading each program–I imagine the advantages I’m seeing are mostly due to the superior random read speeds of SSD vs HDD, coupled with the simpler noop I/O scheduler. This Intel SSD also has very low power consumption, and I will have to do some number crunching to see how much this drive actually uses compared to my old HDD with some similar tasks. Lastly, with no longer needing to worry about a head crashing on a platter, I carry this laptop like a book and move it around as I please :]

Acknowledgments

Special Thanks to my partner for spoiling me rotten ;]

42.375265 -72.518950