1  /* SPDX-License-Identifier: GPL-2.0 */
2  /*
3   * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4   * All Rights Reserved.
5   */
6  #ifndef __XFS_DIR2_H__
7  #define __XFS_DIR2_H__
8  
9  #include "xfs_da_format.h"
10  #include "xfs_da_btree.h"
11  
12  struct xfs_da_args;
13  struct xfs_inode;
14  struct xfs_mount;
15  struct xfs_trans;
16  struct xfs_dir2_sf_hdr;
17  struct xfs_dir2_sf_entry;
18  struct xfs_dir2_data_hdr;
19  struct xfs_dir2_data_entry;
20  struct xfs_dir2_data_unused;
21  struct xfs_dir3_icfree_hdr;
22  struct xfs_dir3_icleaf_hdr;
23  
24  extern const struct xfs_name	xfs_name_dotdot;
25  extern const struct xfs_name	xfs_name_dot;
26  
27  static inline bool
xfs_dir2_samename(const struct xfs_name * n1,const struct xfs_name * n2)28  xfs_dir2_samename(
29  	const struct xfs_name	*n1,
30  	const struct xfs_name	*n2)
31  {
32  	if (n1 == n2)
33  		return true;
34  	if (n1->len != n2->len)
35  		return false;
36  	return !memcmp(n1->name, n2->name, n1->len);
37  }
38  
39  enum xfs_dir2_fmt {
40  	XFS_DIR2_FMT_SF,
41  	XFS_DIR2_FMT_BLOCK,
42  	XFS_DIR2_FMT_LEAF,
43  	XFS_DIR2_FMT_NODE,
44  	XFS_DIR2_FMT_ERROR,
45  };
46  
47  enum xfs_dir2_fmt xfs_dir2_format(struct xfs_da_args *args, int *error);
48  
49  /*
50   * Convert inode mode to directory entry filetype
51   */
52  extern unsigned char xfs_mode_to_ftype(int mode);
53  
54  /*
55   * Generic directory interface routines
56   */
57  extern void xfs_dir_startup(void);
58  extern int xfs_da_mount(struct xfs_mount *mp);
59  extern void xfs_da_unmount(struct xfs_mount *mp);
60  
61  extern int xfs_dir_isempty(struct xfs_inode *dp);
62  extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
63  				struct xfs_inode *pdp);
64  extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
65  				const struct xfs_name *name, xfs_ino_t inum,
66  				xfs_extlen_t tot);
67  extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
68  				const struct xfs_name *name, xfs_ino_t *inum,
69  				struct xfs_name *ci_name);
70  extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
71  				const struct xfs_name *name, xfs_ino_t ino,
72  				xfs_extlen_t tot);
73  extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
74  				const struct xfs_name *name, xfs_ino_t inum,
75  				xfs_extlen_t tot);
76  extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
77  				const struct xfs_name *name);
78  
79  int xfs_dir_lookup_args(struct xfs_da_args *args);
80  int xfs_dir_createname_args(struct xfs_da_args *args);
81  int xfs_dir_removename_args(struct xfs_da_args *args);
82  int xfs_dir_replace_args(struct xfs_da_args *args);
83  
84  /*
85   * Direct call from the bmap code, bypassing the generic directory layer.
86   */
87  extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
88  
89  /*
90   * Interface routines used by userspace utilities
91   */
92  extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
93  				struct xfs_buf *bp);
94  
95  extern void xfs_dir2_data_freescan(struct xfs_mount *mp,
96  		struct xfs_dir2_data_hdr *hdr, int *loghead);
97  extern void xfs_dir2_data_log_entry(struct xfs_da_args *args,
98  		struct xfs_buf *bp, struct xfs_dir2_data_entry *dep);
99  extern void xfs_dir2_data_log_header(struct xfs_da_args *args,
100  		struct xfs_buf *bp);
101  extern void xfs_dir2_data_log_unused(struct xfs_da_args *args,
102  		struct xfs_buf *bp, struct xfs_dir2_data_unused *dup);
103  extern void xfs_dir2_data_make_free(struct xfs_da_args *args,
104  		struct xfs_buf *bp, xfs_dir2_data_aoff_t offset,
105  		xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
106  extern int xfs_dir2_data_use_free(struct xfs_da_args *args,
107  		struct xfs_buf *bp, struct xfs_dir2_data_unused *dup,
108  		xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len,
109  		int *needlogp, int *needscanp);
110  
111  extern struct xfs_dir2_data_free *xfs_dir2_data_freefind(
112  		struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf,
113  		struct xfs_dir2_data_unused *dup);
114  
115  extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
116  
117  xfs_failaddr_t xfs_dir3_leaf_header_check(struct xfs_buf *bp, xfs_ino_t owner);
118  xfs_failaddr_t xfs_dir3_data_header_check(struct xfs_buf *bp, xfs_ino_t owner);
119  xfs_failaddr_t xfs_dir3_block_header_check(struct xfs_buf *bp, xfs_ino_t owner);
120  
121  extern const struct xfs_buf_ops xfs_dir3_block_buf_ops;
122  extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops;
123  extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops;
124  extern const struct xfs_buf_ops xfs_dir3_free_buf_ops;
125  extern const struct xfs_buf_ops xfs_dir3_data_buf_ops;
126  
127  /*
128   * Directory offset/block conversion functions.
129   *
130   * DB blocks here are logical directory block numbers, not filesystem blocks.
131   */
132  
133  /*
134   * Convert dataptr to byte in file space
135   */
136  static inline xfs_dir2_off_t
xfs_dir2_dataptr_to_byte(xfs_dir2_dataptr_t dp)137  xfs_dir2_dataptr_to_byte(xfs_dir2_dataptr_t dp)
138  {
139  	return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG;
140  }
141  
142  /*
143   * Convert byte in file space to dataptr.  It had better be aligned.
144   */
145  static inline xfs_dir2_dataptr_t
xfs_dir2_byte_to_dataptr(xfs_dir2_off_t by)146  xfs_dir2_byte_to_dataptr(xfs_dir2_off_t by)
147  {
148  	return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG);
149  }
150  
151  /*
152   * Convert byte in space to (DB) block
153   */
154  static inline xfs_dir2_db_t
xfs_dir2_byte_to_db(struct xfs_da_geometry * geo,xfs_dir2_off_t by)155  xfs_dir2_byte_to_db(struct xfs_da_geometry *geo, xfs_dir2_off_t by)
156  {
157  	return (xfs_dir2_db_t)(by >> geo->blklog);
158  }
159  
160  /*
161   * Convert dataptr to a block number
162   */
163  static inline xfs_dir2_db_t
xfs_dir2_dataptr_to_db(struct xfs_da_geometry * geo,xfs_dir2_dataptr_t dp)164  xfs_dir2_dataptr_to_db(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp)
165  {
166  	return xfs_dir2_byte_to_db(geo, xfs_dir2_dataptr_to_byte(dp));
167  }
168  
169  /*
170   * Convert byte in space to offset in a block
171   */
172  static inline xfs_dir2_data_aoff_t
xfs_dir2_byte_to_off(struct xfs_da_geometry * geo,xfs_dir2_off_t by)173  xfs_dir2_byte_to_off(struct xfs_da_geometry *geo, xfs_dir2_off_t by)
174  {
175  	return (xfs_dir2_data_aoff_t)(by & (geo->blksize - 1));
176  }
177  
178  /*
179   * Convert dataptr to a byte offset in a block
180   */
181  static inline xfs_dir2_data_aoff_t
xfs_dir2_dataptr_to_off(struct xfs_da_geometry * geo,xfs_dir2_dataptr_t dp)182  xfs_dir2_dataptr_to_off(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp)
183  {
184  	return xfs_dir2_byte_to_off(geo, xfs_dir2_dataptr_to_byte(dp));
185  }
186  
187  /*
188   * Convert block and offset to byte in space
189   */
190  static inline xfs_dir2_off_t
xfs_dir2_db_off_to_byte(struct xfs_da_geometry * geo,xfs_dir2_db_t db,xfs_dir2_data_aoff_t o)191  xfs_dir2_db_off_to_byte(struct xfs_da_geometry *geo, xfs_dir2_db_t db,
192  			xfs_dir2_data_aoff_t o)
193  {
194  	return ((xfs_dir2_off_t)db << geo->blklog) + o;
195  }
196  
197  /*
198   * Convert block (DB) to block (dablk)
199   */
200  static inline xfs_dablk_t
xfs_dir2_db_to_da(struct xfs_da_geometry * geo,xfs_dir2_db_t db)201  xfs_dir2_db_to_da(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
202  {
203  	return (xfs_dablk_t)(db << (geo->blklog - geo->fsblog));
204  }
205  
206  /*
207   * Convert byte in space to (DA) block
208   */
209  static inline xfs_dablk_t
xfs_dir2_byte_to_da(struct xfs_da_geometry * geo,xfs_dir2_off_t by)210  xfs_dir2_byte_to_da(struct xfs_da_geometry *geo, xfs_dir2_off_t by)
211  {
212  	return xfs_dir2_db_to_da(geo, xfs_dir2_byte_to_db(geo, by));
213  }
214  
215  /*
216   * Convert block and offset to dataptr
217   */
218  static inline xfs_dir2_dataptr_t
xfs_dir2_db_off_to_dataptr(struct xfs_da_geometry * geo,xfs_dir2_db_t db,xfs_dir2_data_aoff_t o)219  xfs_dir2_db_off_to_dataptr(struct xfs_da_geometry *geo, xfs_dir2_db_t db,
220  			   xfs_dir2_data_aoff_t o)
221  {
222  	return xfs_dir2_byte_to_dataptr(xfs_dir2_db_off_to_byte(geo, db, o));
223  }
224  
225  /*
226   * Convert block (dablk) to block (DB)
227   */
228  static inline xfs_dir2_db_t
xfs_dir2_da_to_db(struct xfs_da_geometry * geo,xfs_dablk_t da)229  xfs_dir2_da_to_db(struct xfs_da_geometry *geo, xfs_dablk_t da)
230  {
231  	return (xfs_dir2_db_t)(da >> (geo->blklog - geo->fsblog));
232  }
233  
234  /*
235   * Convert block (dablk) to byte offset in space
236   */
237  static inline xfs_dir2_off_t
xfs_dir2_da_to_byte(struct xfs_da_geometry * geo,xfs_dablk_t da)238  xfs_dir2_da_to_byte(struct xfs_da_geometry *geo, xfs_dablk_t da)
239  {
240  	return xfs_dir2_db_off_to_byte(geo, xfs_dir2_da_to_db(geo, da), 0);
241  }
242  
243  /*
244   * Directory tail pointer accessor functions. Based on block geometry.
245   */
246  static inline struct xfs_dir2_block_tail *
xfs_dir2_block_tail_p(struct xfs_da_geometry * geo,struct xfs_dir2_data_hdr * hdr)247  xfs_dir2_block_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_data_hdr *hdr)
248  {
249  	return ((struct xfs_dir2_block_tail *)
250  		((char *)hdr + geo->blksize)) - 1;
251  }
252  
253  static inline struct xfs_dir2_leaf_tail *
xfs_dir2_leaf_tail_p(struct xfs_da_geometry * geo,struct xfs_dir2_leaf * lp)254  xfs_dir2_leaf_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_leaf *lp)
255  {
256  	return (struct xfs_dir2_leaf_tail *)
257  		((char *)lp + geo->blksize -
258  		  sizeof(struct xfs_dir2_leaf_tail));
259  }
260  
261  /*
262   * The Linux API doesn't pass down the total size of the buffer
263   * we read into down to the filesystem.  With the filldir concept
264   * it's not needed for correct information, but the XFS dir2 leaf
265   * code wants an estimate of the buffer size to calculate it's
266   * readahead window and size the buffers used for mapping to
267   * physical blocks.
268   *
269   * Try to give it an estimate that's good enough, maybe at some
270   * point we can change the ->readdir prototype to include the
271   * buffer size.  For now we use the current glibc buffer size.
272   * musl libc hardcodes 2k and dietlibc uses PAGE_SIZE.
273   */
274  #define XFS_READDIR_BUFSIZE	(32768)
275  
276  unsigned char xfs_dir3_get_dtype(struct xfs_mount *mp, uint8_t filetype);
277  unsigned int xfs_dir3_data_end_offset(struct xfs_da_geometry *geo,
278  		struct xfs_dir2_data_hdr *hdr);
279  bool xfs_dir2_namecheck(const void *name, size_t length);
280  
281  /*
282   * The "ascii-ci" feature was created to speed up case-insensitive lookups for
283   * a Samba product.  Because of the inherent problems with CI and UTF-8
284   * encoding, etc, it was decided that Samba would be configured to export
285   * latin1/iso 8859-1 encodings as that covered >90% of the target markets for
286   * the product.  Hence the "ascii-ci" casefolding code could be encoded into
287   * the XFS directory operations and remove all the overhead of casefolding from
288   * Samba.
289   *
290   * To provide consistent hashing behavior between the userspace and kernel,
291   * these functions prepare names for hashing by transforming specific bytes
292   * to other bytes.  Robustness with other encodings is not guaranteed.
293   */
xfs_ascii_ci_need_xfrm(unsigned char c)294  static inline bool xfs_ascii_ci_need_xfrm(unsigned char c)
295  {
296  	if (c >= 0x41 && c <= 0x5a)	/* A-Z */
297  		return true;
298  	if (c >= 0xc0 && c <= 0xd6)	/* latin A-O with accents */
299  		return true;
300  	if (c >= 0xd8 && c <= 0xde)	/* latin O-Y with accents */
301  		return true;
302  	return false;
303  }
304  
xfs_ascii_ci_xfrm(unsigned char c)305  static inline unsigned char xfs_ascii_ci_xfrm(unsigned char c)
306  {
307  	if (xfs_ascii_ci_need_xfrm(c))
308  		c -= 'A' - 'a';
309  	return c;
310  }
311  
312  struct xfs_dir_update_params {
313  	const struct xfs_inode	*dp;
314  	const struct xfs_inode	*ip;
315  	const struct xfs_name	*name;
316  	int			delta;
317  };
318  
319  #ifdef CONFIG_XFS_LIVE_HOOKS
320  void xfs_dir_update_hook(struct xfs_inode *dp, struct xfs_inode *ip,
321  		int delta, const struct xfs_name *name);
322  
323  struct xfs_dir_hook {
324  	struct xfs_hook		dirent_hook;
325  };
326  
327  void xfs_dir_hook_disable(void);
328  void xfs_dir_hook_enable(void);
329  
330  int xfs_dir_hook_add(struct xfs_mount *mp, struct xfs_dir_hook *hook);
331  void xfs_dir_hook_del(struct xfs_mount *mp, struct xfs_dir_hook *hook);
332  void xfs_dir_hook_setup(struct xfs_dir_hook *hook, notifier_fn_t mod_fn);
333  #else
334  # define xfs_dir_update_hook(dp, ip, delta, name)	((void)0)
335  #endif /* CONFIG_XFS_LIVE_HOOKS */
336  
337  struct xfs_parent_args;
338  
339  struct xfs_dir_update {
340  	struct xfs_inode	*dp;
341  	const struct xfs_name	*name;
342  	struct xfs_inode	*ip;
343  	struct xfs_parent_args	*ppargs;
344  };
345  
346  int xfs_dir_create_child(struct xfs_trans *tp, unsigned int resblks,
347  		struct xfs_dir_update *du);
348  int xfs_dir_add_child(struct xfs_trans *tp, unsigned int resblks,
349  		struct xfs_dir_update *du);
350  int xfs_dir_remove_child(struct xfs_trans *tp, unsigned int resblks,
351  		struct xfs_dir_update *du);
352  
353  int xfs_dir_exchange_children(struct xfs_trans *tp, struct xfs_dir_update *du1,
354  		struct xfs_dir_update *du2, unsigned int spaceres);
355  int xfs_dir_rename_children(struct xfs_trans *tp, struct xfs_dir_update *du_src,
356  		struct xfs_dir_update *du_tgt, unsigned int spaceres,
357  		struct xfs_dir_update *du_wip);
358  
359  #endif	/* __XFS_DIR2_H__ */
360