mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
531 lines
16 KiB
C
531 lines
16 KiB
C
#ifndef __RFSD_REISER_FS_H__
|
|
#define __RFSD_REISER_FS_H__
|
|
|
|
#include <linux/types.h>
|
|
|
|
#ifdef __GCC__
|
|
#ifndef __REACTOS__
|
|
#define __PACKED __PACKED
|
|
#else
|
|
#define __PACKED __attribute__((packed))
|
|
#endif
|
|
#else
|
|
#define __PACKED
|
|
#endif
|
|
|
|
/***************************************************************************/
|
|
/* SUPER BLOCK */
|
|
/***************************************************************************/
|
|
|
|
/*
|
|
* Structure of super block on disk, a version of which in RAM is often accessed as REISERFS_SB(s)->s_rs
|
|
* the version in RAM is part of a larger structure containing fields never written to disk.
|
|
*/
|
|
#define UNSET_HASH 0 // read_super will guess about, what hash names
|
|
// in directories were sorted with
|
|
#define TEA_HASH 1
|
|
#define YURA_HASH 2
|
|
#define R5_HASH 3
|
|
#define DEFAULT_HASH R5_HASH
|
|
|
|
|
|
struct journal_params {
|
|
// Block number of the block containing the first journal node.
|
|
__u32 jp_journal_1st_block; /* where does journal start from on its device */
|
|
|
|
// Journal device number (?? for if the journal is on a seperate drive ??)
|
|
__u32 jp_journal_dev; /* journal device st_rdev */
|
|
|
|
// Original journal size. (Needed when using partition on systems w/ different default journal sizes).
|
|
__u32 jp_journal_size; /* size of the journal */
|
|
|
|
__u32 jp_journal_trans_max; /* max number of blocks in a transaction. */
|
|
__u32 jp_journal_magic; /* random value made on fs creation (this was sb_journal_block_count) */
|
|
__u32 jp_journal_max_batch; /* max number of blocks to batch into a trans */
|
|
__u32 jp_journal_max_commit_age; /* in seconds, how old can an async commit be */
|
|
__u32 jp_journal_max_trans_age; /* in seconds, how old can a transaction be */
|
|
};
|
|
|
|
/* this is the super from 3.5.X, where X >= 10 */
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
struct reiserfs_super_block_v1
|
|
{
|
|
// The number of blocks in the partition
|
|
__u32 s_blocks_count; /* blocks count */ //[mark] was _s_blocks_count
|
|
|
|
// The number of free blocks in the partition
|
|
__u32 s_free_blocks_count; /* free blocks count */ //[mark] was _s_free_blocks
|
|
|
|
// Block number of the block containing the root node
|
|
__u32 s_root_block; /* root block number */
|
|
|
|
|
|
struct journal_params s_journal;
|
|
|
|
// The size (in bytes) of a block
|
|
__u16 s_blocksize; /* block size */
|
|
|
|
__u16 s_oid_maxsize; /* max size of object id array, see get_objectid() commentary */
|
|
__u16 s_oid_cursize; /* current size of object id array */
|
|
__u16 s_umount_state; /* this is set to 1 when filesystem was umounted, to 2 - when not */
|
|
char s_magic[10]; /* reiserfs magic string indicates that
|
|
* file system is reiserfs:
|
|
* "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" */
|
|
|
|
// State of the partition: valid(1), error (2)
|
|
__u16 s_fs_state; /* it is set to used by fsck to mark which phase of rebuilding is done */
|
|
|
|
__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 */
|
|
|
|
// The reiserfs version number
|
|
__u16 s_version; /* this field is only reliable on filesystem
|
|
* with non-standard journal */
|
|
__u16 s_reserved_for_journal; /* size in blocks of journal area on main
|
|
* device, we need to keep after
|
|
* making fs with non-standard journal */
|
|
} __PACKED;
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
|
|
#define SB_SIZE_V1 (sizeof(struct reiserfs_super_block_v1))
|
|
|
|
/* this is the on disk super block */
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
struct reiserfs_super_block
|
|
{
|
|
struct reiserfs_super_block_v1 s_v1;
|
|
|
|
// Number of the current inode generation (a counter that is increased every time the tree gets re-balanced).
|
|
__u32 s_inode_generation;
|
|
|
|
__u32 s_flags; /* Right now used only by inode-attributes, if enabled */
|
|
unsigned char s_uuid[16]; /* filesystem unique identifier */
|
|
unsigned char s_label[16]; /* filesystem volume label */
|
|
char s_unused[88] ; /* zero filled by mkreiserfs and
|
|
* reiserfs_convert_objectid_map_v1()
|
|
* so any additions must be updated
|
|
* there as well. */
|
|
} __PACKED;
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
#define SB_SIZE (sizeof(struct reiserfs_super_block))
|
|
|
|
#define REISERFS_VERSION_1 0
|
|
#define REISERFS_VERSION_2 2
|
|
|
|
// ... [ommissions]
|
|
|
|
|
|
/* used by gcc */
|
|
#define REISERFS_SUPER_MAGIC 0x52654973
|
|
/* used by file system utilities that
|
|
look at the superblock, etc. */
|
|
#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
|
|
#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
|
|
#define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs"
|
|
|
|
/* ReiserFS leaves the first 64k unused, so that partition labels have
|
|
enough space. If someone wants to write a fancy bootloader that
|
|
needs more than 64k, let us know, and this will be increased in size.
|
|
This number must be larger than than the largest block size on any
|
|
platform, or code will break. -Hans */
|
|
#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
|
|
#define REISERFS_FIRST_BLOCK unused_define
|
|
#define REISERFS_JOURNAL_OFFSET_IN_BYTES REISERFS_DISK_OFFSET_IN_BYTES
|
|
|
|
/* the spot for the super in versions 3.5 - 3.5.10 (inclusive) */
|
|
#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
/* STAT DATA */
|
|
/***************************************************************************/
|
|
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
//
|
|
// 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 (in bytes) */
|
|
__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 */ //[mark]this is the one filled..
|
|
} __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 */
|
|
} __PACKED;
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
/* inode flags stored in sd_attrs (nee sd_reserved) */
|
|
|
|
/* we want common flags to have the same values as in ext2,
|
|
so chattr(1) will work without problems */
|
|
#define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE_FL
|
|
#define REISERFS_APPEND_FL EXT2_APPEND_FL
|
|
#define REISERFS_SYNC_FL EXT2_SYNC_FL
|
|
#define REISERFS_NOATIME_FL EXT2_NOATIME_FL
|
|
#define REISERFS_NODUMP_FL EXT2_NODUMP_FL
|
|
#define REISERFS_SECRM_FL EXT2_SECRM_FL
|
|
#define REISERFS_UNRM_FL EXT2_UNRM_FL
|
|
#define REISERFS_COMPR_FL EXT2_COMPR_FL
|
|
#define REISERFS_NOTAIL_FL EXT2_NOTAIL_FL
|
|
|
|
/* persistent flags that file inherits from the parent directory */
|
|
#define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL | \
|
|
REISERFS_SYNC_FL | \
|
|
REISERFS_NOATIME_FL | \
|
|
REISERFS_NODUMP_FL | \
|
|
REISERFS_SECRM_FL | \
|
|
REISERFS_COMPR_FL | \
|
|
REISERFS_NOTAIL_FL )
|
|
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
/* Stat Data on disk (reiserfs version of UFS disk inode minus the
|
|
address blocks) */
|
|
struct stat_data {
|
|
__u16 i_mode; /* file type, permissions */ // The low 9 bits (3 octals) contain world/group/user permissions. The next 3 bits (from lower to higher) are the sticky bit, the set GID bit, and the set UID bit. The high 4 bits are the file type (as defined in stat.h: socket, symlink, regular, block dev, directory, char device, fifo)
|
|
__u16 sd_attrs; /* persistent inode flags */
|
|
__u32 i_links_count; /* number of hard links */ //[mark] was sd_nlink
|
|
__u64 i_size; /* file size */
|
|
__u32 i_uid; /* owner */
|
|
__u32 i_gid; /* group */
|
|
__u32 i_atime; /* time of last access */
|
|
__u32 i_mtime; /* time file was last modified */
|
|
__u32 i_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */
|
|
__u32 sd_blocks;
|
|
union {
|
|
__u32 sd_rdev;
|
|
__u32 i_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? */
|
|
} __PACKED u;
|
|
} __PACKED;
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
//
|
|
// this is 44 bytes long
|
|
//
|
|
#define SD_SIZE (sizeof(struct stat_data))
|
|
#define SD_V2_SIZE SD_SIZE
|
|
|
|
|
|
|
|
|
|
/*
|
|
* values for s_umount_state field
|
|
*/
|
|
#define REISERFS_VALID_FS 1
|
|
#define REISERFS_ERROR_FS 2
|
|
|
|
//
|
|
// there are 5 item types currently
|
|
//
|
|
|
|
#define RFSD_KEY_TYPE_v1_STAT_DATA 0
|
|
#define RFSD_KEY_TYPE_v1_INDIRECT 0xFFFFFFFe
|
|
#define RFSD_KEY_TYPE_v1_DIRECT 0xFFFFFFFF
|
|
#define RFSD_KEY_TYPE_v1_DIRENTRY 500
|
|
|
|
#define RFSD_KEY_TYPE_v2_STAT_DATA 0
|
|
#define RFSD_KEY_TYPE_v2_INDIRECT 1
|
|
#define RFSD_KEY_TYPE_v2_DIRECT 2
|
|
#define RFSD_KEY_TYPE_v2_DIRENTRY 3
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
/* KEY & ITEM HEAD */
|
|
/***************************************************************************/
|
|
|
|
typedef struct reiserfs_cpu_key
|
|
{
|
|
__u32 k_dir_id;
|
|
__u32 k_objectid;
|
|
__u64 k_offset;
|
|
__u32 k_type;
|
|
} no_c4091;
|
|
|
|
//
|
|
// directories use this key as well as old files
|
|
//
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
struct offset_v1 {
|
|
__u32 k_offset;
|
|
__u32 k_uniqueness;
|
|
} __PACKED;
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
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
|
|
} __PACKED;
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
|
|
// ...
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
/* Key of an item determines its location in the S+tree, and
|
|
is composed of 4 components */
|
|
struct reiserfs_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;
|
|
} u;
|
|
} __PACKED;
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
|
|
/// ...
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
/* Everything in the filesystem is stored as a set of items. The
|
|
item head contains the key of the item, its free space (for
|
|
indirect items) and specifies the location of the item itself
|
|
within the block. */
|
|
struct item_head
|
|
{
|
|
/* Everything in the tree is found by searching for it based on
|
|
* its key.*/
|
|
struct reiserfs_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_reserved;
|
|
/* Iff this is a directory item, this field equals the
|
|
number of directory entries in the directory item. */
|
|
__u16 ih_entry_count;
|
|
} 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 */
|
|
} __PACKED;
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
/// ...
|
|
|
|
/* object identifier for root dir */
|
|
#define REISERFS_ROOT_OBJECTID 2
|
|
#define REISERFS_ROOT_PARENT_OBJECTID 1
|
|
|
|
/// ...
|
|
|
|
|
|
/*
|
|
* Picture represents a leaf of the S+tree
|
|
* ______________________________________________________
|
|
* | | Array of | | |
|
|
* |Block | Object-Item | F r e e | Objects- |
|
|
* | head | Headers | S p a c e | Items |
|
|
* |______|_______________|___________________|___________|
|
|
*/
|
|
|
|
/* Header of a disk block. More precisely, header of a formatted leaf
|
|
or internal node, and not the header of an unformatted node. */
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
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;
|
|
/* dump this in v4/planA */
|
|
struct reiserfs_key blk_right_delim_key; /* kept only for compatibility */
|
|
};
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
/* DIRECTORY STRUCTURE */
|
|
/***************************************************************************/
|
|
/*
|
|
Picture represents the structure of directory items
|
|
________________________________________________
|
|
| Array of | | | | | |
|
|
| directory |N-1| N-2 | .... | 1st |0th|
|
|
| entry headers | | | | | |
|
|
|_______________|___|_____|________|_______|___|
|
|
<---- directory entries ------>
|
|
|
|
First directory item has k_offset component 1. We store "." and ".."
|
|
in one item, always, we never split "." and ".." into differing
|
|
items. This makes, among other things, the code for removing
|
|
directories simpler. */
|
|
|
|
// ...
|
|
|
|
/*
|
|
Q: How to get key of object pointed to by entry from entry?
|
|
|
|
A: Each directory entry has its header. This header has deh_dir_id and deh_objectid fields, those are key
|
|
of object, entry points to */
|
|
|
|
/* NOT IMPLEMENTED:
|
|
Directory will someday contain stat data of object */
|
|
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
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) */
|
|
} __PACKED;
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Picture represents an internal node of the reiserfs tree
|
|
* ______________________________________________________
|
|
* | | Array of | Array of | Free |
|
|
* |block | keys | pointers | space |
|
|
* | head | N | N+1 | |
|
|
* |______|_______________|___________________|___________|
|
|
*/
|
|
|
|
/***************************************************************************/
|
|
/* DISK CHILD */
|
|
/***************************************************************************/
|
|
/* Disk child pointer: The pointer from an internal node of the tree
|
|
to a node that is on disk. */
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
struct disk_child {
|
|
__u32 dc_block_number; /* Disk child's block number. */
|
|
__u16 dc_size; /* Disk child's used space. */
|
|
__u16 dc_reserved;
|
|
};
|
|
|
|
#ifndef __GCC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif // header
|