xfs_da_btree.h 12.0 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
3
 * Copyright (c) 2013 Red Hat, Inc.
4
 * All Rights Reserved.
L
Linus Torvalds 已提交
5
 *
6 7
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
L
Linus Torvalds 已提交
8 9
 * published by the Free Software Foundation.
 *
10 11 12 13
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
L
Linus Torvalds 已提交
14
 *
15 16 17
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
L
Linus Torvalds 已提交
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 */
#ifndef __XFS_DA_BTREE_H__
#define	__XFS_DA_BTREE_H__

struct xfs_bmap_free;
struct xfs_inode;
struct xfs_trans;
struct zone;

/*========================================================================
 * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
 *========================================================================*/

/*
 * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
 *
34
 * It is used to manage a doubly linked list of all blocks at the same
L
Linus Torvalds 已提交
35 36 37 38 39 40 41 42
 * level in the Btree, and to identify which type of block this is.
 */
#define XFS_DA_NODE_MAGIC	0xfebe	/* magic number: non-leaf blocks */
#define XFS_ATTR_LEAF_MAGIC	0xfbee	/* magic number: attribute leaf blks */
#define	XFS_DIR2_LEAF1_MAGIC	0xd2f1	/* magic number: v2 dirlf single blks */
#define	XFS_DIR2_LEAFN_MAGIC	0xd2ff	/* magic number: v2 dirlf multi blks */

typedef struct xfs_da_blkinfo {
43 44 45 46
	__be32		forw;			/* previous block in list */
	__be32		back;			/* following block in list */
	__be16		magic;			/* validity check on block */
	__be16		pad;			/* unused */
L
Linus Torvalds 已提交
47 48
} xfs_da_blkinfo_t;

49 50 51 52
/*
 * CRC enabled directory structure types
 *
 * The headers change size for the additional verification information, but
53 54 55
 * otherwise the tree layouts and contents are unchanged. Hence the da btree
 * code can use the struct xfs_da_blkinfo for manipulating the tree links and
 * magic numbers without modification for both v2 and v3 nodes.
56
 */
57
#define XFS_DA3_NODE_MAGIC	0x3ebe	/* magic number: non-leaf blocks */
D
Dave Chinner 已提交
58
#define XFS_ATTR3_LEAF_MAGIC	0x3bee	/* magic number: attribute leaf blks */
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
#define	XFS_DIR3_LEAF1_MAGIC	0x3df1	/* magic number: v2 dirlf single blks */
#define	XFS_DIR3_LEAFN_MAGIC	0x3dff	/* magic number: v2 dirlf multi blks */

struct xfs_da3_blkinfo {
	/*
	 * the node link manipulation code relies on the fact that the first
	 * element of this structure is the struct xfs_da_blkinfo so it can
	 * ignore the differences in the rest of the structures.
	 */
	struct xfs_da_blkinfo	hdr;
	__be32			crc;	/* CRC of block */
	__be64			blkno;	/* first block of the buffer */
	__be64			lsn;	/* sequence number of last write */
	uuid_t			uuid;	/* filesystem we belong to */
	__be64			owner;	/* inode that owns the block */
};

L
Linus Torvalds 已提交
76 77 78 79 80 81 82 83 84 85 86
/*
 * This is the structure of the root and intermediate nodes in the Btree.
 * The leaf nodes are defined above.
 *
 * Entries are not packed.
 *
 * Since we have duplicate keys, use a binary search but always follow
 * all match in the block, not just the first match found.
 */
#define	XFS_DA_NODE_MAXDEPTH	5	/* max depth of Btree */

87 88
typedef struct xfs_da_node_hdr {
	struct xfs_da_blkinfo	info;	/* block type, links, etc. */
D
Dave Chinner 已提交
89
	__be16			__count; /* count of active entries */
90 91 92 93 94
	__be16			__level; /* level above leaves (leaf == 0) */
} xfs_da_node_hdr_t;

struct xfs_da3_node_hdr {
	struct xfs_da3_blkinfo	info;	/* block type, links, etc. */
D
Dave Chinner 已提交
95
	__be16			__count; /* count of active entries */
96 97 98 99 100 101 102 103 104 105 106
	__be16			__level; /* level above leaves (leaf == 0) */
	__be32			__pad32;
};

#define XFS_DA3_NODE_CRC_OFF	(offsetof(struct xfs_da3_node_hdr, info.crc))

typedef struct xfs_da_node_entry {
	__be32	hashval;	/* hash value for this descendant */
	__be32	before;		/* Btree block before this key */
} xfs_da_node_entry_t;

L
Linus Torvalds 已提交
107
typedef struct xfs_da_intnode {
108 109
	struct xfs_da_node_hdr	hdr;
	struct xfs_da_node_entry __btree[];
L
Linus Torvalds 已提交
110
} xfs_da_intnode_t;
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

struct xfs_da3_intnode {
	struct xfs_da3_node_hdr	hdr;
	struct xfs_da_node_entry __btree[];
};

/*
 * In-core version of the node header to abstract the differences in the v2 and
 * v3 disk format of the headers. Callers need to convert to/from disk format as
 * appropriate.
 */
struct xfs_da3_icnode_hdr {
	__uint32_t	forw;
	__uint32_t	back;
	__uint16_t	magic;
	__uint16_t	count;
	__uint16_t	level;
};

extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to,
				       struct xfs_da_intnode *from);
extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to,
				     struct xfs_da3_icnode_hdr *from);

static inline int
xfs_da3_node_hdr_size(struct xfs_da_intnode *dap)
{
	if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC))
		return sizeof(struct xfs_da3_node_hdr);
	return sizeof(struct xfs_da_node_hdr);
}

static inline struct xfs_da_node_entry *
xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
{
	if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
		struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap;
		return dap3->__btree;
	}
	return dap->__btree;
}

extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to,
				      struct xfs_da_intnode *from);
extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to,
				    struct xfs_da3_icnode_hdr *from);
L
Linus Torvalds 已提交
157

158
#define	XFS_LBSIZE(mp)	(mp)->m_sb.sb_blocksize
L
Linus Torvalds 已提交
159 160 161 162 163

/*========================================================================
 * Btree searching and modification structure definitions.
 *========================================================================*/

164 165 166 167 168 169 170 171 172
/*
 * Search comparison results
 */
enum xfs_dacmp {
	XFS_CMP_DIFFERENT,	/* names are completely different */
	XFS_CMP_EXACT,		/* names are exactly the same */
	XFS_CMP_CASE		/* names are same but differ in case */
};

L
Linus Torvalds 已提交
173 174 175 176
/*
 * Structure to ease passing around component names.
 */
typedef struct xfs_da_args {
177
	const __uint8_t	*name;		/* string (maybe not NULL terminated) */
L
Linus Torvalds 已提交
178
	int		namelen;	/* length of string (maybe no NULL) */
179
	__uint8_t	filetype;	/* filetype of inode for directories */
180
	__uint8_t	*value;		/* set of bytes (maybe contain NULLs) */
L
Linus Torvalds 已提交
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
	int		valuelen;	/* length of value */
	int		flags;		/* argument flags (eg: ATTR_NOCREATE) */
	xfs_dahash_t	hashval;	/* hash value of name */
	xfs_ino_t	inumber;	/* input/output inode number */
	struct xfs_inode *dp;		/* directory inode to manipulate */
	xfs_fsblock_t	*firstblock;	/* ptr to firstblock for bmap calls */
	struct xfs_bmap_free *flist;	/* ptr to freelist for bmap_finish */
	struct xfs_trans *trans;	/* current trans (changes over time) */
	xfs_extlen_t	total;		/* total blocks needed, for 1st bmap */
	int		whichfork;	/* data or attribute fork */
	xfs_dablk_t	blkno;		/* blkno of attr leaf of interest */
	int		index;		/* index of attr of interest in blk */
	xfs_dablk_t	rmtblkno;	/* remote attr value starting blkno */
	int		rmtblkcnt;	/* remote attr value block count */
	xfs_dablk_t	blkno2;		/* blkno of 2nd attr leaf of interest */
	int		index2;		/* index of 2nd attr in blk */
	xfs_dablk_t	rmtblkno2;	/* remote attr value starting blkno */
	int		rmtblkcnt2;	/* remote attr value block count */
199
	int		op_flags;	/* operation flags */
200
	enum xfs_dacmp	cmpresult;	/* name compare result for lookups */
L
Linus Torvalds 已提交
201 202
} xfs_da_args_t;

203 204 205 206 207 208 209
/*
 * Operation flags:
 */
#define XFS_DA_OP_JUSTCHECK	0x0001	/* check for ok with no space */
#define XFS_DA_OP_RENAME	0x0002	/* this is an atomic rename op */
#define XFS_DA_OP_ADDNAME	0x0004	/* this is an add operation */
#define XFS_DA_OP_OKNOENT	0x0008	/* lookup/add op, ENOENT ok, else die */
210
#define XFS_DA_OP_CILOOKUP	0x0010	/* lookup to return CI name if found */
211

C
Christoph Hellwig 已提交
212 213 214 215 216 217 218
#define XFS_DA_OP_FLAGS \
	{ XFS_DA_OP_JUSTCHECK,	"JUSTCHECK" }, \
	{ XFS_DA_OP_RENAME,	"RENAME" }, \
	{ XFS_DA_OP_ADDNAME,	"ADDNAME" }, \
	{ XFS_DA_OP_OKNOENT,	"OKNOENT" }, \
	{ XFS_DA_OP_CILOOKUP,	"CILOOKUP" }

L
Linus Torvalds 已提交
219 220 221 222 223 224 225 226
/*
 * Storage for holding state during Btree searches and split/join ops.
 *
 * Only need space for 5 intermediate nodes.  With a minimum of 62-way
 * fanout to the Btree, we can support over 900 million directory blocks,
 * which is slightly more than enough.
 */
typedef struct xfs_da_state_blk {
227
	struct xfs_buf	*bp;		/* buffer containing block */
L
Linus Torvalds 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
	xfs_dablk_t	blkno;		/* filesystem blkno of buffer */
	xfs_daddr_t	disk_blkno;	/* on-disk blkno (in BBs) of buffer */
	int		index;		/* relevant index into block */
	xfs_dahash_t	hashval;	/* last hash value in block */
	int		magic;		/* blk's magic number, ie: blk type */
} xfs_da_state_blk_t;

typedef struct xfs_da_state_path {
	int			active;		/* number of active levels */
	xfs_da_state_blk_t	blk[XFS_DA_NODE_MAXDEPTH];
} xfs_da_state_path_t;

typedef struct xfs_da_state {
	xfs_da_args_t		*args;		/* filename arguments */
	struct xfs_mount	*mp;		/* filesystem mount point */
	unsigned int		blocksize;	/* logical block size */
	unsigned int		node_ents;	/* how many entries in danode */
	xfs_da_state_path_t	path;		/* search/split paths */
	xfs_da_state_path_t	altpath;	/* alternate path for join */
	unsigned char		inleaf;		/* insert into 1->lf, 0->splf */
	unsigned char		extravalid;	/* T/F: extrablk is in use */
	unsigned char		extraafter;	/* T/F: extrablk is after new */
M
Malcolm Parsons 已提交
250
	xfs_da_state_blk_t	extrablk;	/* for double-splits on leaves */
L
Linus Torvalds 已提交
251 252 253 254 255 256 257 258 259 260 261
						/* for dirv2 extrablk is data */
} xfs_da_state_t;

/*
 * Utility macros to aid in logging changed structure fields.
 */
#define XFS_DA_LOGOFF(BASE, ADDR)	((char *)(ADDR) - (char *)(BASE))
#define XFS_DA_LOGRANGE(BASE, ADDR, SIZE)	\
		(uint)(XFS_DA_LOGOFF(BASE, ADDR)), \
		(uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1)

262 263 264 265 266
/*
 * Name ops for directory and/or attr name operations
 */
struct xfs_nameops {
	xfs_dahash_t	(*hashname)(struct xfs_name *);
267 268
	enum xfs_dacmp	(*compname)(struct xfs_da_args *,
					const unsigned char *, int);
269 270
};

L
Linus Torvalds 已提交
271 272

/*========================================================================
273
 * Function prototypes.
L
Linus Torvalds 已提交
274 275 276 277 278
 *========================================================================*/

/*
 * Routines used for growing the Btree.
 */
279 280 281
int	xfs_da3_node_create(struct xfs_da_args *args, xfs_dablk_t blkno,
			    int level, struct xfs_buf **bpp, int whichfork);
int	xfs_da3_split(xfs_da_state_t *state);
L
Linus Torvalds 已提交
282 283 284 285

/*
 * Routines used for shrinking the Btree.
 */
286 287 288
int	xfs_da3_join(xfs_da_state_t *state);
void	xfs_da3_fixhashpath(struct xfs_da_state *state,
			    struct xfs_da_state_path *path_to_to_fix);
L
Linus Torvalds 已提交
289 290 291 292

/*
 * Routines used for finding things in the Btree.
 */
293 294
int	xfs_da3_node_lookup_int(xfs_da_state_t *state, int *result);
int	xfs_da3_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
L
Linus Torvalds 已提交
295 296 297 298
					 int forward, int release, int *result);
/*
 * Utility routines.
 */
299
int	xfs_da3_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
L
Linus Torvalds 已提交
300
				       xfs_da_state_blk_t *new_blk);
301
int	xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp,
D
Dave Chinner 已提交
302 303
			 xfs_dablk_t bno, xfs_daddr_t mappedbno,
			 struct xfs_buf **bpp, int which_fork);
L
Linus Torvalds 已提交
304

305 306
extern const struct xfs_buf_ops xfs_da3_node_buf_ops;

L
Linus Torvalds 已提交
307 308 309 310
/*
 * Utility routines.
 */
int	xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno);
311 312
int	xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno,
			      int count);
L
Linus Torvalds 已提交
313 314
int	xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp,
			      xfs_dablk_t bno, xfs_daddr_t mappedbno,
315
			      struct xfs_buf **bp, int whichfork);
L
Linus Torvalds 已提交
316 317
int	xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp,
			       xfs_dablk_t bno, xfs_daddr_t mappedbno,
318
			       struct xfs_buf **bpp, int whichfork,
319
			       const struct xfs_buf_ops *ops);
L
Linus Torvalds 已提交
320
xfs_daddr_t	xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp,
321
				xfs_dablk_t bno, xfs_daddr_t mapped_bno,
322
				int whichfork, const struct xfs_buf_ops *ops);
L
Linus Torvalds 已提交
323
int	xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
324
					  struct xfs_buf *dead_buf);
L
Linus Torvalds 已提交
325

326
uint xfs_da_hashname(const __uint8_t *name_string, int name_length);
327
enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args,
328
				const unsigned char *name, int len);
329 330


L
Linus Torvalds 已提交
331 332 333 334
xfs_da_state_t *xfs_da_state_alloc(void);
void xfs_da_state_free(xfs_da_state_t *state);

extern struct kmem_zone *xfs_da_state_zone;
335
extern const struct xfs_nameops xfs_default_nameops;
L
Linus Torvalds 已提交
336 337

#endif	/* __XFS_DA_BTREE_H__ */