Building a Linux Media Network, one step at a time

Thursday, February 16, 2006

Setting up a Ramdisk

Wow, it's been a while since I've updated. I've been busy building the infrared receiver described here: I'll post more about that once I've got the last few kinks worked out and had a chance to take some pics of it.

For now, though, I'll describe how I've altered the Linux install to make use of a ramdisk for parts of the filesystem. A ramdisk is a section of memory that the operating system treats like a regular disk. One advantage of using a ramdisk instead of a physical disk is that it provides really, really fast read/write times. A big disadvantage is that anything that you write to a ramdisk gets obliterated when your computer shuts down.

I'm using a ramdisk in this situation because when I switch Fulcrum over to compact flash, I want it to treat the CF card as a read-only file system. But because applications expect to be able to write data to /var and /tmp, we need to provide some write capability. We will "graft" the ramdisk onto the root filesystem, and none of the applications will even know they're writing to a ramdisk.

The linux kernel creates a bunch of ramdisks as soon as it starts, and identifies them as separate devices in the /dev filesystem. Do an ls there and you can see them, labelled from /dev/ram0 to /dev/ram15 or so.

The kernel restricts the size of these ramdisks based on the ramdisk_size kernel parameter. The value of this parameter is measured in kilobytes, so to define a ramdisk of 128Mb you would pass this as a kernel parameter in the GRUB configuration file, menu.lst:
(131072 = 128 * 1024)

As far as I know, all ramdisks are created with the same size limit. If you know of a way to independently specify the size of each ramdisk, I would love to hear about it.

Let's deal with ram-ifying /var first. Obviously, the /var directory is full of important files and stuff. We want to:
  • Backup the whole damn thing
  • Save these files someplace safe
  • Empty out the /var directory
Then, on every boot:
  • Tell Linux to move the files from "someplace safe" to the ramdisk
  • Mount the ramdisk on /var
Here's a quick way to do the backup, presuming you have some unallocated space on your hard disk. In the example below, my OS is installed on /dev/hda2 and I've created a partition /dev/hda3 that is exactly the same size using fdisk -u. (Creating the backup target partition is pretty easy, it just takes a little adding and subtracting to determine the number of sectors and the end point of the partition)

# Do a byte-by-byte backup of /dev/hda2 to /dev/hda3
dd if=/dev/hda2 of=/dev/hda3 bs=16MB

Lastly, you can go into /boot/grub/menu.lst and clone the entries there to boot your new partition - or, you can just edit the existing entries by hand if you ever need to boot into that partition. Remember to change both the root(n,m) line and the root=/dev/hda(n) part of the GRUB entry.

Now that you've got a backup (hey - maybe test that it works, while you're at it), we can proceed with ram-ifying /var. Follow these commands:

#A flimsy way of "quieting" the system
#to prevent writes to /var while we work
init 1
#relocate the files
mv /var /var_orig
#create the new empty directory
mkdir /var
mkdir /mnt/rd
cd /etc/init.d
#create a script to do the work at every boot
cat setup_ramdisk << EOF
#! /bin/sh
echo "**** Initializing Ramdisk ****"
mkfs -V -t ext2 /dev/ram1
mount /dev/ram1 /mnt/rd
cp -a /var_orig/* /mnt/rd
umount /mnt/rd
mount /dev/ram1 /var
echo "Ramdisk Created"
# make it executable
chmod a+x setup_ramdisk
cd /etc/rcS.d
# make it run very early it the boot process
ln -s /etc/init.d/setup_ramdisk S03setup_ramdisk

The script that's embedded in those commands is actually what's responsible for most of the heavy-lifting (it's saved to /etc/init.d/setup_ramdisk). What it does is format the ramdisk using the ext2 file system, mount it to a temporary directory, copy all the stuff from the original /var directory, and then move the mount point from the temporary directory to /var.

At this point, double check that you've allowed for a big enough ramdisk in the kernel parameter. Do a df --si /var, grow that number by, say, 20%, and convert that to kilobytes and enter it into /boot/grub/menu.lst as described above.

Reboot, cross your fingers, and hopefully you won't even notice the difference!

If something goes wonky and your system won't boot, select your backed-up partition from the GRUB boot menu. Then mount the original parition and check for any mistakes. The messages during boot will tend to fly past before you can read them, so it may be very helpful to include a "sleep 60" command just after the "Ramdisk Created" line in the setup_ramdisk script.

I'm going to assume that everything has gone swimmingly and you've now got linux using a ramdisk for /var. The last step is to get it to use a ramdisk for /tmp as well.

I ran into a problem here. Because every ramdisk is the same size, and I need roughly 100Mb for /var, I didn't have enough free memory to create a whole new ramdisk for /tmp, which only needs a little bit anyways. The easiest workaround here is to just symbolically link /tmp to /var/tmp.

init 1
rm -rf /tmp
ln -s /var/tmp
chmod a+rw /tmp
chmod a+rw /var_orig/tmp

Make sure you get the permissions right, or nobody but root will be able to do very much.

Let me know how that works for you!


Post a Comment

<< Home