Do spisu tresci tematu 5

5.3.6 Przeksztalcanie nazwy sciezkowej w i-wezel




Spis tresci


Wstep

Dowolny plik w systemie plikow jest opisywany przez nazwe sciezkowa zbudowana za pomoca nazw katalogow oddzielonych "/" i jego nazwy . Poniewaz jadro wewnetrznie posluguje sie iwezlami , konieczne jest przeksztalcanie nazwy sciezkowej w i-wezel . Poczatek przeszukiwania jest latwy do ustalenia , poniewaz rozpoczyna sie ono zawsze od korzenia systemu plikow (gdy sciezka zaczyna sie od znaku "/" )badz od biezacego katalogu procesu (dane na temat korzenia systemu plikowi biezacego katalogu procesu mozna znalezc w u-obszarze procesu .Nie mozna uzywac zmiennej globalnej zawierajacej korzen systemu plikow , gdyz proces funkcja systemowa chroot moze zmienic swoje pojecie korzenia systemu plikow ).

Przy kazdym dostepie do pliku nastepuje przeksztalcanie nazwy sciezkowej w i-wezel . Generalnie odpowiedzialny za to jest algorytm namei , z ktorego korzysta wiekszosc funkcji operujacych na plikach . Jednak niektore funkcje systemowe np. open i write maja wlasne algorytmy przeksztalcajace sciezke w i-wezel . Ja zajme sie ogolnym algorytmem .

Generalnie algorytm namei dziala poslugujac sie roboczymi i-wezlami (pierwszym jest korzen lub aktualny katalog ) wg nastepujacego schematu :

  1. prawdz czy i-wezel roboczy jest i-wezlem katalogu i czy proces ma prawo go wykonywac
  2. wczytaj kolejna pozycje z nazwy sciezkowej
  3. znajdz w pliku katalogowym zwiazanym z i-wezlem roboczym aktualny element nazwu sciezkowej (byc moze nie bedzie trzeba go szukac na dysku ,gdyz znajduje sie juz w pamieci)
  4. pobierz nowy i-wezel (iget) i zwolnij stary(iput)
  5. jzeli nie koniec to wroc do 1


Pomocnicze funkcje

Szczegolnego traktowania wymagaja dowiazania symboliczne (pliki zawierajace nazwy sciezkowe innych plikow). Obsluga ich zajmuje sie funkcja followlink

Funkcja follow_link

DEFINCJA: int follow_link(struct inode * dir, struct inode * inode,
                 int flag, int mode ,struct inode ** result)
     /*   dir - i-wezel katalogu
     /*  inode,mode - i-wezel i typ pliku
WYNIK:0 i wskaznik do iwezla na result w przypadku sukcesu
      kod bledu w przypadku porazki
                            ELOOP  ( mozliwosc petli)
                            ENOENT ( nie istnieje taka pozycja katalogowa )
                            EIO    ( nie mozna wczytac bloku do bufora )                         
{
   if( i-wezel pliku lub katklogu jest rowny null)
   {
      zwolnij i-wezly pliku i katalogu (iput);
      na resinode przypisz null;
      return(-ENOENT);
    }
   if(w iwezlie pliku w strukturze i_op nie jest zdefiniowana funkcja followlink)
   /* plik nie jest dowiazaniem symbolicznym */
   {
      zwolnij i-wezel katalogu ;
      na resinode przypisz i-wezel pliku;
      return( 0);
   }
   /* Tu wywolywana jest funkcja  ext2_followlink wpisana wpisana w stukturze
  i_op w iwezlie pliku , ktorej kod zrodlowy mozna znalezc w pliku 
  linux/fs/ext2/symlink.c. Dla czytelnosci opis jej umieszczam w opisie glownej funkcji followlink
  */
  if(plik nie jest dowiazaniem symbolicznym )
  {
     zwolnij i-wezel katalogu ; 
     na resinode przpisz i-wezel pliku;
     return(0);
   }
   if( licznik dowiazan symbolicznych (przechowywany w u-obszarze procesu 
     - current->link_count) jest wiekszy od 5)
    /* Liczenie ilosci dowiazan symbolicznych zapobiega powstawaniu
   petli*/
  {
          zwolnij i-wezel y katalogu i pliku (iput);
          return(-ELOOP);
  }
  if(z plikiem zwiazany jest blok danych)
  {
          if( nie udalo sie wczytac bloku do bufora)
          {
             zwolnij i-wezly katalogu i pliku;
             return( -EIO);
          }
          else
             na zmienna pomocnicza link przypisz sciezke wczytana z pliku;
  }  
  else 
         na zmienna link przypisz sciezke wpisana do bloku identyfikacyjnego;
  zwieksz licznik dowiazan symbolicznych w u-obszarze;
  znajdz i-wezel opisywany przez nazwe sciezkowa wpisana pod zmienna
  link wywolujac funkcje open_namei( jedna z wersji funkcji namei);
  zmniejsz licznik dowiazan symbolicznych w u_obszarze procesu;
  zwolnij i-wezel pliku;
  if( z iwezlem zwiazany blok danych )
         zwolnij bufor do ktorego wczytano sciezke
}

Tak wiec obsluga dowiazan symbolicznych sprowadza sie do zapoczatkowania przeszukiwania nazwy sciezkowej utworzonej z zawartosci dowiazania symbolicznego. Aby zopobiec zapetleniu sie funkcji , liczy sie dowiazania symboliczne podczas przeszukiwania nazw sciezek i sygnalizuje blad wowczas ' gdy zostanie przekroczona ich gorna granica (5). Jezeli plik nie jest dowiazaniem symbolicznym to followlink zwraca ten plik.

Przed przystapieniem do szczegolowego pisu algorytmu namei zapoznajmy sie wczesniej z pomocnicza funkcja lookup , ktora majac i-wezel katalogu i nazwe pozycji katalogowej znajduje i-wezel tej pozycji.

Funkcja lookup

DEFINICJA: int lookup( struct inode * dir ,const char * name,
                int len , struct inode **resinode)
     /* dir - i-wezel katalogu
     /* name,len - nazwa i dlugosc nazwy pozycji katalogowej
WYNIK:0 i szukany i-wezel na *resinode w przypadku sukcesu
      kod bledu w przypadku porazki
                                ENOENT  ( nie istnieje taka pozycja katalogowa )   
                                EACCES  ( brak koniecznych praw )             
{
     if(katalog roboczy jest rowny null)
         return( -ENOENT);
     sprawdz czy proces ma prawo wykonywac katalog;
     if(skladowa jest "..")
     {
        if(katalog roboczy jest korzeniem systemu plikow
        - jest rowny current->fs->root)
        { 
            na result wpisz katalog wejsciowy;
            return( 0);
        }
        if (katalog roboczy jest korzeniem podmontowanego systemu plikow
         -jest rowny sb->s_mounted)
       {
            zwolnij i-wezel katalogu roboczego;
           jako nowy katalog roboczy wez i-wezel katalogu ,
           do ktorego podmontowano systm plikow (sb->s_coverd);
           if(katalog roboczy jest nullem)
           return( -ENOENT);
           zwieksz licznik odwolan do katalogu roboczego (i_count w i-wezlie);
        }
    }
   if(w i-wezlie katalogu roboczego w strukturze i_op nie jest zdefiniowana
      funkcja lookup)
   {
          zwolnij i-wezel katalogu roboczego;
          return(- ENOENT);
   }
   if(sprawdzanie praw wykonywania katalogu nie przebieglo pomyslnie)
   {
         zwolnij i-wezel katalogu roboczego;
         return( -EACCES);
   }
   if(dlugosc nazwy jest rowna 0)
     /*pozwala to na wystepowanie sciezek typu /pr1//pr2 i traktowanie
     ich jak /pr1/./pr2 */
   {
         na result przypisz katalog roboczy;
         return(0);
   }
   /* W tym miejscu wywolywana jest funkcja  ext2_lookup wpisana do iwezla
     w strukturze i_op ,ktorej kod zrodlowy mozna znalezc w pliku linux/fs/ext2/namei.
        Dla czytelnosci opis jej umieszczam w opisie glownej funkcji lookup.*/
   if(i-wezel katalogu roboczego nie jest iwezlem katalogu )
        return( - ENOENT);
   if(pozycja znajduje sie w tablicy haszujacej -funkcja dcache_lookup
       nie zwrocila nulla)
   {
        if( numer i-wezla znaleziony przez dcache_lookup jest rowny 0)
	    /* Pozycja nie istnieje w katalogu */
        {
             zwolnij i-wezel katalogu(iput);
             return( -ENOENT);
        }
        if(nie udalo sie przydzielic iwezla o numerze zwroconym
          przez dcache_lookup - iget zwrocila blad)
        {
             zwolnij i-wezel katalogu (iput);
             return( -EACCES);
        }
        zwlonij i-wezel katalogu (iput);
        return( 0);
   }
   if(nie udalo sie znalezc pozycji katalogowej na dysku - ext2_find_entry
        zwrocila null)
   {
           if(w miedzyczasie inny proces nie zmienil katalogu)
                dodaj do tablicy haszujacej pozycje katalogowa z numerem i-wezla
                rownym 0 (dcache_add);
           zwolnij i-wezel katalogu(iput);
           return( -ENOENT);
   }
   na ino przypisz znaleziony numer iwezla;
   dodaj nowa pozycje do tablicy haszujacej (dcache_add) z ino jako
   numer i-wezla;
   zwolnij bufor do ktorego byla wczytana pozycja;
   if(nie udalo sie przydzielic iwezla o numerze ino - iget zwrocila blad)
   {
         zwolnij i-wezel katalogu roboczego (iput);
          return(-EACCES);
   }
   zwolnij i-wezel katalogu roboczego(iput);
   return(0);
}

Funkcje dcashe_add i dcashe_lookup szczegolowo zostaly opisane w rozdziale poswieconym katalogom . Ext2_find _entry dziala analogicznie do funkcji czytajacej plik - uzywajac uzywajac funkcij ext2_bread i brelse czyta po kolei bloki danych zwiazane z katalogiem wejsciowym szukajac danej pozycji.

Podsumowujac lookup zwraca i-wezel szukanj pozycji katalogowej. Jezeli znajdowala sie ona juz w pamieci to ustawia ja na koniec kolejki level2_cache (w razie potrzeby przenoszac ja z level1_cache i usuwajac pierwszy element z level2_cache) Jezeli nie bylo jej w pamieci to wstawia ja na koniec kolejki level1_cache usuwajac jej pierwszy element (Jesli nie bylo jej i na dysku to numer i-wezla jest 0 ).


Funkcja namei

Teraz mozemy przejsc do funkcji namei ,ktorej kod mozemy znalezc w

Funkcja namei

DEFINICJA: int namei(const char *pathname, struct inode ** resinode)

WYNIK: 0 i szukany i-wezel na * resinode w przypadku sukcesu
       kod bledu w przypadku porazki - bledy takie jak w funkcjach 
                            followlink i lookup plus
                            ENAMETOOLONG ( sciezka nie miesci sie na jednej stronie )
                            ENOMEM       ( brakuje pamieci , aby wczytac sciezke  )                        
{
     wczytaj nazwe sciezkowa do przestrzeni adresowj jadra ;
    /* wielkosc nazwy nie moze przekraczac wielkosci strony */
    /* W tym momencie wywolywana jest fukcja dir_namei zwracajaca 
    i-wezel katalogu maciezystego szukanego pliku .Kod jej znajduje 
     sie w pliku linux/fs/namei.c . Dla czytelnosci opis jej umieszcze 
    w opisie namei */ 
    if(sciezka zaczyna sie od "/")
            jako katalog roboczu wez korzen systemu plikow (current->fs->root)
    else 
            jako katalog roboczy wez bierzacy katalog procesu(current->fs->pwd);
    zwieksz licznik odwolan do katalogu roboczego (i_count); 
    while(1)
    { 
          wczytaj kolejne skladowe nazwy sciezkowej; 
          if(skladowa pusta) /*koniec sciezki*/
                  break;  
          zwieksz licznik odwolan do katalogu roboczego(i_count); 
          znajdz pozycje katalogowa wywolujac lookup; 
          if(lookup zwrocila blad) 
          { 
                 zwolnij i-wezel katalogu roboczego(iput);
                 wyjdz z bledem zwroconym przez lookup;
          } 
          wywolaj followlink w celu obslugi ewentualnego dowiazania symbolicznego;
          /* Jako wskaznik na ktory followlink wpisze wynik wez wskaznik do
           katalogu roboczego , dzieki temu po followlink katalog roboczy bedzie
          zmieniony na nastepny w nazwie sciezkowej */ 
          if(followlink zwrocila blad ) 
               wyjdz z bledem zwroconym przez followlink;
    } 
    /* tu jest koniec funkcji dir_namei */ 
    wywolaj lookup , aby znalezc koncowy plik;
    if(lookup zwrocila blad ) 
         wyjdz z bledem zwroconym przez lookup; 
    wywolaj followlink do obslugi ewentualnego dowiazania symbolicznego;
    zwolnij strone w pamieci jadra ,gdzie wpisana jest sciezka; 
    zwroc 0;
 } 


Bibilografia


Pytania i odpowiedzi


Autor: Malgorzata Guziak