# UDEV & Cardreader (multiple luns)

## hothead

 Vorwort: Problematik der Benennung von Gerätedateien 

Wer möchte nicht gerne ein auf dem Desktop ein Laufwerk Symbol haben, mit dem er auf einen bestimmte Flashcard, die in einem Cardreader steckt oder auf einen USB-Ramstick zugreifen können. Mit dem devfs war und ist dies zwar möglich, jedoch mit der Einschränkung, dass man, sofern man mehere USB-Speichergeräte hat, diese gemäß der fstab Einträge anhängen muss. 

Der Grund dafür ist die Geräte Benennung durch den Kernel. Das erste angehängte USB-Speichergerät bekommt automatisch den Gerätenamen sda (sd steht meines Wissens für scsi-disk), das zweite sdb u.s.w.

Angenommen du hast folgende Einträge in der fstab:

```

#------------------------------------------------------------------------------------------------------------------------

# Wechseldatentraeger

#------------------------------------------------------------------------------------------------------------------------

/dev/sda1  /mnt/compactfash  auto            noauto,user,exec                0 0

/dev/sdb1  /mnt/multimediacard  auto            noauto,user,exec                0 0

/dev/sdc1  /mnt/smartmedia  auto            noauto,user,exec                0 0

/dev/sdd1  /mnt/ms    auto            noauto,user,exec                0 0

/dev/sde1  /mnt/camera   auto            noauto,user,exec                0 0

/dev/sdf1  /mnt/ramstick   auto            noauto,user,exec                0 0

  
```

Du hast auf dem Desktop Links zu diesen Einträgen mit dem sich der Wechselspeicher mounten/unmounten lässt. Die Links werden jedoch aufgrund der Kernel-Namensgebung nur funktionieren, wenn du die Geräte entsprechend den fstab Einträgen, also den Cardreader als erstes, die Camera als zweites und den Ramstick als drittes anhängst. 

Hängst du dagegen den Ramstick zuerst an, bekommt seine erste Partition vom Kernel automatisch die Gerätedatei `/dev/sda1` zugeteilt. Folglich müsstest du die fstab Einträge ändern oder den Link für die Compactflashkarte nutzen um auf den Ramstick zugreifen zu können. Das ist meiner Meinung nach ziemlich lästig. Man könnte den Links auf dem Desktop die Kernelbezeichnung sda, sdb u.s.w. geben, jedoch msste man dann immer nachvollziehen welches Geräte welche Bezeichnung erhalten hat - auch eine sehr mühsame Methode.

Udev - Linux configurable dynamic device naming support wurde als Neuerung mit dem Kernel 2.6 eingeführt und ermöglicht es mittels einer Regel jedem Gerät, so auch Wechseldatenträgern und sogar einem bestimmten Laufwerk eines Cardreaders eine feste, jedoch zugleich dynamischeGerätedatei zuzuweisen. Damit die Regel funktioniert muss sie eindeutige Kritierien für dieses Gerät enthalten. Diese Kriterien zu ermitteln und daraus die Regel zu erstellen ist Thema des Abschnitts drei.

Die ersten beiden Abschnitte sollen denen zur Hilfe dienen, die noch nicht mit udev arbeiten bzw. deren Cardreader nicht komplett vom Kernel erkannt wird. Solltest du schon mit udev arbeiten und auskennen, sowie multiple-lun Unterstützung im Kernel  haben, kannst du die ersten beiden Abschnitte natürlich überspringen. 

 1. Kernel mit multiple-lun (logical unit number) Unterstützung aufsetzen

Damit du die einzelnen Laufwerke eines Cardreaders überhaupt ansprechen kannst muss der Kernel dies unterstützen.

Ob dein Kernel multiple-lun Unterstützung hat kannst du überprfen indem du den cardreader anstöpselst und dir mit 'dmesg' die messages anzeigen lässt. Die Ausgabe sollte ohne eine eingesteckte Speicherkarte dann so ähnlich aussehen:

```

usb 1-2: new full speed USB device using address 32

scsi56 : SCSI emulation for USB Mass Storage devices

  Vendor: Generic   Model: USB SD Reader     Rev: 1.00

  Type:   Direct-Access                      ANSI SCSI revision: 02

Attached scsi removable disk sdb at scsi56, channel 0, id 0, lun 0

Attached scsi generic sg1 at scsi56, channel 0, id 0, lun 0,  type 0

  Vendor: Generic   Model: USB CF Reader     Rev: 1.01

  Type:   Direct-Access                      ANSI SCSI revision: 02

Attached scsi removable disk sdc at scsi56, channel 0, id 0, lun 1

Attached scsi generic sg2 at scsi56, channel 0, id 0, lun 1,  type 0

  Vendor: Generic   Model: USB SM Reader     Rev: 1.02

  Type:   Direct-Access                      ANSI SCSI revision: 02

Attached scsi removable disk sdd at scsi56, channel 0, id 0, lun 2

Attached scsi generic sg3 at scsi56, channel 0, id 0, lun 2,  type 0

  Vendor: Generic   Model: USB MS Reader     Rev: 1.03

  Type:   Direct-Access                      ANSI SCSI revision: 02

Attached scsi removable disk sde at scsi56, channel 0, id 0, lun 3

Attached scsi generic sg4 at scsi56, channel 0, id 0, lun 3,  type 0

USB Mass Storage device found at 32

```

Sollte nur ein Laufwerk  angezeigt werden fehlt sehr wahrscheinlich die multiple-lun Unterstützung im Kernel. Zu finden ist dies Option im 2.6.xer Kernel bei Configuration mit x- oder menuconfig unter: 

```
 device drivers - scsi device support 
```

wenn es aktiviert ist, dann msste ein 'cat /usr/src/linux/.config | grep SCSI_MULTI_LUN folgendes ausgeben.

```
CONFIG_SCSI_MULTI_LUN=y 
```

Dann muss natürlich der Kernel neu kompiliert werden. Hinweise zum Kernel bauen unter http://www.thomashertweck.de/kernel26.html

Bevor du den Kernel jedoch kompilierst solltest du dir auf jeden Fall die Dokumente auf die ich im folgenden Abschnitt verweise durchlesen. 

 2.  Aufsetzen des Linux configurable dynamic device naming support - kurz udev 

Falls du udev noch nicht am Laufen hast, musst du es natürlich aufsetzen, wie das funktioniert kannst du unter diesen beiden Adressen nachlesen. 

auf Deutsch -  http://www.athemis.de/content/linux/udev_primer_de.html

auf English - http://webpages.charter.net/decibelshelp/LinuxHelp_UDEVPrimer.html#UDEV

 3. Udev Regeln erstellen

Du solltest dir unbedingt dieses Dokument durchlesen, um die Basics der udev-Regeln zu verstehen. http://www.reactivated.net/udevrules.php

Hilfe bietet ihnen natrlich auch jederzeit die udev manpage.

Doch nun möchte ich eine Modell-Regel für einen Cardreader mit vier Laufwerken (luns) erstellen:

Alls erstes musst du natürlich die Gerätenamen der einzelnen luns mit 'dmesg' in Erfahrung bringen (siehe Abschnitt 1).  Um die Regel schreiben zu können musst du dann die Informationen zu den einzelnen luns abrufen. Dazu dient der Befehl 'udevinfo'. 

Als erstes muss man den Pfad im sysfs finden:

```
bash-2.05b$ udevinfo -q path -n /dev/sda

/block/sda

```

Die Ausgabe dient zum Abruf der Information:

```
udevinfo -a -p /sys/block/sda

```

Die Ausgabe wird ziemlich lang sein, der für unsere Regel entscheidende Abschnitt ist jedoch der des SCSI-BUS

```

BUS="scsi"

    ID="53:0:0:0"

    SYSFS{detach_state}="0"

    SYSFS{device_blocked}="0"

    SYSFS{max_sectors}="240"

    SYSFS{model}="Flash Disk      "

    SYSFS{queue_depth}="1"

    SYSFS{rev}="PROL"

    SYSFS{scsi_level}="3"

    SYSFS{state}="running"

    SYSFS{timeout}="30"

    SYSFS{type}="0"

    SYSFS{vendor}="USB 2.0 "
```

Das musst du natürlich für alle luns wiederholen (statt sda - sdb,sdc und sdd einsetzen).  

Am besten die Ausgabe mit "> /home/name_der_datei" in eine Textdatei umleiten. 

Jetzt ist es Zeit mit den gewonnenen Informationen eine Regel zu erstellen, dabei bedienen wir uns folgender Parameter:

```
# BUS="", KERNEL="", SYSFS{model}="",SYSFS{vendor}="", NAME{all_partitions}=""

```

BUS - die Schnittstelle

Als erstes muss die Kernel-Schnittstelle, sprich der BUS definiert werden. Wir wählen hier den SCSI-BUS, da die einzelnen Laufwerke ja über eine scsi Emulation angesprochen werden. Über den USB-BUS ist es nicht möglich den einzelnen Laufwerke einen festen Gerätenamen zu geben.

KERNEL - Kernel Gerätename

KERNEL ist der Kernel Gerätename, in unserem Fall alle möglichen scsi-disk Geräte - sd*

SYSFS - sysfs Geräteparameter

SYSFS{model} und SYSFS{vendor} sind Kriterien, die wir mit dem 'udevinfo' Befehl erhalten haben. Am besten kopiert man diese aus der udevinfo Ausgabe um Fehler zu vermeiden (z.B. fehlende Lehrzeichen !). 

 NAME - Name der Gerätedatei

NAME{all_partitions}="" sagt udev, dass es Gerätedateien für alle 15 möglichen Partitionen einens Blockgerätes mit dem angegebenen Namens im Ordner '/dev' erstellen soll. Das erstellen aller Partitionen ist nötig, da beim Einstecken einer Karte in einen lehres Laufwerk eines vorher angestöpselten Cardreaders kein Kernel Event stattfindet und deswegen auch keine Gerätedatei angelegt wird. Folglich ist es nötig alle Partitionen anzulegen zu lassen, unabhängig ob sie vorhanden sind oder nicht, um Zugriff zu haben ohne denCardreader aus- und wieder anausstöpseln zu müssen. 

Da man aufgrund dessen 16 Gerätedateien für ein Laufwerk des Cardreaders erhält, empfehle ich zu Zwecken der Übersicht ein extra Verzeichnis (hier 'cardreader') anlegen zu lassen. 

Die Regel müsste fr alle vier Laufwerke des Cardreaders so aussehen.

```

 Cardreader

BUS="scsi", KERNEL="sd*", SYSFS{model}="USB SD Reader   ",SYSFS{vendor}="Generic ", NAME{all_partitions}="cardreader/sd"

BUS="scsi", KERNEL="sd*", SYSFS{model}="USB CF Reader   ",SYSFS{vendor}="Generic ", NAME{all_partitions}="cardreader/cf"

BUS="scsi", KERNEL="sd*", SYSFS{model}="USB SM Reader   ",SYSFS{vendor}="Generic ", NAME{all_partitions}="cardreader/sm"

BUS="scsi", KERNEL="sd*", SYSFS{model}="USB MS Reader   ",SYSFS{vendor}="Generic ", NAME{all_partitions}="cardreader/ms"

```

Diese Regel muss in die locale Regel-Datei 

```
/etc/udev/rules.d/10-local.rules
```

eingetragen werden. 

Die Regeln bitte nicht in /etc/udev/rules.d/50-udev.rules schreiben, da die Regeln sonst bei einem udev update verloren gehen können.  Zudem wird jede rules Datei deren Dateiname mit einer Zahl kleiner als fünfzig vor den eigentlichen 50-udev.rules ausgeführt und hat somit Priorität bei der Benennung der Gerätedateien.

Ich hatte noch einen Sonderfall mit meiner Maus, die einen integrierten Cardreader besitzt.

Auf den ersten Blick habe ich keine Unterschiede in den SYSFS Parametern gefunden. 

udevinfo -a -p /sys/block/sda

```
BUS="scsi"

    ID="59:0:0:0"

    SYSFS{detach_state}="0"

    SYSFS{device_blocked}="0"

    SYSFS{max_sectors}="240"

    SYSFS{model}="Flash Disk Drive"

    SYSFS{queue_depth}="1"

    SYSFS{rev}="3.10"

    SYSFS{scsi_level}="3"

    SYSFS{state}="running"

    SYSFS{timeout}="30"

    SYSFS{type}="0"

    SYSFS{vendor}="General "
```

udevinfo -a -p /sys/block/sda

```
BUS="scsi"

    ID="59:0:0:1"

    SYSFS{detach_state}="0"

    SYSFS{device_blocked}="0"

    SYSFS{max_sectors}="240"

    SYSFS{model}="Flash Disk Drive"

    SYSFS{queue_depth}="1"

    SYSFS{rev}="3.10"

    SYSFS{scsi_level}="3"

    SYSFS{state}="running"

    SYSFS{timeout}="30"

    SYSFS{type}="0"

    SYSFS{vendor}="General "
```

Einzig und allein die ID zeigte einen Unterschied auf, da sich die erste Ziffer (hier die 59), die für den Host steht variabel ist lautet meine Regel: 

```

# QTronix Mouse Cardreader

BUS="scsi", ID="*:0:0:0", KERNEL="sd*", SYSFS{model}="Flash Disk Drive", SYSFS{vendor}="General ", NAME{all_partitions}="mouse-cardreader/mmc"

BUS="scsi", ID="*:0:0:1", KERNEL="sd*", SYSFS{model}="Flash Disk Drive", SYSFS{vendor}="General ", NAME{all_partitions}="mouse-cardreader/sd"

```

Ich denke dass man mittels sich der ID bei mangelden Informationen des Herstellers zu den einzelnen Laufwerken im Cardreader, also die Informationen, die man mittels sysfs ausliest, in jedem Fall behelfen kann.

So, nun viel Spaß beim Udev-Regeln schreiben !

Ruben

P.S.: Ergänzungen und Verbesserungen sind natürlich jederzeit willkommen. Schaut bei Problemen und Fragen bitte erst einmal in die udev manpage, welche dafür eigentlich gedacht ist.  Als letztes möchte ich nochmals auf die Seite verweisen, die mir beim Regeln schreiben sehr weitergeholfen hat: http://www.reactivated.net/udevrules.php

----------

## ian!

Von 'DT&T' in das deutsche Forum verschoben.

Wohl einer der besten 'first posts'. Allerdings sind die internationalen Foren strict english.

----------

## UncleOwen

Sehr schön, sehr schön. Kleine Ergänzung: udev ist _kein_ Dateisystem.

----------

## sirro

Zuerstmal: Super klasse Howto! Hab es mit Begeisterung direkt angewendet! Danke!

Nur eine kleine Verbesserung:

 *hothead wrote:*   

> dann müsste ein 'cat /user/src/linux/.config | grep SCSI_MULTI_LUN folgendes ausgeben.

 

- da ist ein e zuviel (user statt usr)

- "useless use of cat"  :Wink:  ein 'grep SCSI_MULTI_LUN /usr/src/linux/.config' oder 'grep SCSI_MULTI_LUN < /usr/src/linux/.config' ist der bessere Weg

----------

