Home | History | Annotate | Download | only in ufs
      1 /*
      2  * Copyright (C) 2013 Raphael S. Carvalho <raphael.scarv (at) gmail.com>
      3  *
      4  * This program is free software; you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation; either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write to the
     16  * Free Software Foundation, Inc.,
     17  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     18 */
     19 
     20 #ifndef _UFS_H_
     21 #define _UFS_H_
     22 
     23 #include <stdint.h>
     24 
     25 /* Sector addresses */
     26 #define UFS1_SBLOCK_OFFSET	8192
     27 #define UFS2_SBLOCK_OFFSET	65536
     28 #define UFS2_SBLOCK2_OFFSET	262144
     29 
     30 #define UFS1_ADDR_SHIFT 2
     31 #define UFS2_ADDR_SHIFT 3
     32 
     33 /* Super magic numbers */
     34 #define UFS1_SUPER_MAGIC	(0x011954)
     35 #define UFS2_SUPER_MAGIC	(0x19540119)
     36 
     37 #define UFS_ROOT_INODE 2
     38 
     39 #define UFS_DIRECT_BLOCKS 12
     40 #define UFS_INDIRECT_BLOCK 1
     41 #define UFS_DOUBLE_INDIRECT_BLOCK 1
     42 #define UFS_TRIPLE_INDIRECT_BLOCK 1
     43 /* Total number of block addr hold by inodes */
     44 #define UFS_NBLOCKS 15
     45 
     46 /* Blocks span 8 fragments */
     47 #define FRAGMENTS_PER_BLK 8
     48 
     49 /* UFS types */
     50 typedef enum {
     51     NONE,
     52     UFS1,
     53     UFS2,
     54     UFS2_PIGGY,
     55 } ufs_t;
     56 
     57 /*
     58  * UFS1/UFS2 SUPERBLOCK structure
     59  * CG stands for Cylinder Group.
     60  *
     61  * Variables prepended with off store offsets relative to
     62  * base address of a Cylinder Group (CG).
     63  */
     64 struct ufs_super_block { // supporting either ufs1 or ufs2
     65     uint8_t  unused[8];
     66     /* Offset values */
     67     uint32_t off_backup_sb; // Backup super block
     68     uint32_t off_group_desc; // Group Descriptor
     69     uint32_t off_inode_tbl; // Inode table
     70     uint32_t off_data_block; // First data block
     71     union {
     72 	struct {  /* Used for UFS1 */
     73 	    uint32_t delta_value; // For calc staggering offset
     74 	    uint32_t cycle_mask; // Mask for staggering offset
     75 	    uint32_t last_written; // Last written time
     76 	    uint32_t nr_frags; // Number of frags in FS
     77 	    uint32_t storable_frags_nr; // Nr of frags that can store data
     78 	} ufs1;
     79 	uint8_t unused1[20];
     80     };
     81     uint32_t nr_cyl_groups; // Number of cylinder groups.
     82     uint32_t block_size; // Block size in bytes.
     83     uint32_t fragment_size; // Fragment size in bytes.
     84     uint8_t  unused2[16];
     85     uint32_t block_addr_mask; // to calculate the address
     86     uint32_t frag_addr_mask;
     87     uint32_t block_shift; // to calculate byte address
     88     uint32_t frag_shift;
     89     uint32_t nr_contiguous_blk; // max number of continuous blks to alloc
     90     uint32_t nr_blks_per_cg; // max number of blks per cylinder group
     91     uint32_t c_blk_frag_shift; // Bits to convert blk and frag address.
     92     uint32_t c_frag_sect_shift; // Bits to convert frag and sect address.
     93     uint32_t superblk_size; // Superblock size.
     94     uint8_t  unused3[76];
     95     uint32_t inodes_per_cg; // Inodes per cylinder group
     96     uint32_t frags_per_cg; // Fragments per cylinder group
     97     union {
     98 	struct { /* Used for UFS2 */
     99 	    uint8_t  unused[888];
    100 	    uint64_t nr_frags; // Number of fragments in FS
    101 	    uint8_t  unused1[232];
    102 	} ufs2;
    103 	uint8_t unused4[1128];
    104     };
    105     uint32_t maxlen_isymlink; // Max length of internal symlink
    106     uint32_t inodes_format; // Format of inodes
    107     uint8_t  unused5[44];
    108     uint32_t magic; // Magic value
    109     uint8_t  pad[160]; // padding up to sector (512 bytes) boundary
    110 } __attribute__((__packed__));
    111 
    112 /*
    113  * Info about UFS1/2 super block.
    114  */
    115 struct ufs_sb_info {
    116     uint32_t blocks_per_cg; // Blocks per cylinder group
    117     uint32_t inodes_per_cg; // Inodes per cylinder group
    118     uint32_t inode_size;
    119     uint32_t inodes_per_block; // Inodes per block
    120     struct { /* UFS1 only! */
    121 	/* Values for calculating staggering offset */
    122 	uint32_t delta_value;
    123 	uint32_t cycle_mask;
    124     } ufs1;
    125     uint32_t off_inode_tbl; // Inode table offset.
    126     uint32_t groups_count; // Number of groups in the fs
    127     uint32_t addr_shift; // 2 ^ addr_shift = size in bytes of default addr.
    128     uint32_t c_blk_frag_shift; // Convert blk/frag addr (vice-versa)
    129     uint32_t maxlen_isymlink; // Max length of internal symlink
    130     struct inode *(*ufs_iget_by_inr)(struct fs_info *, uint32_t);
    131     void (*ufs_read_blkaddrs)(struct inode *, char *);
    132     ufs_t    fs_type; // { UFS1, UFS2, UFS2_PIGGY }
    133 };
    134 
    135 /*
    136  * Get super block info struct
    137  */
    138 static inline struct ufs_sb_info *UFS_SB(struct fs_info *fs)
    139 {
    140     return fs->fs_info;
    141 }
    142 
    143 /*
    144  * Convert frag addr to blk addr
    145  */
    146 static inline block_t frag_to_blk(struct fs_info *fs, uint64_t frag)
    147 {
    148     return frag >> UFS_SB(fs)->c_blk_frag_shift;
    149 }
    150 
    151 /*
    152  * UFS1 inode structures
    153  */
    154 struct ufs1_inode {
    155     uint16_t file_mode;
    156     uint16_t link_count;
    157     uint8_t  unused[4];
    158     uint64_t size;
    159     uint32_t a_time; // Access time
    160     uint32_t a_time_nanosec;
    161     uint32_t m_time; // Modified time
    162     uint32_t m_time_nanosec;
    163     uint32_t ch_time; // Change time
    164     uint32_t ch_time_nanosec;
    165     uint32_t direct_blk_ptr[12];
    166     uint32_t indirect_blk_ptr;
    167     uint32_t double_indirect_blk_ptr;
    168     uint32_t triple_indirect_blk_ptr;
    169     uint32_t flags; // Status flags
    170     uint32_t blocks_held; // Blocks held
    171     uint32_t generation_nrb; // (NFS)
    172     uint32_t used_id;
    173     uint32_t group_id;
    174     uint8_t  unused1[8];
    175 } __attribute__((__packed__));
    176 
    177 /*
    178  * UFS2 inode structures
    179  */
    180 struct ufs2_inode {
    181     uint16_t file_mode;
    182     uint16_t link_count;
    183     uint32_t user_id;
    184     uint32_t group_id;
    185     uint32_t inode_blocksize;
    186     uint64_t size;
    187     uint64_t bytes_held;
    188     uint64_t a_time; // Access time
    189     uint64_t m_time; // Modified time
    190     uint64_t ch_time; // Change time
    191     uint64_t creat_time; // Creation time
    192     uint32_t a_time_nanosec;
    193     uint32_t m_time_nanosec;
    194     uint32_t ch_time_nanosec;
    195     uint32_t creat_time_nanosec;
    196     uint32_t generation_nrb; // (NFS)
    197     uint32_t kernel_flags;
    198     uint32_t flags;
    199     uint32_t ext_attr_size; // Extended attrib size.
    200     uint64_t ext_direct_blk_ptrs[2]; // Ext. attrib blk pointers.
    201     uint64_t direct_blk_ptr[12];
    202     uint64_t indirect_blk_ptr;
    203     uint64_t double_indirect_blk_ptr;
    204     uint64_t triple_indirect_blk_ptr;
    205     uint8_t  unused[24];
    206 } __attribute__((__packed__));
    207 
    208 #define PVT(p) ((struct ufs_inode_pvt *) p->pvt)
    209 
    210 struct ufs_inode_pvt {
    211     uint64_t direct_blk_ptr[12];
    212     uint64_t indirect_blk_ptr;
    213     uint64_t double_indirect_blk_ptr;
    214     uint64_t triple_indirect_blk_ptr;
    215 };
    216 
    217 struct ufs_dir_entry {
    218     uint32_t inode_value;
    219     uint16_t dir_entry_len;
    220     uint8_t  file_type;
    221     uint8_t  name_length;
    222     uint8_t  name[1]; // Dir names are null terminated!!!
    223 } __attribute__((__packed__));
    224 
    225 enum inode_type_flags {
    226     UFS_INO_FIFO	= 0x1000,
    227     UFS_INO_CHARDEV	= 0x2000,
    228     UFS_INO_DIRECTORY 	= 0x4000,
    229     UFS_INO_BLOCKDEV	= 0x6000,
    230     UFS_INO_RFILE	= 0x8000,
    231     UFS_INO_SYMLINK	= 0xA000,
    232     UFS_INO_UNIXSOCKET 	= 0xC000,
    233 };
    234 
    235 enum dir_type_flags {
    236     UFS_DTYPE_UNKNOWN	= 0,
    237     UFS_DTYPE_FIFO 	= 1,
    238     UFS_DTYPE_CHARDEV	= 2,
    239     UFS_DTYPE_DIR 	= 4,
    240     UFS_DTYPE_BLOCK	= 6,
    241     UFS_DTYPE_RFILE	= 8,
    242     UFS_DTYPE_SYMLINK 	= 10,
    243     UFS_DTYPE_SOCKET	= 12,
    244     UFS_DTYPE_WHITEOUT 	= 14,
    245 };
    246 
    247 /* Functions from bmap.c */
    248 extern uint64_t ufs_bmap (struct inode *, block_t, size_t *);
    249 extern int ufs_next_extent(struct inode *, uint32_t);
    250 
    251 #define ufs_debug dprintf
    252 //extern void ufs_checking (struct fs_info *);
    253 
    254 #endif /* _UFS_H_ */
    255