Kořenový souborový systém přes NFS
V rané fázi vývoje může být neustálé nahrávání nového firmware, resp. obrazu kořenového souborové systému do paměti NandFlash časově náročnější a hlavně obtěžující. Každá změna v obsahu kořenového souborového systému (dále jako rootfs), např. nový binární soubor vyvíjené aplikace, znamená, že vývojář musí vytvořit nový obraz rootfs, smazat paměť NandFlash a vypálit do ní nový obraz rootfs.
Alternativou může být použití USB flash disku, z kterého se nová binárka vyvíjené aplikace překopíruje nebo rovnou spustí, případně lze pro stejné účely použít SD/MMC kartu. Toto řešení je ovšem dosti limitující v případě, kdy teprve ladíme samotný obsah rootfs. Tehdy a nejen tehdy je výhodné přistupovat na rootfs přes NFS.
NFS neboli Network File System je speciální souborový systém, který umožňuje sdílet soubory a adresáře mezi počítači prostřednictvím počítačové sítě ethernet. Dokonce je možné na tento tento sdílený adresář přistupovat i ve fázi zavádění linuxového jádra na jiném počítači. Prakticky to znamená, že na svém pracovním počítači máte sdílený adresář, jehož obsah představuje kořenový souborový systém modulu SAM9260. Jak modul bootuje a probíhá zavádění linuxového jádra, tak v určitém okamžiku připojí jádro tento sdílený adresář jako kořenový souborový systém. Úplně stejně jako kdyby kořenový souborový systém byl v paměti NandFlash. Z pohledu jádra, ale i z pohledu uživatele v tom není rozdíl. Samozřejmě přístup k rootfs přes NFS je pomalejší, jelikož se obsah rootfs přenáší přes síť ethernet. Je nasnadě, že při použití NFS je přenesení jakákoliv změny v obsahu rootfs okamžité, vždyť modul jen přistupuje přes síť na sdílený adresář v našem pracovním počítači. Takto lze snadno a hlavně rychle odladit obsah rootfs, otestovat funkčnost nové verze aplikace apod. Obraz rootfs pro nahrání do paměti NandFlash vytváříme až v momentě, kdy obsah rootfs považujeme za stabilizovaný.
Počítač jako NFS server
Aby bylo možné nějaký adresář v našem počítači sdílet, musíme ho přidat do seznamu sdílených adresářů služby NFS server a určit, kdo k němu bude mít přístup. Náš počítač bude v síti vystupovat jako server, který nabízí ke sdílení nějaké prostředky, v našem případě adresář s obsahem kořenového souborového systému modulu SAM9260.
Poznámka: Níže uvedený postup byl vytvořena odzkoušen pro linuxovou distribuci Debian 6.0 Squeeze. Pro jiné distribuce může být postup mírně odlišný.
Poznámka: Níže uvedené příkazy musíme provádět pod účtem superuživatele root.
Postup:
- Nejprve ověříme, že je služba NFS server nainstalována na našem počítači:
# dpkg --get-selections | grep nfs-kernel-server
Výstup příkazu:nfs-kernel-server install
Vidíme, že na mém počítači je služba NFS server už nainstalována. Pokud tomu u vás tak není, tak ji nainstalujete snadno pomocí příkazů:# apt-get update # apt-get install nfs-kernel-server
Služba NFS server bude automaticky spuštěna a nakonfigurována. - Dále ověříme, že je služba NFS server v našem počítači spuštěna:
# service nfs-kernel-server status
Výstup příkazu:nfsd running
Jak vidíme v mém případě služba NFS server běží. Pokud systém odpoví nfsd not running, tak je to snadné - stačí službu NFS server pustit příkazem:# service nfs-kernel-server start
- V libovolném textovém editoru (např. v editoru souborového manažeru Midnight Commander) otevřeme soubor /etc/exports a přidáme do něj řádek pro sdílení naše adresáře. V příkladu budeme předpokládat, že takovým adresářem je adresář /home/emlin/nfs-share. Soubor pak uložíme.Řádek do souboru /etc/exports:
/home/emlin/nfs-share 192.168.1.12(rw,sync,no_subtree_check,no_root_squash)
Tento zápis říká, že adresář /home/emlin/nfs-share je sdílen přes NFS a přistupovat na něj může počítač s IP adresou 192.168.1.12 v režimu čtení/zápis. Volba no_subtree_check vypíná kontrolu, že požadovaný soubor/adresář se nachází uvnitř sdíleného adresáře (urychluje přístup). A volba no_root_squash zajišťuje, že superuživatel root na modulu bude mít stejná práva jako kdyby byl superuživatelem root na našem počítači (normálně je jakýkoliv uživatel z modulu namapován na uživatele nfsnobody na pracovním počítači/NFS serveru). A jelikož obsah rootfs je vlastněn superuživatelem root, tak toto zabezpečení musíme vypnout. - Restartujeme službu NFS server, aby byl upravený soubor /etc/exports znovu načten:
# service nfs-kernel-server restart
Výstup příkazu:Stopping NFS kernel daemon: mountd nfsd. Unexporting directories for NFS kernel daemon.... Exporting directories for NFS kernel daemon.... Starting NFS kernel daemon: nfsd mountd.
Během restartu služby proběhne i kontrola obsahu souboru /etc/exports. V případě nějaké chyby je tato vypsána a služba NFS server zůstane pozastavena.
Kořenový adresář modulu přes NFS
Modul SAM9260 se v případě přístupu ke kořenovému souborovému systému (rootfs) přes NFS chová jako NFS klient. Tedy jako počítač, který přistupuje ke sdíleným prostředkům NFS serveru. My ale potřebujeme, aby linuxové jádro modulu už při svém zavádění dokázalo přistoupit ke sdílenému adresáři na našem pracovním počítači a připojit tento adresář jako kořenový souborový systému modulu. Stejně jako kdyby byl kořenový souborový systém uložen v oddílu paměti NandFlash. Jinými slovy - musíme jádru přikázat, aby kořenový souborový systém hledalo na NFS serveru (= našem počítači) a ne jako normálně v NandFlash paměti modulu.
Mimo to musíme jádru předat i parametry síťového rozhraní (IP adresu atd.), aby jádro vůbec dokázalo kontaktovat NFS server. Normálně se parametry síťového rozhraní nastavují až po zavedení jádra v inicializačním skriptu, který si tyto parametry vyčte z konfiguračního souboru /etc/network/interfaces. To ale v případě kořenového souborového systému na NFS serveru není možné, protože jaksi kořenový souborový systém není připojen a tudíž dostupný. Vzniká zde tedy problém: ”Co bylo dřív? Slepice či vejce?”. Tento problém se řeší právě tím, že jádro inicializuje síťové rozhraní už před pokusem přistoupit na NFS server.
Když to shrneme: za a) musíme jádru přikázat, že kořenový souborový systém má hledat v adresáři na NFS serveru a za b) musíme mu předat parametry síťového rozhraní. Jak na to? Máme v zásadě jen jednu možnost - použít příkazový řádek jádra. A předat parametry na příkazový řádek jádra umí zavaděč U-Boot.
Postup:
- Spustíme modul (případně modul restartujeme, pokud už běží) a automatické zavedení jádra zavaděčem U-Boot přerušíme stiskem libovolné klávesy při startu zavaděče.
- V příkazové řádce zavaděče U-Boot zadáme příkaz:
u-boot> setenv bootargs console ttyS0,115200 ip=192.168.1.12:192.168.1.123:192.168.1.254:255.255.255.0:ucsimply-sam9260::off root=/dev/nfs rw nfsroot=192.168.1.123:/home/emlin/nfs-share
Tím linuxovému jádru předáme informace uložené v proměnné bootargs zavaděče U-Boot. Tj. informace o systémové konzole (parametr console), o nastavení síťového rozhraní (parametr ip ve tvaru IP adresa modulu : IP adresa NFS serveru : IP adresa brány : síťová maska : hostname modulu :: autoconf), určení zařízení s rootfs (parametr root) a určení cesty ke sdílenému adresáři s rootfs (parametr nfsroot ve tvaru IP adresa NFS serveru : adresář na NFS serveru). - Uložíme změny v proměnné prostředí U-Bootu do paměti DataFlash / NandFlash a resetujeme modul:
u-boot> saveenv u-boot> reset
- Modul se resetuje. Hned v úvodu svého zavádění jádro vypíše obsah příkazové řádky jádra, tak jak mu byl předán zavaděčem U-Boot. Ve výpisech jádra bychom tedy měli vidět něco takového:
Linux version 2.6.38.8 (root@vpc-debian) (gcc version 4.5.1 (Sourcery G++ Lite 2 010.09-50) ) #1 PREEMPT Wed May 30 13:38:42 CEST 2012 CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 CPU: VIVT data cache, VIVT instruction cache Machine: uCSimply AT91SAM9260 module Memory policy: ECC disabled, Data cache writeback Clocks: CPU 198 MHz, master 99 MHz, main 18.432 MHz Built 1 zonelists in Zone order, mobility grouping on. Total pages: 8128 Kernel command line: console ttyS0,115200 ip=192.168.1.12:192.168.1.123:192.168.1.254:255.255.255.0:ucsimply-sam9260::off root=/dev/nfs rw nfsroot=192.168.1.123 :/home/emlin/nfs-share ...
Tak si lze snadno zkontrolovat, že jsme obsah proměnné U-Bootu bootargs zadali správně. Ke konci zavádění jádra, těsně před spuštěním inicializačního skriptu, bychom měli ve výpisech jádra vidět něco takového:IP-Config: Complete: device=eth0, addr=192.168.1.12, mask=255.255.255.0, gw=192.168.1.254, host=ucsimply-sam9260, domain=, nis-domain=(none), bootserver=192.168.1.123, rootserver=192.168.1.123, rootpath= eth0: link up (100/Full) VFS: Mounted root (nfs filesystem) on device 0:12. Freeing init memory: 116K
Přičemž výpis VFS: Mounted root (nfs filesystem) on device 0:12. nás informuje o tom, že jádro úspěšně připojilo sdílený adresář na NFS serveru jako kořenový souborový systém.
Na tomto místě je určitě vhodné zmínit jak vrátit nastavení proměnné U-Boot bootargs do původního stavu tak, aby jádro hledalo kořenový souborový systém v oddílu paměti NandFlash. Je to prosté. Nabootujeme do U-Bootu a obsah proměnné přepíšeme výchozím obsahem.
Pokud je obraz linuxového jádra uložen v paměti DataFlash, tak zadáme příkaz:
u-boot> setenv bootargs console ttyS0,115200 ubi.mtd=0 root=ubi0:rootfs rw rootfstype=ubifs
A jestliže je jádro uloženo v paměti NandFlash (stejně jako rootfs), tak zadáme příkaz:
u-boot> setenv bootargs console ttyS0,115200 ubi.mtd=4 root=ubi0:rootfs rw rootfstype=ubifs
Změny trvale uložíme příkazem saveenv a modul resetujeme příkazem reset. Modul by měl pak už nabootovat normálně, tj. jádro by mělo připojit kořenový souborový systém uložený v paměti NandFlash.
Modul jako NFS klient
Jednou z dalších možností, kdy je výhodné využít NFS, je situace, kdy z pracovního počítače potřebujeme do modulu přenést nějaká data. Není nic jednoduššího než tato data přenést do sdíleného adresáře v pracovním počítači a z modulu si je stáhnout v běžícím Linuxu přes NFS. V tomto případě pracovní počítač není úložištěm pro kořenový souborový systém modulu, ale prostě jen poskytuje data.
Sdílený adresář pracovního počítače zpřístupníme na modulu stejně jako obsah jakéhokoliv jiného datového média. Prostě jej připojíme příkazem mount podobně jako USB flash disk, DVD-ROM atd. Ukážeme si to na jednoduchém příkladu. Předpokládejme, že IP adresa NFS serveru je 192.168.1.123 a cesta ke sdílené složce na NFS serveru je /home/emlin/nfs-share. Dále chceme, aby obsah sdíleného adresáře byl v modulu přístupný v adresáři /mnt/nfs. Do příkazové řádky Linuxu v modulu SAM9260 zadáme:
# mount -t nfs -o nolock 192.168.1.123:/home/emlin/nfs-share /mnt/nfs
Pokud jsme byli úspěšní (systém nezareagoval chybovým hlášením), tak je nyní obsah sdíleného adresáře přístupný v adresáři /mnt/nfs. Odborně řečeno - obsah sdíleného adresáře jsme připojili k přípojnému bodu /mnt/nfs.
K odpojení modulu od sdíleného adresáře pak provedeme příkazem umount /mnt/nfs. Tím NFS serveru řekneme, že už nehodláme nadále přistupovat na sdílené adresáře a zároveň zapíšeme všechny změny ve sdílených datech provedené ze strany modulu.