Ramdisk: Implications
- Using a ramdisk is only useful when your application is IO bound, specifically to your hard disk. Unless you are sending thousands of messages over a fast fiber link, chances are that your primary limiter is the speed of your internet connection, and not the speed of your hard drive.
- Exim is already very good at handling large queues on 'slow' mediums such as hard disks; simply set the
split_spool_directory
in the config file and Exim will handle large queues more efficiently by splitting messages into subdirectories instead of a single spool directory.
- Spooling messages to a ramdisk poses the risk of loosing the entire queue in the event of a reboot or power outage, with no way to recover the queue.
- The spool directory can become quite massive, and you risk running out of space on the ramdisk partition very quickly. A few emails with large attachments could quite easily fill up even a sizable ramdisk. Similarly, messages which cannot be delivered immediately sit in the queue until they are successfully delivered, removed manually or expired by Exim, though this is a configurable setting in the Exim config file.
Ramdisk: Configuring a ramdisk
Many linux distros already have some preconfigured but unused ramdisks. Run the following command to list your current ramdisks:
ls /dev/ram*
To see the size allocation, use fdisk
in the standard fashion: (where X
is your ramdisk number)
fdisk -l /dev/ramX
You will probably want to increase the default space allocation. Since ramdisk size is controlled by the kernel, you will need to set a kernel option to increase the allocated space. If your bootloader is GRUB, you can edit the grub.conf
file and add the ramdisk_size
kernel option. Your GRUB config file should then look something like this: (in this example we're setting the ramdisk size to 256MB)
default 0
timeout 5
hiddenmenu
splashimage=(hd0,1)/boot/grub/splash.xpm.gz
title=Gentoo Gateway Server
root (hd0,1)
kernel /boot/vmlinuz root=/dev/sda2 ramdisk_size=256000
After a reboot your new ramdisks should reflect the updated space allocation. Since there is no point in formatting a ramdisk with a journalled filesystem, we'll just use ext2:
mke2fs -m 0 /dev/ram0
The -m 0
option keeps mke2fs from reserving any space on the file system for the root user. You can now create a mount point for the ramdisk, mount it, and begin using it.
mkdir /mnt/ramdisk
mount /dev/ram0 /mnt/ramdisk
df -h /dev/ram0
Additionally, make sure that you have the correct permissions set on the mountpoint (replace username and groupname with the correct group and user for your system):
chown -R username:groupname /mnt/ramdisk
You can now use this partition as though it were a standard hard disk partition. Note that if you unmount the partition, your data will not be lost, and the RAM will not be freed, since the kernel permanently allocates the required space until rebooted.
To automate this procedure, add the following into your /etc/rc.local
script:
/sbin/mke2fs -q -m 0 /dev/ram0
/bin/mount /dev/ram0 /mnt/ramdisk
/bin/chown username:groupname /mnt/ramdisk
/bin/chmod 0750 /mnt/ramdisk
Ramdisk: Exim configuration
You can do a bind mount so that Exim will continue to write to its standard spool directory. To do so, add the following line to your /etc/fstab
file:
/mnt/ramdisk /var/spool/exim none bind 0 0
Alternatively, you can just point Exim to the ramdisk mountpoint. To do so, you'll need to set the following in the exim.conf
file:
spool_directory = /mnt/ramdisk
Obviously you would only do either one of the aforementioned, not both.
A Better Solution: tmpfs
Instead of using a ramdisk, rather use tmpfs, supported by Linux kernel 2.4 and up. The benefit of using tmpfs is that memory is dynamically assignable, making it a far more flexible solution than ramdisks. Additionally, if your tmpfs partition runs out of space, the kernel will automatically begin paging data to your hard disk, whereas the ramdisk solution would simply cause Exim to stop processing messages and crash.
Using tmpfs, you won't need to do any of the of the steps required for the above ramdisk solution. The following steps are required for a successful tmpfs configuration:
Create a mountpoint and set correct permissions:
mkdir /mnt/tmpfs
chown -R username:groupname /mnt/tmpfs
Next, open your /etc/fstab
file and set the tmpfs partition to be created and mounted at boot:
#<fs> <mountpoint> <type> <opts> <dump/pass>
tmpfs /mnt/tmpfs tmpfs size=1G,nr_inodes=10k,mode=0700 0 0
This will create a 1GB tmpfs partition with 10'000 inodes. The exim configuration is the same as when creating a ramdisk - either tell Exim that the location of the new spool directory is located at /mnt/tmpfs
or bind the existing spool directory to the /mnt/tmpfs
mountpoint. Alternatively, you could just mount the tmpfs partition onto Exim's existing spool directory right from the start - so instead of the above changes to the /etc/fstab
file, use this line instead:
#<fs> <mountpoint> <type> <opts> <dump/pass>
tmpfs /var/spool/exim tmpfs size=1G,nr_inodes=10k,mode=0700 0 0
This site has a good article explaining tmpfs and ramdisks, and the differences between them.