162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 1996, 1997, 1998 Hans Reiser, see reiserfs/README for 462306a36Sopenharmony_ci * licensing and copyright details 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/reiserfs_fs.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include <linux/interrupt.h> 1162306a36Sopenharmony_ci#include <linux/sched.h> 1262306a36Sopenharmony_ci#include <linux/bug.h> 1362306a36Sopenharmony_ci#include <linux/workqueue.h> 1462306a36Sopenharmony_ci#include <asm/unaligned.h> 1562306a36Sopenharmony_ci#include <linux/bitops.h> 1662306a36Sopenharmony_ci#include <linux/proc_fs.h> 1762306a36Sopenharmony_ci#include <linux/buffer_head.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* the 32 bit compat definitions with int argument */ 2062306a36Sopenharmony_ci#define REISERFS_IOC32_UNPACK _IOW(0xCD, 1, int) 2162306a36Sopenharmony_ci#define REISERFS_IOC32_GETVERSION FS_IOC32_GETVERSION 2262306a36Sopenharmony_ci#define REISERFS_IOC32_SETVERSION FS_IOC32_SETVERSION 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistruct reiserfs_journal_list; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* bitmasks for i_flags field in reiserfs-specific part of inode */ 2762306a36Sopenharmony_citypedef enum { 2862306a36Sopenharmony_ci /* 2962306a36Sopenharmony_ci * this says what format of key do all items (but stat data) of 3062306a36Sopenharmony_ci * an object have. If this is set, that format is 3.6 otherwise - 3.5 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_ci i_item_key_version_mask = 0x0001, 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci /* 3562306a36Sopenharmony_ci * If this is unset, object has 3.5 stat data, otherwise, 3662306a36Sopenharmony_ci * it has 3.6 stat data with 64bit size, 32bit nlink etc. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci i_stat_data_version_mask = 0x0002, 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* file might need tail packing on close */ 4162306a36Sopenharmony_ci i_pack_on_close_mask = 0x0004, 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci /* don't pack tail of file */ 4462306a36Sopenharmony_ci i_nopack_mask = 0x0008, 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* 4762306a36Sopenharmony_ci * If either of these are set, "safe link" was created for this 4862306a36Sopenharmony_ci * file during truncate or unlink. Safe link is used to avoid 4962306a36Sopenharmony_ci * leakage of disk space on crash with some files open, but unlinked. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci i_link_saved_unlink_mask = 0x0010, 5262306a36Sopenharmony_ci i_link_saved_truncate_mask = 0x0020, 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci i_has_xattr_dir = 0x0040, 5562306a36Sopenharmony_ci i_data_log = 0x0080, 5662306a36Sopenharmony_ci} reiserfs_inode_flags; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistruct reiserfs_inode_info { 5962306a36Sopenharmony_ci __u32 i_key[4]; /* key is still 4 32 bit integers */ 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci /* 6262306a36Sopenharmony_ci * transient inode flags that are never stored on disk. Bitmasks 6362306a36Sopenharmony_ci * for this field are defined above. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci __u32 i_flags; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* offset of first byte stored in direct item. */ 6862306a36Sopenharmony_ci __u32 i_first_direct_byte; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci /* copy of persistent inode flags read from sd_attrs. */ 7162306a36Sopenharmony_ci __u32 i_attrs; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* first unused block of a sequence of unused blocks */ 7462306a36Sopenharmony_ci int i_prealloc_block; 7562306a36Sopenharmony_ci int i_prealloc_count; /* length of that sequence */ 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci /* per-transaction list of inodes which have preallocated blocks */ 7862306a36Sopenharmony_ci struct list_head i_prealloc_list; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* 8162306a36Sopenharmony_ci * new_packing_locality is created; new blocks for the contents 8262306a36Sopenharmony_ci * of this directory should be displaced 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci unsigned new_packing_locality:1; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* 8762306a36Sopenharmony_ci * we use these for fsync or O_SYNC to decide which transaction 8862306a36Sopenharmony_ci * needs to be committed in order for this inode to be properly 8962306a36Sopenharmony_ci * flushed 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_ci unsigned int i_trans_id; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci struct reiserfs_journal_list *i_jl; 9462306a36Sopenharmony_ci atomic_t openers; 9562306a36Sopenharmony_ci struct mutex tailpack; 9662306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_FS_XATTR 9762306a36Sopenharmony_ci struct rw_semaphore i_xattr_sem; 9862306a36Sopenharmony_ci#endif 9962306a36Sopenharmony_ci#ifdef CONFIG_QUOTA 10062306a36Sopenharmony_ci struct dquot __rcu *i_dquot[MAXQUOTAS]; 10162306a36Sopenharmony_ci#endif 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci struct inode vfs_inode; 10462306a36Sopenharmony_ci}; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_citypedef enum { 10762306a36Sopenharmony_ci reiserfs_attrs_cleared = 0x00000001, 10862306a36Sopenharmony_ci} reiserfs_super_block_flags; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* 11162306a36Sopenharmony_ci * struct reiserfs_super_block accessors/mutators since this is a disk 11262306a36Sopenharmony_ci * structure, it will always be in little endian format. 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci#define sb_block_count(sbp) (le32_to_cpu((sbp)->s_v1.s_block_count)) 11562306a36Sopenharmony_ci#define set_sb_block_count(sbp,v) ((sbp)->s_v1.s_block_count = cpu_to_le32(v)) 11662306a36Sopenharmony_ci#define sb_free_blocks(sbp) (le32_to_cpu((sbp)->s_v1.s_free_blocks)) 11762306a36Sopenharmony_ci#define set_sb_free_blocks(sbp,v) ((sbp)->s_v1.s_free_blocks = cpu_to_le32(v)) 11862306a36Sopenharmony_ci#define sb_root_block(sbp) (le32_to_cpu((sbp)->s_v1.s_root_block)) 11962306a36Sopenharmony_ci#define set_sb_root_block(sbp,v) ((sbp)->s_v1.s_root_block = cpu_to_le32(v)) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#define sb_jp_journal_1st_block(sbp) \ 12262306a36Sopenharmony_ci (le32_to_cpu((sbp)->s_v1.s_journal.jp_journal_1st_block)) 12362306a36Sopenharmony_ci#define set_sb_jp_journal_1st_block(sbp,v) \ 12462306a36Sopenharmony_ci ((sbp)->s_v1.s_journal.jp_journal_1st_block = cpu_to_le32(v)) 12562306a36Sopenharmony_ci#define sb_jp_journal_dev(sbp) \ 12662306a36Sopenharmony_ci (le32_to_cpu((sbp)->s_v1.s_journal.jp_journal_dev)) 12762306a36Sopenharmony_ci#define set_sb_jp_journal_dev(sbp,v) \ 12862306a36Sopenharmony_ci ((sbp)->s_v1.s_journal.jp_journal_dev = cpu_to_le32(v)) 12962306a36Sopenharmony_ci#define sb_jp_journal_size(sbp) \ 13062306a36Sopenharmony_ci (le32_to_cpu((sbp)->s_v1.s_journal.jp_journal_size)) 13162306a36Sopenharmony_ci#define set_sb_jp_journal_size(sbp,v) \ 13262306a36Sopenharmony_ci ((sbp)->s_v1.s_journal.jp_journal_size = cpu_to_le32(v)) 13362306a36Sopenharmony_ci#define sb_jp_journal_trans_max(sbp) \ 13462306a36Sopenharmony_ci (le32_to_cpu((sbp)->s_v1.s_journal.jp_journal_trans_max)) 13562306a36Sopenharmony_ci#define set_sb_jp_journal_trans_max(sbp,v) \ 13662306a36Sopenharmony_ci ((sbp)->s_v1.s_journal.jp_journal_trans_max = cpu_to_le32(v)) 13762306a36Sopenharmony_ci#define sb_jp_journal_magic(sbp) \ 13862306a36Sopenharmony_ci (le32_to_cpu((sbp)->s_v1.s_journal.jp_journal_magic)) 13962306a36Sopenharmony_ci#define set_sb_jp_journal_magic(sbp,v) \ 14062306a36Sopenharmony_ci ((sbp)->s_v1.s_journal.jp_journal_magic = cpu_to_le32(v)) 14162306a36Sopenharmony_ci#define sb_jp_journal_max_batch(sbp) \ 14262306a36Sopenharmony_ci (le32_to_cpu((sbp)->s_v1.s_journal.jp_journal_max_batch)) 14362306a36Sopenharmony_ci#define set_sb_jp_journal_max_batch(sbp,v) \ 14462306a36Sopenharmony_ci ((sbp)->s_v1.s_journal.jp_journal_max_batch = cpu_to_le32(v)) 14562306a36Sopenharmony_ci#define sb_jp_jourmal_max_commit_age(sbp) \ 14662306a36Sopenharmony_ci (le32_to_cpu((sbp)->s_v1.s_journal.jp_journal_max_commit_age)) 14762306a36Sopenharmony_ci#define set_sb_jp_journal_max_commit_age(sbp,v) \ 14862306a36Sopenharmony_ci ((sbp)->s_v1.s_journal.jp_journal_max_commit_age = cpu_to_le32(v)) 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci#define sb_blocksize(sbp) (le16_to_cpu((sbp)->s_v1.s_blocksize)) 15162306a36Sopenharmony_ci#define set_sb_blocksize(sbp,v) ((sbp)->s_v1.s_blocksize = cpu_to_le16(v)) 15262306a36Sopenharmony_ci#define sb_oid_maxsize(sbp) (le16_to_cpu((sbp)->s_v1.s_oid_maxsize)) 15362306a36Sopenharmony_ci#define set_sb_oid_maxsize(sbp,v) ((sbp)->s_v1.s_oid_maxsize = cpu_to_le16(v)) 15462306a36Sopenharmony_ci#define sb_oid_cursize(sbp) (le16_to_cpu((sbp)->s_v1.s_oid_cursize)) 15562306a36Sopenharmony_ci#define set_sb_oid_cursize(sbp,v) ((sbp)->s_v1.s_oid_cursize = cpu_to_le16(v)) 15662306a36Sopenharmony_ci#define sb_umount_state(sbp) (le16_to_cpu((sbp)->s_v1.s_umount_state)) 15762306a36Sopenharmony_ci#define set_sb_umount_state(sbp,v) ((sbp)->s_v1.s_umount_state = cpu_to_le16(v)) 15862306a36Sopenharmony_ci#define sb_fs_state(sbp) (le16_to_cpu((sbp)->s_v1.s_fs_state)) 15962306a36Sopenharmony_ci#define set_sb_fs_state(sbp,v) ((sbp)->s_v1.s_fs_state = cpu_to_le16(v)) 16062306a36Sopenharmony_ci#define sb_hash_function_code(sbp) \ 16162306a36Sopenharmony_ci (le32_to_cpu((sbp)->s_v1.s_hash_function_code)) 16262306a36Sopenharmony_ci#define set_sb_hash_function_code(sbp,v) \ 16362306a36Sopenharmony_ci ((sbp)->s_v1.s_hash_function_code = cpu_to_le32(v)) 16462306a36Sopenharmony_ci#define sb_tree_height(sbp) (le16_to_cpu((sbp)->s_v1.s_tree_height)) 16562306a36Sopenharmony_ci#define set_sb_tree_height(sbp,v) ((sbp)->s_v1.s_tree_height = cpu_to_le16(v)) 16662306a36Sopenharmony_ci#define sb_bmap_nr(sbp) (le16_to_cpu((sbp)->s_v1.s_bmap_nr)) 16762306a36Sopenharmony_ci#define set_sb_bmap_nr(sbp,v) ((sbp)->s_v1.s_bmap_nr = cpu_to_le16(v)) 16862306a36Sopenharmony_ci#define sb_version(sbp) (le16_to_cpu((sbp)->s_v1.s_version)) 16962306a36Sopenharmony_ci#define set_sb_version(sbp,v) ((sbp)->s_v1.s_version = cpu_to_le16(v)) 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci#define sb_mnt_count(sbp) (le16_to_cpu((sbp)->s_mnt_count)) 17262306a36Sopenharmony_ci#define set_sb_mnt_count(sbp, v) ((sbp)->s_mnt_count = cpu_to_le16(v)) 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci#define sb_reserved_for_journal(sbp) \ 17562306a36Sopenharmony_ci (le16_to_cpu((sbp)->s_v1.s_reserved_for_journal)) 17662306a36Sopenharmony_ci#define set_sb_reserved_for_journal(sbp,v) \ 17762306a36Sopenharmony_ci ((sbp)->s_v1.s_reserved_for_journal = cpu_to_le16(v)) 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/* LOGGING -- */ 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci/* 18262306a36Sopenharmony_ci * These all interelate for performance. 18362306a36Sopenharmony_ci * 18462306a36Sopenharmony_ci * If the journal block count is smaller than n transactions, you lose speed. 18562306a36Sopenharmony_ci * I don't know what n is yet, I'm guessing 8-16. 18662306a36Sopenharmony_ci * 18762306a36Sopenharmony_ci * typical transaction size depends on the application, how often fsync is 18862306a36Sopenharmony_ci * called, and how many metadata blocks you dirty in a 30 second period. 18962306a36Sopenharmony_ci * The more small files (<16k) you use, the larger your transactions will 19062306a36Sopenharmony_ci * be. 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * If your journal fills faster than dirty buffers get flushed to disk, it 19362306a36Sopenharmony_ci * must flush them before allowing the journal to wrap, which slows things 19462306a36Sopenharmony_ci * down. If you need high speed meta data updates, the journal should be 19562306a36Sopenharmony_ci * big enough to prevent wrapping before dirty meta blocks get to disk. 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * If the batch max is smaller than the transaction max, you'll waste space 19862306a36Sopenharmony_ci * at the end of the journal because journal_end sets the next transaction 19962306a36Sopenharmony_ci * to start at 0 if the next transaction has any chance of wrapping. 20062306a36Sopenharmony_ci * 20162306a36Sopenharmony_ci * The large the batch max age, the better the speed, and the more meta 20262306a36Sopenharmony_ci * data changes you'll lose after a crash. 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci/* don't mess with these for a while */ 20662306a36Sopenharmony_ci/* we have a node size define somewhere in reiserfs_fs.h. -Hans */ 20762306a36Sopenharmony_ci#define JOURNAL_BLOCK_SIZE 4096 /* BUG gotta get rid of this */ 20862306a36Sopenharmony_ci#define JOURNAL_MAX_CNODE 1500 /* max cnodes to allocate. */ 20962306a36Sopenharmony_ci#define JOURNAL_HASH_SIZE 8192 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/* number of copies of the bitmaps to have floating. Must be >= 2 */ 21262306a36Sopenharmony_ci#define JOURNAL_NUM_BITMAPS 5 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci/* 21562306a36Sopenharmony_ci * One of these for every block in every transaction 21662306a36Sopenharmony_ci * Each one is in two hash tables. First, a hash of the current transaction, 21762306a36Sopenharmony_ci * and after journal_end, a hash of all the in memory transactions. 21862306a36Sopenharmony_ci * next and prev are used by the current transaction (journal_hash). 21962306a36Sopenharmony_ci * hnext and hprev are used by journal_list_hash. If a block is in more 22062306a36Sopenharmony_ci * than one transaction, the journal_list_hash links it in multiple times. 22162306a36Sopenharmony_ci * This allows flush_journal_list to remove just the cnode belonging to a 22262306a36Sopenharmony_ci * given transaction. 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_cistruct reiserfs_journal_cnode { 22562306a36Sopenharmony_ci struct buffer_head *bh; /* real buffer head */ 22662306a36Sopenharmony_ci struct super_block *sb; /* dev of real buffer head */ 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci /* block number of real buffer head, == 0 when buffer on disk */ 22962306a36Sopenharmony_ci __u32 blocknr; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci unsigned long state; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* journal list this cnode lives in */ 23462306a36Sopenharmony_ci struct reiserfs_journal_list *jlist; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci struct reiserfs_journal_cnode *next; /* next in transaction list */ 23762306a36Sopenharmony_ci struct reiserfs_journal_cnode *prev; /* prev in transaction list */ 23862306a36Sopenharmony_ci struct reiserfs_journal_cnode *hprev; /* prev in hash list */ 23962306a36Sopenharmony_ci struct reiserfs_journal_cnode *hnext; /* next in hash list */ 24062306a36Sopenharmony_ci}; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cistruct reiserfs_bitmap_node { 24362306a36Sopenharmony_ci int id; 24462306a36Sopenharmony_ci char *data; 24562306a36Sopenharmony_ci struct list_head list; 24662306a36Sopenharmony_ci}; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistruct reiserfs_list_bitmap { 24962306a36Sopenharmony_ci struct reiserfs_journal_list *journal_list; 25062306a36Sopenharmony_ci struct reiserfs_bitmap_node **bitmaps; 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci/* 25462306a36Sopenharmony_ci * one of these for each transaction. The most important part here is the 25562306a36Sopenharmony_ci * j_realblock. this list of cnodes is used to hash all the blocks in all 25662306a36Sopenharmony_ci * the commits, to mark all the real buffer heads dirty once all the commits 25762306a36Sopenharmony_ci * hit the disk, and to make sure every real block in a transaction is on 25862306a36Sopenharmony_ci * disk before allowing the log area to be overwritten 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_cistruct reiserfs_journal_list { 26162306a36Sopenharmony_ci unsigned long j_start; 26262306a36Sopenharmony_ci unsigned long j_state; 26362306a36Sopenharmony_ci unsigned long j_len; 26462306a36Sopenharmony_ci atomic_t j_nonzerolen; 26562306a36Sopenharmony_ci atomic_t j_commit_left; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* all commits older than this on disk */ 26862306a36Sopenharmony_ci atomic_t j_older_commits_done; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci struct mutex j_commit_mutex; 27162306a36Sopenharmony_ci unsigned int j_trans_id; 27262306a36Sopenharmony_ci time64_t j_timestamp; /* write-only but useful for crash dump analysis */ 27362306a36Sopenharmony_ci struct reiserfs_list_bitmap *j_list_bitmap; 27462306a36Sopenharmony_ci struct buffer_head *j_commit_bh; /* commit buffer head */ 27562306a36Sopenharmony_ci struct reiserfs_journal_cnode *j_realblock; 27662306a36Sopenharmony_ci struct reiserfs_journal_cnode *j_freedlist; /* list of buffers that were freed during this trans. free each of these on flush */ 27762306a36Sopenharmony_ci /* time ordered list of all active transactions */ 27862306a36Sopenharmony_ci struct list_head j_list; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* 28162306a36Sopenharmony_ci * time ordered list of all transactions we haven't tried 28262306a36Sopenharmony_ci * to flush yet 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_ci struct list_head j_working_list; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* list of tail conversion targets in need of flush before commit */ 28762306a36Sopenharmony_ci struct list_head j_tail_bh_list; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* list of data=ordered buffers in need of flush before commit */ 29062306a36Sopenharmony_ci struct list_head j_bh_list; 29162306a36Sopenharmony_ci int j_refcount; 29262306a36Sopenharmony_ci}; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistruct reiserfs_journal { 29562306a36Sopenharmony_ci struct buffer_head **j_ap_blocks; /* journal blocks on disk */ 29662306a36Sopenharmony_ci /* newest journal block */ 29762306a36Sopenharmony_ci struct reiserfs_journal_cnode *j_last; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* oldest journal block. start here for traverse */ 30062306a36Sopenharmony_ci struct reiserfs_journal_cnode *j_first; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci struct block_device *j_dev_bd; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci /* first block on s_dev of reserved area journal */ 30562306a36Sopenharmony_ci int j_1st_reserved_block; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci unsigned long j_state; 30862306a36Sopenharmony_ci unsigned int j_trans_id; 30962306a36Sopenharmony_ci unsigned long j_mount_id; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci /* start of current waiting commit (index into j_ap_blocks) */ 31262306a36Sopenharmony_ci unsigned long j_start; 31362306a36Sopenharmony_ci unsigned long j_len; /* length of current waiting commit */ 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* number of buffers requested by journal_begin() */ 31662306a36Sopenharmony_ci unsigned long j_len_alloc; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci atomic_t j_wcount; /* count of writers for current commit */ 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* batch count. allows turning X transactions into 1 */ 32162306a36Sopenharmony_ci unsigned long j_bcount; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* first unflushed transactions offset */ 32462306a36Sopenharmony_ci unsigned long j_first_unflushed_offset; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* last fully flushed journal timestamp */ 32762306a36Sopenharmony_ci unsigned j_last_flush_trans_id; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci struct buffer_head *j_header_bh; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci time64_t j_trans_start_time; /* time this transaction started */ 33262306a36Sopenharmony_ci struct mutex j_mutex; 33362306a36Sopenharmony_ci struct mutex j_flush_mutex; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* wait for current transaction to finish before starting new one */ 33662306a36Sopenharmony_ci wait_queue_head_t j_join_wait; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci atomic_t j_jlock; /* lock for j_join_wait */ 33962306a36Sopenharmony_ci int j_list_bitmap_index; /* number of next list bitmap to use */ 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* no more journal begins allowed. MUST sleep on j_join_wait */ 34262306a36Sopenharmony_ci int j_must_wait; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* next journal_end will flush all journal list */ 34562306a36Sopenharmony_ci int j_next_full_flush; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* next journal_end will flush all async commits */ 34862306a36Sopenharmony_ci int j_next_async_flush; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci int j_cnode_used; /* number of cnodes on the used list */ 35162306a36Sopenharmony_ci int j_cnode_free; /* number of cnodes on the free list */ 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci /* max number of blocks in a transaction. */ 35462306a36Sopenharmony_ci unsigned int j_trans_max; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* max number of blocks to batch into a trans */ 35762306a36Sopenharmony_ci unsigned int j_max_batch; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci /* in seconds, how old can an async commit be */ 36062306a36Sopenharmony_ci unsigned int j_max_commit_age; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* in seconds, how old can a transaction be */ 36362306a36Sopenharmony_ci unsigned int j_max_trans_age; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci /* the default for the max commit age */ 36662306a36Sopenharmony_ci unsigned int j_default_max_commit_age; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci struct reiserfs_journal_cnode *j_cnode_free_list; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci /* orig pointer returned from vmalloc */ 37162306a36Sopenharmony_ci struct reiserfs_journal_cnode *j_cnode_free_orig; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci struct reiserfs_journal_list *j_current_jl; 37462306a36Sopenharmony_ci int j_free_bitmap_nodes; 37562306a36Sopenharmony_ci int j_used_bitmap_nodes; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci int j_num_lists; /* total number of active transactions */ 37862306a36Sopenharmony_ci int j_num_work_lists; /* number that need attention from kreiserfsd */ 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* debugging to make sure things are flushed in order */ 38162306a36Sopenharmony_ci unsigned int j_last_flush_id; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* debugging to make sure things are committed in order */ 38462306a36Sopenharmony_ci unsigned int j_last_commit_id; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci struct list_head j_bitmap_nodes; 38762306a36Sopenharmony_ci struct list_head j_dirty_buffers; 38862306a36Sopenharmony_ci spinlock_t j_dirty_buffers_lock; /* protects j_dirty_buffers */ 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci /* list of all active transactions */ 39162306a36Sopenharmony_ci struct list_head j_journal_list; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci /* lists that haven't been touched by writeback attempts */ 39462306a36Sopenharmony_ci struct list_head j_working_list; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci /* hash table for real buffer heads in current trans */ 39762306a36Sopenharmony_ci struct reiserfs_journal_cnode *j_hash_table[JOURNAL_HASH_SIZE]; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* hash table for all the real buffer heads in all the transactions */ 40062306a36Sopenharmony_ci struct reiserfs_journal_cnode *j_list_hash_table[JOURNAL_HASH_SIZE]; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci /* array of bitmaps to record the deleted blocks */ 40362306a36Sopenharmony_ci struct reiserfs_list_bitmap j_list_bitmap[JOURNAL_NUM_BITMAPS]; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci /* list of inodes which have preallocated blocks */ 40662306a36Sopenharmony_ci struct list_head j_prealloc_list; 40762306a36Sopenharmony_ci int j_persistent_trans; 40862306a36Sopenharmony_ci unsigned long j_max_trans_size; 40962306a36Sopenharmony_ci unsigned long j_max_batch_size; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci int j_errno; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci /* when flushing ordered buffers, throttle new ordered writers */ 41462306a36Sopenharmony_ci struct delayed_work j_work; 41562306a36Sopenharmony_ci struct super_block *j_work_sb; 41662306a36Sopenharmony_ci atomic_t j_async_throttle; 41762306a36Sopenharmony_ci}; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cienum journal_state_bits { 42062306a36Sopenharmony_ci J_WRITERS_BLOCKED = 1, /* set when new writers not allowed */ 42162306a36Sopenharmony_ci J_WRITERS_QUEUED, /* set when log is full due to too many writers */ 42262306a36Sopenharmony_ci J_ABORTED, /* set when log is aborted */ 42362306a36Sopenharmony_ci}; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci/* ick. magic string to find desc blocks in the journal */ 42662306a36Sopenharmony_ci#define JOURNAL_DESC_MAGIC "ReIsErLB" 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_citypedef __u32(*hashf_t) (const signed char *, int); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistruct reiserfs_bitmap_info { 43162306a36Sopenharmony_ci __u32 free_count; 43262306a36Sopenharmony_ci}; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistruct proc_dir_entry; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci#if defined( CONFIG_PROC_FS ) && defined( CONFIG_REISERFS_PROC_INFO ) 43762306a36Sopenharmony_citypedef unsigned long int stat_cnt_t; 43862306a36Sopenharmony_citypedef struct reiserfs_proc_info_data { 43962306a36Sopenharmony_ci spinlock_t lock; 44062306a36Sopenharmony_ci int exiting; 44162306a36Sopenharmony_ci int max_hash_collisions; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci stat_cnt_t breads; 44462306a36Sopenharmony_ci stat_cnt_t bread_miss; 44562306a36Sopenharmony_ci stat_cnt_t search_by_key; 44662306a36Sopenharmony_ci stat_cnt_t search_by_key_fs_changed; 44762306a36Sopenharmony_ci stat_cnt_t search_by_key_restarted; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci stat_cnt_t insert_item_restarted; 45062306a36Sopenharmony_ci stat_cnt_t paste_into_item_restarted; 45162306a36Sopenharmony_ci stat_cnt_t cut_from_item_restarted; 45262306a36Sopenharmony_ci stat_cnt_t delete_solid_item_restarted; 45362306a36Sopenharmony_ci stat_cnt_t delete_item_restarted; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci stat_cnt_t leaked_oid; 45662306a36Sopenharmony_ci stat_cnt_t leaves_removable; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci /* 45962306a36Sopenharmony_ci * balances per level. 46062306a36Sopenharmony_ci * Use explicit 5 as MAX_HEIGHT is not visible yet. 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_ci stat_cnt_t balance_at[5]; /* XXX */ 46362306a36Sopenharmony_ci /* sbk == search_by_key */ 46462306a36Sopenharmony_ci stat_cnt_t sbk_read_at[5]; /* XXX */ 46562306a36Sopenharmony_ci stat_cnt_t sbk_fs_changed[5]; 46662306a36Sopenharmony_ci stat_cnt_t sbk_restarted[5]; 46762306a36Sopenharmony_ci stat_cnt_t items_at[5]; /* XXX */ 46862306a36Sopenharmony_ci stat_cnt_t free_at[5]; /* XXX */ 46962306a36Sopenharmony_ci stat_cnt_t can_node_be_removed[5]; /* XXX */ 47062306a36Sopenharmony_ci long int lnum[5]; /* XXX */ 47162306a36Sopenharmony_ci long int rnum[5]; /* XXX */ 47262306a36Sopenharmony_ci long int lbytes[5]; /* XXX */ 47362306a36Sopenharmony_ci long int rbytes[5]; /* XXX */ 47462306a36Sopenharmony_ci stat_cnt_t get_neighbors[5]; 47562306a36Sopenharmony_ci stat_cnt_t get_neighbors_restart[5]; 47662306a36Sopenharmony_ci stat_cnt_t need_l_neighbor[5]; 47762306a36Sopenharmony_ci stat_cnt_t need_r_neighbor[5]; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci stat_cnt_t free_block; 48062306a36Sopenharmony_ci struct __scan_bitmap_stats { 48162306a36Sopenharmony_ci stat_cnt_t call; 48262306a36Sopenharmony_ci stat_cnt_t wait; 48362306a36Sopenharmony_ci stat_cnt_t bmap; 48462306a36Sopenharmony_ci stat_cnt_t retry; 48562306a36Sopenharmony_ci stat_cnt_t in_journal_hint; 48662306a36Sopenharmony_ci stat_cnt_t in_journal_nohint; 48762306a36Sopenharmony_ci stat_cnt_t stolen; 48862306a36Sopenharmony_ci } scan_bitmap; 48962306a36Sopenharmony_ci struct __journal_stats { 49062306a36Sopenharmony_ci stat_cnt_t in_journal; 49162306a36Sopenharmony_ci stat_cnt_t in_journal_bitmap; 49262306a36Sopenharmony_ci stat_cnt_t in_journal_reusable; 49362306a36Sopenharmony_ci stat_cnt_t lock_journal; 49462306a36Sopenharmony_ci stat_cnt_t lock_journal_wait; 49562306a36Sopenharmony_ci stat_cnt_t journal_being; 49662306a36Sopenharmony_ci stat_cnt_t journal_relock_writers; 49762306a36Sopenharmony_ci stat_cnt_t journal_relock_wcount; 49862306a36Sopenharmony_ci stat_cnt_t mark_dirty; 49962306a36Sopenharmony_ci stat_cnt_t mark_dirty_already; 50062306a36Sopenharmony_ci stat_cnt_t mark_dirty_notjournal; 50162306a36Sopenharmony_ci stat_cnt_t restore_prepared; 50262306a36Sopenharmony_ci stat_cnt_t prepare; 50362306a36Sopenharmony_ci stat_cnt_t prepare_retry; 50462306a36Sopenharmony_ci } journal; 50562306a36Sopenharmony_ci} reiserfs_proc_info_data_t; 50662306a36Sopenharmony_ci#else 50762306a36Sopenharmony_citypedef struct reiserfs_proc_info_data { 50862306a36Sopenharmony_ci} reiserfs_proc_info_data_t; 50962306a36Sopenharmony_ci#endif 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci/* Number of quota types we support */ 51262306a36Sopenharmony_ci#define REISERFS_MAXQUOTAS 2 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci/* reiserfs union of in-core super block data */ 51562306a36Sopenharmony_cistruct reiserfs_sb_info { 51662306a36Sopenharmony_ci /* Buffer containing the super block */ 51762306a36Sopenharmony_ci struct buffer_head *s_sbh; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci /* Pointer to the on-disk super block in the buffer */ 52062306a36Sopenharmony_ci struct reiserfs_super_block *s_rs; 52162306a36Sopenharmony_ci struct reiserfs_bitmap_info *s_ap_bitmap; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci /* pointer to journal information */ 52462306a36Sopenharmony_ci struct reiserfs_journal *s_journal; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci unsigned short s_mount_state; /* reiserfs state (valid, invalid) */ 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci /* Serialize writers access, replace the old bkl */ 52962306a36Sopenharmony_ci struct mutex lock; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci /* Owner of the lock (can be recursive) */ 53262306a36Sopenharmony_ci struct task_struct *lock_owner; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci /* Depth of the lock, start from -1 like the bkl */ 53562306a36Sopenharmony_ci int lock_depth; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci struct workqueue_struct *commit_wq; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci /* Comment? -Hans */ 54062306a36Sopenharmony_ci void (*end_io_handler) (struct buffer_head *, int); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci /* 54362306a36Sopenharmony_ci * pointer to function which is used to sort names in directory. 54462306a36Sopenharmony_ci * Set on mount 54562306a36Sopenharmony_ci */ 54662306a36Sopenharmony_ci hashf_t s_hash_function; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci /* reiserfs's mount options are set here */ 54962306a36Sopenharmony_ci unsigned long s_mount_opt; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci /* This is a structure that describes block allocator options */ 55262306a36Sopenharmony_ci struct { 55362306a36Sopenharmony_ci /* Bitfield for enable/disable kind of options */ 55462306a36Sopenharmony_ci unsigned long bits; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci /* 55762306a36Sopenharmony_ci * size started from which we consider file 55862306a36Sopenharmony_ci * to be a large one (in blocks) 55962306a36Sopenharmony_ci */ 56062306a36Sopenharmony_ci unsigned long large_file_size; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci int border; /* percentage of disk, border takes */ 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci /* 56562306a36Sopenharmony_ci * Minimal file size (in blocks) starting 56662306a36Sopenharmony_ci * from which we do preallocations 56762306a36Sopenharmony_ci */ 56862306a36Sopenharmony_ci int preallocmin; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci /* 57162306a36Sopenharmony_ci * Number of blocks we try to prealloc when file 57262306a36Sopenharmony_ci * reaches preallocmin size (in blocks) or prealloc_list 57362306a36Sopenharmony_ci is empty. 57462306a36Sopenharmony_ci */ 57562306a36Sopenharmony_ci int preallocsize; 57662306a36Sopenharmony_ci } s_alloc_options; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* Comment? -Hans */ 57962306a36Sopenharmony_ci wait_queue_head_t s_wait; 58062306a36Sopenharmony_ci /* increased by one every time the tree gets re-balanced */ 58162306a36Sopenharmony_ci atomic_t s_generation_counter; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci /* File system properties. Currently holds on-disk FS format */ 58462306a36Sopenharmony_ci unsigned long s_properties; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci /* session statistics */ 58762306a36Sopenharmony_ci int s_disk_reads; 58862306a36Sopenharmony_ci int s_disk_writes; 58962306a36Sopenharmony_ci int s_fix_nodes; 59062306a36Sopenharmony_ci int s_do_balance; 59162306a36Sopenharmony_ci int s_unneeded_left_neighbor; 59262306a36Sopenharmony_ci int s_good_search_by_key_reada; 59362306a36Sopenharmony_ci int s_bmaps; 59462306a36Sopenharmony_ci int s_bmaps_without_search; 59562306a36Sopenharmony_ci int s_direct2indirect; 59662306a36Sopenharmony_ci int s_indirect2direct; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* 59962306a36Sopenharmony_ci * set up when it's ok for reiserfs_read_inode2() to read from 60062306a36Sopenharmony_ci * disk inode with nlink==0. Currently this is only used during 60162306a36Sopenharmony_ci * finish_unfinished() processing at mount time 60262306a36Sopenharmony_ci */ 60362306a36Sopenharmony_ci int s_is_unlinked_ok; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci reiserfs_proc_info_data_t s_proc_info_data; 60662306a36Sopenharmony_ci struct proc_dir_entry *procdir; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci /* amount of blocks reserved for further allocations */ 60962306a36Sopenharmony_ci int reserved_blocks; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci /* this lock on now only used to protect reserved_blocks variable */ 61362306a36Sopenharmony_ci spinlock_t bitmap_lock; 61462306a36Sopenharmony_ci struct dentry *priv_root; /* root of /.reiserfs_priv */ 61562306a36Sopenharmony_ci struct dentry *xattr_root; /* root of /.reiserfs_priv/xattrs */ 61662306a36Sopenharmony_ci int j_errno; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci int work_queued; /* non-zero delayed work is queued */ 61962306a36Sopenharmony_ci struct delayed_work old_work; /* old transactions flush delayed work */ 62062306a36Sopenharmony_ci spinlock_t old_work_lock; /* protects old_work and work_queued */ 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci#ifdef CONFIG_QUOTA 62362306a36Sopenharmony_ci char *s_qf_names[REISERFS_MAXQUOTAS]; 62462306a36Sopenharmony_ci int s_jquota_fmt; 62562306a36Sopenharmony_ci#endif 62662306a36Sopenharmony_ci char *s_jdev; /* Stored jdev for mount option showing */ 62762306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci /* 63062306a36Sopenharmony_ci * Detects whether more than one copy of tb exists per superblock 63162306a36Sopenharmony_ci * as a means of checking whether do_balance is executing 63262306a36Sopenharmony_ci * concurrently against another tree reader/writer on a same 63362306a36Sopenharmony_ci * mount point. 63462306a36Sopenharmony_ci */ 63562306a36Sopenharmony_ci struct tree_balance *cur_tb; 63662306a36Sopenharmony_ci#endif 63762306a36Sopenharmony_ci}; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci/* Definitions of reiserfs on-disk properties: */ 64062306a36Sopenharmony_ci#define REISERFS_3_5 0 64162306a36Sopenharmony_ci#define REISERFS_3_6 1 64262306a36Sopenharmony_ci#define REISERFS_OLD_FORMAT 2 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci/* Mount options */ 64562306a36Sopenharmony_cienum reiserfs_mount_options { 64662306a36Sopenharmony_ci /* large tails will be created in a session */ 64762306a36Sopenharmony_ci REISERFS_LARGETAIL, 64862306a36Sopenharmony_ci /* 64962306a36Sopenharmony_ci * small (for files less than block size) tails will 65062306a36Sopenharmony_ci * be created in a session 65162306a36Sopenharmony_ci */ 65262306a36Sopenharmony_ci REISERFS_SMALLTAIL, 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci /* replay journal and return 0. Use by fsck */ 65562306a36Sopenharmony_ci REPLAYONLY, 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* 65862306a36Sopenharmony_ci * -o conv: causes conversion of old format super block to the 65962306a36Sopenharmony_ci * new format. If not specified - old partition will be dealt 66062306a36Sopenharmony_ci * with in a manner of 3.5.x 66162306a36Sopenharmony_ci */ 66262306a36Sopenharmony_ci REISERFS_CONVERT, 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci /* 66562306a36Sopenharmony_ci * -o hash={tea, rupasov, r5, detect} is meant for properly mounting 66662306a36Sopenharmony_ci * reiserfs disks from 3.5.19 or earlier. 99% of the time, this 66762306a36Sopenharmony_ci * option is not required. If the normal autodection code can't 66862306a36Sopenharmony_ci * determine which hash to use (because both hashes had the same 66962306a36Sopenharmony_ci * value for a file) use this option to force a specific hash. 67062306a36Sopenharmony_ci * It won't allow you to override the existing hash on the FS, so 67162306a36Sopenharmony_ci * if you have a tea hash disk, and mount with -o hash=rupasov, 67262306a36Sopenharmony_ci * the mount will fail. 67362306a36Sopenharmony_ci */ 67462306a36Sopenharmony_ci FORCE_TEA_HASH, /* try to force tea hash on mount */ 67562306a36Sopenharmony_ci FORCE_RUPASOV_HASH, /* try to force rupasov hash on mount */ 67662306a36Sopenharmony_ci FORCE_R5_HASH, /* try to force rupasov hash on mount */ 67762306a36Sopenharmony_ci FORCE_HASH_DETECT, /* try to detect hash function on mount */ 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci REISERFS_DATA_LOG, 68062306a36Sopenharmony_ci REISERFS_DATA_ORDERED, 68162306a36Sopenharmony_ci REISERFS_DATA_WRITEBACK, 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci /* 68462306a36Sopenharmony_ci * used for testing experimental features, makes benchmarking new 68562306a36Sopenharmony_ci * features with and without more convenient, should never be used by 68662306a36Sopenharmony_ci * users in any code shipped to users (ideally) 68762306a36Sopenharmony_ci */ 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci REISERFS_NO_BORDER, 69062306a36Sopenharmony_ci REISERFS_NO_UNHASHED_RELOCATION, 69162306a36Sopenharmony_ci REISERFS_HASHED_RELOCATION, 69262306a36Sopenharmony_ci REISERFS_ATTRS, 69362306a36Sopenharmony_ci REISERFS_XATTRS_USER, 69462306a36Sopenharmony_ci REISERFS_POSIXACL, 69562306a36Sopenharmony_ci REISERFS_EXPOSE_PRIVROOT, 69662306a36Sopenharmony_ci REISERFS_BARRIER_NONE, 69762306a36Sopenharmony_ci REISERFS_BARRIER_FLUSH, 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci /* Actions on error */ 70062306a36Sopenharmony_ci REISERFS_ERROR_PANIC, 70162306a36Sopenharmony_ci REISERFS_ERROR_RO, 70262306a36Sopenharmony_ci REISERFS_ERROR_CONTINUE, 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci REISERFS_USRQUOTA, /* User quota option specified */ 70562306a36Sopenharmony_ci REISERFS_GRPQUOTA, /* Group quota option specified */ 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci REISERFS_TEST1, 70862306a36Sopenharmony_ci REISERFS_TEST2, 70962306a36Sopenharmony_ci REISERFS_TEST3, 71062306a36Sopenharmony_ci REISERFS_TEST4, 71162306a36Sopenharmony_ci REISERFS_UNSUPPORTED_OPT, 71262306a36Sopenharmony_ci}; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci#define reiserfs_r5_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_R5_HASH)) 71562306a36Sopenharmony_ci#define reiserfs_rupasov_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_RUPASOV_HASH)) 71662306a36Sopenharmony_ci#define reiserfs_tea_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_TEA_HASH)) 71762306a36Sopenharmony_ci#define reiserfs_hash_detect(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_HASH_DETECT)) 71862306a36Sopenharmony_ci#define reiserfs_no_border(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_NO_BORDER)) 71962306a36Sopenharmony_ci#define reiserfs_no_unhashed_relocation(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_NO_UNHASHED_RELOCATION)) 72062306a36Sopenharmony_ci#define reiserfs_hashed_relocation(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_HASHED_RELOCATION)) 72162306a36Sopenharmony_ci#define reiserfs_test4(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_TEST4)) 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci#define have_large_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_LARGETAIL)) 72462306a36Sopenharmony_ci#define have_small_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_SMALLTAIL)) 72562306a36Sopenharmony_ci#define replay_only(s) (REISERFS_SB(s)->s_mount_opt & (1 << REPLAYONLY)) 72662306a36Sopenharmony_ci#define reiserfs_attrs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_ATTRS)) 72762306a36Sopenharmony_ci#define old_format_only(s) (REISERFS_SB(s)->s_properties & (1 << REISERFS_3_5)) 72862306a36Sopenharmony_ci#define convert_reiserfs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_CONVERT)) 72962306a36Sopenharmony_ci#define reiserfs_data_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_LOG)) 73062306a36Sopenharmony_ci#define reiserfs_data_ordered(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_ORDERED)) 73162306a36Sopenharmony_ci#define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK)) 73262306a36Sopenharmony_ci#define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER)) 73362306a36Sopenharmony_ci#define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL)) 73462306a36Sopenharmony_ci#define reiserfs_expose_privroot(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_EXPOSE_PRIVROOT)) 73562306a36Sopenharmony_ci#define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s)) 73662306a36Sopenharmony_ci#define reiserfs_barrier_none(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_BARRIER_NONE)) 73762306a36Sopenharmony_ci#define reiserfs_barrier_flush(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_BARRIER_FLUSH)) 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci#define reiserfs_error_panic(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_ERROR_PANIC)) 74062306a36Sopenharmony_ci#define reiserfs_error_ro(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_ERROR_RO)) 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_civoid reiserfs_file_buffer(struct buffer_head *bh, int list); 74362306a36Sopenharmony_ciextern struct file_system_type reiserfs_fs_type; 74462306a36Sopenharmony_ciint reiserfs_resize(struct super_block *, unsigned long); 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci#define CARRY_ON 0 74762306a36Sopenharmony_ci#define SCHEDULE_OCCURRED 1 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci#define SB_BUFFER_WITH_SB(s) (REISERFS_SB(s)->s_sbh) 75062306a36Sopenharmony_ci#define SB_JOURNAL(s) (REISERFS_SB(s)->s_journal) 75162306a36Sopenharmony_ci#define SB_JOURNAL_1st_RESERVED_BLOCK(s) (SB_JOURNAL(s)->j_1st_reserved_block) 75262306a36Sopenharmony_ci#define SB_JOURNAL_LEN_FREE(s) (SB_JOURNAL(s)->j_journal_len_free) 75362306a36Sopenharmony_ci#define SB_AP_BITMAP(s) (REISERFS_SB(s)->s_ap_bitmap) 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci#define SB_DISK_JOURNAL_HEAD(s) (SB_JOURNAL(s)->j_header_bh->) 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci#define reiserfs_is_journal_aborted(journal) (unlikely (__reiserfs_is_journal_aborted (journal))) 75862306a36Sopenharmony_cistatic inline int __reiserfs_is_journal_aborted(struct reiserfs_journal 75962306a36Sopenharmony_ci *journal) 76062306a36Sopenharmony_ci{ 76162306a36Sopenharmony_ci return test_bit(J_ABORTED, &journal->j_state); 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/* 76562306a36Sopenharmony_ci * Locking primitives. The write lock is a per superblock 76662306a36Sopenharmony_ci * special mutex that has properties close to the Big Kernel Lock 76762306a36Sopenharmony_ci * which was used in the previous locking scheme. 76862306a36Sopenharmony_ci */ 76962306a36Sopenharmony_civoid reiserfs_write_lock(struct super_block *s); 77062306a36Sopenharmony_civoid reiserfs_write_unlock(struct super_block *s); 77162306a36Sopenharmony_ciint __must_check reiserfs_write_unlock_nested(struct super_block *s); 77262306a36Sopenharmony_civoid reiserfs_write_lock_nested(struct super_block *s, int depth); 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK 77562306a36Sopenharmony_civoid reiserfs_lock_check_recursive(struct super_block *s); 77662306a36Sopenharmony_ci#else 77762306a36Sopenharmony_cistatic inline void reiserfs_lock_check_recursive(struct super_block *s) { } 77862306a36Sopenharmony_ci#endif 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci/* 78162306a36Sopenharmony_ci * Several mutexes depend on the write lock. 78262306a36Sopenharmony_ci * However sometimes we want to relax the write lock while we hold 78362306a36Sopenharmony_ci * these mutexes, according to the release/reacquire on schedule() 78462306a36Sopenharmony_ci * properties of the Bkl that were used. 78562306a36Sopenharmony_ci * Reiserfs performances and locking were based on this scheme. 78662306a36Sopenharmony_ci * Now that the write lock is a mutex and not the bkl anymore, doing so 78762306a36Sopenharmony_ci * may result in a deadlock: 78862306a36Sopenharmony_ci * 78962306a36Sopenharmony_ci * A acquire write_lock 79062306a36Sopenharmony_ci * A acquire j_commit_mutex 79162306a36Sopenharmony_ci * A release write_lock and wait for something 79262306a36Sopenharmony_ci * B acquire write_lock 79362306a36Sopenharmony_ci * B can't acquire j_commit_mutex and sleep 79462306a36Sopenharmony_ci * A can't acquire write lock anymore 79562306a36Sopenharmony_ci * deadlock 79662306a36Sopenharmony_ci * 79762306a36Sopenharmony_ci * What we do here is avoiding such deadlock by playing the same game 79862306a36Sopenharmony_ci * than the Bkl: if we can't acquire a mutex that depends on the write lock, 79962306a36Sopenharmony_ci * we release the write lock, wait a bit and then retry. 80062306a36Sopenharmony_ci * 80162306a36Sopenharmony_ci * The mutexes concerned by this hack are: 80262306a36Sopenharmony_ci * - The commit mutex of a journal list 80362306a36Sopenharmony_ci * - The flush mutex 80462306a36Sopenharmony_ci * - The journal lock 80562306a36Sopenharmony_ci * - The inode mutex 80662306a36Sopenharmony_ci */ 80762306a36Sopenharmony_cistatic inline void reiserfs_mutex_lock_safe(struct mutex *m, 80862306a36Sopenharmony_ci struct super_block *s) 80962306a36Sopenharmony_ci{ 81062306a36Sopenharmony_ci int depth; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(s); 81362306a36Sopenharmony_ci mutex_lock(m); 81462306a36Sopenharmony_ci reiserfs_write_lock_nested(s, depth); 81562306a36Sopenharmony_ci} 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_cistatic inline void 81862306a36Sopenharmony_cireiserfs_mutex_lock_nested_safe(struct mutex *m, unsigned int subclass, 81962306a36Sopenharmony_ci struct super_block *s) 82062306a36Sopenharmony_ci{ 82162306a36Sopenharmony_ci int depth; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(s); 82462306a36Sopenharmony_ci mutex_lock_nested(m, subclass); 82562306a36Sopenharmony_ci reiserfs_write_lock_nested(s, depth); 82662306a36Sopenharmony_ci} 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_cistatic inline void 82962306a36Sopenharmony_cireiserfs_down_read_safe(struct rw_semaphore *sem, struct super_block *s) 83062306a36Sopenharmony_ci{ 83162306a36Sopenharmony_ci int depth; 83262306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(s); 83362306a36Sopenharmony_ci down_read(sem); 83462306a36Sopenharmony_ci reiserfs_write_lock_nested(s, depth); 83562306a36Sopenharmony_ci} 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci/* 83862306a36Sopenharmony_ci * When we schedule, we usually want to also release the write lock, 83962306a36Sopenharmony_ci * according to the previous bkl based locking scheme of reiserfs. 84062306a36Sopenharmony_ci */ 84162306a36Sopenharmony_cistatic inline void reiserfs_cond_resched(struct super_block *s) 84262306a36Sopenharmony_ci{ 84362306a36Sopenharmony_ci if (need_resched()) { 84462306a36Sopenharmony_ci int depth; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(s); 84762306a36Sopenharmony_ci schedule(); 84862306a36Sopenharmony_ci reiserfs_write_lock_nested(s, depth); 84962306a36Sopenharmony_ci } 85062306a36Sopenharmony_ci} 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_cistruct fid; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci/* 85562306a36Sopenharmony_ci * in reading the #defines, it may help to understand that they employ 85662306a36Sopenharmony_ci * the following abbreviations: 85762306a36Sopenharmony_ci * 85862306a36Sopenharmony_ci * B = Buffer 85962306a36Sopenharmony_ci * I = Item header 86062306a36Sopenharmony_ci * H = Height within the tree (should be changed to LEV) 86162306a36Sopenharmony_ci * N = Number of the item in the node 86262306a36Sopenharmony_ci * STAT = stat data 86362306a36Sopenharmony_ci * DEH = Directory Entry Header 86462306a36Sopenharmony_ci * EC = Entry Count 86562306a36Sopenharmony_ci * E = Entry number 86662306a36Sopenharmony_ci * UL = Unsigned Long 86762306a36Sopenharmony_ci * BLKH = BLocK Header 86862306a36Sopenharmony_ci * UNFM = UNForMatted node 86962306a36Sopenharmony_ci * DC = Disk Child 87062306a36Sopenharmony_ci * P = Path 87162306a36Sopenharmony_ci * 87262306a36Sopenharmony_ci * These #defines are named by concatenating these abbreviations, 87362306a36Sopenharmony_ci * where first comes the arguments, and last comes the return value, 87462306a36Sopenharmony_ci * of the macro. 87562306a36Sopenharmony_ci */ 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci#define USE_INODE_GENERATION_COUNTER 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci#define REISERFS_PREALLOCATE 88062306a36Sopenharmony_ci#define DISPLACE_NEW_PACKING_LOCALITIES 88162306a36Sopenharmony_ci#define PREALLOCATION_SIZE 9 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci/* n must be power of 2 */ 88462306a36Sopenharmony_ci#define _ROUND_UP(x,n) (((x)+(n)-1u) & ~((n)-1u)) 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci/* 88762306a36Sopenharmony_ci * to be ok for alpha and others we have to align structures to 8 byte 88862306a36Sopenharmony_ci * boundary. 88962306a36Sopenharmony_ci * FIXME: do not change 4 by anything else: there is code which relies on that 89062306a36Sopenharmony_ci */ 89162306a36Sopenharmony_ci#define ROUND_UP(x) _ROUND_UP(x,8LL) 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci/* 89462306a36Sopenharmony_ci * debug levels. Right now, CONFIG_REISERFS_CHECK means print all debug 89562306a36Sopenharmony_ci * messages. 89662306a36Sopenharmony_ci */ 89762306a36Sopenharmony_ci#define REISERFS_DEBUG_CODE 5 /* extra messages to help find/debug errors */ 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_civoid __reiserfs_warning(struct super_block *s, const char *id, 90062306a36Sopenharmony_ci const char *func, const char *fmt, ...); 90162306a36Sopenharmony_ci#define reiserfs_warning(s, id, fmt, args...) \ 90262306a36Sopenharmony_ci __reiserfs_warning(s, id, __func__, fmt, ##args) 90362306a36Sopenharmony_ci/* assertions handling */ 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci/* always check a condition and panic if it's false. */ 90662306a36Sopenharmony_ci#define __RASSERT(cond, scond, format, args...) \ 90762306a36Sopenharmony_cido { \ 90862306a36Sopenharmony_ci if (!(cond)) \ 90962306a36Sopenharmony_ci reiserfs_panic(NULL, "assertion failure", "(" #cond ") at " \ 91062306a36Sopenharmony_ci __FILE__ ":%i:%s: " format "\n", \ 91162306a36Sopenharmony_ci __LINE__, __func__ , ##args); \ 91262306a36Sopenharmony_ci} while (0) 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci#define RASSERT(cond, format, args...) __RASSERT(cond, #cond, format, ##args) 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci#if defined( CONFIG_REISERFS_CHECK ) 91762306a36Sopenharmony_ci#define RFALSE(cond, format, args...) __RASSERT(!(cond), "!(" #cond ")", format, ##args) 91862306a36Sopenharmony_ci#else 91962306a36Sopenharmony_ci#define RFALSE( cond, format, args... ) do {;} while( 0 ) 92062306a36Sopenharmony_ci#endif 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci#define CONSTF __attribute_const__ 92362306a36Sopenharmony_ci/* 92462306a36Sopenharmony_ci * Disk Data Structures 92562306a36Sopenharmony_ci */ 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci/*************************************************************************** 92862306a36Sopenharmony_ci * SUPER BLOCK * 92962306a36Sopenharmony_ci ***************************************************************************/ 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci/* 93262306a36Sopenharmony_ci * Structure of super block on disk, a version of which in RAM is often 93362306a36Sopenharmony_ci * accessed as REISERFS_SB(s)->s_rs. The version in RAM is part of a larger 93462306a36Sopenharmony_ci * structure containing fields never written to disk. 93562306a36Sopenharmony_ci */ 93662306a36Sopenharmony_ci#define UNSET_HASH 0 /* Detect hash on disk */ 93762306a36Sopenharmony_ci#define TEA_HASH 1 93862306a36Sopenharmony_ci#define YURA_HASH 2 93962306a36Sopenharmony_ci#define R5_HASH 3 94062306a36Sopenharmony_ci#define DEFAULT_HASH R5_HASH 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_cistruct journal_params { 94362306a36Sopenharmony_ci /* where does journal start from on its * device */ 94462306a36Sopenharmony_ci __le32 jp_journal_1st_block; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci /* journal device st_rdev */ 94762306a36Sopenharmony_ci __le32 jp_journal_dev; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci /* size of the journal */ 95062306a36Sopenharmony_ci __le32 jp_journal_size; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci /* max number of blocks in a transaction. */ 95362306a36Sopenharmony_ci __le32 jp_journal_trans_max; 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci /* 95662306a36Sopenharmony_ci * random value made on fs creation 95762306a36Sopenharmony_ci * (this was sb_journal_block_count) 95862306a36Sopenharmony_ci */ 95962306a36Sopenharmony_ci __le32 jp_journal_magic; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci /* max number of blocks to batch into a trans */ 96262306a36Sopenharmony_ci __le32 jp_journal_max_batch; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci /* in seconds, how old can an async commit be */ 96562306a36Sopenharmony_ci __le32 jp_journal_max_commit_age; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci /* in seconds, how old can a transaction be */ 96862306a36Sopenharmony_ci __le32 jp_journal_max_trans_age; 96962306a36Sopenharmony_ci}; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci/* this is the super from 3.5.X, where X >= 10 */ 97262306a36Sopenharmony_cistruct reiserfs_super_block_v1 { 97362306a36Sopenharmony_ci __le32 s_block_count; /* blocks count */ 97462306a36Sopenharmony_ci __le32 s_free_blocks; /* free blocks count */ 97562306a36Sopenharmony_ci __le32 s_root_block; /* root block number */ 97662306a36Sopenharmony_ci struct journal_params s_journal; 97762306a36Sopenharmony_ci __le16 s_blocksize; /* block size */ 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci /* max size of object id array, see get_objectid() commentary */ 98062306a36Sopenharmony_ci __le16 s_oid_maxsize; 98162306a36Sopenharmony_ci __le16 s_oid_cursize; /* current size of object id array */ 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci /* this is set to 1 when filesystem was umounted, to 2 - when not */ 98462306a36Sopenharmony_ci __le16 s_umount_state; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci /* 98762306a36Sopenharmony_ci * reiserfs magic string indicates that file system is reiserfs: 98862306a36Sopenharmony_ci * "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" 98962306a36Sopenharmony_ci */ 99062306a36Sopenharmony_ci char s_magic[10]; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci /* 99362306a36Sopenharmony_ci * it is set to used by fsck to mark which 99462306a36Sopenharmony_ci * phase of rebuilding is done 99562306a36Sopenharmony_ci */ 99662306a36Sopenharmony_ci __le16 s_fs_state; 99762306a36Sopenharmony_ci /* 99862306a36Sopenharmony_ci * indicate, what hash function is being use 99962306a36Sopenharmony_ci * to sort names in a directory 100062306a36Sopenharmony_ci */ 100162306a36Sopenharmony_ci __le32 s_hash_function_code; 100262306a36Sopenharmony_ci __le16 s_tree_height; /* height of disk tree */ 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci /* 100562306a36Sopenharmony_ci * amount of bitmap blocks needed to address 100662306a36Sopenharmony_ci * each block of file system 100762306a36Sopenharmony_ci */ 100862306a36Sopenharmony_ci __le16 s_bmap_nr; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci /* 101162306a36Sopenharmony_ci * this field is only reliable on filesystem with non-standard journal 101262306a36Sopenharmony_ci */ 101362306a36Sopenharmony_ci __le16 s_version; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci /* 101662306a36Sopenharmony_ci * size in blocks of journal area on main device, we need to 101762306a36Sopenharmony_ci * keep after making fs with non-standard journal 101862306a36Sopenharmony_ci */ 101962306a36Sopenharmony_ci __le16 s_reserved_for_journal; 102062306a36Sopenharmony_ci} __attribute__ ((__packed__)); 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci#define SB_SIZE_V1 (sizeof(struct reiserfs_super_block_v1)) 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci/* this is the on disk super block */ 102562306a36Sopenharmony_cistruct reiserfs_super_block { 102662306a36Sopenharmony_ci struct reiserfs_super_block_v1 s_v1; 102762306a36Sopenharmony_ci __le32 s_inode_generation; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci /* Right now used only by inode-attributes, if enabled */ 103062306a36Sopenharmony_ci __le32 s_flags; 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci unsigned char s_uuid[16]; /* filesystem unique identifier */ 103362306a36Sopenharmony_ci unsigned char s_label[16]; /* filesystem volume label */ 103462306a36Sopenharmony_ci __le16 s_mnt_count; /* Count of mounts since last fsck */ 103562306a36Sopenharmony_ci __le16 s_max_mnt_count; /* Maximum mounts before check */ 103662306a36Sopenharmony_ci __le32 s_lastcheck; /* Timestamp of last fsck */ 103762306a36Sopenharmony_ci __le32 s_check_interval; /* Interval between checks */ 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci /* 104062306a36Sopenharmony_ci * zero filled by mkreiserfs and reiserfs_convert_objectid_map_v1() 104162306a36Sopenharmony_ci * so any additions must be updated there as well. */ 104262306a36Sopenharmony_ci char s_unused[76]; 104362306a36Sopenharmony_ci} __attribute__ ((__packed__)); 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci#define SB_SIZE (sizeof(struct reiserfs_super_block)) 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci#define REISERFS_VERSION_1 0 104862306a36Sopenharmony_ci#define REISERFS_VERSION_2 2 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci/* on-disk super block fields converted to cpu form */ 105162306a36Sopenharmony_ci#define SB_DISK_SUPER_BLOCK(s) (REISERFS_SB(s)->s_rs) 105262306a36Sopenharmony_ci#define SB_V1_DISK_SUPER_BLOCK(s) (&(SB_DISK_SUPER_BLOCK(s)->s_v1)) 105362306a36Sopenharmony_ci#define SB_BLOCKSIZE(s) \ 105462306a36Sopenharmony_ci le32_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_blocksize)) 105562306a36Sopenharmony_ci#define SB_BLOCK_COUNT(s) \ 105662306a36Sopenharmony_ci le32_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_block_count)) 105762306a36Sopenharmony_ci#define SB_FREE_BLOCKS(s) \ 105862306a36Sopenharmony_ci le32_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_free_blocks)) 105962306a36Sopenharmony_ci#define SB_REISERFS_MAGIC(s) \ 106062306a36Sopenharmony_ci (SB_V1_DISK_SUPER_BLOCK(s)->s_magic) 106162306a36Sopenharmony_ci#define SB_ROOT_BLOCK(s) \ 106262306a36Sopenharmony_ci le32_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_root_block)) 106362306a36Sopenharmony_ci#define SB_TREE_HEIGHT(s) \ 106462306a36Sopenharmony_ci le16_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_tree_height)) 106562306a36Sopenharmony_ci#define SB_REISERFS_STATE(s) \ 106662306a36Sopenharmony_ci le16_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_umount_state)) 106762306a36Sopenharmony_ci#define SB_VERSION(s) le16_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_version)) 106862306a36Sopenharmony_ci#define SB_BMAP_NR(s) le16_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_bmap_nr)) 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci#define PUT_SB_BLOCK_COUNT(s, val) \ 107162306a36Sopenharmony_ci do { SB_V1_DISK_SUPER_BLOCK(s)->s_block_count = cpu_to_le32(val); } while (0) 107262306a36Sopenharmony_ci#define PUT_SB_FREE_BLOCKS(s, val) \ 107362306a36Sopenharmony_ci do { SB_V1_DISK_SUPER_BLOCK(s)->s_free_blocks = cpu_to_le32(val); } while (0) 107462306a36Sopenharmony_ci#define PUT_SB_ROOT_BLOCK(s, val) \ 107562306a36Sopenharmony_ci do { SB_V1_DISK_SUPER_BLOCK(s)->s_root_block = cpu_to_le32(val); } while (0) 107662306a36Sopenharmony_ci#define PUT_SB_TREE_HEIGHT(s, val) \ 107762306a36Sopenharmony_ci do { SB_V1_DISK_SUPER_BLOCK(s)->s_tree_height = cpu_to_le16(val); } while (0) 107862306a36Sopenharmony_ci#define PUT_SB_REISERFS_STATE(s, val) \ 107962306a36Sopenharmony_ci do { SB_V1_DISK_SUPER_BLOCK(s)->s_umount_state = cpu_to_le16(val); } while (0) 108062306a36Sopenharmony_ci#define PUT_SB_VERSION(s, val) \ 108162306a36Sopenharmony_ci do { SB_V1_DISK_SUPER_BLOCK(s)->s_version = cpu_to_le16(val); } while (0) 108262306a36Sopenharmony_ci#define PUT_SB_BMAP_NR(s, val) \ 108362306a36Sopenharmony_ci do { SB_V1_DISK_SUPER_BLOCK(s)->s_bmap_nr = cpu_to_le16 (val); } while (0) 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci#define SB_ONDISK_JP(s) (&SB_V1_DISK_SUPER_BLOCK(s)->s_journal) 108662306a36Sopenharmony_ci#define SB_ONDISK_JOURNAL_SIZE(s) \ 108762306a36Sopenharmony_ci le32_to_cpu ((SB_ONDISK_JP(s)->jp_journal_size)) 108862306a36Sopenharmony_ci#define SB_ONDISK_JOURNAL_1st_BLOCK(s) \ 108962306a36Sopenharmony_ci le32_to_cpu ((SB_ONDISK_JP(s)->jp_journal_1st_block)) 109062306a36Sopenharmony_ci#define SB_ONDISK_JOURNAL_DEVICE(s) \ 109162306a36Sopenharmony_ci le32_to_cpu ((SB_ONDISK_JP(s)->jp_journal_dev)) 109262306a36Sopenharmony_ci#define SB_ONDISK_RESERVED_FOR_JOURNAL(s) \ 109362306a36Sopenharmony_ci le16_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_reserved_for_journal)) 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci#define is_block_in_log_or_reserved_area(s, block) \ 109662306a36Sopenharmony_ci block >= SB_JOURNAL_1st_RESERVED_BLOCK(s) \ 109762306a36Sopenharmony_ci && block < SB_JOURNAL_1st_RESERVED_BLOCK(s) + \ 109862306a36Sopenharmony_ci ((!is_reiserfs_jr(SB_DISK_SUPER_BLOCK(s)) ? \ 109962306a36Sopenharmony_ci SB_ONDISK_JOURNAL_SIZE(s) + 1 : SB_ONDISK_RESERVED_FOR_JOURNAL(s))) 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ciint is_reiserfs_3_5(struct reiserfs_super_block *rs); 110262306a36Sopenharmony_ciint is_reiserfs_3_6(struct reiserfs_super_block *rs); 110362306a36Sopenharmony_ciint is_reiserfs_jr(struct reiserfs_super_block *rs); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci/* 110662306a36Sopenharmony_ci * ReiserFS leaves the first 64k unused, so that partition labels have 110762306a36Sopenharmony_ci * enough space. If someone wants to write a fancy bootloader that 110862306a36Sopenharmony_ci * needs more than 64k, let us know, and this will be increased in size. 110962306a36Sopenharmony_ci * This number must be larger than the largest block size on any 111062306a36Sopenharmony_ci * platform, or code will break. -Hans 111162306a36Sopenharmony_ci */ 111262306a36Sopenharmony_ci#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024) 111362306a36Sopenharmony_ci#define REISERFS_FIRST_BLOCK unused_define 111462306a36Sopenharmony_ci#define REISERFS_JOURNAL_OFFSET_IN_BYTES REISERFS_DISK_OFFSET_IN_BYTES 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci/* the spot for the super in versions 3.5 - 3.5.10 (inclusive) */ 111762306a36Sopenharmony_ci#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024) 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci/* reiserfs internal error code (used by search_by_key and fix_nodes)) */ 112062306a36Sopenharmony_ci#define CARRY_ON 0 112162306a36Sopenharmony_ci#define REPEAT_SEARCH -1 112262306a36Sopenharmony_ci#define IO_ERROR -2 112362306a36Sopenharmony_ci#define NO_DISK_SPACE -3 112462306a36Sopenharmony_ci#define NO_BALANCING_NEEDED (-4) 112562306a36Sopenharmony_ci#define NO_MORE_UNUSED_CONTIGUOUS_BLOCKS (-5) 112662306a36Sopenharmony_ci#define QUOTA_EXCEEDED -6 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_citypedef __u32 b_blocknr_t; 112962306a36Sopenharmony_citypedef __le32 unp_t; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_cistruct unfm_nodeinfo { 113262306a36Sopenharmony_ci unp_t unfm_nodenum; 113362306a36Sopenharmony_ci unsigned short unfm_freespace; 113462306a36Sopenharmony_ci}; 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci/* there are two formats of keys: 3.5 and 3.6 */ 113762306a36Sopenharmony_ci#define KEY_FORMAT_3_5 0 113862306a36Sopenharmony_ci#define KEY_FORMAT_3_6 1 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci/* there are two stat datas */ 114162306a36Sopenharmony_ci#define STAT_DATA_V1 0 114262306a36Sopenharmony_ci#define STAT_DATA_V2 1 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_cistatic inline struct reiserfs_inode_info *REISERFS_I(const struct inode *inode) 114562306a36Sopenharmony_ci{ 114662306a36Sopenharmony_ci return container_of(inode, struct reiserfs_inode_info, vfs_inode); 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_cistatic inline struct reiserfs_sb_info *REISERFS_SB(const struct super_block *sb) 115062306a36Sopenharmony_ci{ 115162306a36Sopenharmony_ci return sb->s_fs_info; 115262306a36Sopenharmony_ci} 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci/* 115562306a36Sopenharmony_ci * Don't trust REISERFS_SB(sb)->s_bmap_nr, it's a u16 115662306a36Sopenharmony_ci * which overflows on large file systems. 115762306a36Sopenharmony_ci */ 115862306a36Sopenharmony_cistatic inline __u32 reiserfs_bmap_count(struct super_block *sb) 115962306a36Sopenharmony_ci{ 116062306a36Sopenharmony_ci return (SB_BLOCK_COUNT(sb) - 1) / (sb->s_blocksize * 8) + 1; 116162306a36Sopenharmony_ci} 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_cistatic inline int bmap_would_wrap(unsigned bmap_nr) 116462306a36Sopenharmony_ci{ 116562306a36Sopenharmony_ci return bmap_nr > ((1LL << 16) - 1); 116662306a36Sopenharmony_ci} 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ciextern const struct xattr_handler *reiserfs_xattr_handlers[]; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci/* 117162306a36Sopenharmony_ci * this says about version of key of all items (but stat data) the 117262306a36Sopenharmony_ci * object consists of 117362306a36Sopenharmony_ci */ 117462306a36Sopenharmony_ci#define get_inode_item_key_version( inode ) \ 117562306a36Sopenharmony_ci ((REISERFS_I(inode)->i_flags & i_item_key_version_mask) ? KEY_FORMAT_3_6 : KEY_FORMAT_3_5) 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci#define set_inode_item_key_version( inode, version ) \ 117862306a36Sopenharmony_ci ({ if((version)==KEY_FORMAT_3_6) \ 117962306a36Sopenharmony_ci REISERFS_I(inode)->i_flags |= i_item_key_version_mask; \ 118062306a36Sopenharmony_ci else \ 118162306a36Sopenharmony_ci REISERFS_I(inode)->i_flags &= ~i_item_key_version_mask; }) 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci#define get_inode_sd_version(inode) \ 118462306a36Sopenharmony_ci ((REISERFS_I(inode)->i_flags & i_stat_data_version_mask) ? STAT_DATA_V2 : STAT_DATA_V1) 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci#define set_inode_sd_version(inode, version) \ 118762306a36Sopenharmony_ci ({ if((version)==STAT_DATA_V2) \ 118862306a36Sopenharmony_ci REISERFS_I(inode)->i_flags |= i_stat_data_version_mask; \ 118962306a36Sopenharmony_ci else \ 119062306a36Sopenharmony_ci REISERFS_I(inode)->i_flags &= ~i_stat_data_version_mask; }) 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci/* 119362306a36Sopenharmony_ci * This is an aggressive tail suppression policy, I am hoping it 119462306a36Sopenharmony_ci * improves our benchmarks. The principle behind it is that percentage 119562306a36Sopenharmony_ci * space saving is what matters, not absolute space saving. This is 119662306a36Sopenharmony_ci * non-intuitive, but it helps to understand it if you consider that the 119762306a36Sopenharmony_ci * cost to access 4 blocks is not much more than the cost to access 1 119862306a36Sopenharmony_ci * block, if you have to do a seek and rotate. A tail risks a 119962306a36Sopenharmony_ci * non-linear disk access that is significant as a percentage of total 120062306a36Sopenharmony_ci * time cost for a 4 block file and saves an amount of space that is 120162306a36Sopenharmony_ci * less significant as a percentage of space, or so goes the hypothesis. 120262306a36Sopenharmony_ci * -Hans 120362306a36Sopenharmony_ci */ 120462306a36Sopenharmony_ci#define STORE_TAIL_IN_UNFM_S1(n_file_size,n_tail_size,n_block_size) \ 120562306a36Sopenharmony_ci(\ 120662306a36Sopenharmony_ci (!(n_tail_size)) || \ 120762306a36Sopenharmony_ci (((n_tail_size) > MAX_DIRECT_ITEM_LEN(n_block_size)) || \ 120862306a36Sopenharmony_ci ( (n_file_size) >= (n_block_size) * 4 ) || \ 120962306a36Sopenharmony_ci ( ( (n_file_size) >= (n_block_size) * 3 ) && \ 121062306a36Sopenharmony_ci ( (n_tail_size) >= (MAX_DIRECT_ITEM_LEN(n_block_size))/4) ) || \ 121162306a36Sopenharmony_ci ( ( (n_file_size) >= (n_block_size) * 2 ) && \ 121262306a36Sopenharmony_ci ( (n_tail_size) >= (MAX_DIRECT_ITEM_LEN(n_block_size))/2) ) || \ 121362306a36Sopenharmony_ci ( ( (n_file_size) >= (n_block_size) ) && \ 121462306a36Sopenharmony_ci ( (n_tail_size) >= (MAX_DIRECT_ITEM_LEN(n_block_size) * 3)/4) ) ) \ 121562306a36Sopenharmony_ci) 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci/* 121862306a36Sopenharmony_ci * Another strategy for tails, this one means only create a tail if all the 121962306a36Sopenharmony_ci * file would fit into one DIRECT item. 122062306a36Sopenharmony_ci * Primary intention for this one is to increase performance by decreasing 122162306a36Sopenharmony_ci * seeking. 122262306a36Sopenharmony_ci*/ 122362306a36Sopenharmony_ci#define STORE_TAIL_IN_UNFM_S2(n_file_size,n_tail_size,n_block_size) \ 122462306a36Sopenharmony_ci(\ 122562306a36Sopenharmony_ci (!(n_tail_size)) || \ 122662306a36Sopenharmony_ci (((n_file_size) > MAX_DIRECT_ITEM_LEN(n_block_size)) ) \ 122762306a36Sopenharmony_ci) 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci/* 123062306a36Sopenharmony_ci * values for s_umount_state field 123162306a36Sopenharmony_ci */ 123262306a36Sopenharmony_ci#define REISERFS_VALID_FS 1 123362306a36Sopenharmony_ci#define REISERFS_ERROR_FS 2 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci/* 123662306a36Sopenharmony_ci * there are 5 item types currently 123762306a36Sopenharmony_ci */ 123862306a36Sopenharmony_ci#define TYPE_STAT_DATA 0 123962306a36Sopenharmony_ci#define TYPE_INDIRECT 1 124062306a36Sopenharmony_ci#define TYPE_DIRECT 2 124162306a36Sopenharmony_ci#define TYPE_DIRENTRY 3 124262306a36Sopenharmony_ci#define TYPE_MAXTYPE 3 124362306a36Sopenharmony_ci#define TYPE_ANY 15 /* FIXME: comment is required */ 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci/*************************************************************************** 124662306a36Sopenharmony_ci * KEY & ITEM HEAD * 124762306a36Sopenharmony_ci ***************************************************************************/ 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci/* * directories use this key as well as old files */ 125062306a36Sopenharmony_cistruct offset_v1 { 125162306a36Sopenharmony_ci __le32 k_offset; 125262306a36Sopenharmony_ci __le32 k_uniqueness; 125362306a36Sopenharmony_ci} __attribute__ ((__packed__)); 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_cistruct offset_v2 { 125662306a36Sopenharmony_ci __le64 v; 125762306a36Sopenharmony_ci} __attribute__ ((__packed__)); 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_cistatic inline __u16 offset_v2_k_type(const struct offset_v2 *v2) 126062306a36Sopenharmony_ci{ 126162306a36Sopenharmony_ci __u8 type = le64_to_cpu(v2->v) >> 60; 126262306a36Sopenharmony_ci return (type <= TYPE_MAXTYPE) ? type : TYPE_ANY; 126362306a36Sopenharmony_ci} 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_cistatic inline void set_offset_v2_k_type(struct offset_v2 *v2, int type) 126662306a36Sopenharmony_ci{ 126762306a36Sopenharmony_ci v2->v = 126862306a36Sopenharmony_ci (v2->v & cpu_to_le64(~0ULL >> 4)) | cpu_to_le64((__u64) type << 60); 126962306a36Sopenharmony_ci} 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_cistatic inline loff_t offset_v2_k_offset(const struct offset_v2 *v2) 127262306a36Sopenharmony_ci{ 127362306a36Sopenharmony_ci return le64_to_cpu(v2->v) & (~0ULL >> 4); 127462306a36Sopenharmony_ci} 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_cistatic inline void set_offset_v2_k_offset(struct offset_v2 *v2, loff_t offset) 127762306a36Sopenharmony_ci{ 127862306a36Sopenharmony_ci offset &= (~0ULL >> 4); 127962306a36Sopenharmony_ci v2->v = (v2->v & cpu_to_le64(15ULL << 60)) | cpu_to_le64(offset); 128062306a36Sopenharmony_ci} 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci/* 128362306a36Sopenharmony_ci * Key of an item determines its location in the S+tree, and 128462306a36Sopenharmony_ci * is composed of 4 components 128562306a36Sopenharmony_ci */ 128662306a36Sopenharmony_cistruct reiserfs_key { 128762306a36Sopenharmony_ci /* packing locality: by default parent directory object id */ 128862306a36Sopenharmony_ci __le32 k_dir_id; 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci __le32 k_objectid; /* object identifier */ 129162306a36Sopenharmony_ci union { 129262306a36Sopenharmony_ci struct offset_v1 k_offset_v1; 129362306a36Sopenharmony_ci struct offset_v2 k_offset_v2; 129462306a36Sopenharmony_ci } __attribute__ ((__packed__)) u; 129562306a36Sopenharmony_ci} __attribute__ ((__packed__)); 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_cistruct in_core_key { 129862306a36Sopenharmony_ci /* packing locality: by default parent directory object id */ 129962306a36Sopenharmony_ci __u32 k_dir_id; 130062306a36Sopenharmony_ci __u32 k_objectid; /* object identifier */ 130162306a36Sopenharmony_ci __u64 k_offset; 130262306a36Sopenharmony_ci __u8 k_type; 130362306a36Sopenharmony_ci}; 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_cistruct cpu_key { 130662306a36Sopenharmony_ci struct in_core_key on_disk_key; 130762306a36Sopenharmony_ci int version; 130862306a36Sopenharmony_ci /* 3 in all cases but direct2indirect and indirect2direct conversion */ 130962306a36Sopenharmony_ci int key_length; 131062306a36Sopenharmony_ci}; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci/* 131362306a36Sopenharmony_ci * Our function for comparing keys can compare keys of different 131462306a36Sopenharmony_ci * lengths. It takes as a parameter the length of the keys it is to 131562306a36Sopenharmony_ci * compare. These defines are used in determining what is to be passed 131662306a36Sopenharmony_ci * to it as that parameter. 131762306a36Sopenharmony_ci */ 131862306a36Sopenharmony_ci#define REISERFS_FULL_KEY_LEN 4 131962306a36Sopenharmony_ci#define REISERFS_SHORT_KEY_LEN 2 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci/* The result of the key compare */ 132262306a36Sopenharmony_ci#define FIRST_GREATER 1 132362306a36Sopenharmony_ci#define SECOND_GREATER -1 132462306a36Sopenharmony_ci#define KEYS_IDENTICAL 0 132562306a36Sopenharmony_ci#define KEY_FOUND 1 132662306a36Sopenharmony_ci#define KEY_NOT_FOUND 0 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci#define KEY_SIZE (sizeof(struct reiserfs_key)) 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci/* return values for search_by_key and clones */ 133162306a36Sopenharmony_ci#define ITEM_FOUND 1 133262306a36Sopenharmony_ci#define ITEM_NOT_FOUND 0 133362306a36Sopenharmony_ci#define ENTRY_FOUND 1 133462306a36Sopenharmony_ci#define ENTRY_NOT_FOUND 0 133562306a36Sopenharmony_ci#define DIRECTORY_NOT_FOUND -1 133662306a36Sopenharmony_ci#define REGULAR_FILE_FOUND -2 133762306a36Sopenharmony_ci#define DIRECTORY_FOUND -3 133862306a36Sopenharmony_ci#define BYTE_FOUND 1 133962306a36Sopenharmony_ci#define BYTE_NOT_FOUND 0 134062306a36Sopenharmony_ci#define FILE_NOT_FOUND -1 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci#define POSITION_FOUND 1 134362306a36Sopenharmony_ci#define POSITION_NOT_FOUND 0 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci/* return values for reiserfs_find_entry and search_by_entry_key */ 134662306a36Sopenharmony_ci#define NAME_FOUND 1 134762306a36Sopenharmony_ci#define NAME_NOT_FOUND 0 134862306a36Sopenharmony_ci#define GOTO_PREVIOUS_ITEM 2 134962306a36Sopenharmony_ci#define NAME_FOUND_INVISIBLE 3 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci/* 135262306a36Sopenharmony_ci * Everything in the filesystem is stored as a set of items. The 135362306a36Sopenharmony_ci * item head contains the key of the item, its free space (for 135462306a36Sopenharmony_ci * indirect items) and specifies the location of the item itself 135562306a36Sopenharmony_ci * within the block. 135662306a36Sopenharmony_ci */ 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_cistruct item_head { 135962306a36Sopenharmony_ci /* 136062306a36Sopenharmony_ci * Everything in the tree is found by searching for it based on 136162306a36Sopenharmony_ci * its key. 136262306a36Sopenharmony_ci */ 136362306a36Sopenharmony_ci struct reiserfs_key ih_key; 136462306a36Sopenharmony_ci union { 136562306a36Sopenharmony_ci /* 136662306a36Sopenharmony_ci * The free space in the last unformatted node of an 136762306a36Sopenharmony_ci * indirect item if this is an indirect item. This 136862306a36Sopenharmony_ci * equals 0xFFFF iff this is a direct item or stat data 136962306a36Sopenharmony_ci * item. Note that the key, not this field, is used to 137062306a36Sopenharmony_ci * determine the item type, and thus which field this 137162306a36Sopenharmony_ci * union contains. 137262306a36Sopenharmony_ci */ 137362306a36Sopenharmony_ci __le16 ih_free_space_reserved; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci /* 137662306a36Sopenharmony_ci * Iff this is a directory item, this field equals the 137762306a36Sopenharmony_ci * number of directory entries in the directory item. 137862306a36Sopenharmony_ci */ 137962306a36Sopenharmony_ci __le16 ih_entry_count; 138062306a36Sopenharmony_ci } __attribute__ ((__packed__)) u; 138162306a36Sopenharmony_ci __le16 ih_item_len; /* total size of the item body */ 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci /* an offset to the item body within the block */ 138462306a36Sopenharmony_ci __le16 ih_item_location; 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci /* 138762306a36Sopenharmony_ci * 0 for all old items, 2 for new ones. Highest bit is set by fsck 138862306a36Sopenharmony_ci * temporary, cleaned after all done 138962306a36Sopenharmony_ci */ 139062306a36Sopenharmony_ci __le16 ih_version; 139162306a36Sopenharmony_ci} __attribute__ ((__packed__)); 139262306a36Sopenharmony_ci/* size of item header */ 139362306a36Sopenharmony_ci#define IH_SIZE (sizeof(struct item_head)) 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci#define ih_free_space(ih) le16_to_cpu((ih)->u.ih_free_space_reserved) 139662306a36Sopenharmony_ci#define ih_version(ih) le16_to_cpu((ih)->ih_version) 139762306a36Sopenharmony_ci#define ih_entry_count(ih) le16_to_cpu((ih)->u.ih_entry_count) 139862306a36Sopenharmony_ci#define ih_location(ih) le16_to_cpu((ih)->ih_item_location) 139962306a36Sopenharmony_ci#define ih_item_len(ih) le16_to_cpu((ih)->ih_item_len) 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci#define put_ih_free_space(ih, val) do { (ih)->u.ih_free_space_reserved = cpu_to_le16(val); } while(0) 140262306a36Sopenharmony_ci#define put_ih_version(ih, val) do { (ih)->ih_version = cpu_to_le16(val); } while (0) 140362306a36Sopenharmony_ci#define put_ih_entry_count(ih, val) do { (ih)->u.ih_entry_count = cpu_to_le16(val); } while (0) 140462306a36Sopenharmony_ci#define put_ih_location(ih, val) do { (ih)->ih_item_location = cpu_to_le16(val); } while (0) 140562306a36Sopenharmony_ci#define put_ih_item_len(ih, val) do { (ih)->ih_item_len = cpu_to_le16(val); } while (0) 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci#define unreachable_item(ih) (ih_version(ih) & (1 << 15)) 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci#define get_ih_free_space(ih) (ih_version (ih) == KEY_FORMAT_3_6 ? 0 : ih_free_space (ih)) 141062306a36Sopenharmony_ci#define set_ih_free_space(ih,val) put_ih_free_space((ih), ((ih_version(ih) == KEY_FORMAT_3_6) ? 0 : (val))) 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci/* 141362306a36Sopenharmony_ci * these operate on indirect items, where you've got an array of ints 141462306a36Sopenharmony_ci * at a possibly unaligned location. These are a noop on ia32 141562306a36Sopenharmony_ci * 141662306a36Sopenharmony_ci * p is the array of __u32, i is the index into the array, v is the value 141762306a36Sopenharmony_ci * to store there. 141862306a36Sopenharmony_ci */ 141962306a36Sopenharmony_ci#define get_block_num(p, i) get_unaligned_le32((p) + (i)) 142062306a36Sopenharmony_ci#define put_block_num(p, i, v) put_unaligned_le32((v), (p) + (i)) 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci/* * in old version uniqueness field shows key type */ 142362306a36Sopenharmony_ci#define V1_SD_UNIQUENESS 0 142462306a36Sopenharmony_ci#define V1_INDIRECT_UNIQUENESS 0xfffffffe 142562306a36Sopenharmony_ci#define V1_DIRECT_UNIQUENESS 0xffffffff 142662306a36Sopenharmony_ci#define V1_DIRENTRY_UNIQUENESS 500 142762306a36Sopenharmony_ci#define V1_ANY_UNIQUENESS 555 /* FIXME: comment is required */ 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci/* here are conversion routines */ 143062306a36Sopenharmony_cistatic inline int uniqueness2type(__u32 uniqueness) CONSTF; 143162306a36Sopenharmony_cistatic inline int uniqueness2type(__u32 uniqueness) 143262306a36Sopenharmony_ci{ 143362306a36Sopenharmony_ci switch ((int)uniqueness) { 143462306a36Sopenharmony_ci case V1_SD_UNIQUENESS: 143562306a36Sopenharmony_ci return TYPE_STAT_DATA; 143662306a36Sopenharmony_ci case V1_INDIRECT_UNIQUENESS: 143762306a36Sopenharmony_ci return TYPE_INDIRECT; 143862306a36Sopenharmony_ci case V1_DIRECT_UNIQUENESS: 143962306a36Sopenharmony_ci return TYPE_DIRECT; 144062306a36Sopenharmony_ci case V1_DIRENTRY_UNIQUENESS: 144162306a36Sopenharmony_ci return TYPE_DIRENTRY; 144262306a36Sopenharmony_ci case V1_ANY_UNIQUENESS: 144362306a36Sopenharmony_ci default: 144462306a36Sopenharmony_ci return TYPE_ANY; 144562306a36Sopenharmony_ci } 144662306a36Sopenharmony_ci} 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_cistatic inline __u32 type2uniqueness(int type) CONSTF; 144962306a36Sopenharmony_cistatic inline __u32 type2uniqueness(int type) 145062306a36Sopenharmony_ci{ 145162306a36Sopenharmony_ci switch (type) { 145262306a36Sopenharmony_ci case TYPE_STAT_DATA: 145362306a36Sopenharmony_ci return V1_SD_UNIQUENESS; 145462306a36Sopenharmony_ci case TYPE_INDIRECT: 145562306a36Sopenharmony_ci return V1_INDIRECT_UNIQUENESS; 145662306a36Sopenharmony_ci case TYPE_DIRECT: 145762306a36Sopenharmony_ci return V1_DIRECT_UNIQUENESS; 145862306a36Sopenharmony_ci case TYPE_DIRENTRY: 145962306a36Sopenharmony_ci return V1_DIRENTRY_UNIQUENESS; 146062306a36Sopenharmony_ci case TYPE_ANY: 146162306a36Sopenharmony_ci default: 146262306a36Sopenharmony_ci return V1_ANY_UNIQUENESS; 146362306a36Sopenharmony_ci } 146462306a36Sopenharmony_ci} 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci/* 146762306a36Sopenharmony_ci * key is pointer to on disk key which is stored in le, result is cpu, 146862306a36Sopenharmony_ci * there is no way to get version of object from key, so, provide 146962306a36Sopenharmony_ci * version to these defines 147062306a36Sopenharmony_ci */ 147162306a36Sopenharmony_cistatic inline loff_t le_key_k_offset(int version, 147262306a36Sopenharmony_ci const struct reiserfs_key *key) 147362306a36Sopenharmony_ci{ 147462306a36Sopenharmony_ci return (version == KEY_FORMAT_3_5) ? 147562306a36Sopenharmony_ci le32_to_cpu(key->u.k_offset_v1.k_offset) : 147662306a36Sopenharmony_ci offset_v2_k_offset(&(key->u.k_offset_v2)); 147762306a36Sopenharmony_ci} 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_cistatic inline loff_t le_ih_k_offset(const struct item_head *ih) 148062306a36Sopenharmony_ci{ 148162306a36Sopenharmony_ci return le_key_k_offset(ih_version(ih), &(ih->ih_key)); 148262306a36Sopenharmony_ci} 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_cistatic inline loff_t le_key_k_type(int version, const struct reiserfs_key *key) 148562306a36Sopenharmony_ci{ 148662306a36Sopenharmony_ci if (version == KEY_FORMAT_3_5) { 148762306a36Sopenharmony_ci loff_t val = le32_to_cpu(key->u.k_offset_v1.k_uniqueness); 148862306a36Sopenharmony_ci return uniqueness2type(val); 148962306a36Sopenharmony_ci } else 149062306a36Sopenharmony_ci return offset_v2_k_type(&(key->u.k_offset_v2)); 149162306a36Sopenharmony_ci} 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_cistatic inline loff_t le_ih_k_type(const struct item_head *ih) 149462306a36Sopenharmony_ci{ 149562306a36Sopenharmony_ci return le_key_k_type(ih_version(ih), &(ih->ih_key)); 149662306a36Sopenharmony_ci} 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_cistatic inline void set_le_key_k_offset(int version, struct reiserfs_key *key, 149962306a36Sopenharmony_ci loff_t offset) 150062306a36Sopenharmony_ci{ 150162306a36Sopenharmony_ci if (version == KEY_FORMAT_3_5) 150262306a36Sopenharmony_ci key->u.k_offset_v1.k_offset = cpu_to_le32(offset); 150362306a36Sopenharmony_ci else 150462306a36Sopenharmony_ci set_offset_v2_k_offset(&key->u.k_offset_v2, offset); 150562306a36Sopenharmony_ci} 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_cistatic inline void add_le_key_k_offset(int version, struct reiserfs_key *key, 150862306a36Sopenharmony_ci loff_t offset) 150962306a36Sopenharmony_ci{ 151062306a36Sopenharmony_ci set_le_key_k_offset(version, key, 151162306a36Sopenharmony_ci le_key_k_offset(version, key) + offset); 151262306a36Sopenharmony_ci} 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_cistatic inline void add_le_ih_k_offset(struct item_head *ih, loff_t offset) 151562306a36Sopenharmony_ci{ 151662306a36Sopenharmony_ci add_le_key_k_offset(ih_version(ih), &(ih->ih_key), offset); 151762306a36Sopenharmony_ci} 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_cistatic inline void set_le_ih_k_offset(struct item_head *ih, loff_t offset) 152062306a36Sopenharmony_ci{ 152162306a36Sopenharmony_ci set_le_key_k_offset(ih_version(ih), &(ih->ih_key), offset); 152262306a36Sopenharmony_ci} 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_cistatic inline void set_le_key_k_type(int version, struct reiserfs_key *key, 152562306a36Sopenharmony_ci int type) 152662306a36Sopenharmony_ci{ 152762306a36Sopenharmony_ci if (version == KEY_FORMAT_3_5) { 152862306a36Sopenharmony_ci type = type2uniqueness(type); 152962306a36Sopenharmony_ci key->u.k_offset_v1.k_uniqueness = cpu_to_le32(type); 153062306a36Sopenharmony_ci } else 153162306a36Sopenharmony_ci set_offset_v2_k_type(&key->u.k_offset_v2, type); 153262306a36Sopenharmony_ci} 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_cistatic inline void set_le_ih_k_type(struct item_head *ih, int type) 153562306a36Sopenharmony_ci{ 153662306a36Sopenharmony_ci set_le_key_k_type(ih_version(ih), &(ih->ih_key), type); 153762306a36Sopenharmony_ci} 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_cistatic inline int is_direntry_le_key(int version, struct reiserfs_key *key) 154062306a36Sopenharmony_ci{ 154162306a36Sopenharmony_ci return le_key_k_type(version, key) == TYPE_DIRENTRY; 154262306a36Sopenharmony_ci} 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_cistatic inline int is_direct_le_key(int version, struct reiserfs_key *key) 154562306a36Sopenharmony_ci{ 154662306a36Sopenharmony_ci return le_key_k_type(version, key) == TYPE_DIRECT; 154762306a36Sopenharmony_ci} 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_cistatic inline int is_indirect_le_key(int version, struct reiserfs_key *key) 155062306a36Sopenharmony_ci{ 155162306a36Sopenharmony_ci return le_key_k_type(version, key) == TYPE_INDIRECT; 155262306a36Sopenharmony_ci} 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_cistatic inline int is_statdata_le_key(int version, struct reiserfs_key *key) 155562306a36Sopenharmony_ci{ 155662306a36Sopenharmony_ci return le_key_k_type(version, key) == TYPE_STAT_DATA; 155762306a36Sopenharmony_ci} 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci/* item header has version. */ 156062306a36Sopenharmony_cistatic inline int is_direntry_le_ih(struct item_head *ih) 156162306a36Sopenharmony_ci{ 156262306a36Sopenharmony_ci return is_direntry_le_key(ih_version(ih), &ih->ih_key); 156362306a36Sopenharmony_ci} 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_cistatic inline int is_direct_le_ih(struct item_head *ih) 156662306a36Sopenharmony_ci{ 156762306a36Sopenharmony_ci return is_direct_le_key(ih_version(ih), &ih->ih_key); 156862306a36Sopenharmony_ci} 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_cistatic inline int is_indirect_le_ih(struct item_head *ih) 157162306a36Sopenharmony_ci{ 157262306a36Sopenharmony_ci return is_indirect_le_key(ih_version(ih), &ih->ih_key); 157362306a36Sopenharmony_ci} 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_cistatic inline int is_statdata_le_ih(struct item_head *ih) 157662306a36Sopenharmony_ci{ 157762306a36Sopenharmony_ci return is_statdata_le_key(ih_version(ih), &ih->ih_key); 157862306a36Sopenharmony_ci} 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci/* key is pointer to cpu key, result is cpu */ 158162306a36Sopenharmony_cistatic inline loff_t cpu_key_k_offset(const struct cpu_key *key) 158262306a36Sopenharmony_ci{ 158362306a36Sopenharmony_ci return key->on_disk_key.k_offset; 158462306a36Sopenharmony_ci} 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_cistatic inline loff_t cpu_key_k_type(const struct cpu_key *key) 158762306a36Sopenharmony_ci{ 158862306a36Sopenharmony_ci return key->on_disk_key.k_type; 158962306a36Sopenharmony_ci} 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_cistatic inline void set_cpu_key_k_offset(struct cpu_key *key, loff_t offset) 159262306a36Sopenharmony_ci{ 159362306a36Sopenharmony_ci key->on_disk_key.k_offset = offset; 159462306a36Sopenharmony_ci} 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_cistatic inline void set_cpu_key_k_type(struct cpu_key *key, int type) 159762306a36Sopenharmony_ci{ 159862306a36Sopenharmony_ci key->on_disk_key.k_type = type; 159962306a36Sopenharmony_ci} 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_cistatic inline void cpu_key_k_offset_dec(struct cpu_key *key) 160262306a36Sopenharmony_ci{ 160362306a36Sopenharmony_ci key->on_disk_key.k_offset--; 160462306a36Sopenharmony_ci} 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ci#define is_direntry_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRENTRY) 160762306a36Sopenharmony_ci#define is_direct_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRECT) 160862306a36Sopenharmony_ci#define is_indirect_cpu_key(key) (cpu_key_k_type (key) == TYPE_INDIRECT) 160962306a36Sopenharmony_ci#define is_statdata_cpu_key(key) (cpu_key_k_type (key) == TYPE_STAT_DATA) 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci/* are these used ? */ 161262306a36Sopenharmony_ci#define is_direntry_cpu_ih(ih) (is_direntry_cpu_key (&((ih)->ih_key))) 161362306a36Sopenharmony_ci#define is_direct_cpu_ih(ih) (is_direct_cpu_key (&((ih)->ih_key))) 161462306a36Sopenharmony_ci#define is_indirect_cpu_ih(ih) (is_indirect_cpu_key (&((ih)->ih_key))) 161562306a36Sopenharmony_ci#define is_statdata_cpu_ih(ih) (is_statdata_cpu_key (&((ih)->ih_key))) 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci#define I_K_KEY_IN_ITEM(ih, key, n_blocksize) \ 161862306a36Sopenharmony_ci (!COMP_SHORT_KEYS(ih, key) && \ 161962306a36Sopenharmony_ci I_OFF_BYTE_IN_ITEM(ih, k_offset(key), n_blocksize)) 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci/* maximal length of item */ 162262306a36Sopenharmony_ci#define MAX_ITEM_LEN(block_size) (block_size - BLKH_SIZE - IH_SIZE) 162362306a36Sopenharmony_ci#define MIN_ITEM_LEN 1 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci/* object identifier for root dir */ 162662306a36Sopenharmony_ci#define REISERFS_ROOT_OBJECTID 2 162762306a36Sopenharmony_ci#define REISERFS_ROOT_PARENT_OBJECTID 1 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ciextern struct reiserfs_key root_key; 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci/* 163262306a36Sopenharmony_ci * Picture represents a leaf of the S+tree 163362306a36Sopenharmony_ci * ______________________________________________________ 163462306a36Sopenharmony_ci * | | Array of | | | 163562306a36Sopenharmony_ci * |Block | Object-Item | F r e e | Objects- | 163662306a36Sopenharmony_ci * | head | Headers | S p a c e | Items | 163762306a36Sopenharmony_ci * |______|_______________|___________________|___________| 163862306a36Sopenharmony_ci */ 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci/* 164162306a36Sopenharmony_ci * Header of a disk block. More precisely, header of a formatted leaf 164262306a36Sopenharmony_ci * or internal node, and not the header of an unformatted node. 164362306a36Sopenharmony_ci */ 164462306a36Sopenharmony_cistruct block_head { 164562306a36Sopenharmony_ci __le16 blk_level; /* Level of a block in the tree. */ 164662306a36Sopenharmony_ci __le16 blk_nr_item; /* Number of keys/items in a block. */ 164762306a36Sopenharmony_ci __le16 blk_free_space; /* Block free space in bytes. */ 164862306a36Sopenharmony_ci __le16 blk_reserved; 164962306a36Sopenharmony_ci /* dump this in v4/planA */ 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci /* kept only for compatibility */ 165262306a36Sopenharmony_ci struct reiserfs_key blk_right_delim_key; 165362306a36Sopenharmony_ci}; 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci#define BLKH_SIZE (sizeof(struct block_head)) 165662306a36Sopenharmony_ci#define blkh_level(p_blkh) (le16_to_cpu((p_blkh)->blk_level)) 165762306a36Sopenharmony_ci#define blkh_nr_item(p_blkh) (le16_to_cpu((p_blkh)->blk_nr_item)) 165862306a36Sopenharmony_ci#define blkh_free_space(p_blkh) (le16_to_cpu((p_blkh)->blk_free_space)) 165962306a36Sopenharmony_ci#define blkh_reserved(p_blkh) (le16_to_cpu((p_blkh)->blk_reserved)) 166062306a36Sopenharmony_ci#define set_blkh_level(p_blkh,val) ((p_blkh)->blk_level = cpu_to_le16(val)) 166162306a36Sopenharmony_ci#define set_blkh_nr_item(p_blkh,val) ((p_blkh)->blk_nr_item = cpu_to_le16(val)) 166262306a36Sopenharmony_ci#define set_blkh_free_space(p_blkh,val) ((p_blkh)->blk_free_space = cpu_to_le16(val)) 166362306a36Sopenharmony_ci#define set_blkh_reserved(p_blkh,val) ((p_blkh)->blk_reserved = cpu_to_le16(val)) 166462306a36Sopenharmony_ci#define blkh_right_delim_key(p_blkh) ((p_blkh)->blk_right_delim_key) 166562306a36Sopenharmony_ci#define set_blkh_right_delim_key(p_blkh,val) ((p_blkh)->blk_right_delim_key = val) 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci/* values for blk_level field of the struct block_head */ 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci/* 167062306a36Sopenharmony_ci * When node gets removed from the tree its blk_level is set to FREE_LEVEL. 167162306a36Sopenharmony_ci * It is then used to see whether the node is still in the tree 167262306a36Sopenharmony_ci */ 167362306a36Sopenharmony_ci#define FREE_LEVEL 0 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci#define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */ 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci/* 167862306a36Sopenharmony_ci * Given the buffer head of a formatted node, resolve to the 167962306a36Sopenharmony_ci * block head of that node. 168062306a36Sopenharmony_ci */ 168162306a36Sopenharmony_ci#define B_BLK_HEAD(bh) ((struct block_head *)((bh)->b_data)) 168262306a36Sopenharmony_ci/* Number of items that are in buffer. */ 168362306a36Sopenharmony_ci#define B_NR_ITEMS(bh) (blkh_nr_item(B_BLK_HEAD(bh))) 168462306a36Sopenharmony_ci#define B_LEVEL(bh) (blkh_level(B_BLK_HEAD(bh))) 168562306a36Sopenharmony_ci#define B_FREE_SPACE(bh) (blkh_free_space(B_BLK_HEAD(bh))) 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci#define PUT_B_NR_ITEMS(bh, val) do { set_blkh_nr_item(B_BLK_HEAD(bh), val); } while (0) 168862306a36Sopenharmony_ci#define PUT_B_LEVEL(bh, val) do { set_blkh_level(B_BLK_HEAD(bh), val); } while (0) 168962306a36Sopenharmony_ci#define PUT_B_FREE_SPACE(bh, val) do { set_blkh_free_space(B_BLK_HEAD(bh), val); } while (0) 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci/* Get right delimiting key. -- little endian */ 169262306a36Sopenharmony_ci#define B_PRIGHT_DELIM_KEY(bh) (&(blk_right_delim_key(B_BLK_HEAD(bh)))) 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci/* Does the buffer contain a disk leaf. */ 169562306a36Sopenharmony_ci#define B_IS_ITEMS_LEVEL(bh) (B_LEVEL(bh) == DISK_LEAF_NODE_LEVEL) 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci/* Does the buffer contain a disk internal node */ 169862306a36Sopenharmony_ci#define B_IS_KEYS_LEVEL(bh) (B_LEVEL(bh) > DISK_LEAF_NODE_LEVEL \ 169962306a36Sopenharmony_ci && B_LEVEL(bh) <= MAX_HEIGHT) 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci/*************************************************************************** 170262306a36Sopenharmony_ci * STAT DATA * 170362306a36Sopenharmony_ci ***************************************************************************/ 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci/* 170662306a36Sopenharmony_ci * old stat data is 32 bytes long. We are going to distinguish new one by 170762306a36Sopenharmony_ci * different size 170862306a36Sopenharmony_ci*/ 170962306a36Sopenharmony_cistruct stat_data_v1 { 171062306a36Sopenharmony_ci __le16 sd_mode; /* file type, permissions */ 171162306a36Sopenharmony_ci __le16 sd_nlink; /* number of hard links */ 171262306a36Sopenharmony_ci __le16 sd_uid; /* owner */ 171362306a36Sopenharmony_ci __le16 sd_gid; /* group */ 171462306a36Sopenharmony_ci __le32 sd_size; /* file size */ 171562306a36Sopenharmony_ci __le32 sd_atime; /* time of last access */ 171662306a36Sopenharmony_ci __le32 sd_mtime; /* time file was last modified */ 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_ci /* 171962306a36Sopenharmony_ci * time inode (stat data) was last changed 172062306a36Sopenharmony_ci * (except changes to sd_atime and sd_mtime) 172162306a36Sopenharmony_ci */ 172262306a36Sopenharmony_ci __le32 sd_ctime; 172362306a36Sopenharmony_ci union { 172462306a36Sopenharmony_ci __le32 sd_rdev; 172562306a36Sopenharmony_ci __le32 sd_blocks; /* number of blocks file uses */ 172662306a36Sopenharmony_ci } __attribute__ ((__packed__)) u; 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci /* 172962306a36Sopenharmony_ci * first byte of file which is stored in a direct item: except that if 173062306a36Sopenharmony_ci * it equals 1 it is a symlink and if it equals ~(__u32)0 there is no 173162306a36Sopenharmony_ci * direct item. The existence of this field really grates on me. 173262306a36Sopenharmony_ci * Let's replace it with a macro based on sd_size and our tail 173362306a36Sopenharmony_ci * suppression policy. Someday. -Hans 173462306a36Sopenharmony_ci */ 173562306a36Sopenharmony_ci __le32 sd_first_direct_byte; 173662306a36Sopenharmony_ci} __attribute__ ((__packed__)); 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci#define SD_V1_SIZE (sizeof(struct stat_data_v1)) 173962306a36Sopenharmony_ci#define stat_data_v1(ih) (ih_version (ih) == KEY_FORMAT_3_5) 174062306a36Sopenharmony_ci#define sd_v1_mode(sdp) (le16_to_cpu((sdp)->sd_mode)) 174162306a36Sopenharmony_ci#define set_sd_v1_mode(sdp,v) ((sdp)->sd_mode = cpu_to_le16(v)) 174262306a36Sopenharmony_ci#define sd_v1_nlink(sdp) (le16_to_cpu((sdp)->sd_nlink)) 174362306a36Sopenharmony_ci#define set_sd_v1_nlink(sdp,v) ((sdp)->sd_nlink = cpu_to_le16(v)) 174462306a36Sopenharmony_ci#define sd_v1_uid(sdp) (le16_to_cpu((sdp)->sd_uid)) 174562306a36Sopenharmony_ci#define set_sd_v1_uid(sdp,v) ((sdp)->sd_uid = cpu_to_le16(v)) 174662306a36Sopenharmony_ci#define sd_v1_gid(sdp) (le16_to_cpu((sdp)->sd_gid)) 174762306a36Sopenharmony_ci#define set_sd_v1_gid(sdp,v) ((sdp)->sd_gid = cpu_to_le16(v)) 174862306a36Sopenharmony_ci#define sd_v1_size(sdp) (le32_to_cpu((sdp)->sd_size)) 174962306a36Sopenharmony_ci#define set_sd_v1_size(sdp,v) ((sdp)->sd_size = cpu_to_le32(v)) 175062306a36Sopenharmony_ci#define sd_v1_atime(sdp) (le32_to_cpu((sdp)->sd_atime)) 175162306a36Sopenharmony_ci#define set_sd_v1_atime(sdp,v) ((sdp)->sd_atime = cpu_to_le32(v)) 175262306a36Sopenharmony_ci#define sd_v1_mtime(sdp) (le32_to_cpu((sdp)->sd_mtime)) 175362306a36Sopenharmony_ci#define set_sd_v1_mtime(sdp,v) ((sdp)->sd_mtime = cpu_to_le32(v)) 175462306a36Sopenharmony_ci#define sd_v1_ctime(sdp) (le32_to_cpu((sdp)->sd_ctime)) 175562306a36Sopenharmony_ci#define set_sd_v1_ctime(sdp,v) ((sdp)->sd_ctime = cpu_to_le32(v)) 175662306a36Sopenharmony_ci#define sd_v1_rdev(sdp) (le32_to_cpu((sdp)->u.sd_rdev)) 175762306a36Sopenharmony_ci#define set_sd_v1_rdev(sdp,v) ((sdp)->u.sd_rdev = cpu_to_le32(v)) 175862306a36Sopenharmony_ci#define sd_v1_blocks(sdp) (le32_to_cpu((sdp)->u.sd_blocks)) 175962306a36Sopenharmony_ci#define set_sd_v1_blocks(sdp,v) ((sdp)->u.sd_blocks = cpu_to_le32(v)) 176062306a36Sopenharmony_ci#define sd_v1_first_direct_byte(sdp) \ 176162306a36Sopenharmony_ci (le32_to_cpu((sdp)->sd_first_direct_byte)) 176262306a36Sopenharmony_ci#define set_sd_v1_first_direct_byte(sdp,v) \ 176362306a36Sopenharmony_ci ((sdp)->sd_first_direct_byte = cpu_to_le32(v)) 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci/* inode flags stored in sd_attrs (nee sd_reserved) */ 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci/* 176862306a36Sopenharmony_ci * we want common flags to have the same values as in ext2, 176962306a36Sopenharmony_ci * so chattr(1) will work without problems 177062306a36Sopenharmony_ci */ 177162306a36Sopenharmony_ci#define REISERFS_IMMUTABLE_FL FS_IMMUTABLE_FL 177262306a36Sopenharmony_ci#define REISERFS_APPEND_FL FS_APPEND_FL 177362306a36Sopenharmony_ci#define REISERFS_SYNC_FL FS_SYNC_FL 177462306a36Sopenharmony_ci#define REISERFS_NOATIME_FL FS_NOATIME_FL 177562306a36Sopenharmony_ci#define REISERFS_NODUMP_FL FS_NODUMP_FL 177662306a36Sopenharmony_ci#define REISERFS_SECRM_FL FS_SECRM_FL 177762306a36Sopenharmony_ci#define REISERFS_UNRM_FL FS_UNRM_FL 177862306a36Sopenharmony_ci#define REISERFS_COMPR_FL FS_COMPR_FL 177962306a36Sopenharmony_ci#define REISERFS_NOTAIL_FL FS_NOTAIL_FL 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci/* persistent flags that file inherits from the parent directory */ 178262306a36Sopenharmony_ci#define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL | \ 178362306a36Sopenharmony_ci REISERFS_SYNC_FL | \ 178462306a36Sopenharmony_ci REISERFS_NOATIME_FL | \ 178562306a36Sopenharmony_ci REISERFS_NODUMP_FL | \ 178662306a36Sopenharmony_ci REISERFS_SECRM_FL | \ 178762306a36Sopenharmony_ci REISERFS_COMPR_FL | \ 178862306a36Sopenharmony_ci REISERFS_NOTAIL_FL ) 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci/* 179162306a36Sopenharmony_ci * Stat Data on disk (reiserfs version of UFS disk inode minus the 179262306a36Sopenharmony_ci * address blocks) 179362306a36Sopenharmony_ci */ 179462306a36Sopenharmony_cistruct stat_data { 179562306a36Sopenharmony_ci __le16 sd_mode; /* file type, permissions */ 179662306a36Sopenharmony_ci __le16 sd_attrs; /* persistent inode flags */ 179762306a36Sopenharmony_ci __le32 sd_nlink; /* number of hard links */ 179862306a36Sopenharmony_ci __le64 sd_size; /* file size */ 179962306a36Sopenharmony_ci __le32 sd_uid; /* owner */ 180062306a36Sopenharmony_ci __le32 sd_gid; /* group */ 180162306a36Sopenharmony_ci __le32 sd_atime; /* time of last access */ 180262306a36Sopenharmony_ci __le32 sd_mtime; /* time file was last modified */ 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci /* 180562306a36Sopenharmony_ci * time inode (stat data) was last changed 180662306a36Sopenharmony_ci * (except changes to sd_atime and sd_mtime) 180762306a36Sopenharmony_ci */ 180862306a36Sopenharmony_ci __le32 sd_ctime; 180962306a36Sopenharmony_ci __le32 sd_blocks; 181062306a36Sopenharmony_ci union { 181162306a36Sopenharmony_ci __le32 sd_rdev; 181262306a36Sopenharmony_ci __le32 sd_generation; 181362306a36Sopenharmony_ci } __attribute__ ((__packed__)) u; 181462306a36Sopenharmony_ci} __attribute__ ((__packed__)); 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci/* this is 44 bytes long */ 181762306a36Sopenharmony_ci#define SD_SIZE (sizeof(struct stat_data)) 181862306a36Sopenharmony_ci#define SD_V2_SIZE SD_SIZE 181962306a36Sopenharmony_ci#define stat_data_v2(ih) (ih_version (ih) == KEY_FORMAT_3_6) 182062306a36Sopenharmony_ci#define sd_v2_mode(sdp) (le16_to_cpu((sdp)->sd_mode)) 182162306a36Sopenharmony_ci#define set_sd_v2_mode(sdp,v) ((sdp)->sd_mode = cpu_to_le16(v)) 182262306a36Sopenharmony_ci/* sd_reserved */ 182362306a36Sopenharmony_ci/* set_sd_reserved */ 182462306a36Sopenharmony_ci#define sd_v2_nlink(sdp) (le32_to_cpu((sdp)->sd_nlink)) 182562306a36Sopenharmony_ci#define set_sd_v2_nlink(sdp,v) ((sdp)->sd_nlink = cpu_to_le32(v)) 182662306a36Sopenharmony_ci#define sd_v2_size(sdp) (le64_to_cpu((sdp)->sd_size)) 182762306a36Sopenharmony_ci#define set_sd_v2_size(sdp,v) ((sdp)->sd_size = cpu_to_le64(v)) 182862306a36Sopenharmony_ci#define sd_v2_uid(sdp) (le32_to_cpu((sdp)->sd_uid)) 182962306a36Sopenharmony_ci#define set_sd_v2_uid(sdp,v) ((sdp)->sd_uid = cpu_to_le32(v)) 183062306a36Sopenharmony_ci#define sd_v2_gid(sdp) (le32_to_cpu((sdp)->sd_gid)) 183162306a36Sopenharmony_ci#define set_sd_v2_gid(sdp,v) ((sdp)->sd_gid = cpu_to_le32(v)) 183262306a36Sopenharmony_ci#define sd_v2_atime(sdp) (le32_to_cpu((sdp)->sd_atime)) 183362306a36Sopenharmony_ci#define set_sd_v2_atime(sdp,v) ((sdp)->sd_atime = cpu_to_le32(v)) 183462306a36Sopenharmony_ci#define sd_v2_mtime(sdp) (le32_to_cpu((sdp)->sd_mtime)) 183562306a36Sopenharmony_ci#define set_sd_v2_mtime(sdp,v) ((sdp)->sd_mtime = cpu_to_le32(v)) 183662306a36Sopenharmony_ci#define sd_v2_ctime(sdp) (le32_to_cpu((sdp)->sd_ctime)) 183762306a36Sopenharmony_ci#define set_sd_v2_ctime(sdp,v) ((sdp)->sd_ctime = cpu_to_le32(v)) 183862306a36Sopenharmony_ci#define sd_v2_blocks(sdp) (le32_to_cpu((sdp)->sd_blocks)) 183962306a36Sopenharmony_ci#define set_sd_v2_blocks(sdp,v) ((sdp)->sd_blocks = cpu_to_le32(v)) 184062306a36Sopenharmony_ci#define sd_v2_rdev(sdp) (le32_to_cpu((sdp)->u.sd_rdev)) 184162306a36Sopenharmony_ci#define set_sd_v2_rdev(sdp,v) ((sdp)->u.sd_rdev = cpu_to_le32(v)) 184262306a36Sopenharmony_ci#define sd_v2_generation(sdp) (le32_to_cpu((sdp)->u.sd_generation)) 184362306a36Sopenharmony_ci#define set_sd_v2_generation(sdp,v) ((sdp)->u.sd_generation = cpu_to_le32(v)) 184462306a36Sopenharmony_ci#define sd_v2_attrs(sdp) (le16_to_cpu((sdp)->sd_attrs)) 184562306a36Sopenharmony_ci#define set_sd_v2_attrs(sdp,v) ((sdp)->sd_attrs = cpu_to_le16(v)) 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_ci/*************************************************************************** 184862306a36Sopenharmony_ci * DIRECTORY STRUCTURE * 184962306a36Sopenharmony_ci ***************************************************************************/ 185062306a36Sopenharmony_ci/* 185162306a36Sopenharmony_ci * Picture represents the structure of directory items 185262306a36Sopenharmony_ci * ________________________________________________ 185362306a36Sopenharmony_ci * | Array of | | | | | | 185462306a36Sopenharmony_ci * | directory |N-1| N-2 | .... | 1st |0th| 185562306a36Sopenharmony_ci * | entry headers | | | | | | 185662306a36Sopenharmony_ci * |_______________|___|_____|________|_______|___| 185762306a36Sopenharmony_ci * <---- directory entries ------> 185862306a36Sopenharmony_ci * 185962306a36Sopenharmony_ci * First directory item has k_offset component 1. We store "." and ".." 186062306a36Sopenharmony_ci * in one item, always, we never split "." and ".." into differing 186162306a36Sopenharmony_ci * items. This makes, among other things, the code for removing 186262306a36Sopenharmony_ci * directories simpler. 186362306a36Sopenharmony_ci */ 186462306a36Sopenharmony_ci#define SD_OFFSET 0 186562306a36Sopenharmony_ci#define SD_UNIQUENESS 0 186662306a36Sopenharmony_ci#define DOT_OFFSET 1 186762306a36Sopenharmony_ci#define DOT_DOT_OFFSET 2 186862306a36Sopenharmony_ci#define DIRENTRY_UNIQUENESS 500 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_ci#define FIRST_ITEM_OFFSET 1 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci/* 187362306a36Sopenharmony_ci * Q: How to get key of object pointed to by entry from entry? 187462306a36Sopenharmony_ci * 187562306a36Sopenharmony_ci * A: Each directory entry has its header. This header has deh_dir_id 187662306a36Sopenharmony_ci * and deh_objectid fields, those are key of object, entry points to 187762306a36Sopenharmony_ci */ 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci/* 188062306a36Sopenharmony_ci * NOT IMPLEMENTED: 188162306a36Sopenharmony_ci * Directory will someday contain stat data of object 188262306a36Sopenharmony_ci */ 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_cistruct reiserfs_de_head { 188562306a36Sopenharmony_ci __le32 deh_offset; /* third component of the directory entry key */ 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci /* 188862306a36Sopenharmony_ci * objectid of the parent directory of the object, that is referenced 188962306a36Sopenharmony_ci * by directory entry 189062306a36Sopenharmony_ci */ 189162306a36Sopenharmony_ci __le32 deh_dir_id; 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci /* objectid of the object, that is referenced by directory entry */ 189462306a36Sopenharmony_ci __le32 deh_objectid; 189562306a36Sopenharmony_ci __le16 deh_location; /* offset of name in the whole item */ 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci /* 189862306a36Sopenharmony_ci * whether 1) entry contains stat data (for future), and 189962306a36Sopenharmony_ci * 2) whether entry is hidden (unlinked) 190062306a36Sopenharmony_ci */ 190162306a36Sopenharmony_ci __le16 deh_state; 190262306a36Sopenharmony_ci} __attribute__ ((__packed__)); 190362306a36Sopenharmony_ci#define DEH_SIZE sizeof(struct reiserfs_de_head) 190462306a36Sopenharmony_ci#define deh_offset(p_deh) (le32_to_cpu((p_deh)->deh_offset)) 190562306a36Sopenharmony_ci#define deh_dir_id(p_deh) (le32_to_cpu((p_deh)->deh_dir_id)) 190662306a36Sopenharmony_ci#define deh_objectid(p_deh) (le32_to_cpu((p_deh)->deh_objectid)) 190762306a36Sopenharmony_ci#define deh_location(p_deh) (le16_to_cpu((p_deh)->deh_location)) 190862306a36Sopenharmony_ci#define deh_state(p_deh) (le16_to_cpu((p_deh)->deh_state)) 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci#define put_deh_offset(p_deh,v) ((p_deh)->deh_offset = cpu_to_le32((v))) 191162306a36Sopenharmony_ci#define put_deh_dir_id(p_deh,v) ((p_deh)->deh_dir_id = cpu_to_le32((v))) 191262306a36Sopenharmony_ci#define put_deh_objectid(p_deh,v) ((p_deh)->deh_objectid = cpu_to_le32((v))) 191362306a36Sopenharmony_ci#define put_deh_location(p_deh,v) ((p_deh)->deh_location = cpu_to_le16((v))) 191462306a36Sopenharmony_ci#define put_deh_state(p_deh,v) ((p_deh)->deh_state = cpu_to_le16((v))) 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci/* empty directory contains two entries "." and ".." and their headers */ 191762306a36Sopenharmony_ci#define EMPTY_DIR_SIZE \ 191862306a36Sopenharmony_ci(DEH_SIZE * 2 + ROUND_UP (sizeof(".") - 1) + ROUND_UP (sizeof("..") - 1)) 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci/* old format directories have this size when empty */ 192162306a36Sopenharmony_ci#define EMPTY_DIR_SIZE_V1 (DEH_SIZE * 2 + 3) 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci#define DEH_Statdata 0 /* not used now */ 192462306a36Sopenharmony_ci#define DEH_Visible 2 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci/* 64 bit systems (and the S/390) need to be aligned explicitly -jdm */ 192762306a36Sopenharmony_ci#if BITS_PER_LONG == 64 || defined(__s390__) || defined(__hppa__) 192862306a36Sopenharmony_ci# define ADDR_UNALIGNED_BITS (3) 192962306a36Sopenharmony_ci#endif 193062306a36Sopenharmony_ci 193162306a36Sopenharmony_ci/* 193262306a36Sopenharmony_ci * These are only used to manipulate deh_state. 193362306a36Sopenharmony_ci * Because of this, we'll use the ext2_ bit routines, 193462306a36Sopenharmony_ci * since they are little endian 193562306a36Sopenharmony_ci */ 193662306a36Sopenharmony_ci#ifdef ADDR_UNALIGNED_BITS 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ci# define aligned_address(addr) ((void *)((long)(addr) & ~((1UL << ADDR_UNALIGNED_BITS) - 1))) 193962306a36Sopenharmony_ci# define unaligned_offset(addr) (((int)((long)(addr) & ((1 << ADDR_UNALIGNED_BITS) - 1))) << 3) 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci# define set_bit_unaligned(nr, addr) \ 194262306a36Sopenharmony_ci __test_and_set_bit_le((nr) + unaligned_offset(addr), aligned_address(addr)) 194362306a36Sopenharmony_ci# define clear_bit_unaligned(nr, addr) \ 194462306a36Sopenharmony_ci __test_and_clear_bit_le((nr) + unaligned_offset(addr), aligned_address(addr)) 194562306a36Sopenharmony_ci# define test_bit_unaligned(nr, addr) \ 194662306a36Sopenharmony_ci test_bit_le((nr) + unaligned_offset(addr), aligned_address(addr)) 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ci#else 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci# define set_bit_unaligned(nr, addr) __test_and_set_bit_le(nr, addr) 195162306a36Sopenharmony_ci# define clear_bit_unaligned(nr, addr) __test_and_clear_bit_le(nr, addr) 195262306a36Sopenharmony_ci# define test_bit_unaligned(nr, addr) test_bit_le(nr, addr) 195362306a36Sopenharmony_ci 195462306a36Sopenharmony_ci#endif 195562306a36Sopenharmony_ci 195662306a36Sopenharmony_ci#define mark_de_with_sd(deh) set_bit_unaligned (DEH_Statdata, &((deh)->deh_state)) 195762306a36Sopenharmony_ci#define mark_de_without_sd(deh) clear_bit_unaligned (DEH_Statdata, &((deh)->deh_state)) 195862306a36Sopenharmony_ci#define mark_de_visible(deh) set_bit_unaligned (DEH_Visible, &((deh)->deh_state)) 195962306a36Sopenharmony_ci#define mark_de_hidden(deh) clear_bit_unaligned (DEH_Visible, &((deh)->deh_state)) 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci#define de_with_sd(deh) test_bit_unaligned (DEH_Statdata, &((deh)->deh_state)) 196262306a36Sopenharmony_ci#define de_visible(deh) test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) 196362306a36Sopenharmony_ci#define de_hidden(deh) !test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ciextern void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid, 196662306a36Sopenharmony_ci __le32 par_dirid, __le32 par_objid); 196762306a36Sopenharmony_ciextern void make_empty_dir_item(char *body, __le32 dirid, __le32 objid, 196862306a36Sopenharmony_ci __le32 par_dirid, __le32 par_objid); 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci/* two entries per block (at least) */ 197162306a36Sopenharmony_ci#define REISERFS_MAX_NAME(block_size) 255 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ci/* 197462306a36Sopenharmony_ci * this structure is used for operations on directory entries. It is 197562306a36Sopenharmony_ci * not a disk structure. 197662306a36Sopenharmony_ci * 197762306a36Sopenharmony_ci * When reiserfs_find_entry or search_by_entry_key find directory 197862306a36Sopenharmony_ci * entry, they return filled reiserfs_dir_entry structure 197962306a36Sopenharmony_ci */ 198062306a36Sopenharmony_cistruct reiserfs_dir_entry { 198162306a36Sopenharmony_ci struct buffer_head *de_bh; 198262306a36Sopenharmony_ci int de_item_num; 198362306a36Sopenharmony_ci struct item_head *de_ih; 198462306a36Sopenharmony_ci int de_entry_num; 198562306a36Sopenharmony_ci struct reiserfs_de_head *de_deh; 198662306a36Sopenharmony_ci int de_entrylen; 198762306a36Sopenharmony_ci int de_namelen; 198862306a36Sopenharmony_ci char *de_name; 198962306a36Sopenharmony_ci unsigned long *de_gen_number_bit_string; 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_ci __u32 de_dir_id; 199262306a36Sopenharmony_ci __u32 de_objectid; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci struct cpu_key de_entry_key; 199562306a36Sopenharmony_ci}; 199662306a36Sopenharmony_ci 199762306a36Sopenharmony_ci/* 199862306a36Sopenharmony_ci * these defines are useful when a particular member of 199962306a36Sopenharmony_ci * a reiserfs_dir_entry is needed 200062306a36Sopenharmony_ci */ 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci/* pointer to file name, stored in entry */ 200362306a36Sopenharmony_ci#define B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh) \ 200462306a36Sopenharmony_ci (ih_item_body(bh, ih) + deh_location(deh)) 200562306a36Sopenharmony_ci 200662306a36Sopenharmony_ci/* length of name */ 200762306a36Sopenharmony_ci#define I_DEH_N_ENTRY_FILE_NAME_LENGTH(ih,deh,entry_num) \ 200862306a36Sopenharmony_ci(I_DEH_N_ENTRY_LENGTH (ih, deh, entry_num) - (de_with_sd (deh) ? SD_SIZE : 0)) 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci/* hash value occupies bits from 7 up to 30 */ 201162306a36Sopenharmony_ci#define GET_HASH_VALUE(offset) ((offset) & 0x7fffff80LL) 201262306a36Sopenharmony_ci/* generation number occupies 7 bits starting from 0 up to 6 */ 201362306a36Sopenharmony_ci#define GET_GENERATION_NUMBER(offset) ((offset) & 0x7fLL) 201462306a36Sopenharmony_ci#define MAX_GENERATION_NUMBER 127 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci#define SET_GENERATION_NUMBER(offset,gen_number) (GET_HASH_VALUE(offset)|(gen_number)) 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci/* 201962306a36Sopenharmony_ci * Picture represents an internal node of the reiserfs tree 202062306a36Sopenharmony_ci * ______________________________________________________ 202162306a36Sopenharmony_ci * | | Array of | Array of | Free | 202262306a36Sopenharmony_ci * |block | keys | pointers | space | 202362306a36Sopenharmony_ci * | head | N | N+1 | | 202462306a36Sopenharmony_ci * |______|_______________|___________________|___________| 202562306a36Sopenharmony_ci */ 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci/*************************************************************************** 202862306a36Sopenharmony_ci * DISK CHILD * 202962306a36Sopenharmony_ci ***************************************************************************/ 203062306a36Sopenharmony_ci/* 203162306a36Sopenharmony_ci * Disk child pointer: 203262306a36Sopenharmony_ci * The pointer from an internal node of the tree to a node that is on disk. 203362306a36Sopenharmony_ci */ 203462306a36Sopenharmony_cistruct disk_child { 203562306a36Sopenharmony_ci __le32 dc_block_number; /* Disk child's block number. */ 203662306a36Sopenharmony_ci __le16 dc_size; /* Disk child's used space. */ 203762306a36Sopenharmony_ci __le16 dc_reserved; 203862306a36Sopenharmony_ci}; 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci#define DC_SIZE (sizeof(struct disk_child)) 204162306a36Sopenharmony_ci#define dc_block_number(dc_p) (le32_to_cpu((dc_p)->dc_block_number)) 204262306a36Sopenharmony_ci#define dc_size(dc_p) (le16_to_cpu((dc_p)->dc_size)) 204362306a36Sopenharmony_ci#define put_dc_block_number(dc_p, val) do { (dc_p)->dc_block_number = cpu_to_le32(val); } while(0) 204462306a36Sopenharmony_ci#define put_dc_size(dc_p, val) do { (dc_p)->dc_size = cpu_to_le16(val); } while(0) 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci/* Get disk child by buffer header and position in the tree node. */ 204762306a36Sopenharmony_ci#define B_N_CHILD(bh, n_pos) ((struct disk_child *)\ 204862306a36Sopenharmony_ci((bh)->b_data + BLKH_SIZE + B_NR_ITEMS(bh) * KEY_SIZE + DC_SIZE * (n_pos))) 204962306a36Sopenharmony_ci 205062306a36Sopenharmony_ci/* Get disk child number by buffer header and position in the tree node. */ 205162306a36Sopenharmony_ci#define B_N_CHILD_NUM(bh, n_pos) (dc_block_number(B_N_CHILD(bh, n_pos))) 205262306a36Sopenharmony_ci#define PUT_B_N_CHILD_NUM(bh, n_pos, val) \ 205362306a36Sopenharmony_ci (put_dc_block_number(B_N_CHILD(bh, n_pos), val)) 205462306a36Sopenharmony_ci 205562306a36Sopenharmony_ci /* maximal value of field child_size in structure disk_child */ 205662306a36Sopenharmony_ci /* child size is the combined size of all items and their headers */ 205762306a36Sopenharmony_ci#define MAX_CHILD_SIZE(bh) ((int)( (bh)->b_size - BLKH_SIZE )) 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci/* amount of used space in buffer (not including block head) */ 206062306a36Sopenharmony_ci#define B_CHILD_SIZE(cur) (MAX_CHILD_SIZE(cur)-(B_FREE_SPACE(cur))) 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci/* max and min number of keys in internal node */ 206362306a36Sopenharmony_ci#define MAX_NR_KEY(bh) ( (MAX_CHILD_SIZE(bh)-DC_SIZE)/(KEY_SIZE+DC_SIZE) ) 206462306a36Sopenharmony_ci#define MIN_NR_KEY(bh) (MAX_NR_KEY(bh)/2) 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci/*************************************************************************** 206762306a36Sopenharmony_ci * PATH STRUCTURES AND DEFINES * 206862306a36Sopenharmony_ci ***************************************************************************/ 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci/* 207162306a36Sopenharmony_ci * search_by_key fills up the path from the root to the leaf as it descends 207262306a36Sopenharmony_ci * the tree looking for the key. It uses reiserfs_bread to try to find 207362306a36Sopenharmony_ci * buffers in the cache given their block number. If it does not find 207462306a36Sopenharmony_ci * them in the cache it reads them from disk. For each node search_by_key 207562306a36Sopenharmony_ci * finds using reiserfs_bread it then uses bin_search to look through that 207662306a36Sopenharmony_ci * node. bin_search will find the position of the block_number of the next 207762306a36Sopenharmony_ci * node if it is looking through an internal node. If it is looking through 207862306a36Sopenharmony_ci * a leaf node bin_search will find the position of the item which has key 207962306a36Sopenharmony_ci * either equal to given key, or which is the maximal key less than the 208062306a36Sopenharmony_ci * given key. 208162306a36Sopenharmony_ci */ 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_cistruct path_element { 208462306a36Sopenharmony_ci /* Pointer to the buffer at the path in the tree. */ 208562306a36Sopenharmony_ci struct buffer_head *pe_buffer; 208662306a36Sopenharmony_ci /* Position in the tree node which is placed in the buffer above. */ 208762306a36Sopenharmony_ci int pe_position; 208862306a36Sopenharmony_ci}; 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci/* 209162306a36Sopenharmony_ci * maximal height of a tree. don't change this without 209262306a36Sopenharmony_ci * changing JOURNAL_PER_BALANCE_CNT 209362306a36Sopenharmony_ci */ 209462306a36Sopenharmony_ci#define MAX_HEIGHT 5 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_ci/* Must be equals MAX_HEIGHT + FIRST_PATH_ELEMENT_OFFSET */ 209762306a36Sopenharmony_ci#define EXTENDED_MAX_HEIGHT 7 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci/* Must be equal to at least 2. */ 210062306a36Sopenharmony_ci#define FIRST_PATH_ELEMENT_OFFSET 2 210162306a36Sopenharmony_ci 210262306a36Sopenharmony_ci/* Must be equal to FIRST_PATH_ELEMENT_OFFSET - 1 */ 210362306a36Sopenharmony_ci#define ILLEGAL_PATH_ELEMENT_OFFSET 1 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ci/* this MUST be MAX_HEIGHT + 1. See about FEB below */ 210662306a36Sopenharmony_ci#define MAX_FEB_SIZE 6 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci/* 210962306a36Sopenharmony_ci * We need to keep track of who the ancestors of nodes are. When we 211062306a36Sopenharmony_ci * perform a search we record which nodes were visited while 211162306a36Sopenharmony_ci * descending the tree looking for the node we searched for. This list 211262306a36Sopenharmony_ci * of nodes is called the path. This information is used while 211362306a36Sopenharmony_ci * performing balancing. Note that this path information may become 211462306a36Sopenharmony_ci * invalid, and this means we must check it when using it to see if it 211562306a36Sopenharmony_ci * is still valid. You'll need to read search_by_key and the comments 211662306a36Sopenharmony_ci * in it, especially about decrement_counters_in_path(), to understand 211762306a36Sopenharmony_ci * this structure. 211862306a36Sopenharmony_ci * 211962306a36Sopenharmony_ci * Paths make the code so much harder to work with and debug.... An 212062306a36Sopenharmony_ci * enormous number of bugs are due to them, and trying to write or modify 212162306a36Sopenharmony_ci * code that uses them just makes my head hurt. They are based on an 212262306a36Sopenharmony_ci * excessive effort to avoid disturbing the precious VFS code.:-( The 212362306a36Sopenharmony_ci * gods only know how we are going to SMP the code that uses them. 212462306a36Sopenharmony_ci * znodes are the way! 212562306a36Sopenharmony_ci */ 212662306a36Sopenharmony_ci 212762306a36Sopenharmony_ci#define PATH_READA 0x1 /* do read ahead */ 212862306a36Sopenharmony_ci#define PATH_READA_BACK 0x2 /* read backwards */ 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_cistruct treepath { 213162306a36Sopenharmony_ci int path_length; /* Length of the array above. */ 213262306a36Sopenharmony_ci int reada; 213362306a36Sopenharmony_ci /* Array of the path elements. */ 213462306a36Sopenharmony_ci struct path_element path_elements[EXTENDED_MAX_HEIGHT]; 213562306a36Sopenharmony_ci int pos_in_item; 213662306a36Sopenharmony_ci}; 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_ci#define pos_in_item(path) ((path)->pos_in_item) 213962306a36Sopenharmony_ci 214062306a36Sopenharmony_ci#define INITIALIZE_PATH(var) \ 214162306a36Sopenharmony_cistruct treepath var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,} 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci/* Get path element by path and path position. */ 214462306a36Sopenharmony_ci#define PATH_OFFSET_PELEMENT(path, n_offset) ((path)->path_elements + (n_offset)) 214562306a36Sopenharmony_ci 214662306a36Sopenharmony_ci/* Get buffer header at the path by path and path position. */ 214762306a36Sopenharmony_ci#define PATH_OFFSET_PBUFFER(path, n_offset) (PATH_OFFSET_PELEMENT(path, n_offset)->pe_buffer) 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci/* Get position in the element at the path by path and path position. */ 215062306a36Sopenharmony_ci#define PATH_OFFSET_POSITION(path, n_offset) (PATH_OFFSET_PELEMENT(path, n_offset)->pe_position) 215162306a36Sopenharmony_ci 215262306a36Sopenharmony_ci#define PATH_PLAST_BUFFER(path) (PATH_OFFSET_PBUFFER((path), (path)->path_length)) 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci/* 215562306a36Sopenharmony_ci * you know, to the person who didn't write this the macro name does not 215662306a36Sopenharmony_ci * at first suggest what it does. Maybe POSITION_FROM_PATH_END? Or 215762306a36Sopenharmony_ci * maybe we should just focus on dumping paths... -Hans 215862306a36Sopenharmony_ci */ 215962306a36Sopenharmony_ci#define PATH_LAST_POSITION(path) (PATH_OFFSET_POSITION((path), (path)->path_length)) 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci/* 216262306a36Sopenharmony_ci * in do_balance leaf has h == 0 in contrast with path structure, 216362306a36Sopenharmony_ci * where root has level == 0. That is why we need these defines 216462306a36Sopenharmony_ci */ 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci/* tb->S[h] */ 216762306a36Sopenharmony_ci#define PATH_H_PBUFFER(path, h) \ 216862306a36Sopenharmony_ci PATH_OFFSET_PBUFFER(path, path->path_length - (h)) 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_ci/* tb->F[h] or tb->S[0]->b_parent */ 217162306a36Sopenharmony_ci#define PATH_H_PPARENT(path, h) PATH_H_PBUFFER(path, (h) + 1) 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_ci#define PATH_H_POSITION(path, h) \ 217462306a36Sopenharmony_ci PATH_OFFSET_POSITION(path, path->path_length - (h)) 217562306a36Sopenharmony_ci 217662306a36Sopenharmony_ci/* tb->S[h]->b_item_order */ 217762306a36Sopenharmony_ci#define PATH_H_B_ITEM_ORDER(path, h) PATH_H_POSITION(path, h + 1) 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci#define PATH_H_PATH_OFFSET(path, n_h) ((path)->path_length - (n_h)) 218062306a36Sopenharmony_ci 218162306a36Sopenharmony_cistatic inline void *reiserfs_node_data(const struct buffer_head *bh) 218262306a36Sopenharmony_ci{ 218362306a36Sopenharmony_ci return bh->b_data + sizeof(struct block_head); 218462306a36Sopenharmony_ci} 218562306a36Sopenharmony_ci 218662306a36Sopenharmony_ci/* get key from internal node */ 218762306a36Sopenharmony_cistatic inline struct reiserfs_key *internal_key(struct buffer_head *bh, 218862306a36Sopenharmony_ci int item_num) 218962306a36Sopenharmony_ci{ 219062306a36Sopenharmony_ci struct reiserfs_key *key = reiserfs_node_data(bh); 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci return &key[item_num]; 219362306a36Sopenharmony_ci} 219462306a36Sopenharmony_ci 219562306a36Sopenharmony_ci/* get the item header from leaf node */ 219662306a36Sopenharmony_cistatic inline struct item_head *item_head(const struct buffer_head *bh, 219762306a36Sopenharmony_ci int item_num) 219862306a36Sopenharmony_ci{ 219962306a36Sopenharmony_ci struct item_head *ih = reiserfs_node_data(bh); 220062306a36Sopenharmony_ci 220162306a36Sopenharmony_ci return &ih[item_num]; 220262306a36Sopenharmony_ci} 220362306a36Sopenharmony_ci 220462306a36Sopenharmony_ci/* get the key from leaf node */ 220562306a36Sopenharmony_cistatic inline struct reiserfs_key *leaf_key(const struct buffer_head *bh, 220662306a36Sopenharmony_ci int item_num) 220762306a36Sopenharmony_ci{ 220862306a36Sopenharmony_ci return &item_head(bh, item_num)->ih_key; 220962306a36Sopenharmony_ci} 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_cistatic inline void *ih_item_body(const struct buffer_head *bh, 221262306a36Sopenharmony_ci const struct item_head *ih) 221362306a36Sopenharmony_ci{ 221462306a36Sopenharmony_ci return bh->b_data + ih_location(ih); 221562306a36Sopenharmony_ci} 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_ci/* get item body from leaf node */ 221862306a36Sopenharmony_cistatic inline void *item_body(const struct buffer_head *bh, int item_num) 221962306a36Sopenharmony_ci{ 222062306a36Sopenharmony_ci return ih_item_body(bh, item_head(bh, item_num)); 222162306a36Sopenharmony_ci} 222262306a36Sopenharmony_ci 222362306a36Sopenharmony_cistatic inline struct item_head *tp_item_head(const struct treepath *path) 222462306a36Sopenharmony_ci{ 222562306a36Sopenharmony_ci return item_head(PATH_PLAST_BUFFER(path), PATH_LAST_POSITION(path)); 222662306a36Sopenharmony_ci} 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_cistatic inline void *tp_item_body(const struct treepath *path) 222962306a36Sopenharmony_ci{ 223062306a36Sopenharmony_ci return item_body(PATH_PLAST_BUFFER(path), PATH_LAST_POSITION(path)); 223162306a36Sopenharmony_ci} 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci#define get_last_bh(path) PATH_PLAST_BUFFER(path) 223462306a36Sopenharmony_ci#define get_item_pos(path) PATH_LAST_POSITION(path) 223562306a36Sopenharmony_ci#define item_moved(ih,path) comp_items(ih, path) 223662306a36Sopenharmony_ci#define path_changed(ih,path) comp_items (ih, path) 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci/* array of the entry headers */ 223962306a36Sopenharmony_ci /* get item body */ 224062306a36Sopenharmony_ci#define B_I_DEH(bh, ih) ((struct reiserfs_de_head *)(ih_item_body(bh, ih))) 224162306a36Sopenharmony_ci 224262306a36Sopenharmony_ci/* 224362306a36Sopenharmony_ci * length of the directory entry in directory item. This define 224462306a36Sopenharmony_ci * calculates length of i-th directory entry using directory entry 224562306a36Sopenharmony_ci * locations from dir entry head. When it calculates length of 0-th 224662306a36Sopenharmony_ci * directory entry, it uses length of whole item in place of entry 224762306a36Sopenharmony_ci * location of the non-existent following entry in the calculation. 224862306a36Sopenharmony_ci * See picture above. 224962306a36Sopenharmony_ci */ 225062306a36Sopenharmony_cistatic inline int entry_length(const struct buffer_head *bh, 225162306a36Sopenharmony_ci const struct item_head *ih, int pos_in_item) 225262306a36Sopenharmony_ci{ 225362306a36Sopenharmony_ci struct reiserfs_de_head *deh; 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ci deh = B_I_DEH(bh, ih) + pos_in_item; 225662306a36Sopenharmony_ci if (pos_in_item) 225762306a36Sopenharmony_ci return deh_location(deh - 1) - deh_location(deh); 225862306a36Sopenharmony_ci 225962306a36Sopenharmony_ci return ih_item_len(ih) - deh_location(deh); 226062306a36Sopenharmony_ci} 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci/*************************************************************************** 226362306a36Sopenharmony_ci * MISC * 226462306a36Sopenharmony_ci ***************************************************************************/ 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci/* Size of pointer to the unformatted node. */ 226762306a36Sopenharmony_ci#define UNFM_P_SIZE (sizeof(unp_t)) 226862306a36Sopenharmony_ci#define UNFM_P_SHIFT 2 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci/* in in-core inode key is stored on le form */ 227162306a36Sopenharmony_ci#define INODE_PKEY(inode) ((struct reiserfs_key *)(REISERFS_I(inode)->i_key)) 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_ci#define MAX_UL_INT 0xffffffff 227462306a36Sopenharmony_ci#define MAX_INT 0x7ffffff 227562306a36Sopenharmony_ci#define MAX_US_INT 0xffff 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_ci// reiserfs version 2 has max offset 60 bits. Version 1 - 32 bit offset 227862306a36Sopenharmony_cistatic inline loff_t max_reiserfs_offset(struct inode *inode) 227962306a36Sopenharmony_ci{ 228062306a36Sopenharmony_ci if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5) 228162306a36Sopenharmony_ci return (loff_t) U32_MAX; 228262306a36Sopenharmony_ci 228362306a36Sopenharmony_ci return (loff_t) ((~(__u64) 0) >> 4); 228462306a36Sopenharmony_ci} 228562306a36Sopenharmony_ci 228662306a36Sopenharmony_ci#define MAX_KEY_OBJECTID MAX_UL_INT 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ci#define MAX_B_NUM MAX_UL_INT 228962306a36Sopenharmony_ci#define MAX_FC_NUM MAX_US_INT 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci/* the purpose is to detect overflow of an unsigned short */ 229262306a36Sopenharmony_ci#define REISERFS_LINK_MAX (MAX_US_INT - 1000) 229362306a36Sopenharmony_ci 229462306a36Sopenharmony_ci/* 229562306a36Sopenharmony_ci * The following defines are used in reiserfs_insert_item 229662306a36Sopenharmony_ci * and reiserfs_append_item 229762306a36Sopenharmony_ci */ 229862306a36Sopenharmony_ci#define REISERFS_KERNEL_MEM 0 /* kernel memory mode */ 229962306a36Sopenharmony_ci#define REISERFS_USER_MEM 1 /* user memory mode */ 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_ci#define fs_generation(s) (REISERFS_SB(s)->s_generation_counter) 230262306a36Sopenharmony_ci#define get_generation(s) atomic_read (&fs_generation(s)) 230362306a36Sopenharmony_ci#define FILESYSTEM_CHANGED_TB(tb) (get_generation((tb)->tb_sb) != (tb)->fs_gen) 230462306a36Sopenharmony_ci#define __fs_changed(gen,s) (gen != get_generation (s)) 230562306a36Sopenharmony_ci#define fs_changed(gen,s) \ 230662306a36Sopenharmony_ci({ \ 230762306a36Sopenharmony_ci reiserfs_cond_resched(s); \ 230862306a36Sopenharmony_ci __fs_changed(gen, s); \ 230962306a36Sopenharmony_ci}) 231062306a36Sopenharmony_ci 231162306a36Sopenharmony_ci/*************************************************************************** 231262306a36Sopenharmony_ci * FIXATE NODES * 231362306a36Sopenharmony_ci ***************************************************************************/ 231462306a36Sopenharmony_ci 231562306a36Sopenharmony_ci#define VI_TYPE_LEFT_MERGEABLE 1 231662306a36Sopenharmony_ci#define VI_TYPE_RIGHT_MERGEABLE 2 231762306a36Sopenharmony_ci 231862306a36Sopenharmony_ci/* 231962306a36Sopenharmony_ci * To make any changes in the tree we always first find node, that 232062306a36Sopenharmony_ci * contains item to be changed/deleted or place to insert a new 232162306a36Sopenharmony_ci * item. We call this node S. To do balancing we need to decide what 232262306a36Sopenharmony_ci * we will shift to left/right neighbor, or to a new node, where new 232362306a36Sopenharmony_ci * item will be etc. To make this analysis simpler we build virtual 232462306a36Sopenharmony_ci * node. Virtual node is an array of items, that will replace items of 232562306a36Sopenharmony_ci * node S. (For instance if we are going to delete an item, virtual 232662306a36Sopenharmony_ci * node does not contain it). Virtual node keeps information about 232762306a36Sopenharmony_ci * item sizes and types, mergeability of first and last items, sizes 232862306a36Sopenharmony_ci * of all entries in directory item. We use this array of items when 232962306a36Sopenharmony_ci * calculating what we can shift to neighbors and how many nodes we 233062306a36Sopenharmony_ci * have to have if we do not any shiftings, if we shift to left/right 233162306a36Sopenharmony_ci * neighbor or to both. 233262306a36Sopenharmony_ci */ 233362306a36Sopenharmony_cistruct virtual_item { 233462306a36Sopenharmony_ci int vi_index; /* index in the array of item operations */ 233562306a36Sopenharmony_ci unsigned short vi_type; /* left/right mergeability */ 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci /* length of item that it will have after balancing */ 233862306a36Sopenharmony_ci unsigned short vi_item_len; 233962306a36Sopenharmony_ci 234062306a36Sopenharmony_ci struct item_head *vi_ih; 234162306a36Sopenharmony_ci const char *vi_item; /* body of item (old or new) */ 234262306a36Sopenharmony_ci const void *vi_new_data; /* 0 always but paste mode */ 234362306a36Sopenharmony_ci void *vi_uarea; /* item specific area */ 234462306a36Sopenharmony_ci}; 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_cistruct virtual_node { 234762306a36Sopenharmony_ci /* this is a pointer to the free space in the buffer */ 234862306a36Sopenharmony_ci char *vn_free_ptr; 234962306a36Sopenharmony_ci 235062306a36Sopenharmony_ci unsigned short vn_nr_item; /* number of items in virtual node */ 235162306a36Sopenharmony_ci 235262306a36Sopenharmony_ci /* 235362306a36Sopenharmony_ci * size of node , that node would have if it has 235462306a36Sopenharmony_ci * unlimited size and no balancing is performed 235562306a36Sopenharmony_ci */ 235662306a36Sopenharmony_ci short vn_size; 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci /* mode of balancing (paste, insert, delete, cut) */ 235962306a36Sopenharmony_ci short vn_mode; 236062306a36Sopenharmony_ci 236162306a36Sopenharmony_ci short vn_affected_item_num; 236262306a36Sopenharmony_ci short vn_pos_in_item; 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci /* item header of inserted item, 0 for other modes */ 236562306a36Sopenharmony_ci struct item_head *vn_ins_ih; 236662306a36Sopenharmony_ci const void *vn_data; 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci /* array of items (including a new one, excluding item to be deleted) */ 236962306a36Sopenharmony_ci struct virtual_item *vn_vi; 237062306a36Sopenharmony_ci}; 237162306a36Sopenharmony_ci 237262306a36Sopenharmony_ci/* used by directory items when creating virtual nodes */ 237362306a36Sopenharmony_cistruct direntry_uarea { 237462306a36Sopenharmony_ci int flags; 237562306a36Sopenharmony_ci __u16 entry_count; 237662306a36Sopenharmony_ci __u16 entry_sizes[]; 237762306a36Sopenharmony_ci} __attribute__ ((__packed__)); 237862306a36Sopenharmony_ci 237962306a36Sopenharmony_ci/*************************************************************************** 238062306a36Sopenharmony_ci * TREE BALANCE * 238162306a36Sopenharmony_ci ***************************************************************************/ 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_ci/* 238462306a36Sopenharmony_ci * This temporary structure is used in tree balance algorithms, and 238562306a36Sopenharmony_ci * constructed as we go to the extent that its various parts are 238662306a36Sopenharmony_ci * needed. It contains arrays of nodes that can potentially be 238762306a36Sopenharmony_ci * involved in the balancing of node S, and parameters that define how 238862306a36Sopenharmony_ci * each of the nodes must be balanced. Note that in these algorithms 238962306a36Sopenharmony_ci * for balancing the worst case is to need to balance the current node 239062306a36Sopenharmony_ci * S and the left and right neighbors and all of their parents plus 239162306a36Sopenharmony_ci * create a new node. We implement S1 balancing for the leaf nodes 239262306a36Sopenharmony_ci * and S0 balancing for the internal nodes (S1 and S0 are defined in 239362306a36Sopenharmony_ci * our papers.) 239462306a36Sopenharmony_ci */ 239562306a36Sopenharmony_ci 239662306a36Sopenharmony_ci/* size of the array of buffers to free at end of do_balance */ 239762306a36Sopenharmony_ci#define MAX_FREE_BLOCK 7 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci/* maximum number of FEB blocknrs on a single level */ 240062306a36Sopenharmony_ci#define MAX_AMOUNT_NEEDED 2 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci/* someday somebody will prefix every field in this struct with tb_ */ 240362306a36Sopenharmony_cistruct tree_balance { 240462306a36Sopenharmony_ci int tb_mode; 240562306a36Sopenharmony_ci int need_balance_dirty; 240662306a36Sopenharmony_ci struct super_block *tb_sb; 240762306a36Sopenharmony_ci struct reiserfs_transaction_handle *transaction_handle; 240862306a36Sopenharmony_ci struct treepath *tb_path; 240962306a36Sopenharmony_ci 241062306a36Sopenharmony_ci /* array of left neighbors of nodes in the path */ 241162306a36Sopenharmony_ci struct buffer_head *L[MAX_HEIGHT]; 241262306a36Sopenharmony_ci 241362306a36Sopenharmony_ci /* array of right neighbors of nodes in the path */ 241462306a36Sopenharmony_ci struct buffer_head *R[MAX_HEIGHT]; 241562306a36Sopenharmony_ci 241662306a36Sopenharmony_ci /* array of fathers of the left neighbors */ 241762306a36Sopenharmony_ci struct buffer_head *FL[MAX_HEIGHT]; 241862306a36Sopenharmony_ci 241962306a36Sopenharmony_ci /* array of fathers of the right neighbors */ 242062306a36Sopenharmony_ci struct buffer_head *FR[MAX_HEIGHT]; 242162306a36Sopenharmony_ci /* array of common parents of center node and its left neighbor */ 242262306a36Sopenharmony_ci struct buffer_head *CFL[MAX_HEIGHT]; 242362306a36Sopenharmony_ci 242462306a36Sopenharmony_ci /* array of common parents of center node and its right neighbor */ 242562306a36Sopenharmony_ci struct buffer_head *CFR[MAX_HEIGHT]; 242662306a36Sopenharmony_ci 242762306a36Sopenharmony_ci /* 242862306a36Sopenharmony_ci * array of empty buffers. Number of buffers in array equals 242962306a36Sopenharmony_ci * cur_blknum. 243062306a36Sopenharmony_ci */ 243162306a36Sopenharmony_ci struct buffer_head *FEB[MAX_FEB_SIZE]; 243262306a36Sopenharmony_ci struct buffer_head *used[MAX_FEB_SIZE]; 243362306a36Sopenharmony_ci struct buffer_head *thrown[MAX_FEB_SIZE]; 243462306a36Sopenharmony_ci 243562306a36Sopenharmony_ci /* 243662306a36Sopenharmony_ci * array of number of items which must be shifted to the left in 243762306a36Sopenharmony_ci * order to balance the current node; for leaves includes item that 243862306a36Sopenharmony_ci * will be partially shifted; for internal nodes, it is the number 243962306a36Sopenharmony_ci * of child pointers rather than items. It includes the new item 244062306a36Sopenharmony_ci * being created. The code sometimes subtracts one to get the 244162306a36Sopenharmony_ci * number of wholly shifted items for other purposes. 244262306a36Sopenharmony_ci */ 244362306a36Sopenharmony_ci int lnum[MAX_HEIGHT]; 244462306a36Sopenharmony_ci 244562306a36Sopenharmony_ci /* substitute right for left in comment above */ 244662306a36Sopenharmony_ci int rnum[MAX_HEIGHT]; 244762306a36Sopenharmony_ci 244862306a36Sopenharmony_ci /* 244962306a36Sopenharmony_ci * array indexed by height h mapping the key delimiting L[h] and 245062306a36Sopenharmony_ci * S[h] to its item number within the node CFL[h] 245162306a36Sopenharmony_ci */ 245262306a36Sopenharmony_ci int lkey[MAX_HEIGHT]; 245362306a36Sopenharmony_ci 245462306a36Sopenharmony_ci /* substitute r for l in comment above */ 245562306a36Sopenharmony_ci int rkey[MAX_HEIGHT]; 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_ci /* 245862306a36Sopenharmony_ci * the number of bytes by we are trying to add or remove from 245962306a36Sopenharmony_ci * S[h]. A negative value means removing. 246062306a36Sopenharmony_ci */ 246162306a36Sopenharmony_ci int insert_size[MAX_HEIGHT]; 246262306a36Sopenharmony_ci 246362306a36Sopenharmony_ci /* 246462306a36Sopenharmony_ci * number of nodes that will replace node S[h] after balancing 246562306a36Sopenharmony_ci * on the level h of the tree. If 0 then S is being deleted, 246662306a36Sopenharmony_ci * if 1 then S is remaining and no new nodes are being created, 246762306a36Sopenharmony_ci * if 2 or 3 then 1 or 2 new nodes is being created 246862306a36Sopenharmony_ci */ 246962306a36Sopenharmony_ci int blknum[MAX_HEIGHT]; 247062306a36Sopenharmony_ci 247162306a36Sopenharmony_ci /* fields that are used only for balancing leaves of the tree */ 247262306a36Sopenharmony_ci 247362306a36Sopenharmony_ci /* number of empty blocks having been already allocated */ 247462306a36Sopenharmony_ci int cur_blknum; 247562306a36Sopenharmony_ci 247662306a36Sopenharmony_ci /* number of items that fall into left most node when S[0] splits */ 247762306a36Sopenharmony_ci int s0num; 247862306a36Sopenharmony_ci 247962306a36Sopenharmony_ci /* 248062306a36Sopenharmony_ci * number of bytes which can flow to the left neighbor from the left 248162306a36Sopenharmony_ci * most liquid item that cannot be shifted from S[0] entirely 248262306a36Sopenharmony_ci * if -1 then nothing will be partially shifted 248362306a36Sopenharmony_ci */ 248462306a36Sopenharmony_ci int lbytes; 248562306a36Sopenharmony_ci 248662306a36Sopenharmony_ci /* 248762306a36Sopenharmony_ci * number of bytes which will flow to the right neighbor from the right 248862306a36Sopenharmony_ci * most liquid item that cannot be shifted from S[0] entirely 248962306a36Sopenharmony_ci * if -1 then nothing will be partially shifted 249062306a36Sopenharmony_ci */ 249162306a36Sopenharmony_ci int rbytes; 249262306a36Sopenharmony_ci 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ci /* 249562306a36Sopenharmony_ci * index into the array of item headers in 249662306a36Sopenharmony_ci * S[0] of the affected item 249762306a36Sopenharmony_ci */ 249862306a36Sopenharmony_ci int item_pos; 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci /* new nodes allocated to hold what could not fit into S */ 250162306a36Sopenharmony_ci struct buffer_head *S_new[2]; 250262306a36Sopenharmony_ci 250362306a36Sopenharmony_ci /* 250462306a36Sopenharmony_ci * number of items that will be placed into nodes in S_new 250562306a36Sopenharmony_ci * when S[0] splits 250662306a36Sopenharmony_ci */ 250762306a36Sopenharmony_ci int snum[2]; 250862306a36Sopenharmony_ci 250962306a36Sopenharmony_ci /* 251062306a36Sopenharmony_ci * number of bytes which flow to nodes in S_new when S[0] splits 251162306a36Sopenharmony_ci * note: if S[0] splits into 3 nodes, then items do not need to be cut 251262306a36Sopenharmony_ci */ 251362306a36Sopenharmony_ci int sbytes[2]; 251462306a36Sopenharmony_ci 251562306a36Sopenharmony_ci int pos_in_item; 251662306a36Sopenharmony_ci int zeroes_num; 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ci /* 251962306a36Sopenharmony_ci * buffers which are to be freed after do_balance finishes 252062306a36Sopenharmony_ci * by unfix_nodes 252162306a36Sopenharmony_ci */ 252262306a36Sopenharmony_ci struct buffer_head *buf_to_free[MAX_FREE_BLOCK]; 252362306a36Sopenharmony_ci 252462306a36Sopenharmony_ci /* 252562306a36Sopenharmony_ci * kmalloced memory. Used to create virtual node and keep 252662306a36Sopenharmony_ci * map of dirtied bitmap blocks 252762306a36Sopenharmony_ci */ 252862306a36Sopenharmony_ci char *vn_buf; 252962306a36Sopenharmony_ci 253062306a36Sopenharmony_ci int vn_buf_size; /* size of the vn_buf */ 253162306a36Sopenharmony_ci 253262306a36Sopenharmony_ci /* VN starts after bitmap of bitmap blocks */ 253362306a36Sopenharmony_ci struct virtual_node *tb_vn; 253462306a36Sopenharmony_ci 253562306a36Sopenharmony_ci /* 253662306a36Sopenharmony_ci * saved value of `reiserfs_generation' counter see 253762306a36Sopenharmony_ci * FILESYSTEM_CHANGED() macro in reiserfs_fs.h 253862306a36Sopenharmony_ci */ 253962306a36Sopenharmony_ci int fs_gen; 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci#ifdef DISPLACE_NEW_PACKING_LOCALITIES 254262306a36Sopenharmony_ci /* 254362306a36Sopenharmony_ci * key pointer, to pass to block allocator or 254462306a36Sopenharmony_ci * another low-level subsystem 254562306a36Sopenharmony_ci */ 254662306a36Sopenharmony_ci struct in_core_key key; 254762306a36Sopenharmony_ci#endif 254862306a36Sopenharmony_ci}; 254962306a36Sopenharmony_ci 255062306a36Sopenharmony_ci/* These are modes of balancing */ 255162306a36Sopenharmony_ci 255262306a36Sopenharmony_ci/* When inserting an item. */ 255362306a36Sopenharmony_ci#define M_INSERT 'i' 255462306a36Sopenharmony_ci/* 255562306a36Sopenharmony_ci * When inserting into (directories only) or appending onto an already 255662306a36Sopenharmony_ci * existent item. 255762306a36Sopenharmony_ci */ 255862306a36Sopenharmony_ci#define M_PASTE 'p' 255962306a36Sopenharmony_ci/* When deleting an item. */ 256062306a36Sopenharmony_ci#define M_DELETE 'd' 256162306a36Sopenharmony_ci/* When truncating an item or removing an entry from a (directory) item. */ 256262306a36Sopenharmony_ci#define M_CUT 'c' 256362306a36Sopenharmony_ci 256462306a36Sopenharmony_ci/* used when balancing on leaf level skipped (in reiserfsck) */ 256562306a36Sopenharmony_ci#define M_INTERNAL 'n' 256662306a36Sopenharmony_ci 256762306a36Sopenharmony_ci/* 256862306a36Sopenharmony_ci * When further balancing is not needed, then do_balance does not need 256962306a36Sopenharmony_ci * to be called. 257062306a36Sopenharmony_ci */ 257162306a36Sopenharmony_ci#define M_SKIP_BALANCING 's' 257262306a36Sopenharmony_ci#define M_CONVERT 'v' 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_ci/* modes of leaf_move_items */ 257562306a36Sopenharmony_ci#define LEAF_FROM_S_TO_L 0 257662306a36Sopenharmony_ci#define LEAF_FROM_S_TO_R 1 257762306a36Sopenharmony_ci#define LEAF_FROM_R_TO_L 2 257862306a36Sopenharmony_ci#define LEAF_FROM_L_TO_R 3 257962306a36Sopenharmony_ci#define LEAF_FROM_S_TO_SNEW 4 258062306a36Sopenharmony_ci 258162306a36Sopenharmony_ci#define FIRST_TO_LAST 0 258262306a36Sopenharmony_ci#define LAST_TO_FIRST 1 258362306a36Sopenharmony_ci 258462306a36Sopenharmony_ci/* 258562306a36Sopenharmony_ci * used in do_balance for passing parent of node information that has 258662306a36Sopenharmony_ci * been gotten from tb struct 258762306a36Sopenharmony_ci */ 258862306a36Sopenharmony_cistruct buffer_info { 258962306a36Sopenharmony_ci struct tree_balance *tb; 259062306a36Sopenharmony_ci struct buffer_head *bi_bh; 259162306a36Sopenharmony_ci struct buffer_head *bi_parent; 259262306a36Sopenharmony_ci int bi_position; 259362306a36Sopenharmony_ci}; 259462306a36Sopenharmony_ci 259562306a36Sopenharmony_cistatic inline struct super_block *sb_from_tb(struct tree_balance *tb) 259662306a36Sopenharmony_ci{ 259762306a36Sopenharmony_ci return tb ? tb->tb_sb : NULL; 259862306a36Sopenharmony_ci} 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_cistatic inline struct super_block *sb_from_bi(struct buffer_info *bi) 260162306a36Sopenharmony_ci{ 260262306a36Sopenharmony_ci return bi ? sb_from_tb(bi->tb) : NULL; 260362306a36Sopenharmony_ci} 260462306a36Sopenharmony_ci 260562306a36Sopenharmony_ci/* 260662306a36Sopenharmony_ci * there are 4 types of items: stat data, directory item, indirect, direct. 260762306a36Sopenharmony_ci * +-------------------+------------+--------------+------------+ 260862306a36Sopenharmony_ci * | | k_offset | k_uniqueness | mergeable? | 260962306a36Sopenharmony_ci * +-------------------+------------+--------------+------------+ 261062306a36Sopenharmony_ci * | stat data | 0 | 0 | no | 261162306a36Sopenharmony_ci * +-------------------+------------+--------------+------------+ 261262306a36Sopenharmony_ci * | 1st directory item| DOT_OFFSET | DIRENTRY_ .. | no | 261362306a36Sopenharmony_ci * | non 1st directory | hash value | UNIQUENESS | yes | 261462306a36Sopenharmony_ci * | item | | | | 261562306a36Sopenharmony_ci * +-------------------+------------+--------------+------------+ 261662306a36Sopenharmony_ci * | indirect item | offset + 1 |TYPE_INDIRECT | [1] | 261762306a36Sopenharmony_ci * +-------------------+------------+--------------+------------+ 261862306a36Sopenharmony_ci * | direct item | offset + 1 |TYPE_DIRECT | [2] | 261962306a36Sopenharmony_ci * +-------------------+------------+--------------+------------+ 262062306a36Sopenharmony_ci * 262162306a36Sopenharmony_ci * [1] if this is not the first indirect item of the object 262262306a36Sopenharmony_ci * [2] if this is not the first direct item of the object 262362306a36Sopenharmony_ci*/ 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_cistruct item_operations { 262662306a36Sopenharmony_ci int (*bytes_number) (struct item_head * ih, int block_size); 262762306a36Sopenharmony_ci void (*decrement_key) (struct cpu_key *); 262862306a36Sopenharmony_ci int (*is_left_mergeable) (struct reiserfs_key * ih, 262962306a36Sopenharmony_ci unsigned long bsize); 263062306a36Sopenharmony_ci void (*print_item) (struct item_head *, char *item); 263162306a36Sopenharmony_ci void (*check_item) (struct item_head *, char *item); 263262306a36Sopenharmony_ci 263362306a36Sopenharmony_ci int (*create_vi) (struct virtual_node * vn, struct virtual_item * vi, 263462306a36Sopenharmony_ci int is_affected, int insert_size); 263562306a36Sopenharmony_ci int (*check_left) (struct virtual_item * vi, int free, 263662306a36Sopenharmony_ci int start_skip, int end_skip); 263762306a36Sopenharmony_ci int (*check_right) (struct virtual_item * vi, int free); 263862306a36Sopenharmony_ci int (*part_size) (struct virtual_item * vi, int from, int to); 263962306a36Sopenharmony_ci int (*unit_num) (struct virtual_item * vi); 264062306a36Sopenharmony_ci void (*print_vi) (struct virtual_item * vi); 264162306a36Sopenharmony_ci}; 264262306a36Sopenharmony_ci 264362306a36Sopenharmony_ciextern struct item_operations *item_ops[TYPE_ANY + 1]; 264462306a36Sopenharmony_ci 264562306a36Sopenharmony_ci#define op_bytes_number(ih,bsize) item_ops[le_ih_k_type (ih)]->bytes_number (ih, bsize) 264662306a36Sopenharmony_ci#define op_is_left_mergeable(key,bsize) item_ops[le_key_k_type (le_key_version (key), key)]->is_left_mergeable (key, bsize) 264762306a36Sopenharmony_ci#define op_print_item(ih,item) item_ops[le_ih_k_type (ih)]->print_item (ih, item) 264862306a36Sopenharmony_ci#define op_check_item(ih,item) item_ops[le_ih_k_type (ih)]->check_item (ih, item) 264962306a36Sopenharmony_ci#define op_create_vi(vn,vi,is_affected,insert_size) item_ops[le_ih_k_type ((vi)->vi_ih)]->create_vi (vn,vi,is_affected,insert_size) 265062306a36Sopenharmony_ci#define op_check_left(vi,free,start_skip,end_skip) item_ops[(vi)->vi_index]->check_left (vi, free, start_skip, end_skip) 265162306a36Sopenharmony_ci#define op_check_right(vi,free) item_ops[(vi)->vi_index]->check_right (vi, free) 265262306a36Sopenharmony_ci#define op_part_size(vi,from,to) item_ops[(vi)->vi_index]->part_size (vi, from, to) 265362306a36Sopenharmony_ci#define op_unit_num(vi) item_ops[(vi)->vi_index]->unit_num (vi) 265462306a36Sopenharmony_ci#define op_print_vi(vi) item_ops[(vi)->vi_index]->print_vi (vi) 265562306a36Sopenharmony_ci 265662306a36Sopenharmony_ci#define COMP_SHORT_KEYS comp_short_keys 265762306a36Sopenharmony_ci 265862306a36Sopenharmony_ci/* number of blocks pointed to by the indirect item */ 265962306a36Sopenharmony_ci#define I_UNFM_NUM(ih) (ih_item_len(ih) / UNFM_P_SIZE) 266062306a36Sopenharmony_ci 266162306a36Sopenharmony_ci/* 266262306a36Sopenharmony_ci * the used space within the unformatted node corresponding 266362306a36Sopenharmony_ci * to pos within the item pointed to by ih 266462306a36Sopenharmony_ci */ 266562306a36Sopenharmony_ci#define I_POS_UNFM_SIZE(ih,pos,size) (((pos) == I_UNFM_NUM(ih) - 1 ) ? (size) - ih_free_space(ih) : (size)) 266662306a36Sopenharmony_ci 266762306a36Sopenharmony_ci/* 266862306a36Sopenharmony_ci * number of bytes contained by the direct item or the 266962306a36Sopenharmony_ci * unformatted nodes the indirect item points to 267062306a36Sopenharmony_ci */ 267162306a36Sopenharmony_ci 267262306a36Sopenharmony_ci/* following defines use reiserfs buffer header and item header */ 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci/* get stat-data */ 267562306a36Sopenharmony_ci#define B_I_STAT_DATA(bh, ih) ( (struct stat_data * )((bh)->b_data + ih_location(ih)) ) 267662306a36Sopenharmony_ci 267762306a36Sopenharmony_ci/* this is 3976 for size==4096 */ 267862306a36Sopenharmony_ci#define MAX_DIRECT_ITEM_LEN(size) ((size) - BLKH_SIZE - 2*IH_SIZE - SD_SIZE - UNFM_P_SIZE) 267962306a36Sopenharmony_ci 268062306a36Sopenharmony_ci/* 268162306a36Sopenharmony_ci * indirect items consist of entries which contain blocknrs, pos 268262306a36Sopenharmony_ci * indicates which entry, and B_I_POS_UNFM_POINTER resolves to the 268362306a36Sopenharmony_ci * blocknr contained by the entry pos points to 268462306a36Sopenharmony_ci */ 268562306a36Sopenharmony_ci#define B_I_POS_UNFM_POINTER(bh, ih, pos) \ 268662306a36Sopenharmony_ci le32_to_cpu(*(((unp_t *)ih_item_body(bh, ih)) + (pos))) 268762306a36Sopenharmony_ci#define PUT_B_I_POS_UNFM_POINTER(bh, ih, pos, val) \ 268862306a36Sopenharmony_ci (*(((unp_t *)ih_item_body(bh, ih)) + (pos)) = cpu_to_le32(val)) 268962306a36Sopenharmony_ci 269062306a36Sopenharmony_cistruct reiserfs_iget_args { 269162306a36Sopenharmony_ci __u32 objectid; 269262306a36Sopenharmony_ci __u32 dirid; 269362306a36Sopenharmony_ci}; 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_ci/*************************************************************************** 269662306a36Sopenharmony_ci * FUNCTION DECLARATIONS * 269762306a36Sopenharmony_ci ***************************************************************************/ 269862306a36Sopenharmony_ci 269962306a36Sopenharmony_ci#define get_journal_desc_magic(bh) (bh->b_data + bh->b_size - 12) 270062306a36Sopenharmony_ci 270162306a36Sopenharmony_ci#define journal_trans_half(blocksize) \ 270262306a36Sopenharmony_ci ((blocksize - sizeof(struct reiserfs_journal_desc) - 12) / sizeof(__u32)) 270362306a36Sopenharmony_ci 270462306a36Sopenharmony_ci/* journal.c see journal.c for all the comments here */ 270562306a36Sopenharmony_ci 270662306a36Sopenharmony_ci/* first block written in a commit. */ 270762306a36Sopenharmony_cistruct reiserfs_journal_desc { 270862306a36Sopenharmony_ci __le32 j_trans_id; /* id of commit */ 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_ci /* length of commit. len +1 is the commit block */ 271162306a36Sopenharmony_ci __le32 j_len; 271262306a36Sopenharmony_ci 271362306a36Sopenharmony_ci __le32 j_mount_id; /* mount id of this trans */ 271462306a36Sopenharmony_ci __le32 j_realblock[]; /* real locations for each block */ 271562306a36Sopenharmony_ci}; 271662306a36Sopenharmony_ci 271762306a36Sopenharmony_ci#define get_desc_trans_id(d) le32_to_cpu((d)->j_trans_id) 271862306a36Sopenharmony_ci#define get_desc_trans_len(d) le32_to_cpu((d)->j_len) 271962306a36Sopenharmony_ci#define get_desc_mount_id(d) le32_to_cpu((d)->j_mount_id) 272062306a36Sopenharmony_ci 272162306a36Sopenharmony_ci#define set_desc_trans_id(d,val) do { (d)->j_trans_id = cpu_to_le32 (val); } while (0) 272262306a36Sopenharmony_ci#define set_desc_trans_len(d,val) do { (d)->j_len = cpu_to_le32 (val); } while (0) 272362306a36Sopenharmony_ci#define set_desc_mount_id(d,val) do { (d)->j_mount_id = cpu_to_le32 (val); } while (0) 272462306a36Sopenharmony_ci 272562306a36Sopenharmony_ci/* last block written in a commit */ 272662306a36Sopenharmony_cistruct reiserfs_journal_commit { 272762306a36Sopenharmony_ci __le32 j_trans_id; /* must match j_trans_id from the desc block */ 272862306a36Sopenharmony_ci __le32 j_len; /* ditto */ 272962306a36Sopenharmony_ci __le32 j_realblock[]; /* real locations for each block */ 273062306a36Sopenharmony_ci}; 273162306a36Sopenharmony_ci 273262306a36Sopenharmony_ci#define get_commit_trans_id(c) le32_to_cpu((c)->j_trans_id) 273362306a36Sopenharmony_ci#define get_commit_trans_len(c) le32_to_cpu((c)->j_len) 273462306a36Sopenharmony_ci#define get_commit_mount_id(c) le32_to_cpu((c)->j_mount_id) 273562306a36Sopenharmony_ci 273662306a36Sopenharmony_ci#define set_commit_trans_id(c,val) do { (c)->j_trans_id = cpu_to_le32 (val); } while (0) 273762306a36Sopenharmony_ci#define set_commit_trans_len(c,val) do { (c)->j_len = cpu_to_le32 (val); } while (0) 273862306a36Sopenharmony_ci 273962306a36Sopenharmony_ci/* 274062306a36Sopenharmony_ci * this header block gets written whenever a transaction is considered 274162306a36Sopenharmony_ci * fully flushed, and is more recent than the last fully flushed transaction. 274262306a36Sopenharmony_ci * fully flushed means all the log blocks and all the real blocks are on 274362306a36Sopenharmony_ci * disk, and this transaction does not need to be replayed. 274462306a36Sopenharmony_ci */ 274562306a36Sopenharmony_cistruct reiserfs_journal_header { 274662306a36Sopenharmony_ci /* id of last fully flushed transaction */ 274762306a36Sopenharmony_ci __le32 j_last_flush_trans_id; 274862306a36Sopenharmony_ci 274962306a36Sopenharmony_ci /* offset in the log of where to start replay after a crash */ 275062306a36Sopenharmony_ci __le32 j_first_unflushed_offset; 275162306a36Sopenharmony_ci 275262306a36Sopenharmony_ci __le32 j_mount_id; 275362306a36Sopenharmony_ci /* 12 */ struct journal_params jh_journal; 275462306a36Sopenharmony_ci}; 275562306a36Sopenharmony_ci 275662306a36Sopenharmony_ci/* biggest tunable defines are right here */ 275762306a36Sopenharmony_ci#define JOURNAL_BLOCK_COUNT 8192 /* number of blocks in the journal */ 275862306a36Sopenharmony_ci 275962306a36Sopenharmony_ci/* biggest possible single transaction, don't change for now (8/3/99) */ 276062306a36Sopenharmony_ci#define JOURNAL_TRANS_MAX_DEFAULT 1024 276162306a36Sopenharmony_ci#define JOURNAL_TRANS_MIN_DEFAULT 256 276262306a36Sopenharmony_ci 276362306a36Sopenharmony_ci/* 276462306a36Sopenharmony_ci * max blocks to batch into one transaction, 276562306a36Sopenharmony_ci * don't make this any bigger than 900 276662306a36Sopenharmony_ci */ 276762306a36Sopenharmony_ci#define JOURNAL_MAX_BATCH_DEFAULT 900 276862306a36Sopenharmony_ci#define JOURNAL_MIN_RATIO 2 276962306a36Sopenharmony_ci#define JOURNAL_MAX_COMMIT_AGE 30 277062306a36Sopenharmony_ci#define JOURNAL_MAX_TRANS_AGE 30 277162306a36Sopenharmony_ci#define JOURNAL_PER_BALANCE_CNT (3 * (MAX_HEIGHT-2) + 9) 277262306a36Sopenharmony_ci#define JOURNAL_BLOCKS_PER_OBJECT(sb) (JOURNAL_PER_BALANCE_CNT * 3 + \ 277362306a36Sopenharmony_ci 2 * (REISERFS_QUOTA_INIT_BLOCKS(sb) + \ 277462306a36Sopenharmony_ci REISERFS_QUOTA_TRANS_BLOCKS(sb))) 277562306a36Sopenharmony_ci 277662306a36Sopenharmony_ci#ifdef CONFIG_QUOTA 277762306a36Sopenharmony_ci#define REISERFS_QUOTA_OPTS ((1 << REISERFS_USRQUOTA) | (1 << REISERFS_GRPQUOTA)) 277862306a36Sopenharmony_ci/* We need to update data and inode (atime) */ 277962306a36Sopenharmony_ci#define REISERFS_QUOTA_TRANS_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & REISERFS_QUOTA_OPTS ? 2 : 0) 278062306a36Sopenharmony_ci/* 1 balancing, 1 bitmap, 1 data per write + stat data update */ 278162306a36Sopenharmony_ci#define REISERFS_QUOTA_INIT_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & REISERFS_QUOTA_OPTS ? \ 278262306a36Sopenharmony_ci(DQUOT_INIT_ALLOC*(JOURNAL_PER_BALANCE_CNT+2)+DQUOT_INIT_REWRITE+1) : 0) 278362306a36Sopenharmony_ci/* same as with INIT */ 278462306a36Sopenharmony_ci#define REISERFS_QUOTA_DEL_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & REISERFS_QUOTA_OPTS ? \ 278562306a36Sopenharmony_ci(DQUOT_DEL_ALLOC*(JOURNAL_PER_BALANCE_CNT+2)+DQUOT_DEL_REWRITE+1) : 0) 278662306a36Sopenharmony_ci#else 278762306a36Sopenharmony_ci#define REISERFS_QUOTA_TRANS_BLOCKS(s) 0 278862306a36Sopenharmony_ci#define REISERFS_QUOTA_INIT_BLOCKS(s) 0 278962306a36Sopenharmony_ci#define REISERFS_QUOTA_DEL_BLOCKS(s) 0 279062306a36Sopenharmony_ci#endif 279162306a36Sopenharmony_ci 279262306a36Sopenharmony_ci/* 279362306a36Sopenharmony_ci * both of these can be as low as 1, or as high as you want. The min is the 279462306a36Sopenharmony_ci * number of 4k bitmap nodes preallocated on mount. New nodes are allocated 279562306a36Sopenharmony_ci * as needed, and released when transactions are committed. On release, if 279662306a36Sopenharmony_ci * the current number of nodes is > max, the node is freed, otherwise, 279762306a36Sopenharmony_ci * it is put on a free list for faster use later. 279862306a36Sopenharmony_ci*/ 279962306a36Sopenharmony_ci#define REISERFS_MIN_BITMAP_NODES 10 280062306a36Sopenharmony_ci#define REISERFS_MAX_BITMAP_NODES 100 280162306a36Sopenharmony_ci 280262306a36Sopenharmony_ci/* these are based on journal hash size of 8192 */ 280362306a36Sopenharmony_ci#define JBH_HASH_SHIFT 13 280462306a36Sopenharmony_ci#define JBH_HASH_MASK 8191 280562306a36Sopenharmony_ci 280662306a36Sopenharmony_ci#define _jhashfn(sb,block) \ 280762306a36Sopenharmony_ci (((unsigned long)sb>>L1_CACHE_SHIFT) ^ \ 280862306a36Sopenharmony_ci (((block)<<(JBH_HASH_SHIFT - 6)) ^ ((block) >> 13) ^ ((block) << (JBH_HASH_SHIFT - 12)))) 280962306a36Sopenharmony_ci#define journal_hash(t,sb,block) ((t)[_jhashfn((sb),(block)) & JBH_HASH_MASK]) 281062306a36Sopenharmony_ci 281162306a36Sopenharmony_ci/* We need these to make journal.c code more readable */ 281262306a36Sopenharmony_ci#define journal_find_get_block(s, block) __find_get_block(SB_JOURNAL(s)->j_dev_bd, block, s->s_blocksize) 281362306a36Sopenharmony_ci#define journal_getblk(s, block) __getblk(SB_JOURNAL(s)->j_dev_bd, block, s->s_blocksize) 281462306a36Sopenharmony_ci#define journal_bread(s, block) __bread(SB_JOURNAL(s)->j_dev_bd, block, s->s_blocksize) 281562306a36Sopenharmony_ci 281662306a36Sopenharmony_cienum reiserfs_bh_state_bits { 281762306a36Sopenharmony_ci BH_JDirty = BH_PrivateStart, /* buffer is in current transaction */ 281862306a36Sopenharmony_ci BH_JDirty_wait, 281962306a36Sopenharmony_ci /* 282062306a36Sopenharmony_ci * disk block was taken off free list before being in a 282162306a36Sopenharmony_ci * finished transaction, or written to disk. Can be reused immed. 282262306a36Sopenharmony_ci */ 282362306a36Sopenharmony_ci BH_JNew, 282462306a36Sopenharmony_ci BH_JPrepared, 282562306a36Sopenharmony_ci BH_JRestore_dirty, 282662306a36Sopenharmony_ci BH_JTest, /* debugging only will go away */ 282762306a36Sopenharmony_ci}; 282862306a36Sopenharmony_ci 282962306a36Sopenharmony_ciBUFFER_FNS(JDirty, journaled); 283062306a36Sopenharmony_ciTAS_BUFFER_FNS(JDirty, journaled); 283162306a36Sopenharmony_ciBUFFER_FNS(JDirty_wait, journal_dirty); 283262306a36Sopenharmony_ciTAS_BUFFER_FNS(JDirty_wait, journal_dirty); 283362306a36Sopenharmony_ciBUFFER_FNS(JNew, journal_new); 283462306a36Sopenharmony_ciTAS_BUFFER_FNS(JNew, journal_new); 283562306a36Sopenharmony_ciBUFFER_FNS(JPrepared, journal_prepared); 283662306a36Sopenharmony_ciTAS_BUFFER_FNS(JPrepared, journal_prepared); 283762306a36Sopenharmony_ciBUFFER_FNS(JRestore_dirty, journal_restore_dirty); 283862306a36Sopenharmony_ciTAS_BUFFER_FNS(JRestore_dirty, journal_restore_dirty); 283962306a36Sopenharmony_ciBUFFER_FNS(JTest, journal_test); 284062306a36Sopenharmony_ciTAS_BUFFER_FNS(JTest, journal_test); 284162306a36Sopenharmony_ci 284262306a36Sopenharmony_ci/* transaction handle which is passed around for all journal calls */ 284362306a36Sopenharmony_cistruct reiserfs_transaction_handle { 284462306a36Sopenharmony_ci /* 284562306a36Sopenharmony_ci * super for this FS when journal_begin was called. saves calls to 284662306a36Sopenharmony_ci * reiserfs_get_super also used by nested transactions to make 284762306a36Sopenharmony_ci * sure they are nesting on the right FS _must_ be first 284862306a36Sopenharmony_ci * in the handle 284962306a36Sopenharmony_ci */ 285062306a36Sopenharmony_ci struct super_block *t_super; 285162306a36Sopenharmony_ci 285262306a36Sopenharmony_ci int t_refcount; 285362306a36Sopenharmony_ci int t_blocks_logged; /* number of blocks this writer has logged */ 285462306a36Sopenharmony_ci int t_blocks_allocated; /* number of blocks this writer allocated */ 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_ci /* sanity check, equals the current trans id */ 285762306a36Sopenharmony_ci unsigned int t_trans_id; 285862306a36Sopenharmony_ci 285962306a36Sopenharmony_ci void *t_handle_save; /* save existing current->journal_info */ 286062306a36Sopenharmony_ci 286162306a36Sopenharmony_ci /* 286262306a36Sopenharmony_ci * if new block allocation occurres, that block 286362306a36Sopenharmony_ci * should be displaced from others 286462306a36Sopenharmony_ci */ 286562306a36Sopenharmony_ci unsigned displace_new_blocks:1; 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_ci struct list_head t_list; 286862306a36Sopenharmony_ci}; 286962306a36Sopenharmony_ci 287062306a36Sopenharmony_ci/* 287162306a36Sopenharmony_ci * used to keep track of ordered and tail writes, attached to the buffer 287262306a36Sopenharmony_ci * head through b_journal_head. 287362306a36Sopenharmony_ci */ 287462306a36Sopenharmony_cistruct reiserfs_jh { 287562306a36Sopenharmony_ci struct reiserfs_journal_list *jl; 287662306a36Sopenharmony_ci struct buffer_head *bh; 287762306a36Sopenharmony_ci struct list_head list; 287862306a36Sopenharmony_ci}; 287962306a36Sopenharmony_ci 288062306a36Sopenharmony_civoid reiserfs_free_jh(struct buffer_head *bh); 288162306a36Sopenharmony_ciint reiserfs_add_tail_list(struct inode *inode, struct buffer_head *bh); 288262306a36Sopenharmony_ciint reiserfs_add_ordered_list(struct inode *inode, struct buffer_head *bh); 288362306a36Sopenharmony_ciint journal_mark_dirty(struct reiserfs_transaction_handle *, 288462306a36Sopenharmony_ci struct buffer_head *bh); 288562306a36Sopenharmony_ci 288662306a36Sopenharmony_cistatic inline int reiserfs_file_data_log(struct inode *inode) 288762306a36Sopenharmony_ci{ 288862306a36Sopenharmony_ci if (reiserfs_data_log(inode->i_sb) || 288962306a36Sopenharmony_ci (REISERFS_I(inode)->i_flags & i_data_log)) 289062306a36Sopenharmony_ci return 1; 289162306a36Sopenharmony_ci return 0; 289262306a36Sopenharmony_ci} 289362306a36Sopenharmony_ci 289462306a36Sopenharmony_cistatic inline int reiserfs_transaction_running(struct super_block *s) 289562306a36Sopenharmony_ci{ 289662306a36Sopenharmony_ci struct reiserfs_transaction_handle *th = current->journal_info; 289762306a36Sopenharmony_ci if (th && th->t_super == s) 289862306a36Sopenharmony_ci return 1; 289962306a36Sopenharmony_ci if (th && th->t_super == NULL) 290062306a36Sopenharmony_ci BUG(); 290162306a36Sopenharmony_ci return 0; 290262306a36Sopenharmony_ci} 290362306a36Sopenharmony_ci 290462306a36Sopenharmony_cistatic inline int reiserfs_transaction_free_space(struct reiserfs_transaction_handle *th) 290562306a36Sopenharmony_ci{ 290662306a36Sopenharmony_ci return th->t_blocks_allocated - th->t_blocks_logged; 290762306a36Sopenharmony_ci} 290862306a36Sopenharmony_ci 290962306a36Sopenharmony_cistruct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct 291062306a36Sopenharmony_ci super_block 291162306a36Sopenharmony_ci *, 291262306a36Sopenharmony_ci int count); 291362306a36Sopenharmony_ciint reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *); 291462306a36Sopenharmony_civoid reiserfs_vfs_truncate_file(struct inode *inode); 291562306a36Sopenharmony_ciint reiserfs_commit_page(struct inode *inode, struct page *page, 291662306a36Sopenharmony_ci unsigned from, unsigned to); 291762306a36Sopenharmony_civoid reiserfs_flush_old_commits(struct super_block *); 291862306a36Sopenharmony_ciint reiserfs_commit_for_inode(struct inode *); 291962306a36Sopenharmony_ciint reiserfs_inode_needs_commit(struct inode *); 292062306a36Sopenharmony_civoid reiserfs_update_inode_transaction(struct inode *); 292162306a36Sopenharmony_civoid reiserfs_wait_on_write_block(struct super_block *s); 292262306a36Sopenharmony_civoid reiserfs_block_writes(struct reiserfs_transaction_handle *th); 292362306a36Sopenharmony_civoid reiserfs_allow_writes(struct super_block *s); 292462306a36Sopenharmony_civoid reiserfs_check_lock_depth(struct super_block *s, char *caller); 292562306a36Sopenharmony_ciint reiserfs_prepare_for_journal(struct super_block *, struct buffer_head *bh, 292662306a36Sopenharmony_ci int wait); 292762306a36Sopenharmony_civoid reiserfs_restore_prepared_buffer(struct super_block *, 292862306a36Sopenharmony_ci struct buffer_head *bh); 292962306a36Sopenharmony_ciint journal_init(struct super_block *, const char *j_dev_name, int old_format, 293062306a36Sopenharmony_ci unsigned int); 293162306a36Sopenharmony_ciint journal_release(struct reiserfs_transaction_handle *, struct super_block *); 293262306a36Sopenharmony_ciint journal_release_error(struct reiserfs_transaction_handle *, 293362306a36Sopenharmony_ci struct super_block *); 293462306a36Sopenharmony_ciint journal_end(struct reiserfs_transaction_handle *); 293562306a36Sopenharmony_ciint journal_end_sync(struct reiserfs_transaction_handle *); 293662306a36Sopenharmony_ciint journal_mark_freed(struct reiserfs_transaction_handle *, 293762306a36Sopenharmony_ci struct super_block *, b_blocknr_t blocknr); 293862306a36Sopenharmony_ciint journal_transaction_should_end(struct reiserfs_transaction_handle *, int); 293962306a36Sopenharmony_ciint reiserfs_in_journal(struct super_block *sb, unsigned int bmap_nr, 294062306a36Sopenharmony_ci int bit_nr, int searchall, b_blocknr_t *next); 294162306a36Sopenharmony_ciint journal_begin(struct reiserfs_transaction_handle *, 294262306a36Sopenharmony_ci struct super_block *sb, unsigned long); 294362306a36Sopenharmony_ciint journal_join_abort(struct reiserfs_transaction_handle *, 294462306a36Sopenharmony_ci struct super_block *sb); 294562306a36Sopenharmony_civoid reiserfs_abort_journal(struct super_block *sb, int errno); 294662306a36Sopenharmony_civoid reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...); 294762306a36Sopenharmony_ciint reiserfs_allocate_list_bitmaps(struct super_block *s, 294862306a36Sopenharmony_ci struct reiserfs_list_bitmap *, unsigned int); 294962306a36Sopenharmony_ci 295062306a36Sopenharmony_civoid reiserfs_schedule_old_flush(struct super_block *s); 295162306a36Sopenharmony_civoid reiserfs_cancel_old_flush(struct super_block *s); 295262306a36Sopenharmony_civoid add_save_link(struct reiserfs_transaction_handle *th, 295362306a36Sopenharmony_ci struct inode *inode, int truncate); 295462306a36Sopenharmony_ciint remove_save_link(struct inode *inode, int truncate); 295562306a36Sopenharmony_ci 295662306a36Sopenharmony_ci/* objectid.c */ 295762306a36Sopenharmony_ci__u32 reiserfs_get_unused_objectid(struct reiserfs_transaction_handle *th); 295862306a36Sopenharmony_civoid reiserfs_release_objectid(struct reiserfs_transaction_handle *th, 295962306a36Sopenharmony_ci __u32 objectid_to_release); 296062306a36Sopenharmony_ciint reiserfs_convert_objectid_map_v1(struct super_block *); 296162306a36Sopenharmony_ci 296262306a36Sopenharmony_ci/* stree.c */ 296362306a36Sopenharmony_ciint B_IS_IN_TREE(const struct buffer_head *); 296462306a36Sopenharmony_ciextern void copy_item_head(struct item_head *to, 296562306a36Sopenharmony_ci const struct item_head *from); 296662306a36Sopenharmony_ci 296762306a36Sopenharmony_ci/* first key is in cpu form, second - le */ 296862306a36Sopenharmony_ciextern int comp_short_keys(const struct reiserfs_key *le_key, 296962306a36Sopenharmony_ci const struct cpu_key *cpu_key); 297062306a36Sopenharmony_ciextern void le_key2cpu_key(struct cpu_key *to, const struct reiserfs_key *from); 297162306a36Sopenharmony_ci 297262306a36Sopenharmony_ci/* both are in le form */ 297362306a36Sopenharmony_ciextern int comp_le_keys(const struct reiserfs_key *, 297462306a36Sopenharmony_ci const struct reiserfs_key *); 297562306a36Sopenharmony_ciextern int comp_short_le_keys(const struct reiserfs_key *, 297662306a36Sopenharmony_ci const struct reiserfs_key *); 297762306a36Sopenharmony_ci 297862306a36Sopenharmony_ci/* * get key version from on disk key - kludge */ 297962306a36Sopenharmony_cistatic inline int le_key_version(const struct reiserfs_key *key) 298062306a36Sopenharmony_ci{ 298162306a36Sopenharmony_ci int type; 298262306a36Sopenharmony_ci 298362306a36Sopenharmony_ci type = offset_v2_k_type(&(key->u.k_offset_v2)); 298462306a36Sopenharmony_ci if (type != TYPE_DIRECT && type != TYPE_INDIRECT 298562306a36Sopenharmony_ci && type != TYPE_DIRENTRY) 298662306a36Sopenharmony_ci return KEY_FORMAT_3_5; 298762306a36Sopenharmony_ci 298862306a36Sopenharmony_ci return KEY_FORMAT_3_6; 298962306a36Sopenharmony_ci 299062306a36Sopenharmony_ci} 299162306a36Sopenharmony_ci 299262306a36Sopenharmony_cistatic inline void copy_key(struct reiserfs_key *to, 299362306a36Sopenharmony_ci const struct reiserfs_key *from) 299462306a36Sopenharmony_ci{ 299562306a36Sopenharmony_ci memcpy(to, from, KEY_SIZE); 299662306a36Sopenharmony_ci} 299762306a36Sopenharmony_ci 299862306a36Sopenharmony_ciint comp_items(const struct item_head *stored_ih, const struct treepath *path); 299962306a36Sopenharmony_ciconst struct reiserfs_key *get_rkey(const struct treepath *chk_path, 300062306a36Sopenharmony_ci const struct super_block *sb); 300162306a36Sopenharmony_ciint search_by_key(struct super_block *, const struct cpu_key *, 300262306a36Sopenharmony_ci struct treepath *, int); 300362306a36Sopenharmony_ci#define search_item(s,key,path) search_by_key (s, key, path, DISK_LEAF_NODE_LEVEL) 300462306a36Sopenharmony_ciint search_for_position_by_key(struct super_block *sb, 300562306a36Sopenharmony_ci const struct cpu_key *cpu_key, 300662306a36Sopenharmony_ci struct treepath *search_path); 300762306a36Sopenharmony_ciextern void decrement_bcount(struct buffer_head *bh); 300862306a36Sopenharmony_civoid decrement_counters_in_path(struct treepath *search_path); 300962306a36Sopenharmony_civoid pathrelse(struct treepath *search_path); 301062306a36Sopenharmony_ciint reiserfs_check_path(struct treepath *p); 301162306a36Sopenharmony_civoid pathrelse_and_restore(struct super_block *s, struct treepath *search_path); 301262306a36Sopenharmony_ci 301362306a36Sopenharmony_ciint reiserfs_insert_item(struct reiserfs_transaction_handle *th, 301462306a36Sopenharmony_ci struct treepath *path, 301562306a36Sopenharmony_ci const struct cpu_key *key, 301662306a36Sopenharmony_ci struct item_head *ih, 301762306a36Sopenharmony_ci struct inode *inode, const char *body); 301862306a36Sopenharmony_ci 301962306a36Sopenharmony_ciint reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, 302062306a36Sopenharmony_ci struct treepath *path, 302162306a36Sopenharmony_ci const struct cpu_key *key, 302262306a36Sopenharmony_ci struct inode *inode, 302362306a36Sopenharmony_ci const char *body, int paste_size); 302462306a36Sopenharmony_ci 302562306a36Sopenharmony_ciint reiserfs_cut_from_item(struct reiserfs_transaction_handle *th, 302662306a36Sopenharmony_ci struct treepath *path, 302762306a36Sopenharmony_ci struct cpu_key *key, 302862306a36Sopenharmony_ci struct inode *inode, 302962306a36Sopenharmony_ci struct page *page, loff_t new_file_size); 303062306a36Sopenharmony_ci 303162306a36Sopenharmony_ciint reiserfs_delete_item(struct reiserfs_transaction_handle *th, 303262306a36Sopenharmony_ci struct treepath *path, 303362306a36Sopenharmony_ci const struct cpu_key *key, 303462306a36Sopenharmony_ci struct inode *inode, struct buffer_head *un_bh); 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_civoid reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th, 303762306a36Sopenharmony_ci struct inode *inode, struct reiserfs_key *key); 303862306a36Sopenharmony_ciint reiserfs_delete_object(struct reiserfs_transaction_handle *th, 303962306a36Sopenharmony_ci struct inode *inode); 304062306a36Sopenharmony_ciint reiserfs_do_truncate(struct reiserfs_transaction_handle *th, 304162306a36Sopenharmony_ci struct inode *inode, struct page *, 304262306a36Sopenharmony_ci int update_timestamps); 304362306a36Sopenharmony_ci 304462306a36Sopenharmony_ci#define i_block_size(inode) ((inode)->i_sb->s_blocksize) 304562306a36Sopenharmony_ci#define file_size(inode) ((inode)->i_size) 304662306a36Sopenharmony_ci#define tail_size(inode) (file_size (inode) & (i_block_size (inode) - 1)) 304762306a36Sopenharmony_ci 304862306a36Sopenharmony_ci#define tail_has_to_be_packed(inode) (have_large_tails ((inode)->i_sb)?\ 304962306a36Sopenharmony_ci!STORE_TAIL_IN_UNFM_S1(file_size (inode), tail_size(inode), inode->i_sb->s_blocksize):have_small_tails ((inode)->i_sb)?!STORE_TAIL_IN_UNFM_S2(file_size (inode), tail_size(inode), inode->i_sb->s_blocksize):0 ) 305062306a36Sopenharmony_ci 305162306a36Sopenharmony_civoid padd_item(char *item, int total_length, int length); 305262306a36Sopenharmony_ci 305362306a36Sopenharmony_ci/* inode.c */ 305462306a36Sopenharmony_ci/* args for the create parameter of reiserfs_get_block */ 305562306a36Sopenharmony_ci#define GET_BLOCK_NO_CREATE 0 /* don't create new blocks or convert tails */ 305662306a36Sopenharmony_ci#define GET_BLOCK_CREATE 1 /* add anything you need to find block */ 305762306a36Sopenharmony_ci#define GET_BLOCK_NO_HOLE 2 /* return -ENOENT for file holes */ 305862306a36Sopenharmony_ci#define GET_BLOCK_READ_DIRECT 4 /* read the tail if indirect item not found */ 305962306a36Sopenharmony_ci#define GET_BLOCK_NO_IMUX 8 /* i_mutex is not held, don't preallocate */ 306062306a36Sopenharmony_ci#define GET_BLOCK_NO_DANGLE 16 /* don't leave any transactions running */ 306162306a36Sopenharmony_ci 306262306a36Sopenharmony_civoid reiserfs_read_locked_inode(struct inode *inode, 306362306a36Sopenharmony_ci struct reiserfs_iget_args *args); 306462306a36Sopenharmony_ciint reiserfs_find_actor(struct inode *inode, void *p); 306562306a36Sopenharmony_ciint reiserfs_init_locked_inode(struct inode *inode, void *p); 306662306a36Sopenharmony_civoid reiserfs_evict_inode(struct inode *inode); 306762306a36Sopenharmony_ciint reiserfs_write_inode(struct inode *inode, struct writeback_control *wbc); 306862306a36Sopenharmony_ciint reiserfs_get_block(struct inode *inode, sector_t block, 306962306a36Sopenharmony_ci struct buffer_head *bh_result, int create); 307062306a36Sopenharmony_cistruct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, 307162306a36Sopenharmony_ci int fh_len, int fh_type); 307262306a36Sopenharmony_cistruct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, 307362306a36Sopenharmony_ci int fh_len, int fh_type); 307462306a36Sopenharmony_ciint reiserfs_encode_fh(struct inode *inode, __u32 * data, int *lenp, 307562306a36Sopenharmony_ci struct inode *parent); 307662306a36Sopenharmony_ci 307762306a36Sopenharmony_ciint reiserfs_truncate_file(struct inode *, int update_timestamps); 307862306a36Sopenharmony_civoid make_cpu_key(struct cpu_key *cpu_key, struct inode *inode, loff_t offset, 307962306a36Sopenharmony_ci int type, int key_length); 308062306a36Sopenharmony_civoid make_le_item_head(struct item_head *ih, const struct cpu_key *key, 308162306a36Sopenharmony_ci int version, 308262306a36Sopenharmony_ci loff_t offset, int type, int length, int entry_count); 308362306a36Sopenharmony_cistruct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key); 308462306a36Sopenharmony_ci 308562306a36Sopenharmony_cistruct reiserfs_security_handle; 308662306a36Sopenharmony_ciint reiserfs_new_inode(struct reiserfs_transaction_handle *th, 308762306a36Sopenharmony_ci struct inode *dir, umode_t mode, 308862306a36Sopenharmony_ci const char *symname, loff_t i_size, 308962306a36Sopenharmony_ci struct dentry *dentry, struct inode *inode, 309062306a36Sopenharmony_ci struct reiserfs_security_handle *security); 309162306a36Sopenharmony_ci 309262306a36Sopenharmony_civoid reiserfs_update_sd_size(struct reiserfs_transaction_handle *th, 309362306a36Sopenharmony_ci struct inode *inode, loff_t size); 309462306a36Sopenharmony_ci 309562306a36Sopenharmony_cistatic inline void reiserfs_update_sd(struct reiserfs_transaction_handle *th, 309662306a36Sopenharmony_ci struct inode *inode) 309762306a36Sopenharmony_ci{ 309862306a36Sopenharmony_ci reiserfs_update_sd_size(th, inode, inode->i_size); 309962306a36Sopenharmony_ci} 310062306a36Sopenharmony_ci 310162306a36Sopenharmony_civoid sd_attrs_to_i_attrs(__u16 sd_attrs, struct inode *inode); 310262306a36Sopenharmony_ciint reiserfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 310362306a36Sopenharmony_ci struct iattr *attr); 310462306a36Sopenharmony_ci 310562306a36Sopenharmony_ciint __reiserfs_write_begin(struct page *page, unsigned from, unsigned len); 310662306a36Sopenharmony_ci 310762306a36Sopenharmony_ci/* namei.c */ 310862306a36Sopenharmony_civoid reiserfs_init_priv_inode(struct inode *inode); 310962306a36Sopenharmony_civoid set_de_name_and_namelen(struct reiserfs_dir_entry *de); 311062306a36Sopenharmony_ciint search_by_entry_key(struct super_block *sb, const struct cpu_key *key, 311162306a36Sopenharmony_ci struct treepath *path, struct reiserfs_dir_entry *de); 311262306a36Sopenharmony_cistruct dentry *reiserfs_get_parent(struct dentry *); 311362306a36Sopenharmony_ci 311462306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_PROC_INFO 311562306a36Sopenharmony_ciint reiserfs_proc_info_init(struct super_block *sb); 311662306a36Sopenharmony_ciint reiserfs_proc_info_done(struct super_block *sb); 311762306a36Sopenharmony_ciint reiserfs_proc_info_global_init(void); 311862306a36Sopenharmony_ciint reiserfs_proc_info_global_done(void); 311962306a36Sopenharmony_ci 312062306a36Sopenharmony_ci#define PROC_EXP( e ) e 312162306a36Sopenharmony_ci 312262306a36Sopenharmony_ci#define __PINFO( sb ) REISERFS_SB(sb) -> s_proc_info_data 312362306a36Sopenharmony_ci#define PROC_INFO_MAX( sb, field, value ) \ 312462306a36Sopenharmony_ci __PINFO( sb ).field = \ 312562306a36Sopenharmony_ci max( REISERFS_SB( sb ) -> s_proc_info_data.field, value ) 312662306a36Sopenharmony_ci#define PROC_INFO_INC( sb, field ) ( ++ ( __PINFO( sb ).field ) ) 312762306a36Sopenharmony_ci#define PROC_INFO_ADD( sb, field, val ) ( __PINFO( sb ).field += ( val ) ) 312862306a36Sopenharmony_ci#define PROC_INFO_BH_STAT( sb, bh, level ) \ 312962306a36Sopenharmony_ci PROC_INFO_INC( sb, sbk_read_at[ ( level ) ] ); \ 313062306a36Sopenharmony_ci PROC_INFO_ADD( sb, free_at[ ( level ) ], B_FREE_SPACE( bh ) ); \ 313162306a36Sopenharmony_ci PROC_INFO_ADD( sb, items_at[ ( level ) ], B_NR_ITEMS( bh ) ) 313262306a36Sopenharmony_ci#else 313362306a36Sopenharmony_cistatic inline int reiserfs_proc_info_init(struct super_block *sb) 313462306a36Sopenharmony_ci{ 313562306a36Sopenharmony_ci return 0; 313662306a36Sopenharmony_ci} 313762306a36Sopenharmony_ci 313862306a36Sopenharmony_cistatic inline int reiserfs_proc_info_done(struct super_block *sb) 313962306a36Sopenharmony_ci{ 314062306a36Sopenharmony_ci return 0; 314162306a36Sopenharmony_ci} 314262306a36Sopenharmony_ci 314362306a36Sopenharmony_cistatic inline int reiserfs_proc_info_global_init(void) 314462306a36Sopenharmony_ci{ 314562306a36Sopenharmony_ci return 0; 314662306a36Sopenharmony_ci} 314762306a36Sopenharmony_ci 314862306a36Sopenharmony_cistatic inline int reiserfs_proc_info_global_done(void) 314962306a36Sopenharmony_ci{ 315062306a36Sopenharmony_ci return 0; 315162306a36Sopenharmony_ci} 315262306a36Sopenharmony_ci 315362306a36Sopenharmony_ci#define PROC_EXP( e ) 315462306a36Sopenharmony_ci#define VOID_V ( ( void ) 0 ) 315562306a36Sopenharmony_ci#define PROC_INFO_MAX( sb, field, value ) VOID_V 315662306a36Sopenharmony_ci#define PROC_INFO_INC( sb, field ) VOID_V 315762306a36Sopenharmony_ci#define PROC_INFO_ADD( sb, field, val ) VOID_V 315862306a36Sopenharmony_ci#define PROC_INFO_BH_STAT(sb, bh, n_node_level) VOID_V 315962306a36Sopenharmony_ci#endif 316062306a36Sopenharmony_ci 316162306a36Sopenharmony_ci/* dir.c */ 316262306a36Sopenharmony_ciextern const struct inode_operations reiserfs_dir_inode_operations; 316362306a36Sopenharmony_ciextern const struct inode_operations reiserfs_symlink_inode_operations; 316462306a36Sopenharmony_ciextern const struct inode_operations reiserfs_special_inode_operations; 316562306a36Sopenharmony_ciextern const struct file_operations reiserfs_dir_operations; 316662306a36Sopenharmony_ciint reiserfs_readdir_inode(struct inode *, struct dir_context *); 316762306a36Sopenharmony_ci 316862306a36Sopenharmony_ci/* tail_conversion.c */ 316962306a36Sopenharmony_ciint direct2indirect(struct reiserfs_transaction_handle *, struct inode *, 317062306a36Sopenharmony_ci struct treepath *, struct buffer_head *, loff_t); 317162306a36Sopenharmony_ciint indirect2direct(struct reiserfs_transaction_handle *, struct inode *, 317262306a36Sopenharmony_ci struct page *, struct treepath *, const struct cpu_key *, 317362306a36Sopenharmony_ci loff_t, char *); 317462306a36Sopenharmony_civoid reiserfs_unmap_buffer(struct buffer_head *); 317562306a36Sopenharmony_ci 317662306a36Sopenharmony_ci/* file.c */ 317762306a36Sopenharmony_ciextern const struct inode_operations reiserfs_file_inode_operations; 317862306a36Sopenharmony_ciextern const struct inode_operations reiserfs_priv_file_inode_operations; 317962306a36Sopenharmony_ciextern const struct file_operations reiserfs_file_operations; 318062306a36Sopenharmony_ciextern const struct address_space_operations reiserfs_address_space_operations; 318162306a36Sopenharmony_ci 318262306a36Sopenharmony_ci/* fix_nodes.c */ 318362306a36Sopenharmony_ci 318462306a36Sopenharmony_ciint fix_nodes(int n_op_mode, struct tree_balance *tb, 318562306a36Sopenharmony_ci struct item_head *ins_ih, const void *); 318662306a36Sopenharmony_civoid unfix_nodes(struct tree_balance *); 318762306a36Sopenharmony_ci 318862306a36Sopenharmony_ci/* prints.c */ 318962306a36Sopenharmony_civoid __reiserfs_panic(struct super_block *s, const char *id, 319062306a36Sopenharmony_ci const char *function, const char *fmt, ...) 319162306a36Sopenharmony_ci __attribute__ ((noreturn)); 319262306a36Sopenharmony_ci#define reiserfs_panic(s, id, fmt, args...) \ 319362306a36Sopenharmony_ci __reiserfs_panic(s, id, __func__, fmt, ##args) 319462306a36Sopenharmony_civoid __reiserfs_error(struct super_block *s, const char *id, 319562306a36Sopenharmony_ci const char *function, const char *fmt, ...); 319662306a36Sopenharmony_ci#define reiserfs_error(s, id, fmt, args...) \ 319762306a36Sopenharmony_ci __reiserfs_error(s, id, __func__, fmt, ##args) 319862306a36Sopenharmony_civoid reiserfs_info(struct super_block *s, const char *fmt, ...); 319962306a36Sopenharmony_civoid reiserfs_debug(struct super_block *s, int level, const char *fmt, ...); 320062306a36Sopenharmony_civoid print_indirect_item(struct buffer_head *bh, int item_num); 320162306a36Sopenharmony_civoid store_print_tb(struct tree_balance *tb); 320262306a36Sopenharmony_civoid print_cur_tb(char *mes); 320362306a36Sopenharmony_civoid print_de(struct reiserfs_dir_entry *de); 320462306a36Sopenharmony_civoid print_bi(struct buffer_info *bi, char *mes); 320562306a36Sopenharmony_ci#define PRINT_LEAF_ITEMS 1 /* print all items */ 320662306a36Sopenharmony_ci#define PRINT_DIRECTORY_ITEMS 2 /* print directory items */ 320762306a36Sopenharmony_ci#define PRINT_DIRECT_ITEMS 4 /* print contents of direct items */ 320862306a36Sopenharmony_civoid print_block(struct buffer_head *bh, ...); 320962306a36Sopenharmony_civoid print_bmap(struct super_block *s, int silent); 321062306a36Sopenharmony_civoid print_bmap_block(int i, char *data, int size, int silent); 321162306a36Sopenharmony_ci/*void print_super_block (struct super_block * s, char * mes);*/ 321262306a36Sopenharmony_civoid print_objectid_map(struct super_block *s); 321362306a36Sopenharmony_civoid print_block_head(struct buffer_head *bh, char *mes); 321462306a36Sopenharmony_civoid check_leaf(struct buffer_head *bh); 321562306a36Sopenharmony_civoid check_internal(struct buffer_head *bh); 321662306a36Sopenharmony_civoid print_statistics(struct super_block *s); 321762306a36Sopenharmony_cichar *reiserfs_hashname(int code); 321862306a36Sopenharmony_ci 321962306a36Sopenharmony_ci/* lbalance.c */ 322062306a36Sopenharmony_ciint leaf_move_items(int shift_mode, struct tree_balance *tb, int mov_num, 322162306a36Sopenharmony_ci int mov_bytes, struct buffer_head *Snew); 322262306a36Sopenharmony_ciint leaf_shift_left(struct tree_balance *tb, int shift_num, int shift_bytes); 322362306a36Sopenharmony_ciint leaf_shift_right(struct tree_balance *tb, int shift_num, int shift_bytes); 322462306a36Sopenharmony_civoid leaf_delete_items(struct buffer_info *cur_bi, int last_first, int first, 322562306a36Sopenharmony_ci int del_num, int del_bytes); 322662306a36Sopenharmony_civoid leaf_insert_into_buf(struct buffer_info *bi, int before, 322762306a36Sopenharmony_ci struct item_head * const inserted_item_ih, 322862306a36Sopenharmony_ci const char * const inserted_item_body, 322962306a36Sopenharmony_ci int zeros_number); 323062306a36Sopenharmony_civoid leaf_paste_in_buffer(struct buffer_info *bi, int pasted_item_num, 323162306a36Sopenharmony_ci int pos_in_item, int paste_size, 323262306a36Sopenharmony_ci const char * const body, int zeros_number); 323362306a36Sopenharmony_civoid leaf_cut_from_buffer(struct buffer_info *bi, int cut_item_num, 323462306a36Sopenharmony_ci int pos_in_item, int cut_size); 323562306a36Sopenharmony_civoid leaf_paste_entries(struct buffer_info *bi, int item_num, int before, 323662306a36Sopenharmony_ci int new_entry_count, struct reiserfs_de_head *new_dehs, 323762306a36Sopenharmony_ci const char *records, int paste_size); 323862306a36Sopenharmony_ci/* ibalance.c */ 323962306a36Sopenharmony_ciint balance_internal(struct tree_balance *, int, int, struct item_head *, 324062306a36Sopenharmony_ci struct buffer_head **); 324162306a36Sopenharmony_ci 324262306a36Sopenharmony_ci/* do_balance.c */ 324362306a36Sopenharmony_civoid do_balance_mark_leaf_dirty(struct tree_balance *tb, 324462306a36Sopenharmony_ci struct buffer_head *bh, int flag); 324562306a36Sopenharmony_ci#define do_balance_mark_internal_dirty do_balance_mark_leaf_dirty 324662306a36Sopenharmony_ci#define do_balance_mark_sb_dirty do_balance_mark_leaf_dirty 324762306a36Sopenharmony_ci 324862306a36Sopenharmony_civoid do_balance(struct tree_balance *tb, struct item_head *ih, 324962306a36Sopenharmony_ci const char *body, int flag); 325062306a36Sopenharmony_civoid reiserfs_invalidate_buffer(struct tree_balance *tb, 325162306a36Sopenharmony_ci struct buffer_head *bh); 325262306a36Sopenharmony_ci 325362306a36Sopenharmony_ciint get_left_neighbor_position(struct tree_balance *tb, int h); 325462306a36Sopenharmony_ciint get_right_neighbor_position(struct tree_balance *tb, int h); 325562306a36Sopenharmony_civoid replace_key(struct tree_balance *tb, struct buffer_head *, int, 325662306a36Sopenharmony_ci struct buffer_head *, int); 325762306a36Sopenharmony_civoid make_empty_node(struct buffer_info *); 325862306a36Sopenharmony_cistruct buffer_head *get_FEB(struct tree_balance *); 325962306a36Sopenharmony_ci 326062306a36Sopenharmony_ci/* bitmap.c */ 326162306a36Sopenharmony_ci 326262306a36Sopenharmony_ci/* 326362306a36Sopenharmony_ci * structure contains hints for block allocator, and it is a container for 326462306a36Sopenharmony_ci * arguments, such as node, search path, transaction_handle, etc. 326562306a36Sopenharmony_ci */ 326662306a36Sopenharmony_cistruct __reiserfs_blocknr_hint { 326762306a36Sopenharmony_ci /* inode passed to allocator, if we allocate unf. nodes */ 326862306a36Sopenharmony_ci struct inode *inode; 326962306a36Sopenharmony_ci 327062306a36Sopenharmony_ci sector_t block; /* file offset, in blocks */ 327162306a36Sopenharmony_ci struct in_core_key key; 327262306a36Sopenharmony_ci 327362306a36Sopenharmony_ci /* 327462306a36Sopenharmony_ci * search path, used by allocator to deternine search_start by 327562306a36Sopenharmony_ci * various ways 327662306a36Sopenharmony_ci */ 327762306a36Sopenharmony_ci struct treepath *path; 327862306a36Sopenharmony_ci 327962306a36Sopenharmony_ci /* 328062306a36Sopenharmony_ci * transaction handle is needed to log super blocks 328162306a36Sopenharmony_ci * and bitmap blocks changes 328262306a36Sopenharmony_ci */ 328362306a36Sopenharmony_ci struct reiserfs_transaction_handle *th; 328462306a36Sopenharmony_ci 328562306a36Sopenharmony_ci b_blocknr_t beg, end; 328662306a36Sopenharmony_ci 328762306a36Sopenharmony_ci /* 328862306a36Sopenharmony_ci * a field used to transfer search start value (block number) 328962306a36Sopenharmony_ci * between different block allocator procedures 329062306a36Sopenharmony_ci * (determine_search_start() and others) 329162306a36Sopenharmony_ci */ 329262306a36Sopenharmony_ci b_blocknr_t search_start; 329362306a36Sopenharmony_ci 329462306a36Sopenharmony_ci /* 329562306a36Sopenharmony_ci * is set in determine_prealloc_size() function, 329662306a36Sopenharmony_ci * used by underlayed function that do actual allocation 329762306a36Sopenharmony_ci */ 329862306a36Sopenharmony_ci int prealloc_size; 329962306a36Sopenharmony_ci 330062306a36Sopenharmony_ci /* 330162306a36Sopenharmony_ci * the allocator uses different polices for getting disk 330262306a36Sopenharmony_ci * space for formatted/unformatted blocks with/without preallocation 330362306a36Sopenharmony_ci */ 330462306a36Sopenharmony_ci unsigned formatted_node:1; 330562306a36Sopenharmony_ci unsigned preallocate:1; 330662306a36Sopenharmony_ci}; 330762306a36Sopenharmony_ci 330862306a36Sopenharmony_citypedef struct __reiserfs_blocknr_hint reiserfs_blocknr_hint_t; 330962306a36Sopenharmony_ci 331062306a36Sopenharmony_ciint reiserfs_parse_alloc_options(struct super_block *, char *); 331162306a36Sopenharmony_civoid reiserfs_init_alloc_options(struct super_block *s); 331262306a36Sopenharmony_ci 331362306a36Sopenharmony_ci/* 331462306a36Sopenharmony_ci * given a directory, this will tell you what packing locality 331562306a36Sopenharmony_ci * to use for a new object underneat it. The locality is returned 331662306a36Sopenharmony_ci * in disk byte order (le). 331762306a36Sopenharmony_ci */ 331862306a36Sopenharmony_ci__le32 reiserfs_choose_packing(struct inode *dir); 331962306a36Sopenharmony_ci 332062306a36Sopenharmony_civoid show_alloc_options(struct seq_file *seq, struct super_block *s); 332162306a36Sopenharmony_ciint reiserfs_init_bitmap_cache(struct super_block *sb); 332262306a36Sopenharmony_civoid reiserfs_free_bitmap_cache(struct super_block *sb); 332362306a36Sopenharmony_civoid reiserfs_cache_bitmap_metadata(struct super_block *sb, struct buffer_head *bh, struct reiserfs_bitmap_info *info); 332462306a36Sopenharmony_cistruct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, unsigned int bitmap); 332562306a36Sopenharmony_ciint is_reusable(struct super_block *s, b_blocknr_t block, int bit_value); 332662306a36Sopenharmony_civoid reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *, 332762306a36Sopenharmony_ci b_blocknr_t, int for_unformatted); 332862306a36Sopenharmony_ciint reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *, b_blocknr_t *, int, 332962306a36Sopenharmony_ci int); 333062306a36Sopenharmony_cistatic inline int reiserfs_new_form_blocknrs(struct tree_balance *tb, 333162306a36Sopenharmony_ci b_blocknr_t * new_blocknrs, 333262306a36Sopenharmony_ci int amount_needed) 333362306a36Sopenharmony_ci{ 333462306a36Sopenharmony_ci reiserfs_blocknr_hint_t hint = { 333562306a36Sopenharmony_ci .th = tb->transaction_handle, 333662306a36Sopenharmony_ci .path = tb->tb_path, 333762306a36Sopenharmony_ci .inode = NULL, 333862306a36Sopenharmony_ci .key = tb->key, 333962306a36Sopenharmony_ci .block = 0, 334062306a36Sopenharmony_ci .formatted_node = 1 334162306a36Sopenharmony_ci }; 334262306a36Sopenharmony_ci return reiserfs_allocate_blocknrs(&hint, new_blocknrs, amount_needed, 334362306a36Sopenharmony_ci 0); 334462306a36Sopenharmony_ci} 334562306a36Sopenharmony_ci 334662306a36Sopenharmony_cistatic inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle 334762306a36Sopenharmony_ci *th, struct inode *inode, 334862306a36Sopenharmony_ci b_blocknr_t * new_blocknrs, 334962306a36Sopenharmony_ci struct treepath *path, 335062306a36Sopenharmony_ci sector_t block) 335162306a36Sopenharmony_ci{ 335262306a36Sopenharmony_ci reiserfs_blocknr_hint_t hint = { 335362306a36Sopenharmony_ci .th = th, 335462306a36Sopenharmony_ci .path = path, 335562306a36Sopenharmony_ci .inode = inode, 335662306a36Sopenharmony_ci .block = block, 335762306a36Sopenharmony_ci .formatted_node = 0, 335862306a36Sopenharmony_ci .preallocate = 0 335962306a36Sopenharmony_ci }; 336062306a36Sopenharmony_ci return reiserfs_allocate_blocknrs(&hint, new_blocknrs, 1, 0); 336162306a36Sopenharmony_ci} 336262306a36Sopenharmony_ci 336362306a36Sopenharmony_ci#ifdef REISERFS_PREALLOCATE 336462306a36Sopenharmony_cistatic inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle 336562306a36Sopenharmony_ci *th, struct inode *inode, 336662306a36Sopenharmony_ci b_blocknr_t * new_blocknrs, 336762306a36Sopenharmony_ci struct treepath *path, 336862306a36Sopenharmony_ci sector_t block) 336962306a36Sopenharmony_ci{ 337062306a36Sopenharmony_ci reiserfs_blocknr_hint_t hint = { 337162306a36Sopenharmony_ci .th = th, 337262306a36Sopenharmony_ci .path = path, 337362306a36Sopenharmony_ci .inode = inode, 337462306a36Sopenharmony_ci .block = block, 337562306a36Sopenharmony_ci .formatted_node = 0, 337662306a36Sopenharmony_ci .preallocate = 1 337762306a36Sopenharmony_ci }; 337862306a36Sopenharmony_ci return reiserfs_allocate_blocknrs(&hint, new_blocknrs, 1, 0); 337962306a36Sopenharmony_ci} 338062306a36Sopenharmony_ci 338162306a36Sopenharmony_civoid reiserfs_discard_prealloc(struct reiserfs_transaction_handle *th, 338262306a36Sopenharmony_ci struct inode *inode); 338362306a36Sopenharmony_civoid reiserfs_discard_all_prealloc(struct reiserfs_transaction_handle *th); 338462306a36Sopenharmony_ci#endif 338562306a36Sopenharmony_ci 338662306a36Sopenharmony_ci/* hashes.c */ 338762306a36Sopenharmony_ci__u32 keyed_hash(const signed char *msg, int len); 338862306a36Sopenharmony_ci__u32 yura_hash(const signed char *msg, int len); 338962306a36Sopenharmony_ci__u32 r5_hash(const signed char *msg, int len); 339062306a36Sopenharmony_ci 339162306a36Sopenharmony_ci#define reiserfs_set_le_bit __set_bit_le 339262306a36Sopenharmony_ci#define reiserfs_test_and_set_le_bit __test_and_set_bit_le 339362306a36Sopenharmony_ci#define reiserfs_clear_le_bit __clear_bit_le 339462306a36Sopenharmony_ci#define reiserfs_test_and_clear_le_bit __test_and_clear_bit_le 339562306a36Sopenharmony_ci#define reiserfs_test_le_bit test_bit_le 339662306a36Sopenharmony_ci#define reiserfs_find_next_zero_le_bit find_next_zero_bit_le 339762306a36Sopenharmony_ci 339862306a36Sopenharmony_ci/* 339962306a36Sopenharmony_ci * sometimes reiserfs_truncate may require to allocate few new blocks 340062306a36Sopenharmony_ci * to perform indirect2direct conversion. People probably used to 340162306a36Sopenharmony_ci * think, that truncate should work without problems on a filesystem 340262306a36Sopenharmony_ci * without free disk space. They may complain that they can not 340362306a36Sopenharmony_ci * truncate due to lack of free disk space. This spare space allows us 340462306a36Sopenharmony_ci * to not worry about it. 500 is probably too much, but it should be 340562306a36Sopenharmony_ci * absolutely safe 340662306a36Sopenharmony_ci */ 340762306a36Sopenharmony_ci#define SPARE_SPACE 500 340862306a36Sopenharmony_ci 340962306a36Sopenharmony_ci/* prototypes from ioctl.c */ 341062306a36Sopenharmony_ciint reiserfs_fileattr_get(struct dentry *dentry, struct fileattr *fa); 341162306a36Sopenharmony_ciint reiserfs_fileattr_set(struct mnt_idmap *idmap, 341262306a36Sopenharmony_ci struct dentry *dentry, struct fileattr *fa); 341362306a36Sopenharmony_cilong reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); 341462306a36Sopenharmony_cilong reiserfs_compat_ioctl(struct file *filp, 341562306a36Sopenharmony_ci unsigned int cmd, unsigned long arg); 341662306a36Sopenharmony_ciint reiserfs_unpack(struct inode *inode); 3417