


_O_n_l_i_n_e _M_a_n_u_a_l             File Formats                      fs(5)



NNNNAAAAMMMMEEEE
     fs, inode - format of file system volume

SSSSYYYYNNNNTTTTAAAAXXXX
     ####iiiinnnncccclllluuuuddddeeee <<<<ssssyyyyssss////ttttyyyyppppeeeessss....hhhh>>>>
     ####iiiinnnncccclllluuuuddddeeee <<<<ssssyyyyssss////iiiinnnnooooddddeeee....hhhh>>>>
     ####iiiinnnncccclllluuuuddddeeee <<<<ssssyyyyssss////ffffxxxx....hhhh>>>>

DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
     Every file system storage volume has a common format for
     certain vital information.  Every such volume is divided
     into a certain number of blocks.  The block size is a param-
     eter of the file system.

     The actual file system begins with the _s_u_p_e_r _b_l_o_c_k. The lay-
     out of the super block as defined by the include file
     <_s_y_s/_f_x._h> is:

     /*
      *  fx.h -- primary file system space management structures
      *
      * Each logical volume contains exactly one file system.
      * A file system consists of a number of allocation units.
      * Each allocation unit has inodes and data.
      *
      * A file system is described by its super-block, which in turn
      * describes the allocation units.  The super-block is critical
      * data and is replicated in each allocation unit to protect against
      * catastrophic loss.  This is done at mkfs time and the critical
      * super-block data does not change, so the copies need not be
      * referenced further unless disaster strikes.
      *
      * For file system fx, the offsets of the various blocks of interest
      * are given in the super block as:
      *      [fx->fx_sblkno]         Super-block
      *      [fx->fx_aublkno]        Allocation unit block
      *      [fx->fx_iblkno]         Inode blocks
      *      [fx->fx_dblkno]         Data blocks
      * The beginning of allocation unit au in fx, is given by
      * the ``AUBASE(fx, au)'' macro.
      */

     #define SBSIZE          1024
     #define SBLOCK          ((daddr_t)(0))

     /*
      * Addresses stored in i-nodes address extents.  Extents are made up of
      * some number of blocks which is a power of two.  The block size is
      * a parameter of the logical volume.
      *
      * The root inode is the root of the file system.
      * Inode 0 can't be used for normal purposes and
      * historically bad blocks were linked to inode 1,
      * thus the root inode is 2. (inode 1 is no longer used for
      * this purpose, however numerous dump tapes make this
      * assumption, so we are stuck with it)
      * The lost+found directory is given the next available
      * inode when it is created by ``mkfx''.
      */






     #define ROOTINO         ((ino_t)2)      /* i number of all roots */
     #define LOSTFOUNDINO    (ROOTINO + 1)

     /*
      * Allocation unit related limits.
      */

     #define MAXBPU          (DEV_BSIZE * NBBY)

     /*
      * MAXIPU bounds the number of inodes per allocation unit, and
      * is needed only to keep the structure simpler by having the
      * only a single variable size element (the free bit map).
      *
      * N.B.: MAXIPU must be a multiple of INOPB(fx).
      */

     #define MAXIPU          2048    /* max number inodes/alloc unit */

     #define MINBSIZE        DEV_BSIZE

     /*
      * The path name on which the file system is mounted is maintained
      * in fx_fxmnt. MAXMNTLEN defines the amount of space allocated in
      * the super block for this name.
      */

     #define MAXMNTLEN 512

     /*
      * The extent bit-map is logically divided into two sections - the
      * single block map and the multi-block map.  Each of these two sections
      * is (obviously) the same size.
      */

     #define EMAPBLKS        2

     /*
      * We assume here that DEV_IOSIZE is the same as MAXBSIZE, a
      * spectacularly bad assumption.  Due to the design of the multi-
      * tiered bit-map, if 1024-byte blocks are used, there are 14 tiers
      * in the map, which spans two logical blocks.
      */

     #define NTIERS  (DEV_BSHIFT + 4)

     #define ISBIT(emap, bit) ( emap[(bit) / NBBY] & (1 << ((bit) % NBBY)) )

     #define BIT_IN_TIER(b, t)       ((b) >> (t))

     struct tier_descriptor
     {
         short       t_emapblk;              /* relative block within emap */
         short       t_bitoffset;            /* from start of block */
         short       t_nextents;             /* tier length in bits */
         short       t_extsize;              /* number of blocks (not bytes) */
     };

     #ifdef KERNEL
     struct tier_descriptor td[NTIERS];






     #endif KERNEL

     /*
      * Per allocation unit information; one per au block plus
      * one in the fx block which contains system-wide totals.
      * As of TX5, only us_ndir is maintained on disk (too hard to recompute)
      * all the other fields are recomputed at mount time.
      */

     struct usum
     {
         long        us_ndir;                /* number of allocated directories */
         long        us_nifree;              /* number of free inodes */
         long        us_nefree[NTIERS];      /* numbers of free extents */
     };

     struct fx_list
     {
         struct fx_list      *fxl_next;
         ino_t               fxl_ino;
         daddr_t             fxl_bn;
     };

     /*
      * Super block for a file system.
      */

     #define FX_MAGIC        0x011955
     #define FX_BSHIFT       DEV_BSHIFT
     #define FX_BMASK        (DEV_BSIZE - 1)

     /*  values for fx_flags */
     #define FX_LOGWRAPPED   0x01            /* log has wrapped around */
     #define FX_SYNCED       0x02            /* fs sync has occured */
     #define FX_UNMOUNT      0x04            /* file system is unmounting */
     #define FX_BLOCK_OPENS  0x08            /* file system is unmounting */
     #define FX_UMASK        0x0c            /* unmount masks */
     #define FX_RECOVERY     0x10            /* recovery in progress */

     /*
      * struct to keep track of indir blocks in memory.
      * A list is maintained from the super block
      */

     struct indir
     {
         int                 in_blkno;
         struct indir        *in_next;
     };

     struct fx
     {
         long        fx_magic;               /* magic number */
         long        fx_version;             /* file system version */
         struct fx   *fx_link;               /* linked list of file systems */
         struct fx   *fx_rlink;              /*     used for incore super blocks */
         daddr_t     fx_sblkno;              /* addr of super-block in filesys */
         daddr_t     fx_aublkno;             /* offset of au-block in filesys */
         daddr_t     fx_eblkno;              /* offset of emap block(s) in filesys */
         daddr_t     fx_iblkno;              /* offset of inode-blocks in filesys */






         daddr_t     fx_dblkno;              /* offset of first data after au */
         daddr_t     fx_dupoffset;           /* displacement of dup. control blks */
         UID_T       fx_uniqueid;            /* unique i.d. of this file system  */
         time_t      fx_time;                /* last time written */
         long        fx_size;                /* number of blocks in fx */
         long        fx_dsize;               /* number of data blocks in fx */
         long        fx_nau;                 /* number of allocation units */
         long        fx_bsize;               /* size of basic blocks in fx */
     /* these are configuration parameters */
         long        fx_minfree;             /* minimum percentage of free blocks */
         long        fx_maxbpu;              /* max number of blks per alloc unit */
     /* these fields can be computed from the others */
         long        fx_sbsize;              /* actual size of super block */
         long        fx_nindir[NIADDR];      /* values of NINDIR */
         long        fx_inopb;               /* value of INOPB */
         long        fx_sparecon[5];         /* reserved for future constants */
     /* time of last mount */
         time_t      fx_mount_time;
     /* sizes determined by number of allocation units and their sizes */
         long        fx_dbpu;                /* data blocks per allocation unit */
     /* these fields can be computed from the others */
         long        fx_ipu;                 /* inodes per alloc unit */
         long        fx_bpu;                 /* blocks per alloc unit */
     /* this data must be re-computed after crashes */
         long        fx_blocksfree;
         struct usum fx_ustotal;     /* alloc unit summary information */
     /* these fields are set at create time */
         char        fx_sysv;                /* File system uses SYSV semantic */
     /* these fields are cleared at mount time */
         char        fx_clean;               /* file system is clean flag */
         char        fx_ronly;               /* mounted read-only flag */
         char        fx_flags;               /* keeps in-memory flags */
         char        fx_fxmnt[MAXMNTLEN];    /* name mounted on */
     /* these fields retain the current block allocation info */
         long        fx_aurotor;             /* last au searched */
     /* these fields are used in memory only, and have no meaning on disk */
         struct usum         *fx_usp;           /* array ptr of fx_us info buffers */
         struct inode        *fx_lvp;           /* in-core ptr to lv descriptor */
         struct bufhdr       *fx_bufp;          /* back pointer to fx block bufhdr */
         struct fx_list      *fx_deletepending; /* inodes waiting to be closed */
         struct fx_list      *fx_holdlist;      /* blocks awaiting dealloc */
     /* what to audit in this file system */
         unsigned int        fx_aud;            /* flag for what to audit */
     /* these fields are used in memory only, and have no meaning on disk */
         int                 fx_unused2;        /* unused */
         int                 fx_unused3[2];     /* unused */
         int                 fx_unused4;        /* unused */
         int                 fx_unused5;        /* unused */
         int                 fx_lgsn;           /* last log serial number */
         int                 fx_sync;           /* Have we seen the sync */
     /* These fields are mainatined on disk */
         int                 fx_ptier;          /* default primary extent */
         int                 fx_stier;          /* default secondary extent */
     /* These fields are memory only */
         struct indir        *fx_indir;         /* list of accessed indir blocks */
         time_t              fx_dumpdate[10];   /* last dump of each level */
         int                 fx_dumpfreq;       /* days between dumps */
         logsn_t             fx_start_lsn;      /* start recovery block lsn */
         int                 fx_start_rec;      /* start recovery record in blk */
         logsn_t             fx_cur_lsn;        /* current start recovery lsn */






         int                 fx_cur_rec;        /* current recovery record in blk */
     /* padding to 1024 bytes */
         int                 fx_padding[45];    /* unused */
     };


     /*
      * Allocation unit block for a file system.
      */

     #define AU_MAGIC        0x090256

     struct au
     {
         long        au_magic;               /* magic number */
         struct au   *au_link;               /* linked list of alloc units */
         struct au   *au_rlink;              /*     used for incore alloc units */
         time_t      au_time;                /* time last written */
         long        au_aun;                 /* we are the aun'th allocation unit */
         long        au_bpu;                 /* number of total blocks this au */
         short       au_niblk;               /* number of inode blocks this au */
         short       au_spare;
         long        au_ndblk;               /* number of data blocks this au */
         long        au_unused[NTIERS];      /* Not used anymore */
         long        au_ndir;                /* number of free inodes */
         long        au_irotor;              /* position of last used inode */
         char        au_iused[MAXIPU/NBBY];  /* used inode map */
         char        *au_emap[EMAPBLKS];     /* ptrs to in-core emap blocks */
         bool_t      au_emapchg[EMAPBLKS];   /* for flagging changes to map blocks */
         unsigned int au_sum0;               /* hash sum */
         unsigned int au_sum1;               /* hash sum */

     /* actually longer */
     };

     /*
      * Allocation unit macros to locate things in allocation units.
      * They calc file system addresses of allocation unit data structures.
      */

     #define AUBASE(fx, c)   ((daddr_t)((fx)->fx_bpu * (c)))
     #define AUSBLOCK(fx, c) (AUBASE(fx, c) + (fx)->fx_sblkno)       /* super blk */
     #define AUTOD(fx, c)    (AUBASE(fx, c) + (fx)->fx_aublkno)      /* au block */
     #define AUTOE(fx, c)    (AUBASE(fx, c) + (fx)->fx_eblkno)       /* emap blk 1 */
     #define AUIMIN(fx, c)   (AUBASE(fx, c) + (fx)->fx_iblkno)       /* inode blk */
     #define AUDMIN(fx, c)   (AUBASE(fx, c) + (fx)->fx_dblkno)       /* 1st data */

     /*
      * Macros for handling inode numbers:
      *     inode number to file system block offset.
      *     inode number to allocation unit number.
      *     inode number to file system block address.
      */

     #define ITOO(fx, x)     ((x) % INOPB(fx))
     #define ITOU(fx, x)     ((x) / (fx)->fx_ipu)
     #define ITOD(fx, x) \\
             ((daddr_t)(AUIMIN(fx, ITOU(fx, x)) + \\
             (((x) % (fx)->fx_ipu) / INOPB(fx))))







     /*
      * Give allocation unit number for a file system block.
      * Give allocation unit block number for a file system block.
      */

     #define DTOU(fx, d)     ((d) / (fx)->fx_bpu)
     #define DTOUD(fx, d)    ((d) % (fx)->fx_bpu)
     #define DTOD(fx, d)     (((d) % (fx)->fx_bpu) - (fx)->fx_dblkno)

     /*
      * The following macros optimize certain frequently calculated
      * quantities by using shifts and masks in place of divisions
      * modulos and multiplications.
      */

     #define BLKOFF(fx, loc)         /* calculates (loc % DEV_BSIZE) */ \\
             ((loc) & FX_BMASK)
     #define LBLKNO(fx, loc)         /* calculates (loc / DEV_BSIZE) */ \\
             ((loc) >> FX_BSHIFT)
     #define BLKROUNDUP(fx, size)    /* calculates roundup(size, DEV_BSIZE) */ \\
             (((size) + DEV_BSIZE - 1) & FX_BMASK)

     /*
      * Determine the number of available blocks given a
      * percentage to hold in reserve
      */

     #define FREESPACE(fx, pctreservd) \\
             ((fx)->fx_blocksfree - ((fx)->fx_dsize * (pctreservd) / 100))

     /*
      * INOPB is the number of inodes in a secondary storage block.
      */

     #define INOPB(fx)       ((fx)->fx_inopb)

     /*
      * NINDIR is the number of indirects in a file system block.
      */

     #define NINDIR(fx, level)       ((fx)->fx_nindir[level])


December 1989                           TX Programmer's Reference
















