FILSYS(5) UNIX Programmer's Manual FILSYS(5) NAME filsys, fblk, ino - format of file system volume SYNOPSIS #include #include #include #include DESCRIPTION Every file system storage volume (e.g. HP disk, RL disk, RK disk) has a common format for certain vital information. Every such volume is divided into a certain number of BSIZE blocks (in bytes; specified in ). Block 0 is unused and is available to contain a bootstrap program, pack label, or other information. Block 1 (SUPERB) is the _s_u_p_e_r _b_l_o_c_k. The layout of the super block as defined by the include file <_s_y_s/_f_i_l_s_y_s._h> is: /* * Structure of the super-block */ struct filsys { u_short s_isize; /* size in blocks of i-list */ daddr_t s_fsize; /* size in blocks of entire volume */ short s_nfree; /* number of addresses in s_free */ daddr_t s_free[NICFREE]; /* free block list */ short s_ninode; /* number of i-nodes in s_inode */ ino_t s_inode[NICINOD]; /* free i-node list */ char s_flock; /* lock during free list manipulation */ char s_ilock; /* lock during i-list manipulation */ char s_fmod; /* super block modified flag */ char s_ronly; /* mounted read-only flag */ time_t s_time; /* last super block update */ daddr_t s_tfree; /* total free blocks*/ ino_t s_tinode; /* total free inodes */ short s_dinfo[2]; /* interleave stuff */ #define s_m s_dinfo[0] #define s_n s_dinfo[1] char s_fsmnt[12]; /* ordinary file mounted on */ ino_t s_lasti; /* start place for circular search */ ino_t s_nbehind; /* est # free inodes before s_lasti */ }; #ifdef KERNEL struct filsys *getfs(); #endif _S__i_s_i_z_e is the address of the first block after the i-list, which starts just after the super-block, in block 2. Thus Printed 8/5/83 1 FILSYS(5) UNIX Programmer's Manual FILSYS(5) is i-list is _s__i_s_i_z_e-2 blocks long. _S__f_s_i_z_e is the address of the first block not potentially available for allocation to a file. These numbers are used by the system to check for bad block addresses; if an `impossible' block address is allocated from the free list or is freed, a diagnostic is written on the on-line console. Moreover, the free array is cleared, so as to prevent further allocation from a presum- ably corrupted free list. The free list for each volume is maintained as follows. The _s__f_r_e_e array contains, in _s__f_r_e_e[_1], ... , _s__f_r_e_e[_s__n_f_r_e_e-_1], up to NICFREE free block numbers. NIC- FREE is a configuration constant. _S__f_r_e_e[_0] is the block address of the head of a chain of blocks constituting the free list. The layout of each block of the free chain as defined in the include file <_s_y_s/_f_b_l_k._h> is: struct fblk { short df_nfree; daddr_t df_free[NICFREE]; }; The fields _d_f__n_f_r_e_e and _d_f__f_r_e_e in a free block are used exactly like _s__n_f_r_e_e and _s__f_r_e_e in the super block. To allocate a block: decrement _s__n_f_r_e_e, and the new block number is _s__f_r_e_e[_s__n_f_r_e_e]. If the new block address is 0, there are no blocks left, so give an error. If _s__n_f_r_e_e became 0, read the new block into _s__n_f_r_e_e and _s__f_r_e_e. To free a block, check if _s__n_f_r_e_e is NICFREE; if so, copy _s__n_f_r_e_e and the _s__f_r_e_e array into it, write it out, and set _s__n_f_r_e_e to 0. In any event set _s__f_r_e_e[_s__n_f_r_e_e] to the freed block's address and increment _s__n_f_r_e_e. _S__n_i_n_o_d_e is the number of free i-numbers in the _s__i_n_o_d_e array. To allocate an i-node: if _s__n_i_n_o_d_e is greater than 0, decrement it and return _s__i_n_o_d_e[_s__n_i_n_o_d_e]. If it was 0, read the i-list and place the numbers of all free inodes (up to NICINOD) into the _s__i_n_o_d_e array, then try again. To free an i-node, provided _s__n_i_n_o_d_e is less than NICINODE, place its number into _s__i_n_o_d_e[_s__n_i_n_o_d_e] and increment _s__n_i_n_o_d_e. If _s__n_i_n_o_d_e is already NICINODE, don't bother to enter the freed i-node into any table. This list of i-nodes is only to speed up the allocation process; the information as to whether the inode is really free or not is maintained in the inode itself. _S__f_l_o_c_k and _s__i_l_o_c_k are flags maintained in the core copy of the file system while it is mounted and their values on disk are immaterial. The value of _s__f_m_o_d on disk is likewise immaterial; it is used as a flag to indicate that the super-block has changed and should be copied to the disk Printed 8/5/83 2 FILSYS(5) UNIX Programmer's Manual FILSYS(5) during the next periodic update of file system information. _S__r_o_n_l_y is a write-protection indicator; its disk value is also immaterial. _S__t_i_m_e is the last time the super-block of the file system was changed. During a reboot, _s__t_i_m_e of the super-block for the root file system is used to set the system's idea of the time. I-numbers begin at 1, and the storage for i-nodes begins in block 2. I-nodes are 64 bytes long, so 8 of them fit into a block. I-node 2 is reserved for the root directory of the file system, but no other i-number has a built-in meaning. Each i-node represents one file. The format of an i-node as given in the include file <_s_y_s/_i_n_o._h> is: /* * Inode structure as it appears on * a disk block. */ struct dinode { u_short di_mode; /* mode and type of file */ short di_nlink; /* number of links to file */ short di_uid; /* owner's user id */ short di_gid; /* owner's group id */ off_t di_size; /* number of bytes in file */ char di_addr[40]; /* disk block addresses */ time_t di_atime; /* time last accessed */ time_t di_mtime; /* time last modified */ time_t di_ctime; /* time created */ }; #ifndef UCB_NKB #define INOPB 8 /* 8 inodes per block */ /* * 39 of the address bytes are used; * 13 addresses of 3 bytes each. */ #endif #if UCB_NKB==1 #define INOPB 16 /* 16 inodes per BSIZE block */ /* * 21 of the address bytes are used; * 7 addresses of 3 bytes each. */ #endif _D_i__m_o_d_e tells the kind of file; it is encoded identically to the _s_t__m_o_d_e _f_i_e_l_d _o_f _s_t_a_t(2). _D_i__n_l_i_n_k is the number of directory entries (links) that refer to this i-node. _D_i__u_i_d Printed 8/5/83 3 FILSYS(5) UNIX Programmer's Manual FILSYS(5) and _d_i__g_i_d are the owner's user and group IDs. _S_i_z_e is the number of bytes in the file. _D_i__a_t_i_m_e and _d_i__m_t_i_m_e are the times of last access and modification of the file contents (read, write or create) (see _t_i_m_e_s(2)); _D_i__c_t_i_m_e records the time of last modification to the inode or to the file, and is used to determine whether it should be dumped. Special files are recognized by their modes and not by i- number. A block-type special file is one which can poten- tially be mounted as a file system; a character-type special file cannot, though it is not necessarily character- oriented. For special files, the _d_i__a_d_d_r field is occupied by the device code (see _t_y_p_e_s(5)). The device codes of block and character special files overlap. Disk addresses of plain files and directories are kept in the array _d_i__a_d_d_r packed into 3 bytes each. The first 10 addresses specify device blocks directly. The last 3 addresses are singly, doubly, and triply indirect and point to blocks of 128 block pointers. Pointers in indirect blocks have the type _d_a_d_d_r__t (see _t_y_p_e_s(5)). For block _b in a file to exist, it is not necessary that all blocks less than _b exist. A zero block number either in the address words of the i-node or in an indirect block indi- cates that the corresponding block has never been allocated. Such a missing block reads as if it contained all zero words. SEE ALSO stat(2), dir(5), types(5), dcheck(8), fsck(8), icheck(8), mount(8) Printed 8/5/83 4