Monter un disque multimedia sur Linux Redhat Enterprise 4 / CENTOS 4 - "FAT: invalid first entry of FAT"

L'implémentation du système de fichier FAT sur certains disques multimedia est parfoi fantaisiste, au point qu'il en devient parfois difficile de monter certains périphériques ésotériques sur Linux pour cause de nom compatibilité FAT... On se retrouve alors avec des erreurs noyau de type : FAT: invalid first entry of FAT (0xffffff8 != 0xf00f800) - VFS: Can't find a valid FAT filesystem on dev sda4.

Mais les derniers noyaux 2.6 donnent la solution. Voyons comment la mettre en oeuvre sur des versions antérieures...

J'ai tenté de monter un disque dur externe QP2DX/KM sur un système linux RHEL4 / CENTOS4 afin de sauvegarder quelques éléments. Malheureusement, lors de la détection, /var/log/messages indiquait l'erreur suivante:

kernel: FAT: invalid first entry of FAT (0xffffff8 != 0xf00f800)
kernel: VFS: Can't find a valid FAT filesystem on dev sdb1.

Ayant cherché sur Google d'autres internautes ayant eu mon problème, j'ai découvert que de nombreux périphériques fournissaient un accès USB à des disques FAT, mais avec une implémentation douteuse (samplers, appareils photos numériques, certains disques multimédia, etc..).

La réponse se trouve dans les sources du kernel, ou la portion de code suivante est exécutée dans le code de détection FAT (linux-2.6.9/fs/fat/inode.c):

       if (FAT_FIRST_ENT(sb, media) == first) {
               /* all is as it should be */
       } else if (media == 0xf8 && FAT_FIRST_ENT(sb, 0xfe) == first) {
               /* bad, reported on pc9800 */
       } else if (media == 0xf0 && FAT_FIRST_ENT(sb, 0xf8) == first) {
               /* bad, reported with a MO disk on win95/me */
       } else if (first == 0) {
               /* bad, reported with a SmartMedia card */
       } else {
               if (!silent)
                       printk(KERN_ERR "FAT: invalid first entry of FAT "
                              "(0x%x != 0x%x)\n",
                              FAT_FIRST_ENT(sb, media), first);
               goto out_invalid;
       }

Ce qui, pour les non lecteurs de C signifie que kernel essaye d'interpréter les différences de format ext3 avec quelques cas particuliers, puis ejecte en erreur si il y a différence. or la dernière version du kernel traite ce même problème de la façon suivante :

   /*      
    * The low byte of FAT's first entry must have same value with
    * media-field.  But in real world, too many devices is
    * writing wrong value.  So, removed that validity check.
    *  
    * if (FAT_FIRST_ENT(sb, media) != first)
    */

C'est à dire que le traitement d'erreur est purement et simplement supprimé à cause des disparités d'implémentation du file system FAT sur les périphériques USB. Nous allons donc implémenter cette modification sur notre RHES 4 (ou CENTOS 4).

Tout d'abord, il nous faut récupérer les sources, après avoir récupéré la version de notre kernel :

 uname -r
 >> 2.6.9-55.EL 
 wget http://mirror.centos.org/centos-4/4.5/os/SRPMS/kernel-2.6.9-55.EL.src.rpm
 rpm -ivh kernel-2.6.9-55.EL.src.rpm

Il nous faut ensuite préparer l'environnement de compilation, c'est à dire décompresser les sources et appliquer les patch :

 rpmbuild --target=i686 -bp /usr/src/redhat/SPECS/kernel-2.6.spec

Nous allons ensuite mettre en place le correctif en supprimant dans inode.c la portion incriminée ci dessus citée:

 cd /usr/src/redhat/BUILD/kernel-2.6.9/linux-2.6.9/fs/fat
 vi inode.c

Il aurait été sage de faire un patch au kernel et de le rebuilder complètement. Au vu de la longeur de la manip,je vais ici uniquement reconstruire le module considéré en modifiant le makefile. Toujours dans le même répertoire, remplacer Makefile par :

#
# Makefile for the Linux fat filesystem support.
#

obj-m   := fat.o
fat-objs := cache.o dir.o file.o inode.o misc.o fatfs_syms.o
KDIR := /lib/modules/2.6.9-55.EL/build
PWD := $(shell pwd)
default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

Puis compiler ce module avec 'make'.

Il ne nous reste plus qu'à l'installer après avoir renommé l'ancien

 mv /lib/modules/2.6.9-55.EL/kernel/fs/fat/fat.ko /lib/modules/2.6.9-55.EL/kernel/fs/fat/fat.ko.old
 cp fat.ko /lib/modules/2.6.9-55.EL/kernel/fs/fat/fat.ko
 chown root:root !!$
 chmod 744 !!$
 modprobe fat

Puis de monter notre périphérique favori, qui désormais ne fait plus d'erreur!!!!