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 struct xfs_name xfs_name_dotdot; 25 26 /* 27 * Convert inode mode to directory entry filetype 28 */ 29 extern unsigned char xfs_mode_to_ftype(int mode); 30 31 /* 32 * Generic directory interface routines 33 */ 34 extern void xfs_dir_startup(void); 35 extern int xfs_da_mount(struct xfs_mount *mp); 36 extern void xfs_da_unmount(struct xfs_mount *mp); 37 38 extern int xfs_dir_isempty(struct xfs_inode *dp); 39 extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, 40 struct xfs_inode *pdp); 41 extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, 42 struct xfs_name *name, xfs_ino_t inum, 43 xfs_extlen_t tot); 44 extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, 45 struct xfs_name *name, xfs_ino_t *inum, 46 struct xfs_name *ci_name); 47 extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, 48 struct xfs_name *name, xfs_ino_t ino, 49 xfs_extlen_t tot); 50 extern bool xfs_dir2_sf_replace_needblock(struct xfs_inode *dp, 51 xfs_ino_t inum); 52 extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, 53 struct xfs_name *name, xfs_ino_t inum, 54 xfs_extlen_t tot); 55 extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, 56 struct xfs_name *name); 57 58 /* 59 * Direct call from the bmap code, bypassing the generic directory layer. 60 */ 61 extern int xfs_dir2_sf_to_block(struct xfs_da_args *args); 62 63 /* 64 * Interface routines used by userspace utilities 65 */ 66 extern int xfs_dir2_isblock(struct xfs_da_args *args, int *r); 67 extern int xfs_dir2_isleaf(struct xfs_da_args *args, int *r); 68 extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, 69 struct xfs_buf *bp); 70 71 extern void xfs_dir2_data_freescan(struct xfs_mount *mp, 72 struct xfs_dir2_data_hdr *hdr, int *loghead); 73 extern void xfs_dir2_data_log_entry(struct xfs_da_args *args, 74 struct xfs_buf *bp, struct xfs_dir2_data_entry *dep); 75 extern void xfs_dir2_data_log_header(struct xfs_da_args *args, 76 struct xfs_buf *bp); 77 extern void xfs_dir2_data_log_unused(struct xfs_da_args *args, 78 struct xfs_buf *bp, struct xfs_dir2_data_unused *dup); 79 extern void xfs_dir2_data_make_free(struct xfs_da_args *args, 80 struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, 81 xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); 82 extern int xfs_dir2_data_use_free(struct xfs_da_args *args, 83 struct xfs_buf *bp, struct xfs_dir2_data_unused *dup, 84 xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, 85 int *needlogp, int *needscanp); 86 87 extern struct xfs_dir2_data_free *xfs_dir2_data_freefind( 88 struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf, 89 struct xfs_dir2_data_unused *dup); 90 91 extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); 92 93 extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; 94 extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; 95 extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops; 96 extern const struct xfs_buf_ops xfs_dir3_free_buf_ops; 97 extern const struct xfs_buf_ops xfs_dir3_data_buf_ops; 98 99 /* 100 * Directory offset/block conversion functions. 101 * 102 * DB blocks here are logical directory block numbers, not filesystem blocks. 103 */ 104 105 /* 106 * Convert dataptr to byte in file space 107 */ 108 static inline xfs_dir2_off_t 109 xfs_dir2_dataptr_to_byte(xfs_dir2_dataptr_t dp) 110 { 111 return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG; 112 } 113 114 /* 115 * Convert byte in file space to dataptr. It had better be aligned. 116 */ 117 static inline xfs_dir2_dataptr_t 118 xfs_dir2_byte_to_dataptr(xfs_dir2_off_t by) 119 { 120 return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG); 121 } 122 123 /* 124 * Convert byte in space to (DB) block 125 */ 126 static inline xfs_dir2_db_t 127 xfs_dir2_byte_to_db(struct xfs_da_geometry *geo, xfs_dir2_off_t by) 128 { 129 return (xfs_dir2_db_t)(by >> geo->blklog); 130 } 131 132 /* 133 * Convert dataptr to a block number 134 */ 135 static inline xfs_dir2_db_t 136 xfs_dir2_dataptr_to_db(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp) 137 { 138 return xfs_dir2_byte_to_db(geo, xfs_dir2_dataptr_to_byte(dp)); 139 } 140 141 /* 142 * Convert byte in space to offset in a block 143 */ 144 static inline xfs_dir2_data_aoff_t 145 xfs_dir2_byte_to_off(struct xfs_da_geometry *geo, xfs_dir2_off_t by) 146 { 147 return (xfs_dir2_data_aoff_t)(by & (geo->blksize - 1)); 148 } 149 150 /* 151 * Convert dataptr to a byte offset in a block 152 */ 153 static inline xfs_dir2_data_aoff_t 154 xfs_dir2_dataptr_to_off(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp) 155 { 156 return xfs_dir2_byte_to_off(geo, xfs_dir2_dataptr_to_byte(dp)); 157 } 158 159 /* 160 * Convert block and offset to byte in space 161 */ 162 static inline xfs_dir2_off_t 163 xfs_dir2_db_off_to_byte(struct xfs_da_geometry *geo, xfs_dir2_db_t db, 164 xfs_dir2_data_aoff_t o) 165 { 166 return ((xfs_dir2_off_t)db << geo->blklog) + o; 167 } 168 169 /* 170 * Convert block (DB) to block (dablk) 171 */ 172 static inline xfs_dablk_t 173 xfs_dir2_db_to_da(struct xfs_da_geometry *geo, xfs_dir2_db_t db) 174 { 175 return (xfs_dablk_t)(db << (geo->blklog - geo->fsblog)); 176 } 177 178 /* 179 * Convert byte in space to (DA) block 180 */ 181 static inline xfs_dablk_t 182 xfs_dir2_byte_to_da(struct xfs_da_geometry *geo, xfs_dir2_off_t by) 183 { 184 return xfs_dir2_db_to_da(geo, xfs_dir2_byte_to_db(geo, by)); 185 } 186 187 /* 188 * Convert block and offset to dataptr 189 */ 190 static inline xfs_dir2_dataptr_t 191 xfs_dir2_db_off_to_dataptr(struct xfs_da_geometry *geo, xfs_dir2_db_t db, 192 xfs_dir2_data_aoff_t o) 193 { 194 return xfs_dir2_byte_to_dataptr(xfs_dir2_db_off_to_byte(geo, db, o)); 195 } 196 197 /* 198 * Convert block (dablk) to block (DB) 199 */ 200 static inline xfs_dir2_db_t 201 xfs_dir2_da_to_db(struct xfs_da_geometry *geo, xfs_dablk_t da) 202 { 203 return (xfs_dir2_db_t)(da >> (geo->blklog - geo->fsblog)); 204 } 205 206 /* 207 * Convert block (dablk) to byte offset in space 208 */ 209 static inline xfs_dir2_off_t 210 xfs_dir2_da_to_byte(struct xfs_da_geometry *geo, xfs_dablk_t da) 211 { 212 return xfs_dir2_db_off_to_byte(geo, xfs_dir2_da_to_db(geo, da), 0); 213 } 214 215 /* 216 * Directory tail pointer accessor functions. Based on block geometry. 217 */ 218 static inline struct xfs_dir2_block_tail * 219 xfs_dir2_block_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_data_hdr *hdr) 220 { 221 return ((struct xfs_dir2_block_tail *) 222 ((char *)hdr + geo->blksize)) - 1; 223 } 224 225 static inline struct xfs_dir2_leaf_tail * 226 xfs_dir2_leaf_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_leaf *lp) 227 { 228 return (struct xfs_dir2_leaf_tail *) 229 ((char *)lp + geo->blksize - 230 sizeof(struct xfs_dir2_leaf_tail)); 231 } 232 233 /* 234 * The Linux API doesn't pass down the total size of the buffer 235 * we read into down to the filesystem. With the filldir concept 236 * it's not needed for correct information, but the XFS dir2 leaf 237 * code wants an estimate of the buffer size to calculate it's 238 * readahead window and size the buffers used for mapping to 239 * physical blocks. 240 * 241 * Try to give it an estimate that's good enough, maybe at some 242 * point we can change the ->readdir prototype to include the 243 * buffer size. For now we use the current glibc buffer size. 244 * musl libc hardcodes 2k and dietlibc uses PAGE_SIZE. 245 */ 246 #define XFS_READDIR_BUFSIZE (32768) 247 248 unsigned char xfs_dir3_get_dtype(struct xfs_mount *mp, uint8_t filetype); 249 unsigned int xfs_dir3_data_end_offset(struct xfs_da_geometry *geo, 250 struct xfs_dir2_data_hdr *hdr); 251 bool xfs_dir2_namecheck(const void *name, size_t length); 252 253 #endif /* __XFS_DIR2_H__ */ 254