Notice:

This page has been converted from a dynamic Wordpress article to a static HTML document. As a result, some content may missing or not rendered correctly.

Prolonging An SSD's Life By Mitigating Writes ~ Thu, 10 May 2012 02:00:46 +0000

Warning: The following details a process that is no longer supported. I do not yet have a replacement. (2012 November 13)

Last weekend, I updated my HTPC with all new hard drives and software. I had been putting it off because of an incompatibility between my IR receiver and the latest kernel drivers. But a couple weeks ago, I learned about the flirc device and immediately ordered one. Flirc doesn't require any complicated setup or special drivers to work. Therefore, I was free to perform my long overdue HTPC upgrade.

Anyway, the core of my upgrade is a 64GB Solid State Disk (SSD) for the operating system. Since SSDs have a fixed lifespan (baring disaster), I want to limit the number of writes done to the disk. Given that my HTPC has 4GB of RAM, that is mostly unused (even when watching HD content), I am able to limit writes to my SSD by using RAM based disks. In particular, I have offloaded my /tmp and /var/log directories to RAM.

Putting /tmp in RAM is pretty much a no-brainer. The data doesn't need to live across system boots so you can get away with using a tmpfs mount definition like so:

tmpfs /tmp tmpfs nodev,nosuid,size=1G 0 0

This definition limits my /tmp directory to 1GB in size and allows any user to read and write it.

The /var/log directory, however, is a bit trickier:

  1. General users should not be able to write to it.
  2. The data needs to be retained across system boots.
  3. It should be mounted beore anything writes to it.
  4. It should be unmounted at the last possible moment.

So, to solve problem #1, we can opt to use a ramfs mount (you can read about the difference between tmpfs and ramfs in the kernel documentation). Problems #2 -- #4 are where things get complicated. That is, unless you are using Arch Linux.

Arch Linux doesn't use the SysV init system. Arch has its own init system that is similar to BSD init systems. This init system includes "hooks" at key stages of the boot, and shutdown, process that can be used to solve problems 2, 3, and 4. You can read more about the hooks on the Arch Linux wiki. I'm merely going to explain my solution.

First, we need a place to store the data between boots. As another measure to prolong the life of my SSD, I opted to allocate a dedicated portion of my disk for the data store. I did this by creating a loopback image:

$ dd if=/dev/zero bs=1M count=512 of=/var/opt/var_log.img
$ chmod og-rw /var/opt/var_log.img # to prevent general users from snooping on it
$ mkfs.jfs /var/opt/var_log.img # fast recovery and restore

Having done this, I will always use the same blocks on my SSD for storing my /var/log data. Since they will only ever be written to at shutdown, these blocks will not be written to very often. And since the blocks are pre-allocated to this image, no other process will ever write to these blocks.

Next, I configured my mount definition:

none /var/log ramfs defaults,noatime,noauto 0 0

The key bit in this definition is the "noauto" option. This will prevent the init scripts from attempting to mount /var/log before I do.

Finally, I wrote two hooks to manage this ramdisk:

# mount /var/log to a ramdisk before starting any processes that use it

# Set to a disk image for storing the data when offline
IMG="/var/opt/var_log.img"

# A temporary mount point for saving and restoring (no trailing slash)
TMP_MOUNT="/var/tmp"

function restore_var {
  /bin/mount -o loop ${IMG} ${TMP_MOUNT}
  /bin/mount /var/log
  /usr/bin/rsync -a --delete ${TMP_MOUNT}/ /var/log/
  /bin/umount ${TMP_MOUNT}
}

add_hook sysinit_premount restore_var
# save /var/log to a loopback image before shutdown

# Set to a disk image for storing the data when offline
IMG="/var/opt/var_log.img"

# A temporary mount point for saving and restoring (no trailing slash)
TMP_MOUNT="/var/tmp"

function save_var {
  /bin/mount -o loop ${IMG} ${TMP_MOUNT}
  /usr/bin/rsync -a --delete /var/log/ ${TMP_MOUNT}
  /bin/umount ${TMP_MOUNT}
}

add_hook shutdown_preumount save_var

Technically, these hooks could reside in the same file. I opted to put them in separate files for clarity's sake.

Important Note:

Before you implement this, you should understand something very important. By storing /var/log in RAM, you could potentially lose all information in /var/log since the last system boot. This could happen if your machine somehow enters a state (freezes) such that you cannot go through the shutdown process. Also, you could miss a few messages at either system boot or system shutdown (although, I think this solution catches all important ones).

For an HTPC, that is behind a firewall, I don't see this as a problem. If I lose my logs, then I'm not really losing any important data. Sure, it'd be nice to have them to (hopefully) help diagnose the problem that cause the loss, but chances are it is some sort of failing hardware (e.g. the video card overheating). That, or an extended power loss.

If you really want to keep your logs. Then you should also send the messages to another syslog server on your network.

Addendum (10 May 2012):

Mentioned in a thread on the Arch Linux forums, there is a system daemon that does this. The daemon only uses tmpfs for RAM storage, and it syncs back to disk much more often, but it could make this much simpler if that's what you need.

Bash,  Code,  Linux,  Operating Systems,  Technology