1147476Sdumbbell/*-
2147476Sdumbbell * Copyright 2000 Hans Reiser
3147476Sdumbbell * See README for licensing and copyright details
4147476Sdumbbell *
5147476Sdumbbell * Ported to FreeBSD by Jean-S�bastien P�dron <jspedron@club-internet.fr>
6147476Sdumbbell *
7147476Sdumbbell * $FreeBSD$
8147476Sdumbbell */
9147476Sdumbbell
10147476Sdumbbell#ifndef _GNU_REISERFS_REISERFS_FS_H
11147476Sdumbbell#define	_GNU_REISERFS_REISERFS_FS_H
12147476Sdumbbell
13147476Sdumbbell#include <sys/cdefs.h>
14147476Sdumbbell#include <sys/types.h>
15147476Sdumbbell#include <sys/endian.h>
16147476Sdumbbell#include <sys/param.h>
17147476Sdumbbell#include <sys/systm.h>
18147476Sdumbbell#include <sys/kernel.h>
19147476Sdumbbell#include <sys/mount.h>
20147476Sdumbbell#include <sys/namei.h>
21164033Srwatson#include <sys/priv.h>
22147476Sdumbbell#include <sys/proc.h>
23147476Sdumbbell#include <sys/vnode.h>
24147476Sdumbbell#include <sys/unistd.h>
25147476Sdumbbell
26147476Sdumbbell#include <sys/bio.h>
27147476Sdumbbell#include <sys/buf.h>
28147476Sdumbbell#include <sys/conf.h>
29147476Sdumbbell#include <sys/fcntl.h>
30147476Sdumbbell#include <sys/syslog.h>
31147476Sdumbbell
32147476Sdumbbell#include <sys/malloc.h>
33147476Sdumbbell#include <sys/dirent.h>
34147476Sdumbbell#include <sys/stat.h>
35147476Sdumbbell//#include <sys/mutex.h>
36147476Sdumbbell
37147476Sdumbbell#include <sys/ctype.h>
38147476Sdumbbell#include <sys/bitstring.h>
39147476Sdumbbell
40147476Sdumbbell#include <geom/geom.h>
41147476Sdumbbell#include <geom/geom_vfs.h>
42147476Sdumbbell
43147476Sdumbbell#include <gnu/fs/reiserfs/reiserfs_mount.h>
44147476Sdumbbell#include <gnu/fs/reiserfs/reiserfs_fs_sb.h>
45147476Sdumbbell#include <gnu/fs/reiserfs/reiserfs_fs_i.h>
46147476Sdumbbell
47147476Sdumbbell/* n must be power of 2 */
48147476Sdumbbell#define	_ROUND_UP(x, n)	(((x) + (n) - 1u) & ~((n) - 1u))
49147476Sdumbbell
50147476Sdumbbell/* To be ok for alpha and others we have to align structures to 8 byte
51147476Sdumbbell * boundary. */
52147476Sdumbbell#define	ROUND_UP(x)	_ROUND_UP(x, 8LL)
53147476Sdumbbell
54147476Sdumbbell/* -------------------------------------------------------------------
55147476Sdumbbell * Global variables
56147476Sdumbbell * -------------------------------------------------------------------*/
57147476Sdumbbell
58147476Sdumbbellextern struct vop_vector reiserfs_vnodeops;
59147476Sdumbbellextern struct vop_vector reiserfs_specops;
60147476Sdumbbell
61147476Sdumbbell/* -------------------------------------------------------------------
62147476Sdumbbell * Super block
63147476Sdumbbell * -------------------------------------------------------------------*/
64147476Sdumbbell
65147476Sdumbbell#define	REISERFS_BSIZE 1024
66147476Sdumbbell
67147476Sdumbbell/* ReiserFS leaves the first 64k unused, so that partition labels have
68147476Sdumbbell * enough space. If someone wants to write a fancy bootloader that needs
69147476Sdumbbell * more than 64k, let us know, and this will be increased in size.
70147476Sdumbbell * This number must be larger than than the largest block size on any
71147476Sdumbbell * platform, or code will break. -Hans */
72147476Sdumbbell#define	REISERFS_DISK_OFFSET 64
73147476Sdumbbell#define	REISERFS_DISK_OFFSET_IN_BYTES                                        \
74147476Sdumbbell    ((REISERFS_DISK_OFFSET) * (REISERFS_BSIZE))
75147476Sdumbbell
76147476Sdumbbell/* The spot for the super in versions 3.5 - 3.5.10 (inclusive) */
77147476Sdumbbell#define	REISERFS_OLD_DISK_OFFSET 8
78147476Sdumbbell#define	REISERFS_OLD_DISK_OFFSET_IN_BYTES                                    \
79147476Sdumbbell    ((REISERFS_OLD_DISK_OFFSET) * (REISERFS_BSIZE))
80147476Sdumbbell
81147476Sdumbbell/*
82147476Sdumbbell * Structure of a super block on disk, a version of which in RAM is
83147476Sdumbbell * often accessed as REISERFS_SB(s)->r_rs. The version in RAM is part of
84147476Sdumbbell * a larger structure containing fields never written to disk.
85147476Sdumbbell */
86147476Sdumbbell
87147476Sdumbbell#define	UNSET_HASH	0 /* read_super will guess about, what hash names
88147476Sdumbbell			     in directories were sorted with */
89147476Sdumbbell#define	TEA_HASH	1
90147476Sdumbbell#define	YURA_HASH	2
91147476Sdumbbell#define	R5_HASH		3
92147476Sdumbbell#define	DEFAULT_HASH	R5_HASH
93147476Sdumbbell
94147476Sdumbbellstruct journal_params {
95147476Sdumbbell	uint32_t	jp_journal_1st_block;      /* Where does journal start
96147476Sdumbbell						      from on its device */
97147476Sdumbbell	uint32_t	jp_journal_dev;            /* Journal device st_rdev */
98147476Sdumbbell	uint32_t	jp_journal_size;           /* Size of the journal */
99147476Sdumbbell	uint32_t	jp_journal_trans_max;      /* Max number of blocks in
100147476Sdumbbell						      a transaction */
101147476Sdumbbell	uint32_t	jp_journal_magic;          /* Random value made on
102147476Sdumbbell						      fs creation (this was
103147476Sdumbbell						      sb_journal_block_count) */
104147476Sdumbbell	uint32_t	jp_journal_max_batch;      /* Max number of blocks to
105147476Sdumbbell						      batch into a
106147476Sdumbbell						      transaction */
107147476Sdumbbell	uint32_t	jp_journal_max_commit_age; /* In seconds, how old can
108147476Sdumbbell						      an async commit be */
109147476Sdumbbell	uint32_t	jp_journal_max_trans_age;  /* In seconds, how old a
110147476Sdumbbell						      transaction be */
111147476Sdumbbell};
112147476Sdumbbell
113147476Sdumbbellstruct reiserfs_super_block_v1 {
114147476Sdumbbell	uint32_t	s_block_count; /* Blocks count      */
115147476Sdumbbell	uint32_t	s_free_blocks; /* Free blocks count */
116147476Sdumbbell	uint32_t	s_root_block;  /* Root block number */
117147476Sdumbbell
118147476Sdumbbell	struct journal_params s_journal;
119147476Sdumbbell
120147476Sdumbbell	uint16_t	s_blocksize;
121147476Sdumbbell	uint16_t	s_oid_maxsize;
122147476Sdumbbell	uint16_t	s_oid_cursize;
123147476Sdumbbell	uint16_t	s_umount_state;
124147476Sdumbbell
125147476Sdumbbell	char 		s_magic[10];
126147476Sdumbbell
127147476Sdumbbell	uint16_t	s_fs_state;
128147476Sdumbbell	uint32_t	s_hash_function_code;
129147476Sdumbbell	uint16_t	s_tree_height;
130147476Sdumbbell	uint16_t	s_bmap_nr;
131147476Sdumbbell	uint16_t	s_version;
132147476Sdumbbell	uint16_t	s_reserved_for_journal;
133147476Sdumbbell} __packed;
134147476Sdumbbell
135147476Sdumbbell#define	SB_SIZE_V1 (sizeof(struct reiserfs_super_block_v1))
136147476Sdumbbell
137147476Sdumbbellstruct reiserfs_super_block {
138147476Sdumbbell	struct reiserfs_super_block_v1 s_v1;
139147476Sdumbbell	uint32_t	s_inode_generation;
140147476Sdumbbell	uint32_t	s_flags;
141147476Sdumbbell	unsigned char	s_uuid[16];
142147476Sdumbbell	unsigned char	s_label[16];
143147476Sdumbbell	char		s_unused[88];
144147476Sdumbbell} __packed;
145147476Sdumbbell
146147476Sdumbbell#define	SB_SIZE (sizeof(struct reiserfs_super_block))
147147476Sdumbbell
148147476Sdumbbell#define	REISERFS_VERSION_1	0
149147476Sdumbbell#define	REISERFS_VERSION_2	2
150147476Sdumbbell
151147476Sdumbbell#define	REISERFS_SB(sbi)		(sbi)
152147476Sdumbbell#define	SB_DISK_SUPER_BLOCK(sbi)	(REISERFS_SB(sbi)->s_rs)
153147476Sdumbbell#define	SB_V1_DISK_SUPER_BLOCK(sbi)	(&(SB_DISK_SUPER_BLOCK(sbi)->s_v1))
154147476Sdumbbell
155147476Sdumbbell#define	SB_BLOCKSIZE(sbi)						\
156147476Sdumbbell    le32toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_blocksize))
157147476Sdumbbell#define	SB_BLOCK_COUNT(sbi)						\
158147476Sdumbbell    le32toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_block_count))
159147476Sdumbbell#define	SB_FREE_BLOCKS(s)						\
160147476Sdumbbell    le32toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_free_blocks))
161147476Sdumbbell
162147476Sdumbbell#define	SB_REISERFS_MAGIC(sbi)						\
163147476Sdumbbell    (SB_V1_DISK_SUPER_BLOCK(sbi)->s_magic)
164147476Sdumbbell
165147476Sdumbbell#define	SB_ROOT_BLOCK(sbi)						\
166147476Sdumbbell    le32toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_root_block))
167147476Sdumbbell
168147476Sdumbbell#define	SB_TREE_HEIGHT(sbi)						\
169147476Sdumbbell    le16toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_tree_height))
170147476Sdumbbell
171147476Sdumbbell#define	SB_REISERFS_STATE(sbi)						\
172147476Sdumbbell    le16toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_umount_state))
173147476Sdumbbell
174147476Sdumbbell#define	SB_VERSION(sbi)	le16toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_version))
175147476Sdumbbell#define	SB_BMAP_NR(sbi)	le16toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_bmap_nr))
176147476Sdumbbell
177147476Sdumbbell#define	REISERFS_SUPER_MAGIC_STRING	"ReIsErFs"
178147476Sdumbbell#define	REISER2FS_SUPER_MAGIC_STRING	"ReIsEr2Fs"
179147476Sdumbbell#define	REISER2FS_JR_SUPER_MAGIC_STRING	"ReIsEr3Fs"
180147476Sdumbbell
181147476Sdumbbellextern const char reiserfs_3_5_magic_string[];
182147476Sdumbbellextern const char reiserfs_3_6_magic_string[];
183147476Sdumbbellextern const char reiserfs_jr_magic_string[];
184147476Sdumbbell
185147476Sdumbbellint	is_reiserfs_3_5(struct reiserfs_super_block *rs);
186147476Sdumbbellint	is_reiserfs_3_6(struct reiserfs_super_block *rs);
187147476Sdumbbellint	is_reiserfs_jr(struct reiserfs_super_block *rs);
188147476Sdumbbell
189147476Sdumbbell/* ReiserFS internal error code (used by search_by_key and fix_nodes) */
190147476Sdumbbell#define	IO_ERROR	-2
191147476Sdumbbell
192147476Sdumbbelltypedef uint32_t b_blocknr_t;
193147476Sdumbbelltypedef uint32_t unp_t;
194147476Sdumbbell
195147476Sdumbbellstruct unfm_nodeinfo {
196147476Sdumbbell	unp_t		unfm_nodenum;
197147476Sdumbbell	unsigned short	unfm_freespace;
198147476Sdumbbell};
199147476Sdumbbell
200147476Sdumbbell/* There are two formats of keys: 3.5 and 3.6 */
201147476Sdumbbell#define	KEY_FORMAT_3_5	0
202147476Sdumbbell#define	KEY_FORMAT_3_6	1
203147476Sdumbbell
204147476Sdumbbell/* There are two stat datas */
205147476Sdumbbell#define	STAT_DATA_V1	0
206147476Sdumbbell#define	STAT_DATA_V2	1
207147476Sdumbbell
208147476Sdumbbell#define	REISERFS_I(ip)	(ip)
209147476Sdumbbell
210147476Sdumbbell#define	get_inode_item_key_version(ip)					\
211147476Sdumbbell    ((REISERFS_I(ip)->i_flags & i_item_key_version_mask) ?		\
212147476Sdumbbell     KEY_FORMAT_3_6 : KEY_FORMAT_3_5)
213147476Sdumbbell
214147476Sdumbbell#define	set_inode_item_key_version(ip, version) ({			\
215147476Sdumbbell	if ((version) == KEY_FORMAT_3_6)				\
216147476Sdumbbell    		REISERFS_I(ip)->i_flags |= i_item_key_version_mask;	\
217147476Sdumbbell    	else								\
218147476Sdumbbell    		REISERFS_I(ip)->i_flags &= ~i_item_key_version_mask;	\
219147476Sdumbbell})
220147476Sdumbbell
221147476Sdumbbell#define	get_inode_sd_version(ip)					\
222147476Sdumbbell    ((REISERFS_I(ip)->i_flags & i_stat_data_version_mask) ?		\
223147476Sdumbbell     STAT_DATA_V2 : STAT_DATA_V1)
224147476Sdumbbell
225147476Sdumbbell#define	set_inode_sd_version(inode, version) ({				\
226147476Sdumbbell	if((version) == STAT_DATA_V2)					\
227147476Sdumbbell		REISERFS_I(ip)->i_flags |= i_stat_data_version_mask;	\
228147476Sdumbbell	else								\
229147476Sdumbbell		REISERFS_I(ip)->i_flags &= ~i_stat_data_version_mask;	\
230147476Sdumbbell})
231147476Sdumbbell
232147476Sdumbbell/* Values for s_umount_state field */
233147476Sdumbbell#define	REISERFS_VALID_FS	1
234147476Sdumbbell#define	REISERFS_ERROR_FS	2
235147476Sdumbbell
236147476Sdumbbell/* There are 5 item types currently */
237147476Sdumbbell#define	TYPE_STAT_DATA		0
238147476Sdumbbell#define	TYPE_INDIRECT		1
239147476Sdumbbell#define	TYPE_DIRECT		2
240147476Sdumbbell#define	TYPE_DIRENTRY		3
241147476Sdumbbell#define	TYPE_MAXTYPE		3
242147476Sdumbbell#define	TYPE_ANY		15
243147476Sdumbbell
244147476Sdumbbell/* -------------------------------------------------------------------
245147476Sdumbbell * Key & item head
246147476Sdumbbell * -------------------------------------------------------------------*/
247147476Sdumbbell
248147476Sdumbbellstruct offset_v1 {
249147476Sdumbbell	uint32_t	k_offset;
250147476Sdumbbell	uint32_t	k_uniqueness;
251147476Sdumbbell} __packed;
252147476Sdumbbell
253147476Sdumbbellstruct offset_v2 {
254147476Sdumbbell#if BYTE_ORDER == LITTLE_ENDIAN
255147476Sdumbbell	/* little endian version */
256147476Sdumbbell	uint64_t	k_offset:60;
257147476Sdumbbell	uint64_t	k_type:4;
258147476Sdumbbell#else
259147476Sdumbbell	/* big endian version */
260147476Sdumbbell	uint64_t	k_type:4;
261147476Sdumbbell	uint64_t	k_offset:60;
262147476Sdumbbell#endif
263147476Sdumbbell} __packed;
264147476Sdumbbell
265147476Sdumbbell#if (BYTE_ORDER == BIG_ENDIAN)
266147476Sdumbbelltypedef union {
267147476Sdumbbell	struct offset_v2	offset_v2;
268147476Sdumbbell	uint64_t		linear;
269147476Sdumbbell} __packed offset_v2_esafe_overlay;
270147476Sdumbbell
271147476Sdumbbellstatic inline uint16_t
272147476Sdumbbelloffset_v2_k_type(const struct offset_v2 *v2)
273147476Sdumbbell{
274147476Sdumbbell
275147476Sdumbbell	offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
276147476Sdumbbell	tmp.linear = le64toh(tmp.linear);
277147476Sdumbbell	return ((tmp.offset_v2.k_type <= TYPE_MAXTYPE) ?
278147476Sdumbbell	    tmp.offset_v2.k_type : TYPE_ANY);
279147476Sdumbbell}
280147476Sdumbbell
281147476Sdumbbellstatic inline void
282147476Sdumbbellset_offset_v2_k_type(struct offset_v2 *v2, int type)
283147476Sdumbbell{
284147476Sdumbbell
285147476Sdumbbell	offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2;
286147476Sdumbbell	tmp->linear = le64toh(tmp->linear);
287147476Sdumbbell	tmp->offset_v2.k_type = type;
288147476Sdumbbell	tmp->linear = htole64(tmp->linear);
289147476Sdumbbell}
290147476Sdumbbell
291147476Sdumbbellstatic inline off_t
292147476Sdumbbelloffset_v2_k_offset(const struct offset_v2 *v2)
293147476Sdumbbell{
294147476Sdumbbell
295147476Sdumbbell	offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
296147476Sdumbbell	tmp.linear = le64toh(tmp.linear);
297147476Sdumbbell	return (tmp.offset_v2.k_offset);
298147476Sdumbbell}
299147476Sdumbbell
300147476Sdumbbellstatic inline void
301147476Sdumbbellset_offset_v2_k_offset(struct offset_v2 *v2, off_t offset)
302147476Sdumbbell{
303147476Sdumbbell
304147476Sdumbbell	offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2;
305147476Sdumbbell	tmp->linear = le64toh(tmp->linear);
306147476Sdumbbell	tmp->offset_v2.k_offset = offset;
307147476Sdumbbell	tmp->linear = htole64(tmp->linear);
308147476Sdumbbell}
309147476Sdumbbell#else /* BYTE_ORDER != BIG_ENDIAN */
310147476Sdumbbell#define	offset_v2_k_type(v2)		((v2)->k_type)
311147476Sdumbbell#define	set_offset_v2_k_type(v2, val)	(offset_v2_k_type(v2) = (val))
312147476Sdumbbell#define	offset_v2_k_offset(v2)		((v2)->k_offset)
313147476Sdumbbell#define	set_offset_v2_k_offset(v2, val)	(offset_v2_k_offset(v2) = (val))
314147476Sdumbbell#endif /* BYTE_ORDER == BIG_ENDIAN */
315147476Sdumbbell
316147476Sdumbbell/*
317147476Sdumbbell * Key of an item determines its location in the S+tree, and
318147476Sdumbbell * is composed of 4 components
319147476Sdumbbell */
320147476Sdumbbellstruct key {
321147476Sdumbbell	uint32_t	k_dir_id;    /* Packing locality: by default parent
322147476Sdumbbell					directory object id */
323147476Sdumbbell	uint32_t	k_objectid;  /* Object identifier */
324147476Sdumbbell	union {
325147476Sdumbbell		struct offset_v1	k_offset_v1;
326147476Sdumbbell		struct offset_v2	k_offset_v2;
327147476Sdumbbell	} __packed u;
328147476Sdumbbell} __packed;
329147476Sdumbbell
330147476Sdumbbellstruct cpu_key {
331147476Sdumbbell	struct key	on_disk_key;
332147476Sdumbbell	int		version;
333147476Sdumbbell	int		key_length; /* 3 in all cases but direct2indirect
334147476Sdumbbell				       and indirect2direct conversion */
335147476Sdumbbell};
336147476Sdumbbell
337147476Sdumbbell/*
338147476Sdumbbell * Our function for comparing keys can compare keys of different
339147476Sdumbbell * lengths. It takes as a parameter the length of the keys it is to
340147476Sdumbbell * compare. These defines are used in determining what is to be passed
341147476Sdumbbell * to it as that parameter.
342147476Sdumbbell */
343147476Sdumbbell#define	REISERFS_FULL_KEY_LEN	4
344147476Sdumbbell#define	REISERFS_SHORT_KEY_LEN	2
345147476Sdumbbell
346147476Sdumbbell#define	KEY_SIZE	(sizeof(struct key))
347147476Sdumbbell#define	SHORT_KEY_SIZE	(sizeof(uint32_t) + sizeof(uint32_t))
348147476Sdumbbell
349147476Sdumbbell/* Return values for search_by_key and clones */
350147476Sdumbbell#define	ITEM_FOUND		 1
351147476Sdumbbell#define	ITEM_NOT_FOUND		 0
352147476Sdumbbell#define	ENTRY_FOUND		 1
353147476Sdumbbell#define	ENTRY_NOT_FOUND		 0
354147476Sdumbbell#define	DIRECTORY_NOT_FOUND	-1
355147476Sdumbbell#define	REGULAR_FILE_FOUND	-2
356147476Sdumbbell#define	DIRECTORY_FOUND		-3
357147476Sdumbbell#define	BYTE_FOUND		 1
358147476Sdumbbell#define	BYTE_NOT_FOUND		 0
359147476Sdumbbell#define	FILE_NOT_FOUND		-1
360147476Sdumbbell
361147476Sdumbbell#define	POSITION_FOUND		 1
362147476Sdumbbell#define	POSITION_NOT_FOUND	 0
363147476Sdumbbell
364147476Sdumbbell/* Return values for reiserfs_find_entry and search_by_entry_key */
365147476Sdumbbell#define	NAME_FOUND		1
366147476Sdumbbell#define	NAME_NOT_FOUND		0
367147476Sdumbbell#define	GOTO_PREVIOUS_ITEM	2
368147476Sdumbbell#define	NAME_FOUND_INVISIBLE	3
369147476Sdumbbell
370147476Sdumbbell/*
371147476Sdumbbell * Everything in the filesystem is stored as a set of items. The item
372147476Sdumbbell * head contains the key of the item, its free space (for indirect
373147476Sdumbbell * items) and specifies the location of the item itself within the
374147476Sdumbbell * block.
375147476Sdumbbell */
376147476Sdumbbellstruct item_head {
377147476Sdumbbell	/*
378147476Sdumbbell	 * Everything in the tree is found by searching for it based on
379147476Sdumbbell	 * its key.
380147476Sdumbbell	 */
381147476Sdumbbell	struct key	ih_key;
382147476Sdumbbell	union {
383147476Sdumbbell		/*
384147476Sdumbbell		 * The free space in the last unformatted node of an
385147476Sdumbbell		 * indirect item if this is an indirect item. This
386147476Sdumbbell		 * equals 0xFFFF iff this is a direct item or stat data
387147476Sdumbbell		 * item. Note that the key, not this field, is used to
388147476Sdumbbell		 * determine the item type, and thus which field this
389147476Sdumbbell		 * union contains.
390147476Sdumbbell		 */
391147476Sdumbbell		uint16_t	ih_free_space_reserved;
392147476Sdumbbell
393147476Sdumbbell		/*
394147476Sdumbbell		 * If this is a directory item, this field equals the number of
395147476Sdumbbell		 * directory entries in the directory item.
396147476Sdumbbell		 */
397147476Sdumbbell		uint16_t	ih_entry_count;
398147476Sdumbbell	} __packed u;
399147476Sdumbbell	uint16_t	ih_item_len;      /* Total size of the item body */
400147476Sdumbbell	uint16_t	ih_item_location; /* An offset to the item body within
401147476Sdumbbell					     the block */
402147476Sdumbbell	uint16_t	ih_version;       /* 0 for all old items, 2 for new
403147476Sdumbbell					     ones. Highest bit is set by fsck
404147476Sdumbbell					     temporary, cleaned after all
405147476Sdumbbell					     done */
406147476Sdumbbell} __packed;
407147476Sdumbbell
408147476Sdumbbell/* Size of item header */
409147476Sdumbbell#define	IH_SIZE (sizeof(struct item_head))
410147476Sdumbbell
411147476Sdumbbell#define	ih_free_space(ih)	le16toh((ih)->u.ih_free_space_reserved)
412147476Sdumbbell#define	ih_version(ih)		le16toh((ih)->ih_version)
413147476Sdumbbell#define	ih_entry_count(ih)	le16toh((ih)->u.ih_entry_count)
414147476Sdumbbell#define	ih_location(ih)		le16toh((ih)->ih_item_location)
415147476Sdumbbell#define	ih_item_len(ih)		le16toh((ih)->ih_item_len)
416147476Sdumbbell
417147476Sdumbbell/*
418147476Sdumbbell * These operate on indirect items, where you've got an array of ints at
419147476Sdumbbell * a possibly unaligned location. These are a noop on IA32.
420147476Sdumbbell *
421147476Sdumbbell * p is the array of uint32_t, i is the index into the array, v is the
422147476Sdumbbell * value to store there.
423147476Sdumbbell */
424147476Sdumbbell#define	get_unaligned(ptr)						\
425147476Sdumbbell    ({ __typeof__(*(ptr)) __tmp;					\
426147476Sdumbbell     memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
427147476Sdumbbell
428147476Sdumbbell#define	put_unaligned(val, ptr)						\
429147476Sdumbbell    ({ __typeof__(*(ptr)) __tmp = (val);				\
430147476Sdumbbell     memcpy((ptr), &__tmp, sizeof(*(ptr)));				\
431147476Sdumbbell     (void)0; })
432147476Sdumbbell
433147476Sdumbbell#define	get_block_num(p, i)	le32toh(get_unaligned((p) + (i)))
434147476Sdumbbell#define	put_block_num(p, i, v)	put_unaligned(htole32(v), (p) + (i))
435147476Sdumbbell
436147476Sdumbbell/* In old version uniqueness field shows key type */
437147476Sdumbbell#define	V1_SD_UNIQUENESS	0
438147476Sdumbbell#define	V1_INDIRECT_UNIQUENESS	0xfffffffe
439147476Sdumbbell#define	V1_DIRECT_UNIQUENESS	0xffffffff
440147476Sdumbbell#define	V1_DIRENTRY_UNIQUENESS	500
441147476Sdumbbell#define	V1_ANY_UNIQUENESS	555
442147476Sdumbbell
443147476Sdumbbell/* Here are conversion routines */
444147476Sdumbbellstatic inline int	uniqueness2type(uint32_t uniqueness);
445147476Sdumbbellstatic inline uint32_t	type2uniqueness(int type);
446147476Sdumbbell
447147476Sdumbbellstatic inline int
448147476Sdumbbelluniqueness2type(uint32_t uniqueness)
449147476Sdumbbell{
450147476Sdumbbell
451147476Sdumbbell	switch ((int)uniqueness) {
452147476Sdumbbell	case V1_SD_UNIQUENESS:
453147476Sdumbbell		return (TYPE_STAT_DATA);
454147476Sdumbbell	case V1_INDIRECT_UNIQUENESS:
455147476Sdumbbell		return (TYPE_INDIRECT);
456147476Sdumbbell	case V1_DIRECT_UNIQUENESS:
457147476Sdumbbell		return (TYPE_DIRECT);
458147476Sdumbbell	case V1_DIRENTRY_UNIQUENESS:
459147476Sdumbbell		return (TYPE_DIRENTRY);
460147476Sdumbbell	default:
461147476Sdumbbell		log(LOG_NOTICE, "reiserfs: unknown uniqueness (%u)\n",
462147476Sdumbbell		    uniqueness);
463147476Sdumbbell	case V1_ANY_UNIQUENESS:
464147476Sdumbbell		return (TYPE_ANY);
465147476Sdumbbell	}
466147476Sdumbbell}
467147476Sdumbbell
468147476Sdumbbellstatic inline uint32_t
469147476Sdumbbelltype2uniqueness(int type)
470147476Sdumbbell{
471147476Sdumbbell
472147476Sdumbbell	switch (type) {
473147476Sdumbbell	case TYPE_STAT_DATA:
474147476Sdumbbell		return (V1_SD_UNIQUENESS);
475147476Sdumbbell	case TYPE_INDIRECT:
476147476Sdumbbell		return (V1_INDIRECT_UNIQUENESS);
477147476Sdumbbell	case TYPE_DIRECT:
478147476Sdumbbell		return (V1_DIRECT_UNIQUENESS);
479147476Sdumbbell	case TYPE_DIRENTRY:
480147476Sdumbbell		return (V1_DIRENTRY_UNIQUENESS);
481147476Sdumbbell	default:
482147476Sdumbbell		log(LOG_NOTICE, "reiserfs: unknown type (%u)\n", type);
483147476Sdumbbell	case TYPE_ANY:
484147476Sdumbbell		return (V1_ANY_UNIQUENESS);
485147476Sdumbbell	}
486147476Sdumbbell}
487147476Sdumbbell
488147476Sdumbbell/*
489147476Sdumbbell * Key is pointer to on disk key which is stored in le, result is cpu,
490147476Sdumbbell * there is no way to get version of object from key, so, provide
491147476Sdumbbell * version to these defines.
492147476Sdumbbell */
493147476Sdumbbellstatic inline off_t
494147476Sdumbbellle_key_k_offset(int version, const struct key *key)
495147476Sdumbbell{
496147476Sdumbbell
497147476Sdumbbell	return ((version == KEY_FORMAT_3_5) ?
498147476Sdumbbell	    le32toh(key->u.k_offset_v1.k_offset) :
499147476Sdumbbell	    offset_v2_k_offset(&(key->u.k_offset_v2)));
500147476Sdumbbell}
501147476Sdumbbell
502147476Sdumbbellstatic inline off_t
503147476Sdumbbellle_ih_k_offset(const struct item_head *ih)
504147476Sdumbbell{
505147476Sdumbbell
506147476Sdumbbell	return (le_key_k_offset(ih_version(ih), &(ih->ih_key)));
507147476Sdumbbell}
508147476Sdumbbell
509147476Sdumbbellstatic inline off_t
510147476Sdumbbellle_key_k_type(int version, const struct key *key)
511147476Sdumbbell{
512147476Sdumbbell
513147476Sdumbbell	return ((version == KEY_FORMAT_3_5) ?
514147476Sdumbbell	    uniqueness2type(le32toh(key->u.k_offset_v1.k_uniqueness)) :
515147476Sdumbbell	    offset_v2_k_type(&(key->u.k_offset_v2)));
516147476Sdumbbell}
517147476Sdumbbell
518147476Sdumbbellstatic inline off_t
519147476Sdumbbellle_ih_k_type(const struct item_head *ih)
520147476Sdumbbell{
521147476Sdumbbell	return (le_key_k_type(ih_version(ih), &(ih->ih_key)));
522147476Sdumbbell}
523147476Sdumbbell
524147476Sdumbbellstatic inline void
525147476Sdumbbellset_le_key_k_offset(int version, struct key *key, off_t offset)
526147476Sdumbbell{
527147476Sdumbbell
528147476Sdumbbell	(version == KEY_FORMAT_3_5) ?
529147476Sdumbbell	    (key->u.k_offset_v1.k_offset = htole32(offset)) :
530147476Sdumbbell	    (set_offset_v2_k_offset(&(key->u.k_offset_v2), offset));
531147476Sdumbbell}
532147476Sdumbbell
533147476Sdumbbellstatic inline void
534147476Sdumbbellset_le_ih_k_offset(struct item_head *ih, off_t offset)
535147476Sdumbbell{
536147476Sdumbbell
537147476Sdumbbell	set_le_key_k_offset(ih_version(ih), &(ih->ih_key), offset);
538147476Sdumbbell}
539147476Sdumbbell
540147476Sdumbbellstatic inline void
541147476Sdumbbellset_le_key_k_type(int version, struct key *key, int type)
542147476Sdumbbell{
543147476Sdumbbell
544147476Sdumbbell	(version == KEY_FORMAT_3_5) ?
545147476Sdumbbell	    (key->u.k_offset_v1.k_uniqueness =
546147476Sdumbbell	     htole32(type2uniqueness(type))) :
547147476Sdumbbell	    (set_offset_v2_k_type(&(key->u.k_offset_v2), type));
548147476Sdumbbell}
549147476Sdumbbell
550147476Sdumbbellstatic inline void
551147476Sdumbbellset_le_ih_k_type(struct item_head *ih, int type)
552147476Sdumbbell{
553147476Sdumbbell
554147476Sdumbbell	set_le_key_k_type(ih_version(ih), &(ih->ih_key), type);
555147476Sdumbbell}
556147476Sdumbbell
557147476Sdumbbell#define	is_direntry_le_key(version, key)				\
558147476Sdumbbell    (le_key_k_type(version, key) == TYPE_DIRENTRY)
559147476Sdumbbell#define	is_direct_le_key(version, key)					\
560147476Sdumbbell    (le_key_k_type(version, key) == TYPE_DIRECT)
561147476Sdumbbell#define	is_indirect_le_key(version, key)				\
562147476Sdumbbell    (le_key_k_type(version, key) == TYPE_INDIRECT)
563147476Sdumbbell#define	is_statdata_le_key(version, key)				\
564147476Sdumbbell    (le_key_k_type(version, key) == TYPE_STAT_DATA)
565147476Sdumbbell
566147476Sdumbbell/* Item header has version. */
567147476Sdumbbell#define	is_direntry_le_ih(ih)						\
568147476Sdumbbell    is_direntry_le_key(ih_version(ih), &((ih)->ih_key))
569147476Sdumbbell#define	is_direct_le_ih(ih)						\
570147476Sdumbbell    is_direct_le_key(ih_version(ih), &((ih)->ih_key))
571147476Sdumbbell#define	is_indirect_le_ih(ih)						\
572147476Sdumbbell    is_indirect_le_key(ih_version(ih), &((ih)->ih_key))
573147476Sdumbbell#define	is_statdata_le_ih(ih)						\
574147476Sdumbbell    is_statdata_le_key(ih_version(ih), &((ih)->ih_key))
575147476Sdumbbell
576147476Sdumbbellstatic inline void
577147476Sdumbbellset_cpu_key_k_offset(struct cpu_key *key, off_t offset)
578147476Sdumbbell{
579147476Sdumbbell
580147476Sdumbbell	(key->version == KEY_FORMAT_3_5) ?
581147476Sdumbbell	    (key->on_disk_key.u.k_offset_v1.k_offset = offset) :
582147476Sdumbbell	    (key->on_disk_key.u.k_offset_v2.k_offset = offset);
583147476Sdumbbell}
584147476Sdumbbell
585147476Sdumbbellstatic inline void
586147476Sdumbbellset_cpu_key_k_type(struct cpu_key *key, int type)
587147476Sdumbbell{
588147476Sdumbbell
589147476Sdumbbell	(key->version == KEY_FORMAT_3_5) ?
590147476Sdumbbell	    (key->on_disk_key.u.k_offset_v1.k_uniqueness =
591147476Sdumbbell	     type2uniqueness(type)):
592147476Sdumbbell	    (key->on_disk_key.u.k_offset_v2.k_type = type);
593147476Sdumbbell}
594147476Sdumbbell
595147476Sdumbbell#define	is_direntry_cpu_key(key)	(cpu_key_k_type (key) == TYPE_DIRENTRY)
596147476Sdumbbell#define	is_direct_cpu_key(key)		(cpu_key_k_type (key) == TYPE_DIRECT)
597147476Sdumbbell#define	is_indirect_cpu_key(key)	(cpu_key_k_type (key) == TYPE_INDIRECT)
598147476Sdumbbell#define	is_statdata_cpu_key(key)	(cpu_key_k_type (key) == TYPE_STAT_DATA)
599147476Sdumbbell
600147476Sdumbbell/* Maximal length of item */
601147476Sdumbbell#define	MAX_ITEM_LEN(block_size)	(block_size - BLKH_SIZE - IH_SIZE)
602147476Sdumbbell#define	MIN_ITEM_LEN			1
603147476Sdumbbell
604147476Sdumbbell/* Object identifier for root dir */
605147476Sdumbbell#define	REISERFS_ROOT_OBJECTID		2
606147476Sdumbbell#define	REISERFS_ROOT_PARENT_OBJECTID	1
607147476Sdumbbell
608147476Sdumbbell/* key is pointer to cpu key, result is cpu */
609147476Sdumbbellstatic inline off_t
610147476Sdumbbellcpu_key_k_offset(const struct cpu_key *key)
611147476Sdumbbell{
612147476Sdumbbell
613147476Sdumbbell	return ((key->version == KEY_FORMAT_3_5) ?
614147476Sdumbbell	    key->on_disk_key.u.k_offset_v1.k_offset :
615147476Sdumbbell	    key->on_disk_key.u.k_offset_v2.k_offset);
616147476Sdumbbell}
617147476Sdumbbell
618147476Sdumbbellstatic inline off_t
619147476Sdumbbellcpu_key_k_type(const struct cpu_key *key)
620147476Sdumbbell{
621147476Sdumbbell
622147476Sdumbbell	return ((key->version == KEY_FORMAT_3_5) ?
623147476Sdumbbell	    uniqueness2type(key->on_disk_key.u.k_offset_v1.k_uniqueness) :
624147476Sdumbbell	    key->on_disk_key.u.k_offset_v2.k_type);
625147476Sdumbbell}
626147476Sdumbbell
627147476Sdumbbell/*
628147476Sdumbbell * Header of a disk block.  More precisely, header of a formatted leaf
629147476Sdumbbell * or internal node, and not the header of an unformatted node.
630147476Sdumbbell */
631147476Sdumbbellstruct block_head {
632147476Sdumbbell	uint16_t	blk_level;            /* Level of a block in the
633147476Sdumbbell						 tree. */
634147476Sdumbbell	uint16_t	blk_nr_item;          /* Number of keys/items in a
635147476Sdumbbell						 block. */
636147476Sdumbbell	uint16_t	blk_free_space;       /* Block free space in bytes. */
637147476Sdumbbell	uint16_t	blk_reserved;         /* Dump this in v4/planA */
638147476Sdumbbell	struct key	blk_right_delim_key;  /* Kept only for compatibility */
639147476Sdumbbell};
640147476Sdumbbell
641147476Sdumbbell#define	BLKH_SIZE		(sizeof(struct block_head))
642147476Sdumbbell#define	blkh_level(p_blkh)	(le16toh((p_blkh)->blk_level))
643147476Sdumbbell#define	blkh_nr_item(p_blkh)	(le16toh((p_blkh)->blk_nr_item))
644147476Sdumbbell#define	blkh_free_space(p_blkh)	(le16toh((p_blkh)->blk_free_space))
645147476Sdumbbell
646147476Sdumbbell#define	FREE_LEVEL	0 /* When node gets removed from the tree its
647147476Sdumbbell			     blk_level is set to FREE_LEVEL. It is then
648147476Sdumbbell			     used to see whether the node is still in the
649147476Sdumbbell			     tree */
650147476Sdumbbell
651147476Sdumbbell/* Values for blk_level field of the struct block_head */
652147476Sdumbbell#define	DISK_LEAF_NODE_LEVEL	1 /* Leaf node level.*/
653147476Sdumbbell
654147476Sdumbbell/*
655147476Sdumbbell * Given the buffer head of a formatted node, resolve to the block head
656147476Sdumbbell * of that node.
657147476Sdumbbell */
658147476Sdumbbell#define	B_BLK_HEAD(p_s_bp)	((struct block_head *)((p_s_bp)->b_data))
659147476Sdumbbell#define	B_NR_ITEMS(p_s_bp)	(blkh_nr_item(B_BLK_HEAD(p_s_bp)))
660147476Sdumbbell#define	B_LEVEL(p_s_bp)		(blkh_level(B_BLK_HEAD(p_s_bp)))
661147476Sdumbbell#define	B_FREE_SPACE(p_s_bp)	(blkh_free_space(B_BLK_HEAD(p_s_bp)))
662147476Sdumbbell
663147476Sdumbbell/* -------------------------------------------------------------------
664147476Sdumbbell * Stat data
665147476Sdumbbell * -------------------------------------------------------------------*/
666147476Sdumbbell
667147476Sdumbbell/*
668147476Sdumbbell * Old stat data is 32 bytes long. We are going to distinguish new one
669147476Sdumbbell * by different size.
670147476Sdumbbell */
671147476Sdumbbellstruct stat_data_v1 {
672147476Sdumbbell	uint16_t	sd_mode;  /* File type, permissions */
673147476Sdumbbell	uint16_t	sd_nlink; /* Number of hard links */
674147476Sdumbbell	uint16_t	sd_uid;   /* Owner */
675147476Sdumbbell	uint16_t	sd_gid;   /* Group */
676147476Sdumbbell	uint32_t	sd_size;  /* File size */
677147476Sdumbbell	uint32_t	sd_atime; /* Time of last access */
678147476Sdumbbell	uint32_t	sd_mtime; /* Time file was last modified  */
679147476Sdumbbell	uint32_t	sd_ctime; /* Time inode (stat data) was last changed
680147476Sdumbbell				     (except changes to sd_atime and
681147476Sdumbbell				     sd_mtime) */
682147476Sdumbbell	union {
683147476Sdumbbell		uint32_t 	sd_rdev;
684147476Sdumbbell		uint32_t	sd_blocks;  /* Number of blocks file uses */
685147476Sdumbbell	} __packed u;
686147476Sdumbbell	uint32_t	sd_first_direct_byte; /* First byte of file which is
687147476Sdumbbell						 stored in a direct item:
688147476Sdumbbell						 except that if it equals 1
689147476Sdumbbell						 it is a symlink and if it
690147476Sdumbbell						 equals ~(uint32_t)0 there
691147476Sdumbbell						 is no direct item. The
692147476Sdumbbell						 existence of this field
693147476Sdumbbell						 really grates on me. Let's
694147476Sdumbbell						 replace it with a macro based
695147476Sdumbbell						 on sd_size and our tail
696147476Sdumbbell						 suppression policy. Someday.
697147476Sdumbbell						 -Hans */
698147476Sdumbbell} __packed;
699147476Sdumbbell
700147476Sdumbbell#define	SD_V1_SIZE			(sizeof(struct stat_data_v1))
701147476Sdumbbell#define	stat_data_v1(ih)		(ih_version (ih) == KEY_FORMAT_3_5)
702147476Sdumbbell#define	sd_v1_mode(sdp)			(le16toh((sdp)->sd_mode))
703147476Sdumbbell#define	set_sd_v1_mode(sdp, v)		((sdp)->sd_mode = htole16(v))
704147476Sdumbbell#define	sd_v1_nlink(sdp)		(le16toh((sdp)->sd_nlink))
705147476Sdumbbell#define	set_sd_v1_nlink(sdp, v)		((sdp)->sd_nlink = htole16(v))
706147476Sdumbbell#define	sd_v1_uid(sdp)			(le16toh((sdp)->sd_uid))
707147476Sdumbbell#define	set_sd_v1_uid(sdp, v)		((sdp)->sd_uid = htole16(v))
708147476Sdumbbell#define	sd_v1_gid(sdp)			(le16toh((sdp)->sd_gid))
709147476Sdumbbell#define	set_sd_v1_gid(sdp, v)		((sdp)->sd_gid = htole16(v))
710147476Sdumbbell#define	sd_v1_size(sdp)			(le32toh((sdp)->sd_size))
711147476Sdumbbell#define	set_sd_v1_size(sdp, v)		((sdp)->sd_size = htole32(v))
712147476Sdumbbell#define	sd_v1_atime(sdp)		(le32toh((sdp)->sd_atime))
713147476Sdumbbell#define	set_sd_v1_atime(sdp, v)		((sdp)->sd_atime = htole32(v))
714147476Sdumbbell#define	sd_v1_mtime(sdp)		(le32toh((sdp)->sd_mtime))
715147476Sdumbbell#define	set_sd_v1_mtime(sdp, v)		((sdp)->sd_mtime = htole32(v))
716147476Sdumbbell#define	sd_v1_ctime(sdp)		(le32toh((sdp)->sd_ctime))
717147476Sdumbbell#define	set_sd_v1_ctime(sdp, v)		((sdp)->sd_ctime = htole32(v))
718147476Sdumbbell#define	sd_v1_rdev(sdp)			(le32toh((sdp)->u.sd_rdev))
719147476Sdumbbell#define	set_sd_v1_rdev(sdp, v)		((sdp)->u.sd_rdev = htole32(v))
720147476Sdumbbell#define	sd_v1_blocks(sdp)		(le32toh((sdp)->u.sd_blocks))
721147476Sdumbbell#define	set_sd_v1_blocks(sdp, v)	((sdp)->u.sd_blocks = htole32(v))
722147476Sdumbbell#define	sd_v1_first_direct_byte(sdp)					\
723147476Sdumbbell    (le32toh((sdp)->sd_first_direct_byte))
724147476Sdumbbell#define	set_sd_v1_first_direct_byte(sdp, v)				\
725147476Sdumbbell    ((sdp)->sd_first_direct_byte = htole32(v))
726147476Sdumbbell
727147476Sdumbbell/*
728147476Sdumbbell * We want common flags to have the same values as in ext2,
729147476Sdumbbell * so chattr(1) will work without problems
730147476Sdumbbell */
731202283Slulf#include <fs/ext2fs/ext2fs.h>
732202283Slulf#include <fs/ext2fs/ext2_dinode.h>
733202283Slulf#define	REISERFS_IMMUTABLE_FL	EXT2_IMMUTABLE
734202283Slulf#define	REISERFS_APPEND_FL	EXT2_APPEND
735202283Slulf#define	REISERFS_SYNC_FL	EXT2_SYNC
736202283Slulf#define	REISERFS_NOATIME_FL	EXT2_NOATIME
737202283Slulf#define	REISERFS_NODUMP_FL	EXT2_NODUMP
738202283Slulf#define	REISERFS_SECRM_FL	EXT2_SECRM
739202283Slulf#define	REISERFS_UNRM_FL	EXT2_UNRM
740202283Slulf#define	REISERFS_COMPR_FL	EXT2_COMPR
741147476Sdumbbell#define	REISERFS_NOTAIL_FL	EXT2_NOTAIL_FL
742147476Sdumbbell
743147476Sdumbbell/*
744147476Sdumbbell * Stat Data on disk (reiserfs version of UFS disk inode minus the
745147476Sdumbbell * address blocks)
746147476Sdumbbell */
747147476Sdumbbellstruct stat_data {
748147476Sdumbbell	uint16_t	sd_mode;  /* File type, permissions */
749147476Sdumbbell	uint16_t	sd_attrs; /* Persistent inode flags */
750147476Sdumbbell	uint32_t	sd_nlink; /* Number of hard links */
751147476Sdumbbell	uint64_t	sd_size;  /* File size */
752147476Sdumbbell	uint32_t	sd_uid;   /* Owner */
753147476Sdumbbell	uint32_t	sd_gid;   /* Group */
754147476Sdumbbell	uint32_t	sd_atime; /* Time of last access */
755147476Sdumbbell	uint32_t	sd_mtime; /* Time file was last modified  */
756147476Sdumbbell	uint32_t	sd_ctime; /* Time inode (stat data) was last changed
757147476Sdumbbell				     (except changes to sd_atime and
758147476Sdumbbell				     sd_mtime) */
759147476Sdumbbell	uint32_t	sd_blocks;
760147476Sdumbbell	union {
761147476Sdumbbell		uint32_t	sd_rdev;
762147476Sdumbbell		uint32_t	sd_generation;
763147476Sdumbbell		//uint32_t	sd_first_direct_byte;
764147476Sdumbbell		/*
765147476Sdumbbell		 * First byte of file which is stored in a
766147476Sdumbbell		 * direct item: except that if it equals 1
767147476Sdumbbell		 * it is a symlink and if it equals
768147476Sdumbbell		 * ~(uint32_t)0 there is no direct item.  The
769147476Sdumbbell		 * existence of this field really grates
770147476Sdumbbell		 * on me. Let's replace it with a macro
771147476Sdumbbell		 * based on sd_size and our tail
772147476Sdumbbell		 * suppression policy?
773147476Sdumbbell		 */
774147476Sdumbbell	} __packed u;
775147476Sdumbbell} __packed;
776147476Sdumbbell
777147476Sdumbbell/* This is 44 bytes long */
778147476Sdumbbell#define	SD_SIZE				(sizeof(struct stat_data))
779147476Sdumbbell#define	SD_V2_SIZE			SD_SIZE
780147476Sdumbbell#define	stat_data_v2(ih)		(ih_version (ih) == KEY_FORMAT_3_6)
781147476Sdumbbell#define	sd_v2_mode(sdp)			(le16toh((sdp)->sd_mode))
782147476Sdumbbell#define	set_sd_v2_mode(sdp, v)		((sdp)->sd_mode = htole16(v))
783147476Sdumbbell/* sd_reserved */
784147476Sdumbbell/* set_sd_reserved */
785147476Sdumbbell#define	sd_v2_nlink(sdp)		(le32toh((sdp)->sd_nlink))
786147476Sdumbbell#define	set_sd_v2_nlink(sdp, v)		((sdp)->sd_nlink = htole32(v))
787147476Sdumbbell#define	sd_v2_size(sdp)			(le64toh((sdp)->sd_size))
788147476Sdumbbell#define	set_sd_v2_size(sdp, v)		((sdp)->sd_size = cpu_to_le64(v))
789147476Sdumbbell#define	sd_v2_uid(sdp)			(le32toh((sdp)->sd_uid))
790147476Sdumbbell#define	set_sd_v2_uid(sdp, v)		((sdp)->sd_uid = htole32(v))
791147476Sdumbbell#define	sd_v2_gid(sdp)			(le32toh((sdp)->sd_gid))
792147476Sdumbbell#define	set_sd_v2_gid(sdp, v)		((sdp)->sd_gid = htole32(v))
793147476Sdumbbell#define	sd_v2_atime(sdp)		(le32toh((sdp)->sd_atime))
794147476Sdumbbell#define	set_sd_v2_atime(sdp, v)		((sdp)->sd_atime = htole32(v))
795147476Sdumbbell#define	sd_v2_mtime(sdp)		(le32toh((sdp)->sd_mtime))
796147476Sdumbbell#define	set_sd_v2_mtime(sdp, v)		((sdp)->sd_mtime = htole32(v))
797147476Sdumbbell#define	sd_v2_ctime(sdp)		(le32toh((sdp)->sd_ctime))
798147476Sdumbbell#define	set_sd_v2_ctime(sdp, v)		((sdp)->sd_ctime = htole32(v))
799147476Sdumbbell#define	sd_v2_blocks(sdp)		(le32toh((sdp)->sd_blocks))
800147476Sdumbbell#define	set_sd_v2_blocks(sdp, v)	((sdp)->sd_blocks = htole32(v))
801147476Sdumbbell#define	sd_v2_rdev(sdp)			(le32toh((sdp)->u.sd_rdev))
802147476Sdumbbell#define	set_sd_v2_rdev(sdp, v)		((sdp)->u.sd_rdev = htole32(v))
803147476Sdumbbell#define	sd_v2_generation(sdp)		(le32toh((sdp)->u.sd_generation))
804147476Sdumbbell#define	set_sd_v2_generation(sdp, v)	((sdp)->u.sd_generation = htole32(v))
805147476Sdumbbell#define	sd_v2_attrs(sdp)		(le16toh((sdp)->sd_attrs))
806147476Sdumbbell#define	set_sd_v2_attrs(sdp, v)		((sdp)->sd_attrs = htole16(v))
807147476Sdumbbell
808147476Sdumbbell/* -------------------------------------------------------------------
809147476Sdumbbell * Directory structure
810147476Sdumbbell * -------------------------------------------------------------------*/
811147476Sdumbbell
812147476Sdumbbell#define	SD_OFFSET		0
813147476Sdumbbell#define	SD_UNIQUENESS		0
814147476Sdumbbell#define	DOT_OFFSET		1
815147476Sdumbbell#define	DOT_DOT_OFFSET		2
816147476Sdumbbell#define	DIRENTRY_UNIQUENESS	500
817147476Sdumbbell
818147476Sdumbbell#define	FIRST_ITEM_OFFSET	1
819147476Sdumbbell
820147476Sdumbbellstruct reiserfs_de_head {
821147476Sdumbbell	uint32_t	deh_offset;    /* Third component of the directory
822147476Sdumbbell					  entry key */
823147476Sdumbbell	uint32_t	deh_dir_id;    /* Objectid of the parent directory of
824147476Sdumbbell					  the object, that is referenced by
825147476Sdumbbell					  directory entry */
826147476Sdumbbell	uint32_t	deh_objectid;  /* Objectid of the object, that is
827147476Sdumbbell					  referenced by directory entry */
828147476Sdumbbell	uint16_t	deh_location;  /* Offset of name in the whole item */
829147476Sdumbbell	uint16_t	deh_state;     /* Whether 1) entry contains stat data
830147476Sdumbbell					  (for future), and 2) whether entry
831147476Sdumbbell					  is hidden (unlinked) */
832147476Sdumbbell} __packed;
833147476Sdumbbell
834147476Sdumbbell#define	DEH_SIZE			sizeof(struct reiserfs_de_head)
835147476Sdumbbell#define	deh_offset(p_deh)		(le32toh((p_deh)->deh_offset))
836147476Sdumbbell#define	deh_dir_id(p_deh)		(le32toh((p_deh)->deh_dir_id))
837147476Sdumbbell#define	deh_objectid(p_deh)		(le32toh((p_deh)->deh_objectid))
838147476Sdumbbell#define	deh_location(p_deh)		(le16toh((p_deh)->deh_location))
839147476Sdumbbell#define	deh_state(p_deh)		(le16toh((p_deh)->deh_state))
840147476Sdumbbell
841147476Sdumbbell#define	put_deh_offset(p_deh, v)	((p_deh)->deh_offset = htole32((v)))
842147476Sdumbbell#define	put_deh_dir_id(p_deh, v)	((p_deh)->deh_dir_id = htole32((v)))
843147476Sdumbbell#define	put_deh_objectid(p_deh, v)	((p_deh)->deh_objectid = htole32((v)))
844147476Sdumbbell#define	put_deh_location(p_deh, v)	((p_deh)->deh_location = htole16((v)))
845147476Sdumbbell#define	put_deh_state(p_deh, v)		((p_deh)->deh_state = htole16((v)))
846147476Sdumbbell
847147476Sdumbbell/* Empty directory contains two entries "." and ".." and their headers */
848147476Sdumbbell#define	EMPTY_DIR_SIZE							\
849147476Sdumbbell    (DEH_SIZE * 2 + ROUND_UP(strlen(".")) + ROUND_UP(strlen("..")))
850147476Sdumbbell
851147476Sdumbbell/* Old format directories have this size when empty */
852147476Sdumbbell#define	EMPTY_DIR_SIZE_V1	(DEH_SIZE * 2 + 3)
853147476Sdumbbell
854147476Sdumbbell#define	DEH_Statdata	0 /* Not used now */
855147476Sdumbbell#define	DEH_Visible	2
856147476Sdumbbell
857147512Sdumbbell/* Macro to map Linux' *_bit function to bitstring.h macros */
858147512Sdumbbell#define	set_bit(bit, name)		bit_set((bitstr_t *)name, bit)
859147512Sdumbbell#define	clear_bit(bit, name)		bit_clear((bitstr_t *)name, bit)
860147512Sdumbbell#define	test_bit(bit, name)		bit_test((bitstr_t *)name, bit)
861147476Sdumbbell
862147512Sdumbbell#define	set_bit_unaligned(bit, name)	set_bit(bit, name)
863147512Sdumbbell#define	clear_bit_unaligned(bit, name)	clear_bit(bit, name)
864147512Sdumbbell#define	test_bit_unaligned(bit, name)	test_bit(bit, name)
865147476Sdumbbell
866147476Sdumbbell#define	mark_de_with_sd(deh)						\
867147476Sdumbbell    set_bit_unaligned(DEH_Statdata, &((deh)->deh_state))
868147476Sdumbbell#define	mark_de_without_sd(deh)						\
869147476Sdumbbell    clear_bit_unaligned(DEH_Statdata, &((deh)->deh_state))
870147476Sdumbbell#define	mark_de_visible(deh)						\
871147476Sdumbbell    set_bit_unaligned (DEH_Visible, &((deh)->deh_state))
872147476Sdumbbell#define	mark_de_hidden(deh)						\
873147476Sdumbbell    clear_bit_unaligned (DEH_Visible, &((deh)->deh_state))
874147476Sdumbbell
875147476Sdumbbell#define	de_with_sd(deh)							\
876147476Sdumbbell    test_bit_unaligned(DEH_Statdata, &((deh)->deh_state))
877147476Sdumbbell#define	de_visible(deh)							\
878147476Sdumbbell    test_bit_unaligned(DEH_Visible, &((deh)->deh_state))
879147476Sdumbbell#define	de_hidden(deh)							\
880147476Sdumbbell    !test_bit_unaligned(DEH_Visible, &((deh)->deh_state))
881147476Sdumbbell
882147476Sdumbbell/* Two entries per block (at least) */
883147476Sdumbbell#define	REISERFS_MAX_NAME(block_size)	255
884147476Sdumbbell
885147476Sdumbbell/*
886147476Sdumbbell * This structure is used for operations on directory entries. It is not
887147476Sdumbbell * a disk structure. When reiserfs_find_entry or search_by_entry_key
888147476Sdumbbell * find directory entry, they return filled reiserfs_dir_entry structure
889147476Sdumbbell */
890147476Sdumbbellstruct reiserfs_dir_entry {
891147476Sdumbbell	struct buf *de_bp;
892147476Sdumbbell	int	 de_item_num;
893147476Sdumbbell	struct item_head *de_ih;
894147476Sdumbbell	int	 de_entry_num;
895147476Sdumbbell	struct reiserfs_de_head *de_deh;
896147476Sdumbbell	int	 de_entrylen;
897147476Sdumbbell	int	 de_namelen;
898147476Sdumbbell	char	*de_name;
899147476Sdumbbell	char	*de_gen_number_bit_string;
900147476Sdumbbell
901147476Sdumbbell	uint32_t de_dir_id;
902147476Sdumbbell	uint32_t de_objectid;
903147476Sdumbbell
904147476Sdumbbell	struct cpu_key de_entry_key;
905147476Sdumbbell};
906147476Sdumbbell
907147476Sdumbbell/* Pointer to file name, stored in entry */
908147476Sdumbbell#define	B_I_DEH_ENTRY_FILE_NAME(bp, ih, deh)				\
909147476Sdumbbell    (B_I_PITEM(bp, ih) + deh_location(deh))
910147476Sdumbbell
911147476Sdumbbell/* Length of name */
912147476Sdumbbell#define	I_DEH_N_ENTRY_FILE_NAME_LENGTH(ih, deh, entry_num)		\
913147476Sdumbbell    (I_DEH_N_ENTRY_LENGTH(ih, deh, entry_num) -				\
914147476Sdumbbell     (de_with_sd(deh) ? SD_SIZE : 0))
915147476Sdumbbell
916147476Sdumbbell/* Hash value occupies bits from 7 up to 30 */
917147476Sdumbbell#define	GET_HASH_VALUE(offset)		((offset) & 0x7fffff80LL)
918147476Sdumbbell
919147476Sdumbbell/* Generation number occupies 7 bits starting from 0 up to 6 */
920147476Sdumbbell#define	GET_GENERATION_NUMBER(offset)	((offset) & 0x7fLL)
921147476Sdumbbell#define	MAX_GENERATION_NUMBER		127
922147476Sdumbbell
923147476Sdumbbell/* Get item body */
924147476Sdumbbell#define	B_I_PITEM(bp, ih)	((bp)->b_data + ih_location(ih))
925147476Sdumbbell#define	B_I_DEH(bp, ih)		((struct reiserfs_de_head *)(B_I_PITEM(bp, ih)))
926147476Sdumbbell
927147476Sdumbbell/*
928147476Sdumbbell * Length of the directory entry in directory item. This define
929147476Sdumbbell * calculates length of i-th directory entry using directory entry
930147476Sdumbbell * locations from dir entry head. When it calculates length of 0-th
931147476Sdumbbell * directory entry, it uses length of whole item in place of entry
932147476Sdumbbell * location of the non-existent following entry in the calculation. See
933147476Sdumbbell * picture above.
934147476Sdumbbell */
935147476Sdumbbellstatic inline int
936147476Sdumbbellentry_length (const struct buf *bp, const struct item_head *ih,
937147476Sdumbbell    int pos_in_item)
938147476Sdumbbell{
939147476Sdumbbell	struct reiserfs_de_head *deh;
940147476Sdumbbell
941147476Sdumbbell	deh = B_I_DEH(bp, ih) + pos_in_item;
942147476Sdumbbell	if (pos_in_item)
943147476Sdumbbell		return (deh_location(deh - 1) - deh_location(deh));
944147476Sdumbbell
945147476Sdumbbell	return (ih_item_len(ih) - deh_location(deh));
946147476Sdumbbell}
947147476Sdumbbell
948147476Sdumbbell/*
949147476Sdumbbell * Number of entries in the directory item, depends on ENTRY_COUNT
950147476Sdumbbell * being at the start of directory dynamic data.
951147476Sdumbbell */
952147476Sdumbbell#define	I_ENTRY_COUNT(ih)	(ih_entry_count((ih)))
953147476Sdumbbell
954147476Sdumbbell/* -------------------------------------------------------------------
955147476Sdumbbell * Disk child
956147476Sdumbbell * -------------------------------------------------------------------*/
957147476Sdumbbell
958147476Sdumbbell/*
959147476Sdumbbell * Disk child pointer: The pointer from an internal node of the tree
960147476Sdumbbell * to a node that is on disk.
961147476Sdumbbell */
962147476Sdumbbellstruct disk_child {
963147476Sdumbbell	uint32_t	dc_block_number; /* Disk child's block number. */
964147476Sdumbbell	uint16_t	dc_size;         /* Disk child's used space. */
965147476Sdumbbell	uint16_t	dc_reserved;
966147476Sdumbbell};
967147476Sdumbbell
968147476Sdumbbell#define	DC_SIZE			(sizeof(struct disk_child))
969147476Sdumbbell#define	dc_block_number(dc_p)	(le32toh((dc_p)->dc_block_number))
970147476Sdumbbell#define	dc_size(dc_p)		(le16toh((dc_p)->dc_size))
971147476Sdumbbell#define	put_dc_block_number(dc_p, val)					\
972147476Sdumbbell    do { (dc_p)->dc_block_number = htole32(val); } while (0)
973147476Sdumbbell#define	put_dc_size(dc_p, val)						\
974147476Sdumbbell    do { (dc_p)->dc_size = htole16(val); } while (0)
975147476Sdumbbell
976147476Sdumbbell/* Get disk child by buffer header and position in the tree node. */
977147476Sdumbbell#define	B_N_CHILD(p_s_bp, n_pos)					\
978147476Sdumbbell    ((struct disk_child *)((p_s_bp)->b_data + BLKH_SIZE +		\
979147476Sdumbbell			   B_NR_ITEMS(p_s_bp) * KEY_SIZE +		\
980147476Sdumbbell			   DC_SIZE * (n_pos)))
981147476Sdumbbell
982147476Sdumbbell/* Get disk child number by buffer header and position in the tree node. */
983147476Sdumbbell#define	B_N_CHILD_NUM(p_s_bp, n_pos)					\
984147476Sdumbbell    (dc_block_number(B_N_CHILD(p_s_bp, n_pos)))
985147476Sdumbbell#define	PUT_B_N_CHILD_NUM(p_s_bp, n_pos, val)				\
986147476Sdumbbell    (put_dc_block_number(B_N_CHILD(p_s_bp, n_pos), val))
987147476Sdumbbell
988147476Sdumbbell/* -------------------------------------------------------------------
989147476Sdumbbell * Path structures and defines
990147476Sdumbbell * -------------------------------------------------------------------*/
991147476Sdumbbell
992147476Sdumbbellstruct path_element {
993147476Sdumbbell	struct buf	*pe_buffer;  /* Pointer to the buffer at the path in
994147476Sdumbbell					the tree. */
995147476Sdumbbell	int		pe_position; /* Position in the tree node which is
996147476Sdumbbell					placed in the buffer above. */
997147476Sdumbbell};
998147476Sdumbbell
999147476Sdumbbell#define	MAX_HEIGHT			5 /* Maximal height of a tree. Don't
1000147476Sdumbbell					     change this without changing
1001147476Sdumbbell					     JOURNAL_PER_BALANCE_CNT */
1002147476Sdumbbell#define	EXTENDED_MAX_HEIGHT		7 /* Must be equals MAX_HEIGHT +
1003147476Sdumbbell					     FIRST_PATH_ELEMENT_OFFSET */
1004147476Sdumbbell#define	FIRST_PATH_ELEMENT_OFFSET	2 /* Must be equal to at least 2. */
1005147476Sdumbbell#define	ILLEGAL_PATH_ELEMENT_OFFSET	1 /* Must be equal to
1006147476Sdumbbell					     FIRST_PATH_ELEMENT_OFFSET - 1 */
1007147476Sdumbbell#define	MAX_FEB_SIZE			6 /* This MUST be MAX_HEIGHT + 1.
1008147476Sdumbbell					     See about FEB below */
1009147476Sdumbbell
1010147476Sdumbbellstruct path {
1011147476Sdumbbell	/* Length of the array below. */
1012147476Sdumbbell	int	path_length;
1013147476Sdumbbell	/* Array of the path element */
1014147476Sdumbbell	struct path_element path_elements[EXTENDED_MAX_HEIGHT];
1015147476Sdumbbell	int	pos_in_item;
1016147476Sdumbbell};
1017147476Sdumbbell
1018147476Sdumbbell#define	pos_in_item(path)	((path)->pos_in_item)
1019147476Sdumbbell
1020153081Sru#ifdef __amd64__
1021153081Sru/* To workaround a bug in gcc. He generates a call to memset() which
1022153081Sru * is a inline function; this causes a compile time error. */
1023147476Sdumbbell#define	INITIALIZE_PATH(var)						\
1024153081Sru    struct path var;							\
1025153081Sru    bzero(&var, sizeof(var));						\
1026153081Sru    var.path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
1027153081Sru#else
1028153081Sru#define	INITIALIZE_PATH(var)						\
1029147476Sdumbbell    struct path var = { ILLEGAL_PATH_ELEMENT_OFFSET, }
1030153081Sru#endif
1031147476Sdumbbell
1032147476Sdumbbell/* Get path element by path and path position. */
1033147476Sdumbbell#define	PATH_OFFSET_PELEMENT(p_s_path, n_offset)			\
1034147476Sdumbbell    ((p_s_path)->path_elements + (n_offset))
1035147476Sdumbbell
1036147476Sdumbbell/* Get buffer header at the path by path and path position. */
1037147476Sdumbbell#define	PATH_OFFSET_PBUFFER(p_s_path, n_offset)				\
1038147476Sdumbbell    (PATH_OFFSET_PELEMENT(p_s_path, n_offset)->pe_buffer)
1039147476Sdumbbell
1040147476Sdumbbell/* Get position in the element at the path by path and path position. */
1041147476Sdumbbell#define	PATH_OFFSET_POSITION(p_s_path, n_offset)			\
1042147476Sdumbbell    (PATH_OFFSET_PELEMENT(p_s_path, n_offset)->pe_position)
1043147476Sdumbbell
1044147476Sdumbbell#define	PATH_PLAST_BUFFER(p_s_path)					\
1045147476Sdumbbell    (PATH_OFFSET_PBUFFER((p_s_path), (p_s_path)->path_length))
1046147476Sdumbbell
1047147476Sdumbbell#define	PATH_LAST_POSITION(p_s_path)					\
1048147476Sdumbbell    (PATH_OFFSET_POSITION((p_s_path), (p_s_path)->path_length))
1049147476Sdumbbell
1050147476Sdumbbell#define	PATH_PITEM_HEAD(p_s_path)					\
1051147476Sdumbbell    B_N_PITEM_HEAD(PATH_PLAST_BUFFER(p_s_path), PATH_LAST_POSITION(p_s_path))
1052147476Sdumbbell
1053147476Sdumbbell#define	get_last_bp(path)	PATH_PLAST_BUFFER(path)
1054147476Sdumbbell#define	get_ih(path)		PATH_PITEM_HEAD(path)
1055147476Sdumbbell
1056147476Sdumbbell/* -------------------------------------------------------------------
1057147476Sdumbbell * Misc.
1058147476Sdumbbell * -------------------------------------------------------------------*/
1059147476Sdumbbell
1060147476Sdumbbell/* Size of pointer to the unformatted node. */
1061147476Sdumbbell#define	UNFM_P_SIZE	(sizeof(unp_t))
1062147476Sdumbbell#define	UNFM_P_SHIFT	2
1063147476Sdumbbell
1064147476Sdumbbell/* In in-core inode key is stored on le form */
1065147476Sdumbbell#define	INODE_PKEY(ip)	((struct key *)(REISERFS_I(ip)->i_key))
1066147476Sdumbbell
1067147476Sdumbbell#define	MAX_UL_INT	0xffffffff
1068147476Sdumbbell#define	MAX_INT		0x7ffffff
1069147476Sdumbbell#define	MAX_US_INT	0xffff
1070147476Sdumbbell
1071147476Sdumbbell/* The purpose is to detect overflow of an unsigned short */
1072147476Sdumbbell#define	REISERFS_LINK_MAX	(MAX_US_INT - 1000)
1073147476Sdumbbell
1074147476Sdumbbell#define	fs_generation(sbi)	(REISERFS_SB(sbi)->s_generation_counter)
1075147476Sdumbbell#define	get_generation(sbi)	(fs_generation(sbi))
1076147476Sdumbbell
1077147476Sdumbbell#define	__fs_changed(gen, sbi)	(gen != get_generation (sbi))
1078147476Sdumbbell/*#define	fs_changed(gen, sbi)	({ cond_resched();		\
1079147476Sdumbbell    __fs_changed(gen, sbi); })*/
1080147476Sdumbbell#define	fs_changed(gen, sbi)	(__fs_changed(gen, sbi))
1081147476Sdumbbell
1082147476Sdumbbell/* -------------------------------------------------------------------
1083147476Sdumbbell * Fixate node
1084147476Sdumbbell * -------------------------------------------------------------------*/
1085147476Sdumbbell
1086147476Sdumbbell/*
1087147476Sdumbbell * To make any changes in the tree we always first find node, that
1088147476Sdumbbell * contains item to be changed/deleted or place to insert a new item.
1089147476Sdumbbell * We call this node S. To do balancing we need to decide what we will
1090147476Sdumbbell * shift to left/right neighbor, or to a new node, where new item will
1091147476Sdumbbell * be etc. To make this analysis simpler we build virtual node. Virtual
1092147476Sdumbbell * node is an array of items, that will replace items of node S. (For
1093147476Sdumbbell * instance if we are going to delete an item, virtual node does not
1094147476Sdumbbell * contain it). Virtual node keeps information about item sizes and
1095147476Sdumbbell * types, mergeability of first and last items, sizes of all entries in
1096147476Sdumbbell * directory item. We use this array of items when calculating what we
1097147476Sdumbbell * can shift to neighbors and how many nodes we have to have if we do
1098147476Sdumbbell * not any shiftings, if we shift to left/right neighbor or to both.
1099147476Sdumbbell */
1100147476Sdumbbellstruct virtual_item {
1101147476Sdumbbell	int			 vi_index;    /* Index in the array of item
1102147476Sdumbbell						 operations */
1103147476Sdumbbell	unsigned short		 vi_type;     /* Left/right mergeability */
1104147476Sdumbbell	unsigned short		 vi_item_len; /* Length of item that it will
1105147476Sdumbbell						 have after balancing */
1106147476Sdumbbell	struct item_head	*vi_ih;
1107147476Sdumbbell	const char		*vi_item;     /* Body of item (old or new) */
1108147476Sdumbbell	const void		*vi_new_data; /* 0 always but paste mode */
1109147476Sdumbbell	void			*vi_uarea;    /* Item specific area */
1110147476Sdumbbell};
1111147476Sdumbbell
1112147476Sdumbbellstruct virtual_node {
1113147476Sdumbbell	char		*vn_free_ptr; /* This is a pointer to the free space
1114147476Sdumbbell					 in the buffer */
1115147476Sdumbbell	unsigned short	 vn_nr_item;  /* Number of items in virtual node */
1116147476Sdumbbell	short		 vn_size;     /* Size of node , that node would have
1117147476Sdumbbell					 if it has unlimited size and no
1118147476Sdumbbell					 balancing is performed */
1119147476Sdumbbell	short		 vn_mode;     /* Mode of balancing (paste, insert,
1120147476Sdumbbell					 delete, cut) */
1121147476Sdumbbell	short		 vn_affected_item_num;
1122147476Sdumbbell	short		 vn_pos_in_item;
1123147476Sdumbbell	struct item_head *vn_ins_ih;  /* Item header of inserted item, 0 for
1124147476Sdumbbell					 other modes */
1125147476Sdumbbell	const void	*vn_data;
1126147476Sdumbbell	struct virtual_item *vn_vi;   /* Array of items (including a new one,
1127147476Sdumbbell					 excluding item to be deleted) */
1128147476Sdumbbell};
1129147476Sdumbbell
1130147476Sdumbbell/* Used by directory items when creating virtual nodes */
1131147476Sdumbbellstruct direntry_uarea {
1132147476Sdumbbell	int		flags;
1133147476Sdumbbell	uint16_t	entry_count;
1134147476Sdumbbell	uint16_t	entry_sizes[1];
1135147476Sdumbbell} __packed;
1136147476Sdumbbell
1137147476Sdumbbell/* -------------------------------------------------------------------
1138147476Sdumbbell * Tree balance
1139147476Sdumbbell * -------------------------------------------------------------------*/
1140147476Sdumbbell
1141147476Sdumbbellstruct reiserfs_iget_args {
1142147476Sdumbbell	uint32_t	objectid;
1143147476Sdumbbell	uint32_t	dirid;
1144147476Sdumbbell};
1145147476Sdumbbell
1146147476Sdumbbellstruct item_operations {
1147147476Sdumbbell	int	(*bytes_number)(struct item_head * ih, int block_size);
1148147476Sdumbbell	void	(*decrement_key)(struct cpu_key *);
1149147476Sdumbbell	int	(*is_left_mergeable)(struct key * ih, unsigned long bsize);
1150147476Sdumbbell	void	(*print_item)(struct item_head *, char * item);
1151147476Sdumbbell	void	(*check_item)(struct item_head *, char * item);
1152147476Sdumbbell
1153147476Sdumbbell	int	(*create_vi)(struct virtual_node * vn,
1154147476Sdumbbell	    struct virtual_item * vi, int is_affected, int insert_size);
1155147476Sdumbbell	int	(*check_left)(struct virtual_item * vi, int free,
1156147476Sdumbbell	    int start_skip, int end_skip);
1157147476Sdumbbell	int	(*check_right)(struct virtual_item * vi, int free);
1158147476Sdumbbell	int	(*part_size)(struct virtual_item * vi, int from, int to);
1159147476Sdumbbell	int	(*unit_num)(struct virtual_item * vi);
1160147476Sdumbbell	void	(*print_vi)(struct virtual_item * vi);
1161147476Sdumbbell};
1162147476Sdumbbell
1163147476Sdumbbellextern struct item_operations *item_ops[TYPE_ANY + 1];
1164147476Sdumbbell
1165147476Sdumbbell#define	op_bytes_number(ih, bsize)					\
1166147476Sdumbbell    item_ops[le_ih_k_type(ih)]->bytes_number(ih, bsize)
1167147476Sdumbbell
1168147476Sdumbbell#define	COMP_KEYS	comp_keys
1169147476Sdumbbell#define	COMP_SHORT_KEYS	comp_short_keys
1170147476Sdumbbell
1171147476Sdumbbell/* Get the item header */
1172147476Sdumbbell#define	B_N_PITEM_HEAD(bp, item_num)					\
1173147476Sdumbbell    ((struct item_head *)((bp)->b_data + BLKH_SIZE) + (item_num))
1174147476Sdumbbell
1175147476Sdumbbell/* Get key */
1176147476Sdumbbell#define	B_N_PDELIM_KEY(bp, item_num)					\
1177147476Sdumbbell    ((struct key *)((bp)->b_data + BLKH_SIZE) + (item_num))
1178147476Sdumbbell
1179147476Sdumbbell/* -------------------------------------------------------------------
1180147476Sdumbbell * Function declarations
1181147476Sdumbbell * -------------------------------------------------------------------*/
1182147476Sdumbbell
1183147476Sdumbbell/* reiserfs_stree.c */
1184147476Sdumbbellint	B_IS_IN_TREE(const struct buf *p_s_bp);
1185147476Sdumbbell
1186147476Sdumbbellextern void	copy_item_head(struct item_head * p_v_to,
1187147476Sdumbbell		    const struct item_head * p_v_from);
1188147476Sdumbbell
1189147476Sdumbbellextern int	comp_keys(const struct key *le_key,
1190147476Sdumbbell		    const struct cpu_key *cpu_key);
1191147476Sdumbbellextern int	comp_short_keys(const struct key *le_key,
1192147476Sdumbbell		    const struct cpu_key *cpu_key);
1193147476Sdumbbell
1194147476Sdumbbellextern int	comp_le_keys(const struct key *, const struct key *);
1195147476Sdumbbell
1196147476Sdumbbellstatic inline int
1197147476Sdumbbellle_key_version(const struct key *key)
1198147476Sdumbbell{
1199147476Sdumbbell	int type;
1200147476Sdumbbell
1201147476Sdumbbell	type = offset_v2_k_type(&(key->u.k_offset_v2));
1202147476Sdumbbell	if (type != TYPE_DIRECT && type != TYPE_INDIRECT &&
1203147476Sdumbbell	    type != TYPE_DIRENTRY)
1204147476Sdumbbell		return (KEY_FORMAT_3_5);
1205147476Sdumbbell
1206147476Sdumbbell	return (KEY_FORMAT_3_6);
1207147476Sdumbbell}
1208147476Sdumbbell
1209147476Sdumbbellstatic inline void
1210147476Sdumbbellcopy_key(struct key *to, const struct key *from)
1211147476Sdumbbell{
1212147476Sdumbbell
1213147476Sdumbbell	memcpy(to, from, KEY_SIZE);
1214147476Sdumbbell}
1215147476Sdumbbell
1216147476Sdumbbellconst struct key	*get_lkey(const struct path *p_s_chk_path,
1217147476Sdumbbell			    const struct reiserfs_sb_info *p_s_sbi);
1218147476Sdumbbellconst struct key	*get_rkey(const struct path *p_s_chk_path,
1219147476Sdumbbell			    const struct reiserfs_sb_info *p_s_sbi);
1220189525Sdasint	bin_search(const void * p_v_key, const void * p_v_base,
1221147476Sdumbbell		    int p_n_num, int p_n_width, int * p_n_pos);
1222147476Sdumbbell
1223147476Sdumbbellvoid	pathrelse(struct path *p_s_search_path);
1224147476Sdumbbellint	reiserfs_check_path(struct path *p);
1225147476Sdumbbell
1226147476Sdumbbellint	search_by_key(struct reiserfs_sb_info *p_s_sbi,
1227147476Sdumbbell	    const struct cpu_key *p_s_key,
1228147476Sdumbbell	    struct path *p_s_search_path,
1229147476Sdumbbell	    int n_stop_level);
1230147476Sdumbbell#define	search_item(sbi, key, path)					\
1231147476Sdumbbell    search_by_key(sbi, key, path, DISK_LEAF_NODE_LEVEL)
1232147476Sdumbbellint	search_for_position_by_key(struct reiserfs_sb_info *p_s_sbi,
1233147476Sdumbbell	    const struct cpu_key *p_s_cpu_key,
1234147476Sdumbbell	    struct path *p_s_search_path);
1235147476Sdumbbellvoid	decrement_counters_in_path(struct path *p_s_search_path);
1236147476Sdumbbell
1237147476Sdumbbell/* reiserfs_inode.c */
1238147476Sdumbbellvop_read_t	reiserfs_read;
1239147476Sdumbbellvop_inactive_t	reiserfs_inactive;
1240147476Sdumbbellvop_reclaim_t	reiserfs_reclaim;
1241147476Sdumbbell
1242147476Sdumbbellint	reiserfs_get_block(struct reiserfs_node *ip, long block,
1243147476Sdumbbell	    off_t offset, struct uio *uio);
1244147476Sdumbbell
1245147476Sdumbbellvoid	make_cpu_key(struct cpu_key *cpu_key, struct reiserfs_node *ip,
1246147476Sdumbbell	    off_t offset, int type, int key_length);
1247147476Sdumbbell
1248147476Sdumbbellvoid	reiserfs_read_locked_inode(struct reiserfs_node *ip,
1249147476Sdumbbell	    struct reiserfs_iget_args *args);
1250147476Sdumbbellint	reiserfs_iget(struct mount *mp, const struct cpu_key *key,
1251147476Sdumbbell	    struct vnode **vpp, struct thread *td);
1252147476Sdumbbell
1253147476Sdumbbellvoid	sd_attrs_to_i_attrs(uint16_t sd_attrs, struct reiserfs_node *ip);
1254147476Sdumbbellvoid	i_attrs_to_sd_attrs(struct reiserfs_node *ip, uint16_t *sd_attrs);
1255147476Sdumbbell
1256147476Sdumbbell/* reiserfs_namei.c */
1257147476Sdumbbellvop_readdir_t		reiserfs_readdir;
1258147476Sdumbbellvop_cachedlookup_t	reiserfs_lookup;
1259147476Sdumbbell
1260147476Sdumbbellvoid	set_de_name_and_namelen(struct reiserfs_dir_entry * de);
1261147476Sdumbbellint	search_by_entry_key(struct reiserfs_sb_info *sbi,
1262147476Sdumbbell	    const struct cpu_key *key, struct path *path,
1263147476Sdumbbell	    struct reiserfs_dir_entry *de);
1264147476Sdumbbell
1265147476Sdumbbell/* reiserfs_prints.c */
1266147476Sdumbbellchar	*reiserfs_hashname(int code);
1267147476Sdumbbellvoid	 reiserfs_dump_buffer(caddr_t buf, off_t len);
1268147476Sdumbbell
1269147476Sdumbbell#if defined(REISERFS_DEBUG)
1270147476Sdumbbell#define	reiserfs_log(lvl, fmt, ...)					\
1271147476Sdumbbell    log(lvl, "ReiserFS/%s: " fmt, __func__, ## __VA_ARGS__)
1272147476Sdumbbell#elif defined (REISERFS_DEBUG_CONS)
1273147476Sdumbbell#define	reiserfs_log(lvl, fmt, ...)					\
1274147476Sdumbbell    printf("%s:%d: " fmt, __func__, __LINE__, ## __VA_ARGS__)
1275147476Sdumbbell#else
1276147476Sdumbbell#define	reiserfs_log(lvl, fmt, ...)
1277147476Sdumbbell#endif
1278147476Sdumbbell
1279147476Sdumbbell#define	reiserfs_log_0(lvl, fmt, ...)					\
1280147476Sdumbbell    printf("%s:%d: " fmt, __func__, __LINE__, ## __VA_ARGS__)
1281147476Sdumbbell
1282147476Sdumbbell/* reiserfs_hashes.c */
1283147476Sdumbbelluint32_t	keyed_hash(const signed char *msg, int len);
1284147476Sdumbbelluint32_t	yura_hash(const signed char *msg, int len);
1285147476Sdumbbelluint32_t	r5_hash(const signed char *msg, int len);
1286147476Sdumbbell
1287147476Sdumbbell#define	reiserfs_test_le_bit  test_bit
1288147476Sdumbbell
1289147476Sdumbbell#endif /* !defined _GNU_REISERFS_REISERFS_FS_H */
1290