]> git.ozlabs.org Git - yaboot.git/blobdiff - include/reiserfs/reiserfs.h
Commit yaboot 1.3.0
[yaboot.git] / include / reiserfs / reiserfs.h
diff --git a/include/reiserfs/reiserfs.h b/include/reiserfs/reiserfs.h
new file mode 100644 (file)
index 0000000..2e27a27
--- /dev/null
@@ -0,0 +1,405 @@
+#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_ */