Do spisu treści tematu 

6.4.2 Algorytm iput 



Spis treści

Wprowadzenie

Jeżeli proces zakończył operację z plikiem (a więc także z i węzłem ), musi on zwolnić
kopię pamięciową i-węzła, aby inne procesy mogły pobrać wolny i-węzeł.
Generalnie algorytm polega na zmniejszeniu licznika otwarć pliku(i_count),
oraz wykonaniu specjalnych czynności w przypadku, gdy proces jest ostatnim
zamykającym plik(i_count==0). Czynności te to: Algorytm ten w Linuxie 2.0.32 jest realizowany przez funkcję iput, znajdującą się
w pliku inode.c.

 Skomentowany Kod

void iput(struct inode * inode)
{
                if (!inode)
                        return;
                    Wykonaj test blokady
                   wait_on_inode(inode);
                      Jeżeli licznik otwarć(i_count) = 0 wyjdź;
                   if (!inode->i_count) {
                         printk("VFS: iput: trying to free free inode\n");
                        printk("VFS: device %s, inode %lu, mode=0%07o\n",
                        kdevname(inode->i_rdev), inode->i_ino, inode->i_mode);
                         return;
                    }
                    Jeżeli inode jest typu PIPE, obudż wszystkie przerywalne procesy
                     z kolejki PIPE_WAIT(*inode)
                   if (inode->i_pipe)
                          wake_up_interruptible(&PIPE_WAIT(*inode));
repeat:
                    Jeżeli licznik otwarć jest > 1 to zmniejsz go o 1 i wyjdz;
                if (inode->i_count>1) {
                     inode->i_count--;
                     return;
                }
                  Zwolnij procesy czekające na wolny i-węzel w kolejce inode_wait;
                wake_up(&inode_wait);

                  Jeżeli inode byl typu PIPE, zwolnij związana z nim stronę pamięci
                if (inode->i_pipe) {
                unsigned long page = (unsigned long) PIPE_BASE(*inode);
                PIPE_BASE(*inode) = NULL;
                  free_page(page);
                }
                Jeżeli wskaźniki do funkcji put_inode i pośrednie są OK
               if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode) {
                  wykonaj  funkcje put_inode odpowiednią do systemu plików;
                inode->i_sb->s_op->put_inode(inode);
                   jeżeli liczba dowiązań do pliku wynosi 0, wyjdź
                if (!inode->i_nlink)
                        return;
        }

         Jeżeli i-węzel należy zaktualizować
        if (inode->i_dirt) {
                 nagraj i-węzel
                write_inode(inode);     /* we can sleep - so do again */
                  wykonaj test na blokadę
                wait_on_inode(inode);
                goto repeat;
        }
         Jeżeli i-węzel ma charakter nagrywalny(plik,katalog lub link) i
         są zdefiniowane operacje na quota
        if (IS_WRITABLE(inode)) {
                if (inode->i_sb && inode->i_sb->dq_op) {
                        /* Here we can sleep also. Let's do it again
                         * Dmitry Gorodchanin 02/11/96 */
                          zalóż blokadę na inode
                        inode->i_lock = 1;
                           uaktualnij quotę
                        inode->i_sb->dq_op->drop(inode);
                           zdejmij blokadę
                        unlock_inode(inode);
                        goto repeat;
                }
        }
          zmniejsz licznik otwarć pliku
        inode->i_count--;

        if (inode->i_count)
        /*
         * Huoh, we were supposed to be the last user, but someone has
         * grabbed it while we were sleeping. Dont destroy inode VM
         * mappings, it might cause a memory leak.
         */
                return;

        if (inode->i_mmap) {
                printk("iput: inode %lu on device %s still has mappings.\n",
                        inode->i_ino, kdevname(inode->i_dev));
                inode->i_mmap = NULL;
        }
          zwiększ licznik wolnych i-węzlow
        nr_free_inodes++;
        return;
}


Funkcje pomocnicze

wait_on_inode()
jezeli flaga i_lock jest ustawiona zaśnij w kolejce zwiazanej z i-węzlem (wait_queue)

write_inode() ( w ext2 - ext_write_inode ),
drop_inode,
put_inode (w ext2 ext2_put_inode),
są to operacje wykonywane fizycznie na dysku, zależne od konkretnego systemu plikow,
zazwyczaj wykonywane przez super block. Czasami znajdują sie w nich także uaktualnienia pól struktury inode, np. czasu zmian itp.



 

 Bibliografia

    1.Pliki zrodlowe Linuxa:     2.Projekt Linux
    3.Maurice J. Bach "Budowa systemu operacyjnego UNIX" - rozdzial 4
    4.  Linux Kernel Hackers Guide


Autor:  Tomasz Sawicki