| #ifndef _REISERFS_H_ |
| #define _REISERFS_H_ |
| #include "byteorder.h" |
| #include "types.h" |
| |
| /* ReiserFS Super Block */ |
| /* include/linux/reiserfs_fs_sb.h */ |
| #define REISERFS_MAX_SUPPORTED_VERSION 2 |
| #define REISERFS_SUPER_MAGIC_STRING "ReIsErFs" |
| #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" |
| #define REISERFS_MAX_TREE_HEIGHT 7 |
| |
| struct reiserfs_super_block |
| { |
| __u32 s_block_count; |
| __u32 s_free_blocks; /* free blocks count */ |
| __u32 s_root_block; /* root block number */ |
| __u32 s_journal_block; /* journal block number */ |
| __u32 s_journal_dev; /* journal device number */ |
| __u32 s_orig_journal_size; /* size of the journal */ |
| __u32 s_journal_trans_max; /* max number of blocks in |
| a transaction. */ |
| __u32 s_journal_block_count; /* total size of the journal. |
| can change over time */ |
| __u32 s_journal_max_batch; /* max number of blocks to |
| batch into a trans */ |
| __u32 s_journal_max_commit_age; /* in seconds, how old can an |
| async commit be */ |
| __u32 s_journal_max_trans_age; /* in seconds, how old can a |
| transaction be */ |
| __u16 s_blocksize; /* block size */ |
| __u16 s_oid_maxsize; /* max size of object id array, */ |
| __u16 s_oid_cursize; /* current size of obj id array */ |
| __u16 s_state; /* valid or error */ |
| char s_magic[12]; /* reiserfs magic string indicates |
| that file system is reiserfs */ |
| __u32 s_hash_function_code; /* indicate, what hash function is |
| being use to sort names in a |
| directory */ |
| __u16 s_tree_height; /* height of disk tree */ |
| __u16 s_bmap_nr; /* amount of bitmap blocks needed |
| to address each block of file |
| system */ |
| __u16 s_version; |
| __u16 s_marked_in_use; |
| __u16 s_inode_generation; |
| char s_unused[124]; /* zero filled by mkreiserfs */ |
| char padding_to_quad[ 2 ]; /* aligned to __u32 */ |
| } __attribute__ ((__packed__)); |
| #define SB_SIZE (sizeof (struct reiserfs_super_block) ) |
| |
| /* ReiserFS Journal */ |
| /* include/linux/reiserfs_fs.h */ |
| /* must be correct to keep the desc and commit structs at 4k */ |
| #define JOURNAL_TRANS_HALF 1018 |
| |
| /* first block written in a commit */ |
| struct reiserfs_journal_desc { |
| __u32 j_trans_id; /* id of commit */ |
| __u32 j_len; /* length of commit. len +1 is the |
| commit block */ |
| __u32 j_mount_id; /* mount id of this trans*/ |
| __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for each block */ |
| char j_magic[12]; |
| }; |
| |
| /* last block written in a commit */ |
| struct reiserfs_journal_commit { |
| __u32 j_trans_id; /* must match j_trans_id from the |
| desc block */ |
| __u32 j_len; /* ditto */ |
| __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for each block */ |
| char j_digest[16]; /* md5 sum of all the blocks |
| involved, including desc and |
| commit. not used, kill it */ |
| }; |
| |
| /* |
| ** This header block gets written whenever a transaction is considered |
| ** fully flushed, and is more recent than the last fully flushed |
| ** transaction. fully flushed means all the log blocks and all the real |
| ** blocks are on disk, and this transaction does not need to be replayed. |
| */ |
| struct reiserfs_journal_header { |
| __u32 j_last_flush_trans_id; /* id of last fully flushed transaction */ |
| __u32 j_first_unflushed_offset; /* offset in the log of where to start |
| replay after a crash */ |
| __u32 j_mount_id; |
| }; |
| |
| /* Magic to find journal descriptors */ |
| #define JOURNAL_DESC_MAGIC "ReIsErLB" |
| |
| /* ReiserFS Tree structures/accessors */ |
| /* Item version determines which offset_v# struct to use */ |
| #define ITEM_VERSION_1 0 |
| #define ITEM_VERSION_2 1 |
| #define IH_KEY_OFFSET(ih) (INFO->version < 2 \ |
| || ih_version(ih) == ITEM_VERSION_1 \ |
| ? (ih)->ih_key.u.k_offset_v1.k_offset \ |
| : offset_v2_k_offset(&(ih)->ih_key.u.k_offset_v2)) |
| |
| #define IH_KEY_ISTYPE(ih, type) (INFO->version < 2 \ |
| || ih_version(ih) == ITEM_VERSION_1 \ |
| ? (ih)->ih_key.u.k_offset_v1.k_uniqueness == V1_##type \ |
| : offset_v2_k_type(&(ih)->ih_key.u.k_offset_v2) == V2_##type) |
| |
| // |
| // directories use this key as well as old files |
| // |
| struct offset_v1 { |
| __u32 k_offset; |
| __u32 k_uniqueness; |
| } __attribute__ ((__packed__)); |
| |
| struct offset_v2 { |
| #ifdef __LITTLE_ENDIAN |
| /* little endian version */ |
| __u64 k_offset:60; |
| __u64 k_type: 4; |
| #else |
| /* big endian version */ |
| __u64 k_type: 4; |
| __u64 k_offset:60; |
| #endif |
| } __attribute__ ((__packed__)); |
| |
| #ifndef __LITTLE_ENDIAN |
| inline __u16 offset_v2_k_type( struct offset_v2 *v2 ); |
| inline loff_t offset_v2_k_offset( struct offset_v2 *v2 ); |
| #else |
| # define offset_v2_k_type(v2) ((v2)->k_type) |
| # define offset_v2_k_offset(v2) ((v2)->k_offset) |
| #endif |
| |
| /* Key of an item determines its location in the S+tree, and |
| is composed of 4 components */ |
| struct key { |
| __u32 k_dir_id; /* packing locality: by default parent |
| directory object id */ |
| __u32 k_objectid; /* object identifier */ |
| union { |
| struct offset_v1 k_offset_v1; |
| struct offset_v2 k_offset_v2; |
| } __attribute__ ((__packed__)) u; |
| } __attribute__ ((__packed__)); |
| #define KEY_SIZE (sizeof (struct key)) |
| |
| // |
| // there are 5 item types currently |
| // |
| #define TYPE_STAT_DATA 0 |
| #define TYPE_INDIRECT 1 |
| #define TYPE_DIRECT 2 |
| #define TYPE_DIRENTRY 3 |
| #define TYPE_ANY 15 // FIXME: comment is required |
| |
| // |
| // in old version uniqueness field shows key type |
| // |
| #define V1_SD_UNIQUENESS 0 |
| #define V1_INDIRECT_UNIQUENESS 0xfffffffe |
| #define V1_DIRECT_UNIQUENESS 0xffffffff |
| #define V1_DIRENTRY_UNIQUENESS 500 |
| #define V1_ANY_UNIQUENESS 555 // FIXME: comment is required |
| inline int uniqueness2type (__u32 uniqueness); |
| |
| struct item_head |
| { |
| struct key ih_key; /* Everything in the tree is found by |
| searching for its key.*/ |
| |
| union { |
| __u16 ih_free_space_reserved; /* The free space in the last unformatted |
| node of an indirect item if this is an |
| indirect item. This equals 0xFFFF |
| iff this is a direct item or stat |
| data item. Note that the key, not |
| this field, is used to determine |
| the item type, and thus which field |
| this union contains. */ |
| __u16 ih_entry_count; /* Iff this is a directory item, this |
| field equals the number of directory |
| entries in the directory item. */ |
| } __attribute__ ((__packed__)) u; |
| __u16 ih_item_len; /* total size of the item body */ |
| __u16 ih_item_location; /* Offset to the item within the block */ |
| __u16 ih_version; /* ITEM_VERSION_[01] of key type */ |
| } __attribute__ ((__packed__)); |
| #define IH_SIZE (sizeof(struct item_head)) |
| |
| #define ih_version(ih) le16_to_cpu((ih)->ih_version) |
| #define ih_entry_count(ih) le16_to_cpu((ih)->u.ih_entry_count) |
| #define ih_location(ih) le16_to_cpu((ih)->ih_item_location) |
| #define ih_item_len(ih) le16_to_cpu((ih)->ih_item_len) |
| |
| /* Header of a disk block. More precisely, header of a formatted leaf |
| or internal node, and not the header of an unformatted node. */ |
| struct block_head { |
| __u16 blk_level; /* Level of a block in the tree */ |
| __u16 blk_nr_item; /* Number of keys/items in a block */ |
| __u16 blk_free_space; /* Block free space in bytes */ |
| __u16 blk_reserved; |
| struct key blk_right_delim_key; /* kept only for compatibility */ |
| }; |
| #define BLKH_SIZE (sizeof(struct block_head)) |
| |
| #define blkh_level(p_blkh) (le16_to_cpu((p_blkh)->blk_level)) |
| #define blkh_nr_item(p_blkh) (le16_to_cpu((p_blkh)->blk_nr_item)) |
| |
| #define BLKH_LEVEL_FREE 0 /* Freed from the tree */ |
| #define BLKH_LEVEL_LEAF 1 /* Leaf node level*/ |
| |
| struct disk_child { |
| __u32 dc_block_number; /* Disk child's block number */ |
| __u16 dc_size; /* Disk child's used space */ |
| __u16 dc_reserved; |
| }; |
| |
| #define DC_SIZE (sizeof(struct disk_child)) |
| #define dc_block_number(dc_p) (le32_to_cpu((dc_p)->dc_block_number)) |
| #define dc_size(dc_p) (le16_to_cpu((dc_p)->dc_size)) |
| |
| /* Stat data */ |
| struct stat_data_v1 |
| { |
| __u16 sd_mode; /* file type, permissions */ |
| __u16 sd_nlink; /* number of hard links */ |
| __u16 sd_uid; /* owner */ |
| __u16 sd_gid; /* group */ |
| __u32 sd_size; /* file size */ |
| __u32 sd_atime; /* time of last access */ |
| __u32 sd_mtime; /* time file was last modified */ |
| __u32 sd_ctime; /* time inode (stat data) was last changed |
| (except changes to sd_atime and sd_mtime) */ |
| union { |
| __u32 sd_rdev; |
| __u32 sd_blocks; /* number of blocks file uses */ |
| } __attribute__ ((__packed__)) u; |
| __u32 sd_first_direct_byte; /* 0 = no direct item, 1 = symlink */ |
| } __attribute__ ((__packed__)); |
| #define SD_V1_SIZE (sizeof(struct stat_data_v1)) |
| |
| #define stat_data_v1(ih) (ih_version (ih) == ITEM_VERSION_1) |
| #define sd_v1_size(sdp) (le32_to_cpu((sdp)->sd_size)) |
| |
| /* Stat Data on disk (reiserfs version of UFS disk inode minus the |
| address blocks) */ |
| struct stat_data { |
| __u16 sd_mode; /* file type, permissions */ |
| __u16 sd_reserved; |
| __u32 sd_nlink; /* number of hard links */ |
| __u64 sd_size; /* file size */ |
| __u32 sd_uid; /* owner */ |
| __u32 sd_gid; /* group */ |
| __u32 sd_atime; /* time of last access */ |
| __u32 sd_mtime; /* time file was last modified */ |
| __u32 sd_ctime; /* time inode (stat data) was last changed |
| (except changes to sd_atime and sd_mtime) */ |
| __u32 sd_blocks; |
| __u32 sd_rdev; |
| } __attribute__ ((__packed__)); |
| #define SD_V2_SIZE (sizeof(struct stat_data)) |
| #define stat_data_v2(ih) (ih_version (ih) == ITEM_VERSION_2) |
| #define sd_v2_size(sdp) (le64_to_cpu((sdp)->sd_size)) |
| |
| /* valid for any stat data */ |
| #define sd_size(ih,sdp) ((ih_version(ih) == ITEM_VERSION_2) ? \ |
| sd_v2_size((struct stat_data *)sdp) : \ |
| sd_v1_size((struct stat_data_v1 *)sdp)) |
| #define sd_mode(sdp) (le16_to_cpu((sdp)->sd_mode)) |
| |
| struct reiserfs_de_head |
| { |
| __u32 deh_offset; /* third component of the directory entry key */ |
| __u32 deh_dir_id; /* objectid of the parent directory of the object, |
| that is referenced by directory entry */ |
| __u32 deh_objectid; /* objectid of the object, that is referenced by |
| directory entry */ |
| __u16 deh_location; /* offset of name in the whole item */ |
| __u16 deh_state; /* whether 1) entry contains stat data (for future), and 2) whether entry is hidden (unlinked) */ |
| } __attribute__ ((__packed__)); |
| #define DEH_SIZE sizeof(struct reiserfs_de_head) |
| |
| #define deh_offset(p_deh) (le32_to_cpu((p_deh)->deh_offset)) |
| #define deh_dir_id(p_deh) (le32_to_cpu((p_deh)->deh_dir_id)) |
| #define deh_objectid(p_deh) (le32_to_cpu((p_deh)->deh_objectid)) |
| #define deh_location(p_deh) (le16_to_cpu((p_deh)->deh_location)) |
| #define deh_state(p_deh) (le16_to_cpu((p_deh)->deh_state)) |
| |
| /* empty directory contains two entries "." and ".." and their headers */ |
| #define EMPTY_DIR_SIZE \ |
| (DEH_SIZE * 2 + ROUND_UP (strlen (".")) + ROUND_UP (strlen (".."))) |
| |
| /* old format directories have this size when empty */ |
| #define EMPTY_DIR_SIZE_V1 (DEH_SIZE * 2 + 3) |
| |
| #define DEH_Statdata 0 /* not used now */ |
| #define DEH_Visible 2 |
| |
| /* 64 bit systems need to aligned explicitly -jdm */ |
| #if BITS_PER_LONG == 64 |
| # define ADDR_UNALIGNED_BITS (5) |
| #endif |
| |
| #define test_bit(x,y) ext2fs_test_bit(x,y) |
| |
| #ifdef ADDR_UNALIGNED_BITS |
| # define aligned_address(addr) ((void *)((long)(addr) & ~((1UL << ADDR_UNALIGNED_BITS) - 1))) |
| # define unaligned_offset(addr) (((int)((long)(addr) & ((1 << ADDR_UNALIGNED_BITS) - 1))) << 3) |
| # define set_bit_unaligned(nr, addr) set_bit((nr) + unaligned_offset(addr), aligned_address(addr)) |
| # define clear_bit_unaligned(nr, addr) clear_bit((nr) + unaligned_offset(addr), aligned_address(addr)) |
| # define test_bit_unaligned(nr, addr) test_bit((nr) + unaligned_offset(addr), aligned_address(addr)) |
| #else |
| # define set_bit_unaligned(nr, addr) set_bit(nr, addr) |
| # define clear_bit_unaligned(nr, addr) clear_bit(nr, addr) |
| # define test_bit_unaligned(nr, addr) test_bit(nr, addr) |
| #endif |
| |
| #define SD_OFFSET 0 |
| #define SD_UNIQUENESS 0 |
| #define DOT_OFFSET 1 |
| #define DOT_DOT_OFFSET 2 |
| #define DIRENTRY_UNIQUENESS 500 |
| |
| #define V1_TYPE_STAT_DATA 0x0 |
| #define V1_TYPE_DIRECT 0xffffffff |
| #define V1_TYPE_INDIRECT 0xfffffffe |
| #define V1_TYPE_DIRECTORY_MAX 0xfffffffd |
| #define V2_TYPE_STAT_DATA 0 |
| #define V2_TYPE_INDIRECT 1 |
| #define V2_TYPE_DIRECT 2 |
| #define V2_TYPE_DIRENTRY 3 |
| |
| |
| #define REISERFS_ROOT_OBJECTID 2 |
| #define REISERFS_ROOT_PARENT_OBJECTID 1 |
| #define REISERFS_SUPERBLOCK_BLOCK 16 |
| /* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */ |
| #define REISERFS_OLD_SUPERBLOCK_BLOCK 2 |
| #define REISERFS_OLD_BLOCKSIZE 4096 |
| |
| #define S_ISREG(mode) (((mode) & 0170000) == 0100000) |
| #define S_ISDIR(mode) (((mode) & 0170000) == 0040000) |
| #define S_ISLNK(mode) (((mode) & 0170000) == 0120000) |
| #define PATH_MAX 1024 /* include/linux/limits.h */ |
| #define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ |
| |
| /* Cache stuff, adapted from GRUB source */ |
| #define FSYSREISER_CACHE_SIZE (REISERFS_MAX_TREE_HEIGHT*REISERFS_OLD_BLOCKSIZE) |
| #define SECTOR_SIZE 512 |
| #define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE |
| #define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3 |
| |
| |
| struct reiserfs_state |
| { |
| /* Context */ |
| struct key fileinfo; |
| struct boot_file_t *file; |
| struct item_head *current_ih; |
| char *current_item; |
| __u64 partition_offset; |
| |
| /* Commonly used values, cpu order */ |
| __u32 journal_block; /* Start of journal */ |
| __u32 journal_block_count; /* The size of the journal */ |
| __u32 journal_first_desc; /* The first valid descriptor block in journal |
| (relative to journal_block) */ |
| |
| __u16 version; /* The ReiserFS version. */ |
| __u16 tree_depth; /* The current depth of the reiser tree. */ |
| __u8 blocksize_shift; /* 1 << blocksize_shift == blocksize. */ |
| __u16 blocksize; /* The reiserfs block size (power of 2) */ |
| |
| /* Cache */ |
| __u16 cached_slots; |
| __u16 journal_transactions; |
| __u32 blocks[REISERFS_MAX_TREE_HEIGHT]; |
| __u32 next_key_nr[REISERFS_MAX_TREE_HEIGHT]; |
| }; |
| |
| #define ROOT ((char *)FSYS_BUF) |
| #define CACHE(i) (ROOT + ((i) * INFO->blocksize)) |
| #define LEAF CACHE (BLKH_LEVEL_LEAF) |
| |
| #define BLOCKHEAD(cache) ((struct block_head *) cache) |
| #define ITEMHEAD ((struct item_head *) ((int) LEAF + BLKH_SIZE)) |
| #define KEY(cache) ((struct key *) ((int) cache + BLKH_SIZE)) |
| #define DC(cache) ((struct disk_child *) \ |
| ((int) cache + BLKH_SIZE + KEY_SIZE * nr_item)) |
| |
| /* |
| * The journal cache. For each transaction it contains the number of |
| * blocks followed by the real block numbers of this transaction. |
| * |
| * If the block numbers of some transaction won't fit in this space, |
| * this list is stopped with a 0xffffffff marker and the remaining |
| * uncommitted transactions aren't cached. |
| */ |
| #define JOURNAL_START ((__u32 *) (FSYS_BUF + FSYSREISER_CACHE_SIZE)) |
| #define JOURNAL_END ((__u32 *) (FSYS_BUF + sizeof(FSYS_BUF))) |
| |
| |
| #endif /* _REISERFS_H_ */ |