1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2022-2024 Oracle. 4 * All rights reserved. 5 */ 6 #include "xfs.h" 7 #include "xfs_fs.h" 8 #include "xfs_format.h" 9 #include "xfs_da_format.h" 10 #include "xfs_log_format.h" 11 #include "xfs_shared.h" 12 #include "xfs_trans_resv.h" 13 #include "xfs_mount.h" 14 #include "xfs_bmap_btree.h" 15 #include "xfs_inode.h" 16 #include "xfs_error.h" 17 #include "xfs_trace.h" 18 #include "xfs_trans.h" 19 #include "xfs_da_btree.h" 20 #include "xfs_attr.h" 21 #include "xfs_dir2.h" 22 #include "xfs_dir2_priv.h" 23 #include "xfs_attr_sf.h" 24 #include "xfs_bmap.h" 25 #include "xfs_defer.h" 26 #include "xfs_log.h" 27 #include "xfs_xattr.h" 28 #include "xfs_parent.h" 29 #include "xfs_trans_space.h" 30 #include "xfs_attr_item.h" 31 #include "xfs_health.h" 32 33 struct kmem_cache *xfs_parent_args_cache; 34 35 /* 36 * Parent pointer attribute handling. 37 * 38 * Because the attribute name is a filename component, it will never be longer 39 * than 255 bytes and must not contain nulls or slashes. These are roughly the 40 * same constraints that apply to attribute names. 41 * 42 * The attribute value must always be a struct xfs_parent_rec. This means the 43 * attribute will never be in remote format because 12 bytes is nowhere near 44 * xfs_attr_leaf_entsize_local_max() (~75% of block size). 45 * 46 * Creating a new parent attribute will always create a new attribute - there 47 * should never, ever be an existing attribute in the tree for a new inode. 48 * ENOSPC behavior is problematic - creating the inode without the parent 49 * pointer is effectively a corruption, so we allow parent attribute creation 50 * to dip into the reserve block pool to avoid unexpected ENOSPC errors from 51 * occurring. 52 */ 53 54 /* Return true if parent pointer attr name is valid. */ 55 bool 56 xfs_parent_namecheck( 57 unsigned int attr_flags, 58 const void *name, 59 size_t length) 60 { 61 /* 62 * Parent pointers always use logged operations, so there should never 63 * be incomplete xattrs. 64 */ 65 if (attr_flags & XFS_ATTR_INCOMPLETE) 66 return false; 67 68 return xfs_dir2_namecheck(name, length); 69 } 70 71 /* Return true if parent pointer attr value is valid. */ 72 bool 73 xfs_parent_valuecheck( 74 struct xfs_mount *mp, 75 const void *value, 76 size_t valuelen) 77 { 78 const struct xfs_parent_rec *rec = value; 79 80 if (!xfs_has_parent(mp)) 81 return false; 82 83 /* The xattr value must be a parent record. */ 84 if (valuelen != sizeof(struct xfs_parent_rec)) 85 return false; 86 87 /* The parent record must be local. */ 88 if (value == NULL) 89 return false; 90 91 /* The parent inumber must be valid. */ 92 if (!xfs_verify_dir_ino(mp, be64_to_cpu(rec->p_ino))) 93 return false; 94 95 return true; 96 } 97 98 /* Compute the attribute name hash for a parent pointer. */ 99 xfs_dahash_t 100 xfs_parent_hashval( 101 struct xfs_mount *mp, 102 const uint8_t *name, 103 int namelen, 104 xfs_ino_t parent_ino) 105 { 106 struct xfs_name xname = { 107 .name = name, 108 .len = namelen, 109 }; 110 111 /* 112 * Use the same dirent name hash as would be used on the directory, but 113 * mix in the parent inode number to avoid collisions on hardlinked 114 * files with identical names but different parents. 115 */ 116 return xfs_dir2_hashname(mp, &xname) ^ 117 upper_32_bits(parent_ino) ^ lower_32_bits(parent_ino); 118 } 119 120 /* Compute the attribute name hash from the xattr components. */ 121 xfs_dahash_t 122 xfs_parent_hashattr( 123 struct xfs_mount *mp, 124 const uint8_t *name, 125 int namelen, 126 const void *value, 127 int valuelen) 128 { 129 const struct xfs_parent_rec *rec = value; 130 131 /* Requires a local attr value in xfs_parent_rec format */ 132 if (valuelen != sizeof(struct xfs_parent_rec)) { 133 ASSERT(valuelen == sizeof(struct xfs_parent_rec)); 134 return 0; 135 } 136 137 if (!value) { 138 ASSERT(value != NULL); 139 return 0; 140 } 141 142 return xfs_parent_hashval(mp, name, namelen, be64_to_cpu(rec->p_ino)); 143 } 144 145 /* 146 * Initialize the parent pointer arguments structure. Caller must have zeroed 147 * the contents of @args. @tp is only required for updates. 148 */ 149 static void 150 xfs_parent_da_args_init( 151 struct xfs_da_args *args, 152 struct xfs_trans *tp, 153 struct xfs_parent_rec *rec, 154 struct xfs_inode *child, 155 xfs_ino_t owner, 156 const struct xfs_name *parent_name) 157 { 158 args->geo = child->i_mount->m_attr_geo; 159 args->whichfork = XFS_ATTR_FORK; 160 args->attr_filter = XFS_ATTR_PARENT; 161 args->op_flags = XFS_DA_OP_LOGGED | XFS_DA_OP_OKNOENT; 162 args->trans = tp; 163 args->dp = child; 164 args->owner = owner; 165 args->name = parent_name->name; 166 args->namelen = parent_name->len; 167 args->value = rec; 168 args->valuelen = sizeof(struct xfs_parent_rec); 169 xfs_attr_sethash(args); 170 } 171 172 /* Make sure the incore state is ready for a parent pointer query/update. */ 173 static inline int 174 xfs_parent_iread_extents( 175 struct xfs_trans *tp, 176 struct xfs_inode *child) 177 { 178 /* Parent pointers require that the attr fork must exist. */ 179 if (XFS_IS_CORRUPT(child->i_mount, !xfs_inode_has_attr_fork(child))) { 180 xfs_inode_mark_sick(child, XFS_SICK_INO_PARENT); 181 return -EFSCORRUPTED; 182 } 183 184 return xfs_iread_extents(tp, child, XFS_ATTR_FORK); 185 } 186 187 /* Add a parent pointer to reflect a dirent addition. */ 188 int 189 xfs_parent_addname( 190 struct xfs_trans *tp, 191 struct xfs_parent_args *ppargs, 192 struct xfs_inode *dp, 193 const struct xfs_name *parent_name, 194 struct xfs_inode *child) 195 { 196 int error; 197 198 error = xfs_parent_iread_extents(tp, child); 199 if (error) 200 return error; 201 202 xfs_inode_to_parent_rec(&ppargs->rec, dp); 203 xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child, 204 child->i_ino, parent_name); 205 xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_SET); 206 return 0; 207 } 208 209 /* Remove a parent pointer to reflect a dirent removal. */ 210 int 211 xfs_parent_removename( 212 struct xfs_trans *tp, 213 struct xfs_parent_args *ppargs, 214 struct xfs_inode *dp, 215 const struct xfs_name *parent_name, 216 struct xfs_inode *child) 217 { 218 int error; 219 220 error = xfs_parent_iread_extents(tp, child); 221 if (error) 222 return error; 223 224 xfs_inode_to_parent_rec(&ppargs->rec, dp); 225 xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child, 226 child->i_ino, parent_name); 227 xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_REMOVE); 228 return 0; 229 } 230 231 /* Replace one parent pointer with another to reflect a rename. */ 232 int 233 xfs_parent_replacename( 234 struct xfs_trans *tp, 235 struct xfs_parent_args *ppargs, 236 struct xfs_inode *old_dp, 237 const struct xfs_name *old_name, 238 struct xfs_inode *new_dp, 239 const struct xfs_name *new_name, 240 struct xfs_inode *child) 241 { 242 int error; 243 244 error = xfs_parent_iread_extents(tp, child); 245 if (error) 246 return error; 247 248 xfs_inode_to_parent_rec(&ppargs->rec, old_dp); 249 xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child, 250 child->i_ino, old_name); 251 252 xfs_inode_to_parent_rec(&ppargs->new_rec, new_dp); 253 ppargs->args.new_name = new_name->name; 254 ppargs->args.new_namelen = new_name->len; 255 ppargs->args.new_value = &ppargs->new_rec; 256 ppargs->args.new_valuelen = sizeof(struct xfs_parent_rec); 257 xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_REPLACE); 258 return 0; 259 } 260 261 /* 262 * Extract parent pointer information from any parent pointer xattr into 263 * @parent_ino/gen. The last two parameters can be NULL pointers. 264 * 265 * Returns 0 if this is not a parent pointer xattr at all; or -EFSCORRUPTED for 266 * garbage. 267 */ 268 int 269 xfs_parent_from_attr( 270 struct xfs_mount *mp, 271 unsigned int attr_flags, 272 const unsigned char *name, 273 unsigned int namelen, 274 const void *value, 275 unsigned int valuelen, 276 xfs_ino_t *parent_ino, 277 uint32_t *parent_gen) 278 { 279 const struct xfs_parent_rec *rec = value; 280 281 ASSERT(attr_flags & XFS_ATTR_PARENT); 282 283 if (!xfs_parent_namecheck(attr_flags, name, namelen)) 284 return -EFSCORRUPTED; 285 if (!xfs_parent_valuecheck(mp, value, valuelen)) 286 return -EFSCORRUPTED; 287 288 if (parent_ino) 289 *parent_ino = be64_to_cpu(rec->p_ino); 290 if (parent_gen) 291 *parent_gen = be32_to_cpu(rec->p_gen); 292 return 0; 293 } 294 295 /* 296 * Look up a parent pointer record (@parent_name -> @pptr) of @ip. 297 * 298 * Caller must hold at least ILOCK_SHARED. The scratchpad need not be 299 * initialized. 300 * 301 * Returns 0 if the pointer is found, -ENOATTR if there is no match, or a 302 * negative errno. 303 */ 304 int 305 xfs_parent_lookup( 306 struct xfs_trans *tp, 307 struct xfs_inode *ip, 308 const struct xfs_name *parent_name, 309 struct xfs_parent_rec *pptr, 310 struct xfs_da_args *scratch) 311 { 312 memset(scratch, 0, sizeof(struct xfs_da_args)); 313 xfs_parent_da_args_init(scratch, tp, pptr, ip, ip->i_ino, parent_name); 314 return xfs_attr_get_ilocked(scratch); 315 } 316 317 /* Sanity-check a parent pointer before we try to perform repairs. */ 318 static inline bool 319 xfs_parent_sanity_check( 320 struct xfs_mount *mp, 321 const struct xfs_name *parent_name, 322 const struct xfs_parent_rec *pptr) 323 { 324 if (!xfs_parent_namecheck(XFS_ATTR_PARENT, parent_name->name, 325 parent_name->len)) 326 return false; 327 328 if (!xfs_parent_valuecheck(mp, pptr, sizeof(*pptr))) 329 return false; 330 331 return true; 332 } 333 334 335 /* 336 * Attach the parent pointer (@parent_name -> @pptr) to @ip immediately. 337 * Caller must not have a transaction or hold the ILOCK. This is for 338 * specialized repair functions only. The scratchpad need not be initialized. 339 */ 340 int 341 xfs_parent_set( 342 struct xfs_inode *ip, 343 xfs_ino_t owner, 344 const struct xfs_name *parent_name, 345 struct xfs_parent_rec *pptr, 346 struct xfs_da_args *scratch) 347 { 348 if (!xfs_parent_sanity_check(ip->i_mount, parent_name, pptr)) { 349 ASSERT(0); 350 return -EFSCORRUPTED; 351 } 352 353 memset(scratch, 0, sizeof(struct xfs_da_args)); 354 xfs_parent_da_args_init(scratch, NULL, pptr, ip, owner, parent_name); 355 return xfs_attr_set(scratch, XFS_ATTRUPDATE_CREATE, false); 356 } 357 358 /* 359 * Remove the parent pointer (@parent_name -> @pptr) from @ip immediately. 360 * Caller must not have a transaction or hold the ILOCK. This is for 361 * specialized repair functions only. The scratchpad need not be initialized. 362 */ 363 int 364 xfs_parent_unset( 365 struct xfs_inode *ip, 366 xfs_ino_t owner, 367 const struct xfs_name *parent_name, 368 struct xfs_parent_rec *pptr, 369 struct xfs_da_args *scratch) 370 { 371 if (!xfs_parent_sanity_check(ip->i_mount, parent_name, pptr)) { 372 ASSERT(0); 373 return -EFSCORRUPTED; 374 } 375 376 memset(scratch, 0, sizeof(struct xfs_da_args)); 377 xfs_parent_da_args_init(scratch, NULL, pptr, ip, owner, parent_name); 378 return xfs_attr_set(scratch, XFS_ATTRUPDATE_REMOVE, false); 379 } 380
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.