blob: 2e27a27e3ab47866fc0f4d850e883c79057913b9 [file] [log] [blame] [raw]
#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_ */