Monthly Archives: March 2011

NFS Performance: rsize and wsize

NFS is supposed to be a very simple and fast network file protocol. However, when I tried to use it on my Xen box between a Debian Squeeze DomU and an NFS server running on the Debian Squeeze Dom0, I noticed that write performance was abysmal: any write more than a couple KB in size would not only slow down to a crawl, but also bog down the DomU, making it rather difficult to even cancel the write.

After some researching and testing, I tracked it down to the rsize and wsize mount options: they specify the size of the chunks sent at a single time. Apparently, they are set to 1M if you don’t specify anything else. In my case, wsize=131072 and rsize=262144 showed the highest write and read speeds respectively. However, wsize=131072 is not too far away from the cliff after which writing drops to a crawl, so I decided to back it down to 65536.

Patching DSDT in recent Linux kernels without recompiling

Up until a year or two ago, the Linux kernel let you replace the ACPI DSDT by adding a customized version to the initrd. However, more recent versions disable that by default. If you’re using Grub2 as your bootloader though, the alternative is simple: just add acpi /boot/dsdt.aml to your Grub config. If you prefer a more elegant solution, just add the attached 01_acpi.txt to /etc/grub.d, renamed it to 01_acpi and chmod +x it; then run update-grub2 to rebuild your Grub config. It originally came from ubuntuforums.org and I removed the -e flag in the acpi line, which caused the new DSDT only to be visible to Grub, but not to the OS.

I believe the acpi command in Grub2 originally came from the Hackintosh community – messing around with DSDTs is a lot more common there because Mac OS X is rather picky.

For those of you who don’t know what I’m talking about: the DSDT describes certain hardware features your PC has, such as buttons, CPU power save modes, and lots of other things. Some mainboards have very poorly done BIOSes that have equally messed up DSDT tables. I won’t go into a lot of detail regarding how to fix those here though (it’s as simple as cat /proc/acpi/dsdt > dsdt.dat; iasl -d dsdt.dat; editing dsdt.dsl to your liking; iasl -tc dsdt.dsl (this last step will probably produce a number of errors that can be solved by googling for the error number and making the appropriate changes in dsdt.dsl)).

Another valuable hint for people messing around with DSDTs: the DSDT is not the only place that can contain this kind of information, the other place would be the SSDT and possibly additional SSDTs. You can find them in /sys/firmware/acpi/tables and decompile them just like the DSDT as described above. Instead of recompiling the SSDT by itself, you could probably also consider merging it into your custom DSDT at the appropriate places.

Using motd to warn you of upcoming fsck

Has it ever happened to you that you remotely rebooted a Linux server and wondered why after 10 minutes you still couldn’t Ping or SSH into it? Quite often, this is caused by a lengthy run of fsck on one of your ext3 file systems (on current multi-TB disks, they can take an hour or longer). They usually get triggered automatically around every six months or 30 mounts, and there’s no easy way of knowing when it will happen.

My solution to this is rather simple: tune2fs -l tells you when the next fsck is coming up, so why not run a script upon every boot and have it write that information into /etc/motd so that you can see it every time you SSH in? The script is below (as a bonus, drives being fscked in less than 5 mounts or a week are printed in red), so all you need to do is put it somewhere on your hard drive and add something like
# Add FSCK status to MOTD
[ -f /root/fsck_stats.sh ] && bash /root/fsck_stats.sh >> /var/run/motd

to the init script that generates your motd (on Debian Squeeze, that would be /etc/init.d/bootlogs).

#!/bin/bash

echo

for disk in /dev/sda1 /dev/mapper/vm--storage-vms /dev/sdb1
do
cur_mounts=$(tune2fs -l $disk | grep "Mount count:" | awk '{print $3}')
max_mounts=$(tune2fs -l $disk | grep "Maximum mount count:" | awk '{print $4}')
diff_mounts=$(echo $max_mounts-$cur_mounts | bc)
last_check=$(tune2fs -l $disk | grep "Last checked:" | awk '{print $3}')
next_check=$(tune2fs -l $disk | grep "Next check after:" | awk '{print $4" "$5" "$6" "$7" "$8}')
next_check_timestamp=$(date -d "$next_check" "+%s")
cur_timestamp=$(date "+%s")
diff_next=$(echo $next_check_timestamp-$cur_timestamp | bc)

color=""
[ $diff_mounts -lt 5 ] && color="\033[31m"
[ $diff_next -lt 604800 ] && color="\033[31m"

echo -e "$color Next FSCK on $(basename $disk): $next_check or in $diff_mounts mounts\033[0m"