A lot of people are switching their Windows machines to boot of solid state disk drives (SSDD) to get faster boot times. The price of these drives has been dropping, but since I use Linux (Kuuntu, actually, which is Ubuntu with KDE) it didn’t make much sense to me. I maybe reboot my machine once a month. What do I care if my reboot time is 30 seconds faster?
Fry’s had a 64GB SSDD on sale this week. After rebate it was around $85 after rebate (you can get roughly the same deal at Newegg). They had a 32GB drive (which had slower specs, too) for even less. So I couldn’t resist. The drive was for a laptop, but the SATA connectors fit. I bought a $4 pair of brackets to make it fit, but in the end since the thing doesn’t spin, I just let it sit on top of a drive tray — I’ll probably secure it later, but for now it is just sitting on the inside. I formatted the whole device with btrfs (no partitions at all) and sure enough I had about 59GB of useful space in a new volume.
I edited fstab to have the line:
UUID=f9f6588e-dc7f-4675-b132-8b008486d243 /ssdd1 btrfs defaults,ssd,noatime,discard
Of course, your UUID will vary. I had to create /ssdd1 as root and then I did a mount -a to put the drive in place. Now… how to make things go faster?
My basic idea was to copy stuff that KDE, X Windows, etc. uses a lot to the SSDD. I didn’t care so much about user files and I didn’t want the constant writing of /tmp or things from /var (in general) since SSDDs have some limit on write endurance (although modern drives do pretty well if you look into that). And I didn’t want to get messed up with things in /boot or things that I would need if the drive ever failed to mount (/bin, /sbin, and /lib, for example).
What I did was make exact copies of /usr/share, /usr/lib, /usr/bin and put them on /ssdd1/usr/share, and so forth. You have to make exact copies since some things in /usr/bin are suid — that is, they run as their owner and a normal cp won’t do the job (not without a lot of options; look at -p, for example). I used cpio:
find . -print | cpio -admp /ssdd1/usr/bin
Obviously, you need to be root to do that and you need to be in the /usr/bin directory. Once I had the directories in place, I had to move the old directories (I was too chicken to delete them) and link to the new one. Before you do that, though, I’d check that /usr/bin/sudo was in place on the SSDD and that its sticky bit was set. If you lose that and you have no root account set…. well… let’s not do that, ok?
Moving /usr/bin is a little tricky because you need to be root, but sudo is in /usr/bin! The easiest thing to do is just become root even though that angers the Ubuntu faithful:
Then you can do commands like the following:
mv /usr/bin /usr/bin-old ; ln -s /ssdd1/usr/bin /usr/bin
If things go wrong you can still get to things via /usr/bin-old. So if you do mess up you could do something like:
/usr/bin-old/sudo mv /usr/bin-old /usr/bin
That actually sped things up quite a bit. Booting is notably faster and the response time of X in general is greatly improved.
I then repeated the steps but this time I made shadow directories for ~/.config and ~/.kde. I redirected these to /ssdd1/home/alw/.config and /ssdd1/home/alw/.kde, respectively. This also made the system much snappier.
There are other ways you could have done this. I considered loop mounting over the existing directories, for example. This would be very safe since if the drive didn’t mount you’d just lose performance. The issue is you’d need to occasionally sync the real directory and the shadow directory to be sure any updates were applied. I had bad luck with a scheme like that for putting Firefox’s files into a ram drive — if it does get out of sync, look out. Of course, my scheme has a similar issue — if you lose the SSDD your old files are out of date. But with my setup there is no way for updates to occur to the old files (for example, if the SSDD fails to mount and you don’t notice) making them mismatched in both directions. You can rsync them from time to time, either way, but with my method if the SSDD fails to mount you will know it immediately. Also, the old files stay visible making syncing them easier if you care to do that.
Meanwhile, I’m happy with how fast this has made my system. Granted, it was fast to start with (8G of RAM, 3.6GHz, and 4 cores), but the system does boot much faster, Gimp loads almost immediately, and switching between tabs in Chrome is notably faster. Since the system files are just moved and not removed, this “update” is fairly safe — you can still get to the original files if you have to. Just remember that updates will not change the old copies.
UPDATE: Turns out Apparmor realizes that things aren’t in /usr/bin anymore and starts blocking things. The only thing I noticed was my printers (the CUPS daemon won’t start). You need to go to /etc/apparmor.d/tunables and edit the alias file. Then reload apparmor and reload affected services (or reboot, which is easier). Here’s mine:
alias /usr/bin/ -> /ssdd1/usr/bin/,
alias /usr/lib/ -> /ssdd1/usr/lib/,
alias /usr/share/ -> /ssdd1/usr/share/,
UPDATE #2: VirtualBox does not like /usr/lib as a symbolic link, I’m not sure why but the code specifically checks for this case and throws an error. I had thought about using bind mounts instead of symlinks before and this pushed me over the edge. So I still use the symlinks for stuff in my home directory but for /usr instead of creating bin, share, and lib links I created empty directories to use as mount points. Then in /etc/fstab I put:
/ssdd1/usr/bin /usr/bin bind defaults,bind 0 0
And similar lines for /usr/share and /usr/lib. Now Apparmor is happy and so is VirtualBox. I assume fstab mounts in order, so be sure those lines come AFTER the mount of /ssdd1, of course.
And one more update: Nepomuk and Strigi — which always give me grief anyway — write huge files to ~/.kde/share/apps/nepomuk/blah blah blah. This will quickly fill up a small SSDD. So one more link. I made ~/.nepomuk and then linked it in the ~/.kde tree. UNFORTUNATELY, filling up a btrfs volume causes it (at least in my case) to become totally unusable and unrepairable. So I would up switching everything to ext4. No compression, but better than having a total crash of the drive when it gets full.
After I had the crash I decided it would be nice if the regular hard drive had a pretty recent copy of what it was supposed to have. Since I had the space full crash about a week after I installed, it wasn’t so bad, but what if it had been a year or more later? Luckily, I had followed a simple pattern to replace the directories. Given some directory I wanted to replace called /x/y/z, I copy it to /ssdd1/x/y/z and then rename the original to /x/y/z-nossdd. Finally a bind mount or symlink points the original location at the SSDD.
Given that pattern, it was easy to create a daily cron job (/etc/cron.daily) named ssdd-backup:
for dir in /home/alw/.kde /opt/google /usr/bin /usr/share /usr/lib /usr/include /usr/lib32 /home/alw/.config /home/alw/.local
rsync --archive --update --quiet /ssdd1$dir/ $dir-nossdd
This runs every day early in the morning and ensure that the old directories get any updates. The update is NOT two way. If you change something in xxx-nossdd, that does not propagate to the SSDD (but why would you?). Of course, you’ll want to modify the first line to name the directories you actually shadowed.