Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / fs / reiserfs / reiserfs_private.h
diff --git a/qemu/roms/u-boot/fs/reiserfs/reiserfs_private.h b/qemu/roms/u-boot/fs/reiserfs/reiserfs_private.h
new file mode 100644 (file)
index 0000000..9d14c71
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ *  Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
+ *
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000, 2001  Free Software Foundation, Inc.
+ *
+ *  (C) Copyright 2003 - 2004
+ *  Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
+ *
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/* An implementation for the ReiserFS filesystem ported from GRUB.
+ * Some parts of this code (mainly the structures and defines) are
+ * from the original reiser fs code, as found in the linux kernel.
+ */
+
+#ifndef __BYTE_ORDER
+#if defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#elif defined(__BIG_ENDIAN) && !defined(__LITTLE_ENDIAN)
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#error "unable to define __BYTE_ORDER"
+#endif
+#endif /* not __BYTE_ORDER */
+
+#define FSYS_BUFLEN  0x8000
+#define FSYS_BUF     fsys_buf
+
+/* This is the new super block of a journaling reiserfs system */
+struct reiserfs_super_block
+{
+  __u32 s_block_count;                 /* blocks 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_journal_size;                        /* size of the journal on FS creation.  used to make sure they don't overflow it */
+  __u32 s_journal_trans_max;           /* max number of blocks in a transaction.  */
+  __u32 s_journal_magic;               /* random value made on fs creation */
+  __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 object id array */
+  __u16 s_state;                       /* valid or error       */
+  char s_magic[16];                    /* reiserfs magic string indicates that file system is reiserfs */
+  __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;
+  char s_unused[128];                  /* zero filled by mkreiserfs */
+};
+
+
+#define sb_root_block(sbp)           (__le32_to_cpu((sbp)->s_root_block))
+#define sb_journal_block(sbp)        (__le32_to_cpu((sbp)->s_journal_block))
+#define set_sb_journal_block(sbp,v)   ((sbp)->s_journal_block = __cpu_to_le32(v))
+#define sb_journal_size(sbp)         (__le32_to_cpu((sbp)->s_journal_size))
+#define sb_blocksize(sbp)            (__le16_to_cpu((sbp)->s_blocksize))
+#define set_sb_blocksize(sbp,v)       ((sbp)->s_blocksize = __cpu_to_le16(v))
+#define sb_version(sbp)                      (__le16_to_cpu((sbp)->s_version))
+#define set_sb_version(sbp,v)        ((sbp)->s_version = __cpu_to_le16(v))
+
+
+#define REISERFS_MAX_SUPPORTED_VERSION 2
+#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
+#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
+#define REISER3FS_SUPER_MAGIC_STRING "ReIsEr3Fs"
+
+#define MAX_HEIGHT 7
+
+/* 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 the first blocks */
+  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 the last blocks */
+  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 {
+  /* id of last fully flushed transaction */
+  __u32 j_last_flush_trans_id;
+  /* offset in the log of where to start replay after a crash */
+  __u32 j_first_unflushed_offset;
+  /* mount id to detect very old transactions */
+  __u32 j_mount_id;
+};
+
+/* magic string to find desc blocks in the journal */
+#define JOURNAL_DESC_MAGIC "ReIsErLB"
+
+
+/*
+ * directories use this key as well as old files
+ */
+struct offset_v1
+{
+  /*
+   * for regular files this is the offset to the first byte of the
+   * body, contained in the object-item, as measured from the start of
+   * the entire body of the object.
+   *
+   * for directory entries, k_offset consists of hash derived from
+   * hashing the name and using few bits (23 or more) of the resulting
+   * hash, and generation number that allows distinguishing names with
+   * hash collisions. If number of collisions overflows generation
+   * number, we return EEXIST. High order bit is 0 always
+   */
+  __u32 k_offset;
+  __u32 k_uniqueness;
+};
+
+struct offset_v2 {
+  /*
+   * for regular files this is the offset to the first byte of the
+   * body, contained in the object-item, as measured from the start of
+   * the entire body of the object.
+   *
+   * for directory entries, k_offset consists of hash derived from
+   * hashing the name and using few bits (23 or more) of the resulting
+   * hash, and generation number that allows distinguishing names with
+   * hash collisions. If number of collisions overflows generation
+   * number, we return EEXIST. High order bit is 0 always
+   */
+
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+           /* little endian version */
+           __u64 k_offset:60;
+           __u64 k_type: 4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+           /* big endian version */
+           __u64 k_type: 4;
+           __u64 k_offset:60;
+#else
+#error "__LITTLE_ENDIAN_BITFIELD or __BIG_ENDIAN_BITFIELD must be defined"
+#endif
+} __attribute__ ((__packed__));
+
+#define TYPE_MAXTYPE 3
+#define TYPE_ANY 15
+
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+typedef union {
+    struct offset_v2 offset_v2;
+    __u64 linear;
+} __attribute__ ((__packed__)) offset_v2_esafe_overlay;
+
+static inline __u16 offset_v2_k_type( const struct offset_v2 *v2 )
+{
+    offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
+    tmp.linear = __le64_to_cpu( tmp.linear );
+    return (tmp.offset_v2.k_type <= TYPE_MAXTYPE)?tmp.offset_v2.k_type:TYPE_ANY;
+}
+
+static inline loff_t offset_v2_k_offset( const struct offset_v2 *v2 )
+{
+    offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
+    tmp.linear = __le64_to_cpu( tmp.linear );
+    return tmp.offset_v2.k_offset;
+}
+#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define offset_v2_k_type(v2)          ((v2)->k_type)
+# define offset_v2_k_offset(v2)                ((v2)->k_offset)
+#else
+#error "__BYTE_ORDER must be __LITTLE_ENDIAN or __BIG_ENDIAN"
+#endif
+
+struct key
+{
+  /* packing locality: by default parent directory object id */
+  __u32 k_dir_id;
+  /* object identifier */
+  __u32 k_objectid;
+  /* the offset and node type (old and new form) */
+  union
+  {
+    struct offset_v1 v1;
+    struct offset_v2 v2;
+  }
+  u;
+};
+
+#define KEY_SIZE (sizeof (struct key))
+
+/* 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. */
+  struct key  blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes
+                                     only) */
+};
+#define BLKH_SIZE (sizeof (struct block_head))
+#define DISK_LEAF_NODE_LEVEL  1 /* Leaf node level.                      */
+
+struct item_head
+{
+       /* Everything in the tree is found by searching for it based on
+        * its key.*/
+       struct key ih_key;
+       union {
+               /* 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_free_space;
+               /* Iff this is a directory item, this field equals the
+                  number of directory entries in the directory item. */
+               __u16 ih_entry_count;
+       } __attribute__ ((__packed__)) u;
+       __u16 ih_item_len;           /* total size of the item body */
+       __u16 ih_item_location;      /* an offset to the item body
+                                     * within the block */
+       __u16 ih_version;            /* 0 for all old items, 2 for new
+                                       ones. Highest bit is set by fsck
+                                       temporary, cleaned after all
+                                       done */
+} __attribute__ ((__packed__));
+
+/* size of item header    */
+#define IH_SIZE (sizeof (struct item_head))
+
+#define ITEM_VERSION_1 0
+#define ITEM_VERSION_2 1
+
+#define ih_version(ih)   (__le16_to_cpu((ih)->ih_version))
+
+#define IH_KEY_OFFSET(ih) (ih_version(ih) == ITEM_VERSION_1 \
+                          ? __le32_to_cpu((ih)->ih_key.u.v1.k_offset) \
+                          : offset_v2_k_offset(&((ih)->ih_key.u.v2)))
+
+#define IH_KEY_ISTYPE(ih, type) (ih_version(ih) == ITEM_VERSION_1 \
+                                ? __le32_to_cpu((ih)->ih_key.u.v1.k_uniqueness) == V1_##type \
+                                : offset_v2_k_type(&((ih)->ih_key.u.v2)) == V2_##type)
+
+/***************************************************************************/
+/*                     DISK CHILD                                         */
+/***************************************************************************/
+/* Disk child pointer: The pointer from an internal node of the tree
+   to a node that is on disk. */
+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))
+
+
+/*
+ * old stat data is 32 bytes long. We are going to distinguish new one by
+ * different size
+ */
+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; /* first byte of file which is stored
+                                  in a direct item: except that if it
+                                  equals 1 it is a symlink and if it
+                                  equals ~(__u32)0 there is no
+                                  direct item.  The existence of this
+                                  field really grates on me. Let's
+                                  replace it with a macro based on
+                                  sd_size and our tail suppression
+                                  policy.  Someday.  -Hans */
+} __attribute__ ((__packed__));
+
+#define stat_data_v1(ih)       (ih_version(ih) == ITEM_VERSION_1)
+#define sd_v1_mode(sdp)                ((sdp)->sd_mode)
+#define sd_v1_nlink(sdp)       (__le16_to_cpu((sdp)->sd_nlink))
+#define sd_v1_uid(sdp)         (__le16_to_cpu((sdp)->sd_uid))
+#define sd_v1_gid(sdp)         (__le16_to_cpu((sdp)->sd_gid))
+#define sd_v1_size(sdp)                (__le32_to_cpu((sdp)->sd_size))
+#define sd_v1_mtime(sdp)       (__le32_to_cpu((sdp)->sd_mtime))
+
+/* 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_attrs;    /* persistent inode flags */
+    __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;
+    union {
+       __u32 sd_rdev;
+       __u32 sd_generation;
+      /*__u32 sd_first_direct_byte; */
+      /* first byte of file which is stored in a
+                                      direct item: except that if it equals 1
+                                      it is a symlink and if it equals
+                                      ~(__u32)0 there is no direct item.  The
+                                      existence of this field really grates
+                                      on me. Let's replace it with a macro
+                                      based on sd_size and our tail
+                                      suppression policy? */
+  } __attribute__ ((__packed__)) u;
+} __attribute__ ((__packed__));
+
+#define stat_data_v2(ih)       (ih_version(ih) == ITEM_VERSION_2)
+#define sd_v2_mode(sdp)                (__le16_to_cpu((sdp)->sd_mode))
+#define sd_v2_nlink(sdp)       (__le32_to_cpu((sdp)->sd_nlink))
+#define sd_v2_size(sdp)                (__le64_to_cpu((sdp)->sd_size))
+#define sd_v2_uid(sdp)         (__le32_to_cpu((sdp)->sd_uid))
+#define sd_v2_gid(sdp)         (__le32_to_cpu((sdp)->sd_gid))
+#define sd_v2_mtime(sdp)       (__le32_to_cpu((sdp)->sd_mtime))
+
+#define sd_mode(sdp)        (__le16_to_cpu((sdp)->sd_mode))
+#define sd_size(sdp)        (__le32_to_cpu((sdp)->sd_size))
+#define sd_size_hi(sdp)      (__le32_to_cpu((sdp)->sd_size_hi))
+
+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) */
+};
+
+#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))
+
+
+#define DEH_Statdata (1 << 0)                  /* not used now */
+#define DEH_Visible  (1 << 2)
+
+#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_DISK_OFFSET_IN_BYTES (64 * 1024)
+/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */
+#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
+#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 */
+
+/* The size of the node cache */
+#define FSYSREISER_CACHE_SIZE 24*1024
+#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
+#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
+
+/* Info about currently opened file */
+struct fsys_reiser_fileinfo
+{
+  __u32 k_dir_id;
+  __u32 k_objectid;
+};
+
+/* In memory info about the currently mounted filesystem */
+struct fsys_reiser_info
+{
+  /* The last read item head */
+  struct item_head *current_ih;
+  /* The last read item */
+  char *current_item;
+  /* The information for the currently opened file */
+  struct fsys_reiser_fileinfo fileinfo;
+  /* The start of the journal */
+  __u32 journal_block;
+  /* The size of the journal */
+  __u32 journal_block_count;
+  /* The first valid descriptor block in journal
+     (relative to journal_block) */
+  __u32 journal_first_desc;
+
+  /* The ReiserFS version. */
+  __u16 version;
+  /* The current depth of the reiser tree. */
+  __u16 tree_depth;
+  /* SECTOR_SIZE << blocksize_shift == blocksize. */
+  __u8 blocksize_shift;
+  /* 1 << full_blocksize_shift == blocksize. */
+  __u8 fullblocksize_shift;
+  /* The reiserfs block size  (must be a power of 2) */
+  __u16 blocksize;
+  /* The number of cached tree nodes */
+  __u16 cached_slots;
+  /* The number of valid transactions in journal */
+  __u16 journal_transactions;
+
+  unsigned int blocks[MAX_HEIGHT];
+  unsigned int next_key_nr[MAX_HEIGHT];
+};
+
+/* The cached s+tree blocks in FSYS_BUF,  see below
+ * for a more detailed description.
+ */
+#define ROOT    ((char *) ((int) FSYS_BUF))
+#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift))
+#define LEAF    CACHE (DISK_LEAF_NODE_LEVEL)
+
+#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 fsys_reiser_info block.
+ */
+#define INFO \
+    ((struct fsys_reiser_info *) ((int) FSYS_BUF + FSYSREISER_CACHE_SIZE))
+/*
+ * 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 *) (INFO + 1))
+#define JOURNAL_END     ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
+
+
+static __inline__ unsigned long
+log2 (unsigned long word)
+{
+#ifdef __I386__
+  __asm__ ("bsfl %1,%0"
+          : "=r" (word)
+          : "r" (word));
+  return word;
+#else
+  int i;
+
+  for(i=0; i<(8*sizeof(word)); i++)
+    if ((1<<i) & word)
+      return i;
+
+  return 0;
+#endif
+}
+
+static __inline__ int
+is_power_of_two (unsigned long word)
+{
+  return (word & -word) == word;
+}
+
+extern const char *bb_mode_string(int mode);
+extern int reiserfs_devread (int sector, int byte_offset, int byte_len, char *buf);