Archive for August, 2007

Why does Linux only see 1GB of my 2GB SD Card?

Friday, August 31st, 2007

This mailing list post explains why.

A 2GB SD card reports a 1024 byte block size instead of the 512 byte block size that all smaller SD cards employ. However, I/O is performed in 512 byte blocks by the USB mass storage driver. The card reader is supposed to know about this and report a 512 byte block size, while multiplying the number of blocks reported by the card by 2, in order to report the correct card geometry to the operating system.

Older card readers do not know about this conversion, and may even assume that all SD cards have a 512 byte block size. Thus, a 512 byte block size is reported, along with the number of blocks reported by the card. This cuts the reported capacity of the card in half.

But the filesystem that exists on the card reports a 2GB size. On a system where the card physically only shows up as 1GB, this causes the FAT filesystem driver to read past the end of the card. This will produce read/write errors, and could even crash the filesystem driver if it is not equipped to deal with this case.

Windows reportedly employs one of two solutions to ensure that 2GB cards are correctly recognized.

The first solution is to assume that the card has a PC partition table on it (a mostly correct assumption for any card purchased retail). The Windows USB mass storage driver then examines the partition table to determine the number of blocks on the physical device, and ignores the number of blocks reported by the reader. A possible flaw with this scheme is that the Windows driver may not account for cases where a partition table has been erroneously or maliciously constructed, leading to an incorrect physical size being entered, and thus a device which cannot be correctly repartitioned or reformatted. It may also not account for the device being divided into several partitions. And of course this scheme won’t work for a card which is formatted without a partition table.

The other solution is to ignore the number of blocks reported by the reader, and to probe the size of the card by issuing test reads, probably in large increments at first and then smaller increments, until a read failure occurs. The read failure is assumed to occur because the read occurred past the end of the device. A possible flaw in this scheme is that a card with one or more defective sectors could cause the storage driver to believe it has found the end of the device, when in fact the read error occurs because of a bad sector.

At the moment, the solution for Linux and other operating systems which do not implement such hacks and which trust the card reader to report a useful block count and block size of the inserted card, is to buy a new card reader.

msmtp and Gmail

Wednesday, August 22nd, 2007

account gmail
host smtp.gmail.com
from username@gmail.com
auth on
user username@gmail.com
password mypass
tls on
tls_starttls off
tls_certcheck off
logfile /tmp/gmail.log

The synopsis: GMail doesn’t accept STARTTLS connections on port 25. The key is “tls_starttls off”, which causes the client to connect using SSL on port 465 instead…

Kerberos ticket forwarding and Reverse DNS

Tuesday, August 21st, 2007

You might get some confusing errors when attempting to login to your network from an outside network. The application reports “GSSAPI error: Miscellaneous failure” or “GSSAPI mech specific error: Server not found in Kerberos database”. Your Kerberos KDC log shows:

Aug 21 13:01:49 xanadu krb5kdc[30485]: TGS_REQ (3 etypes {16 1 3}) 66.9.16.190: UNKNOWN_SERVER: authtime 1187288
525,  nemesis@REALM.COM for krbtgt/ISP.COM@REALM.COM, Server not found in Kerberos database

What is important to note here is that the request is for a ticket for krbtgt/ISP.COM and not krbtgt/REALM.COM.

This happens because the client computer looks up the reverse DNS of the server computer, and attempts to get a ticket for the realm it appears to be a member of.

In this case, the server can be resolved to IP address by server.realm.com, but the Reverse DNS is controlled by the ISP, and so a reverse lookup on the server’s IP address gives a hostname that is on the ISP’s domain somewhere.

There are only a few ways to fix this:

  • Correct the public Reverse DNS for the remote server’s IP address (difficult to impossible depending on your ISP)
  • Add appropriate Reverse DNS entries for the remote server’s IP address to the client’s DNS server, and make the client’s DNS server authoritative for the remote server’s subnet
  • Add appropriate entries for the remote server to the client’s HOSTS file

The last option is probably the least painful if you are just trying to get seamless access from your work computer to home, for example.

A short howto for Linux volume labels

Wednesday, August 1st, 2007

You may have noticed from time to time as Linux evolves and device drivers change, the device nodes used to access your hard disks may sometimes change. Besides updating the root device on the kernel command line in your bootloader configuration, you also have to go through your /etc/fstab and make all the appropriate changes. That is assuming you still have a working kernel around…

Easier thing to do is refer to the volumes not by device node, but by LABEL or UUID. Every filesystem is assigned a UUID when it is created, and you can manually assign a human-readable LABEL by using the filesystem tuning tools. Once you have assigned a LABEL and/or UUID, then anywhere you would refer to a /dev/hdXX or /dev/sdXX device, use UUID=… or LABEL=… instead, where … is the actual UUID or LABEL that is assigned.

To set labels for a few filesystems:


ReiserFS: reiserfstune -l <label> /dev/XXXX
EXT2/3: tune2fs -L <label> /dev/XXXX
Swap: mkswap -L <label> /dev/XXXX

To retrieve labels and UUIDs for a few filesystems:


ReiserFS: reiserfstune /dev/XXXX (must be unmounted)
EXT2/3: tune2fs -l /dev/XXXX ("Filesystem volume name", "Filesystem UUID")
Swap: No way to retrieve, just relabel it with mkswap -L

After rebooting you will be able to see the volume labels in /proc/partitions.

Note: Only v1 (“new style”) swap devices can be labeled.

Error behavior

In ext2/ext3, you can also set the error behavior in the superblock so that when a filesystem error is encountered (due to corruption, CPU/memory failure or disk failure), the filesystem will be automatically remounted read-only or the kernel panicked. The default is to continue on errors. This is usually set in the fstab (errors=remount-ro or errors=panic), but it may be more convenient to have the default behavior set in the superblock. Simply issue tune2fs -e remount-ro /dev/hda1 for all your ext2/ext3 filesystems, and you will no longer have to have the verbosity in your /etc/fstab too…

PDC202xx_old driver is broken in Linux 2.6

Wednesday, August 1st, 2007

At some point, I started noticing my system (MSI BXMaster) would completely freeze under heavy disk load. After watching the logs, I would see something akin to the following:

Mar 11 17:27:19 dbz kernel: hdg: dma_timer_expiry: dma status == 0x60
Mar 11 17:27:19 dbz kernel: hdg: DMA timeout retry
Mar 11 17:27:19 dbz kernel: PDC202XX: Secondary channel reset.
Mar 11 17:27:19 dbz kernel: PDC202XX: Primary channel reset.
Mar 11 17:27:19 dbz kernel: hdg: timeout waiting for DMA
Mar 11 17:27:40 dbz kernel: hdg: dma_timer_expiry: dma status == 0x60
Mar 11 17:27:40 dbz kernel: hdg: DMA timeout retry
Mar 11 17:27:40 dbz kernel: PDC202XX: Secondary channel reset.
Mar 11 17:27:40 dbz kernel: PDC202XX: Primary channel reset.
Mar 11 17:27:40 dbz kernel: hdg: timeout waiting for DMA
Mar 11 17:28:02 dbz kernel: hdg: dma_timer_expiry: dma status == 0x60
Mar 11 17:28:02 dbz kernel: hdg: DMA timeout retry
Mar 11 17:28:02 dbz kernel: PDC202XX: Secondary channel reset.
Mar 11 17:28:02 dbz kernel: PDC202XX: Primary channel reset.
Mar 11 17:28:02 dbz kernel: hdg: timeout waiting for DMA
Mar 11 17:28:22 dbz kernel: hdg: dma_timer_expiry: dma status == 0x60
Mar 11 17:28:22 dbz kernel: hdg: DMA timeout retry
Mar 11 17:28:22 dbz kernel: PDC202XX: Secondary channel reset.
Mar 11 17:28:22 dbz kernel: PDC202XX: Primary channel reset.
Mar 11 17:28:22 dbz kernel: hdg: timeout waiting for DMA

Well, I was unable to find a 2.6 kernel that would work reliabily on my Promise chip (PDC20265), I went back several versions.

The fix is to NOT use the pdc202xx_old driver, but instead use the libata driver for old Promise chips (CONFIG_PATA_PDC_OLD=y). You will probably need to recompile your kernel for this because distribution kernels are not using libata yet.

Also, this will change your disk devices from /dev/hdX to /dev/sdX so be sure to update your /etc/fstab correspondingly.

If your distribution kernel includes CONFIG_PATA_PDC_OLD=m, you can use this by adding it to the initrd image. For initramfs-tools, the file /etc/initramfs-tools/modules should exist. Edit it, and add “pata_pdc202xx_old” without the quotes on a new line. Run update-initramfs -k all -u and you should be all set. This preloads the libata driver during the initrd, so that the faulty pdc202xx_old driver cannot be loaded later.