mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-10-31 16:31:25 +01:00 
			
		
		
		
	Signed-off-by: Wolfgang Denk <wd@denx.de> [trini: Fixup common/cmd_io.c] Signed-off-by: Tom Rini <trini@ti.com>
		
			
				
	
	
		
			509 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			509 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *  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);
 |