Algorytm przydzielania bloku getblk( ) input: output: file system number block number locked buffer that can now be used for block while (buffer not found) if (block in hash queue) if (buffer busy) /* scenario 5 */ sleep (event buffer becomes free); continue; /* back to while loop */ lock buffer; /* scenario 1 */ remove buffer from free list; return buffer; else /* block not on hash queue */ if (no free buffers) /* scenario 4 */ sleep (event any buffer becomes free); continue; /* back to white loop */ remove buffer from free list; if (buffer marked for delayed write) /* scenario 3 */ asynchronous write buffer to disk; continue; /* back to while loop */ /* scenario 2--found a free buffer */ remove buffer from old hash queue; put buffer onto new hash queue; return buffer;
Algorytm zwalniania bufora brelse( ) input: locked buffer output: none wakeup( all procs, waiting for any buffer to become free); wakeup( all procs, waiting for this buffer to become free); raise processor execution level to block interrupts; if (buffer contents valid && buffer not old) enqueue buffer at end of free list; else enqueue buffer at beginning of free list; lower processor execution level to allow interrupts; unlock(buffer);
Algorytmy czytania bloku 1. czytanie pojedynczego bloku bread( ) input: block number output: buffer containing data getblk(block number); if (buffer data valid) return buffer; initiate disk read; sleep(event disk read complete); return (buffer); /*synchronous*/
2. czytanie bloku z look-ahead breada() input: output: block number for immediate read block number for asynchronous read buffer containing data for immeciiate read if (first block not in cache) getblk(first block); if (buffer data not valid) initiate disk read; if (second block not in cache) getbl k(second block); if (buffer data valid) brelse(second block); else initiate disk read; if (first block was originally in cache) bread (first block); return buffer; sleep (event first buffer contains valid data); return buffer; /*synchronous*/ /*asynchronous*/
Algorytm zapisu bloku bwrite( ) input: buffer output: none initiate disk write; if (l/o synchronous) sleep(event I/O complete); brelse(buffer); else if (buffer marked for delayed write mark buffer to put at head of free list;
Algorytm czytania INODE iget() input: file system inode number output: locked inode while (not done) if (inode in inode cache) if (inode locked) sleep (event inode becomes unlocked); continue; /* loop */ /*tutaj ominiety kod dot. wej if (inode on inode free list) remove from free list; increment inode reference count; return (inode); /* inode not in inode cache */ if (no inodes on free list) return(error); remove new inode from free list, reset inode number and file system; remove inode from old hash queue, place on new one; bread(inode block); initialize inode (reference count = 1); return (inode);
Zwalnianie kopii INODE w pamieci iput() input: pointer to in-core inode output: none lock inode if not already locked; decrement inode reference count; if (reference count==0) if(inode link count==0) free disk blocks for file (algorithm free); set file type to 0; ifree(inode); if (file accessed or inode changed or file changed) update disk inode; put inode on free list; release inode lock;
Algorytm przydzialu nowego INODE ialloc() input: file system output: locked inode while (not done) if (superblock locked) sleep (event superblock becomes free); continue; /* loop */ if (inode list in superblock is empty) lock superblock; get remembered inode for free inode search; search disk for free inodes until superblock full, or no more free inodes (algorithms bread and brelse); unlock superblock; wakeup (event superblock becomes free); if (no free inodes found on disk) return (no inode); set remembered inode for next free inode search; /*there are inodes in superblock inode list */ iget(inode number from superblock inode list); if (inode not free after all) write inode to disk; iput(inode); continue; /* loop */ /*inode is free */ initialize inode; write inode to disk; decrement file system free inode count; return (inode);
Algorytm zwalniania INODE ifree( ) input: file system inode number output: none increment file system free inode count; if (superblock locked) return; if (inode list full) if (inode number less than remembered inode for search) remembered inode for search = input inode number; else store inode number in inode list; return;
Algorytm przydzialu bloku dyskowego alloc() input: file system number output: buffer for new block while (superblock locked) sleep (event superblock not locked); remove block from superblock free list; if (removed last block from free list) lock superblock; bread (block just taken from free list); copy block numbers in block into superblock; brelse(block buffer); unlock superblock; wakeup(event superblock not locked); getblk (block removed from superblock list); zero buffer contents; decrement total count of free blocks; mark superblock modified; return buffer;
bmap () input: output: inode byte offset block number in file system byte offset into block bytes of I/O in block read ahead block number calculate logical block number in file from byte offset; calculate start byte in block for I/O; /* output 2*/ calculate number of bytes to copy to user; /* output 3 */ check if read-ahead applicable, mark inode; /* output 4 */ determine level of block indirection; while (not at necessary level of indirection) calculate index into inode or indirect block from logical block number in file; get disk block number from inode or indirect block; brelse(buffer from previous disk read, if any); if (no more levels of indirection) return (block number); bread (indirect block); adjust logical block number in file according to level of indirection;
namei( ) input: path name output: locked inode if (path name starts from root) wd = iget(root); else wd = iget(current directory inode); while (there is more path name) read next path name component from input; verify wd is a directory, access permissions OK; if (wd is root && component is "..") continue; /* loop */ read wd using algorithms bmap, bread and brelse; if (component matches an entry in wd) get inode number for matched component; iput(wd); wd = iget(matched component); else /* component not in directory */ / return (no inode); return (wd);
Algorytm tworzenia nowego pliku creat( ) input: output: file name permission settings file descriptor namei(file name); if (file already exists) if (not permitted access) iput(inode); return (error); else /* file does not exist yet */ ialloc(); create new directory entry in parent directory; include new file name and newly assigned inode number; allocate file table entry for inode initialize count; if (file did exist at time of create) free all file blocks (algorithm free); unlock (inode); return(user file descriptor);
Algorytm otwierania pliku open() inputs: output: filename type of open file permissions (for creation type of open) file handle namei(filename); if (file does not exist or not permitted access) return(error); allocate file table entry for inode, initialize count, offset; allocate user file descriptor entry, set pointer to file table entry; if (type of open specifies truncate file) free(all file blocks); unlock(inode); /* locked in namei */ return(user file descriptor);
Algorytmy czvtania i zapisu do pliku read/write() input: output: handle address number of bytes number of bytes read/written get file table entry from user file descriptor; check file accessibility; set params in u-area: address, byte count, l/o direction; get inode from file table; lock inode; set byte offset in u-area from file table offset; while (count not satisfied) disk block = bmap(file offset); calculate offset into block, number of bytes to read; /*==== read write differ in this part =====*/ /* version for read */ if (number of bytes == 0) break; /* end of file */ bread(disk block) /*breada if with read ahead*/ copy data to user address; /* version for write */ if(new block) alloc(); /*multiple allocations if indirect block*/ if (failure in allocation) break; /*out of disk space*/ else if(writing part of block) bread(disk block); else getblk(); copy data to buffer; mark buffer as updated; /*===== algorithms similar from this point ====*/ update u-area fields: file byte offset, read count, user address; brelse(buffer); /* locked in bread */ unlock(inode); update file table offset for next read; return (total number of bytes read/written);
Algorytm otwierania pipe bez nazwy pipe( ) input: none output: read file descriptor write file descriptor; ialloc(new inode); allocate file table entry for reading, another for writing; initialize file table entries to point to new inode; allocate user file descriptor for reading; initialize to point to respective file table entries; set inode reference count to 2; initialize count of inode readers, writers to 1;
Algorytm tworzenia nowej pozycji katalogowej mknod( ) inputs: file name file type permissions major, minor device no. (block or character special files) output: none if (new node not named pipe and user not super user) return(error); namei(file name); if (new node already exists) iput(parent inode); return (error); ialloc(); create new directory entry in parent directory: include new node name and newly assigned inode number; iput(parent inode); if (new node is block or character special file) write major, minor numbers into inode structure; iput(new node inode);
! mount( ) inputs: output: file name of block special file directory name of mount point options (read only) none if (not super user) return(error); get inode for block special file (algorithm namei); make legality checks; get inode for mounted on directory name (algorithm namei); if (not directory, or reference count > 1) release inodes (algorithm iput); return (error); find empty slot in mount table; invoke block device driver open routine; get free buffer from buffer cache; read superblock into free buffer; initialize superblock fields; get root inode of mounted device (algorithm iget), save in mount table; mark inode of mounted on directory as mount point; release special file inode (algorithm iput); unlock inode of mount point directory;
! umount() input: special file name of file system to be unmounted output: none if (not superuser) return(error); get inode of special file (algorithm namei); extract major, minor number of device being unmounted; get mount table entry, based on major, minor number; release inode of special file (algorithm iput); remove shared text entries from region table for files belonging to file system; update superblock, inodes, flush buffers; if (files from file system still in use) return (error); get root inode of mounted file system from mount table; lock inode; release inode (algorithm iput); /* iget was in mount */ invoke close routine for special device; invalidate buffers in pool from unmounted file system; get inode of mount point from mount table; lock inode; clear flag marking it as mount point; release inode (algorithm iput); /* iget in mount */ free buffer used for superblock; free mount table slot;
Zmodyfikowany algorytm iget (dla wielu systemów plików) iget( ) input: file system inode number output: locked inode while (not done) if (inode in inode cache) if (inode locked) sleep (event inode becomes unlocked); continue; /* loop */ /* special processing for mount points */ if (inode a mount point) find mount table entry for mount point; get new file system number from mount table; use root inode number in search; continue; * loop again */ if (inode on inode free list) remove from free list; increment inode reference count; return (inode); /* inode not in inode cache */ remove new inode from free list; reset inode number and file system; remove inode from old hash queue, place on new one; read inode from disk (algorithm bread); initialize inode (e.g. reference count to 1); return inode;
Zmodyfikowany algorytm namei int namei() input: path name output: locked inode if (path name starts from root) working inode = root inode (algorithm iget); else working inode = current directory inode (algorithm iget); while (there is more path name) read next path name component from input; verify that inode is of directory, permissions; if (inode is of changed root and component is.. ) continue; /* loop */ component search: read inode (directory) (algorithms bmap, bread, brelse); if (component matches a directory entry) get inode number for matched component; if (found inode of root and working inode is root and and component name is.. ) /* crossing mount point */ get mount table entry for working inode; release working inode (algorithm iput); working inode = mounted on inode; lock mounted on inode; increment reference count of working inode; go to component search; /* for.. */ iput (working inode); working inode = iget (new inode number); else /* component not in directory */ return (no inode); return (working inode);
link( ) input: output: existing file name new file name none get inode for existing file name (algorith namei); if (too many links on file or linking directory without superuser permission) release inode (algorithm iput); return(error); increment link count on inode; update disk copy of inode; unlock inode; get parent inode for directory to contain new file name (algorith namei); if (new file name already exists or new file on different file system) undo update done above; return(error); create new directory entry in parent directory of new file name: include new file name, inode number of existing file name; release parent directory inode (algorith iput); release inode of existing file (algorith iput);
" unlink( ) input: file name output: none get parent inode of file to be unlinked (algorithm namei); if (last component of file name is. ) increment inode reference count; else get inode of file to be unlinked (algorithm iget); if (file is directory but user is not superuser) release inodes (algorithm iput) ; return(error); if (shared text file and link count currently 1) remove from region table; write parent directory: zero inode number of unlinked file; release inode parent directory (algorithm iput); decrement file link count; release file inode (algorithm iput); /* iput checks if link count is 0: if so, * releases file blocks (algorithm free) and * frees inode (algorithm ifree); */