Linux VFS ========= Toto tu pisu proto, ze naprosto jasne ukazuje, jak unix z filesystemem pracuje, proto to je uzitecne i proto ty, co se nezabyvaji primo linuxem. Na zacatku linux podporoval pouze jeden filesystem a to minix. Pozdeji bylo ale nutne pridat i dalsi filesystemy. Proto byl vytvoren vfs. To je vlastne soubor funkci, ktere delaji vyssi funkce, jako je cachovani, prace se soubory, otvirani podle jmena etd.. Pouzivaji k tomu naproste minimum low level funkci, ktere obsahuje vlastni ovladac fs. Vsechny funkce ovladace jsou volany pomoci tabulek, ktere obsahuji bud adresu funkce a nebo NULL. V tom pripade se pouzije standartni funkce z vfs, ktera funkci provede pomoci volani nekterych nizsich funkci. To umoznuje psat napriklad ovladac od dos filesystemu, kde vsechno pracuje naprosto jinak. Je to ale samozdrejme pracnejsi a slozitejsi. Prvni takova tabulka je: struct super_operations { void (*read_inode) (struct inode *); int (*notify_change) (struct inode *, struct iattr *); void (*write_inode) (struct inode *); void (*put_inode) (struct inode *); void (*put_super) (struct super_block *); void (*write_super) (struct super_block *); void (*statfs) (struct super_block *, struct statfs *, int); int (*remount_fs) (struct super_block *, int *, char *); }; To je tabulka pro praci se superblokem. Obsahuje ty uplne zakladni funkce pro praci s filesystemem mimo mount. Protoze v dobe volani mount se jeste tato tabulke nezna(je vrace ve strukture, kterou mount vraci) Vyznam polozek: read_inode nacteni zakladnich udaju nektere inody...tedy neco jako open nebo stat. Jakmile ma jadro udaje o inode v pameti, muze se souborem bezne pracovat-ukladat atd... write_inode ulozeni dat o inode z pameti sped na disk. pouziva se hlavne pri provadeni close. Soubor v linuxu nema nulovou delku, kdyz se snim pracuje. Jadro jednoduse pouziva inodu v pameti a neotvira ji...tady nekde prameni pomalost ls.. Pri volani stat se otvira inoda a to se vola funkce namei, kde se k tomu souboru musi dolest po adresarove strukture, potom se zjisti cislo inody. Musi projit cela tabulka inod, jsetli jiz neni otevrena, potom se vytahnou dulezite informace..a zavola se iput, ktera inodu zase uvolni. Write_inode se vola pouze v pripade, ze inoda je dirty. Tato smycka bezi celkem rychle na ext2fs, protoze je tam dobre udelana directory cache a tak se rychle dostane, kam potrebuje. Ovsem treba na msdos nebo umsdos to je katastrofa. put_inode Vynuluje velikost inody a ovolni ji z disku...tedy neco jako delete write_super Updatne hodnoty v superblocku. Vola se pri sync..tusim put_super Updatne hodnoty v superblock a unmoutne filesystem statfs Vrati indormace o volnem miste apod.... S pokud mame inodu v pameti, muzeme s ni pracovat pomoci inode_operations: struct inode_operations { struct file_operations * default_file_ops; int (*create) (struct inode *,const char *,int,int,struct inode **); int (*lookup) (struct inode *,const char *,int,struct inode **); int (*link) (struct inode *,struct inode *,const char *,int); int (*unlink) (struct inode *,const char *,int); int (*symlink) (struct inode *,const char *,int,const char *); int (*mkdir) (struct inode *,const char *,int,int); int (*rmdir) (struct inode *,const char *,int); int (*mknod) (struct inode *,const char *,int,int,int); int (*rename) (struct inode *,const char *,int,struct inode *,const char *,int); int (*readlink) (struct inode *,char *,int); int (*follow_link) (struct inode *,struct inode *,int,int,struct inode **); int (*readpage) (struct inode *, struct page *); int (*writepage) (struct inode *, struct page *); int (*bmap) (struct inode *,int); void (*truncate) (struct inode *); int (*permission) (struct inode *, int); int (*smap) (struct inode *,int); }; vyznam: Prace s adresari: create vytvori novou adresarovou polozku lookup nacte adresarovou polozku link prideli adresarovou polozku inode-vytvori hard link unlink zrusi odkaz na inodu a pokud uz nic na ni neukazuje, smaze ji symlink vytvori symbolicky link-vlastni inodu se jmenem+adresarovou polozku mkdir,rmdir,mknod,rename snad jasne... prace s linky: readlink nacte cestu ze symbolickeho linku follow_link nasleduje link-otevre novou inodu se souborem kam symlink ukazuje prace s beznymi soubory: readpage writepage nacteni a ulozeni stranky...je vyuzivano mm pro mapovani souboru vetsinou je mozne pouzit readpage_generic a writepage_generic, ktere vyuzivaji bmap bmap block map...vraci, se kterych bloku se inoda sklada... potom generic mmap a writepage/readpage muzou vyuzivat jejich vlastni tabulku, kde je soubor ulozen a cist je bez toho, aby se zdrzovali nejakym volanim ovladace truncate skraceni souboru Ta uplne zakladni prace se souborem je ve zvlastni tabulce: struct file_operations { int (*lseek) (struct inode *, struct file *, off_t, int); int (*read) (struct inode *, struct file *, char *, int); int (*write) (struct inode *, struct file *, const char *, int); int (*readdir) (struct inode *, struct file *, void *, filldir_t); int (*select) (struct inode *, struct file *, int, select_table *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct inode *, struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); void (*release) (struct inode *, struct file *); int (*fsync) (struct inode *, struct file *); int (*fasync) (struct inode *, struct file *, int); int (*check_media_change) (kdev_t dev); int (*revalidate) (kdev_t dev); }; Tato tabulka uz obsahuje praci se souborem tak, jak ji zname Valna cast teto tabulky je implementovana pomoci vfs. A vola inode/sb operace. bezny filesystem implementuje pouze: pro bezny soubor: read nacte data z inody..je trosku odlisna od bezneho pohledu, protoze dostava pozici odkud cist. Nema tedy klasicky nahled na vec, kde system ma nekde ukazatel na pozici a read ho nacte a posune. Je to tim, ze jedna inoda muze byt sdilena X procesy...a proto by takovy ukazatel blbnul Je tu mozne pouzit i generic_file read, ktery pomoci bmap nacte sam write co asi... Tady generic sluzby nepomuzou, protoze kdyz se zapisuje za konec inody, musi se prodlouzit mmap Je take vetsinou generic...mapovani do pameti fsync flusne vsechny cache pro adresar(protoze adresare jsou vlastne bezne soubory): read readdir fsync Tim jsem vycerpal veskere problemy spojene s delanim noveho filesystemoveho ovladace. Pro uplnost jen strukturu inode a superblock: struct inode { kdev_t i_dev; /*zarizeni, na kterem se data nachazeji*/ unsigned long i_ino; /*cislo inody*/ umode_t i_mode; /*jaka je-adresar,file apod*/ nlink_t i_nlink;/*kolik adresarovych polozek na ni ukazuje..0=inoda je free*/ uid_t i_uid; /*vlastnici*/ gid_t i_gid; kdev_t i_rdev; off_t i_size; /*velikost*/ time_t i_atime;/*casy vytvoreni,modifikace apod.*/ time_t i_mtime; time_t i_ctime; unsigned long i_blksize;/*velikost bloku pouzita na fs*/ unsigned long i_blocks;/*pocet datovych bloku inody*/ unsigned long i_version;/*vyuzivane nfs pro cachovani*/ unsigned long i_nrpages; struct semaphore i_sem; /*pro sdileni vice procesy*/ struct inode_operations *i_op; /*zname tabulky*/ struct super_block *i_sb; struct wait_queue *i_wait;/*procesy cekajici na praci s inodou*/ struct file_lock *i_flock;/*zamykani souboru*/ struct vm_area_struct *i_mmap; /*kam je namapovana*/ struct page *i_pages; /*jeji stranky*/ struct dquot *i_dquot[MAXQUOTAS]; struct inode *i_next, *i_prev; /*udkazy na dalsi inody...*/ struct inode *i_hash_next, *i_hash_prev; struct inode *i_bound_to, *i_bound_by; struct inode *i_mount; unsigned short i_count; /*kolikrat je otevrena*/ unsigned short i_flags; /*flagy...rwx*/ unsigned char i_lock; unsigned char i_dirt; /*souhlasi ze stavem na disku?*/ unsigned char i_pipe; /*pri icp*/ unsigned char i_sock; unsigned char i_seek; unsigned char i_update; unsigned short i_writecount; union { struct pipe_inode_info pipe_i; struct minix_inode_info minix_i; struct ext_inode_info ext_i; struct ext2_inode_info ext2_i; struct hpfs_inode_info hpfs_i; struct msdos_inode_info msdos_i; struct umsdos_inode_info umsdos_i; struct iso_inode_info isofs_i; struct nfs_inode_info nfs_i; struct xiafs_inode_info xiafs_i; struct sysv_inode_info sysv_i; struct socket socket_i; void * generic_ip; } u; }; struct file { /*tato struktura je vytvorana volanim open*/ mode_t f_mode; /*adresar,file apod*/ loff_t f_pos; /*pozice v souboru*/ unsigned short f_flags; /*flagy*/ unsigned short f_count; loff_t f_reada; struct file *f_next, *f_prev; int f_owner; /* pid or -pgrp where SIGIO should be sent */ struct inode * f_inode; /*zname struktury.....*/ struct file_operations * f_op; unsigned long f_version;/*pro nfs cachi*/ void *private_data; /* needed for tty driver, and maybe others */ }; struct super_block { kdev_t s_dev; /*na kterem disky se vyskytuje*/ unsigned long s_blocksize; /*velikost bloku*/ unsigned char s_blocksize_bits; unsigned char s_lock; unsigned char s_rd_only; /*jestli je readonly*/ unsigned char s_dirt; /*jestli souhlasi se stavem na disku*/ struct file_system_type *s_type;/*ktery filesystem*/ struct super_operations *s_op; /*znama tabulka*/ struct dquot_operations *dq_op; /*pro quote-omezovani disku uzivatelum*/ unsigned long s_flags; unsigned long s_magic; /*poznavaci string*/ unsigned long s_time; struct inode * s_covered; struct inode * s_mounted; struct wait_queue * s_wait; union { struct minix_sb_info minix_sb; struct ext_sb_info ext_sb; struct ext2_sb_info ext2_sb; struct hpfs_sb_info hpfs_sb; struct msdos_sb_info msdos_sb; struct isofs_sb_info isofs_sb; struct nfs_sb_info nfs_sb; struct xiafs_sb_info xiafs_sb; struct sysv_sb_info sysv_sb; void *generic_sbp; } u; };