1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2018-2024 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <djwong@kernel.org> 5 */ 6 #include "xfs.h" 7 #include "xfs_fs.h" 8 #include "xfs_shared.h" 9 #include "xfs_format.h" 10 #include "xfs_log_format.h" 11 #include "xfs_trans_resv.h" 12 #include "xfs_bit.h" 13 #include "xfs_sb.h" 14 #include "xfs_mount.h" 15 #include "xfs_defer.h" 16 #include "xfs_trans.h" 17 #include "xfs_metafile.h" 18 #include "xfs_metadir.h" 19 #include "xfs_trace.h" 20 #include "xfs_inode.h" 21 #include "xfs_quota.h" 22 #include "xfs_ialloc.h" 23 #include "xfs_bmap_btree.h" 24 #include "xfs_da_format.h" 25 #include "xfs_da_btree.h" 26 #include "xfs_trans_space.h" 27 #include "xfs_ag.h" 28 #include "xfs_dir2.h" 29 #include "xfs_dir2_priv.h" 30 #include "xfs_parent.h" 31 #include "xfs_health.h" 32 #include "xfs_errortag.h" 33 #include "xfs_error.h" 34 #include "xfs_btree.h" 35 #include "xfs_alloc.h" 36 37 /* 38 * Metadata Directory Tree 39 * ======================= 40 * 41 * These functions provide an abstraction layer for looking up, creating, and 42 * deleting metadata inodes that live within a special metadata directory tree. 43 * 44 * This code does not manage the five existing metadata inodes: real time 45 * bitmap & summary; and the user, group, and quotas. All other metadata 46 * inodes must use only the xfs_meta{dir,file}_* functions. 47 * 48 * Callers wishing to create or hardlink a metadata inode must create an 49 * xfs_metadir_update structure, call the appropriate xfs_metadir* function, 50 * and then call xfs_metadir_commit or xfs_metadir_cancel to commit or cancel 51 * the update. Files in the metadata directory tree currently cannot be 52 * unlinked. 53 * 54 * When the metadir feature is enabled, all metadata inodes must have the 55 * "metadata" inode flag set to prevent them from being exposed to the outside 56 * world. 57 * 58 * Callers must take the ILOCK of any inode in the metadata directory tree to 59 * synchronize access to that inode. It is never necessary to take the IOLOCK 60 * or the MMAPLOCK since metadata inodes must not be exposed to user space. 61 */ 62 63 static inline void 64 xfs_metadir_set_xname( 65 struct xfs_name *xname, 66 const char *path, 67 unsigned char ftype) 68 { 69 xname->name = (const unsigned char *)path; 70 xname->len = strlen(path); 71 xname->type = ftype; 72 } 73 74 /* 75 * Given a parent directory @dp and a metadata inode path component @xname, 76 * Look up the inode number in the directory, returning it in @ino. 77 * @xname.type must match the directory entry's ftype. 78 * 79 * Caller must hold ILOCK_EXCL. 80 */ 81 static inline int 82 xfs_metadir_lookup( 83 struct xfs_trans *tp, 84 struct xfs_inode *dp, 85 struct xfs_name *xname, 86 xfs_ino_t *ino) 87 { 88 struct xfs_mount *mp = dp->i_mount; 89 struct xfs_da_args args = { 90 .trans = tp, 91 .dp = dp, 92 .geo = mp->m_dir_geo, 93 .name = xname->name, 94 .namelen = xname->len, 95 .hashval = xfs_dir2_hashname(mp, xname), 96 .whichfork = XFS_DATA_FORK, 97 .op_flags = XFS_DA_OP_OKNOENT, 98 .owner = dp->i_ino, 99 }; 100 int error; 101 102 if (!S_ISDIR(VFS_I(dp)->i_mode)) { 103 xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR); 104 return -EFSCORRUPTED; 105 } 106 if (xfs_is_shutdown(mp)) 107 return -EIO; 108 109 error = xfs_dir_lookup_args(&args); 110 if (error) 111 return error; 112 113 if (!xfs_verify_ino(mp, args.inumber)) { 114 xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR); 115 return -EFSCORRUPTED; 116 } 117 if (xname->type != XFS_DIR3_FT_UNKNOWN && xname->type != args.filetype) { 118 xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR); 119 return -EFSCORRUPTED; 120 } 121 122 trace_xfs_metadir_lookup(dp, xname, args.inumber); 123 *ino = args.inumber; 124 return 0; 125 } 126 127 /* 128 * Look up and read a metadata inode from the metadata directory. If the path 129 * component doesn't exist, return -ENOENT. 130 */ 131 int 132 xfs_metadir_load( 133 struct xfs_trans *tp, 134 struct xfs_inode *dp, 135 const char *path, 136 enum xfs_metafile_type metafile_type, 137 struct xfs_inode **ipp) 138 { 139 struct xfs_name xname; 140 xfs_ino_t ino; 141 int error; 142 143 xfs_metadir_set_xname(&xname, path, XFS_DIR3_FT_UNKNOWN); 144 145 xfs_ilock(dp, XFS_ILOCK_EXCL); 146 error = xfs_metadir_lookup(tp, dp, &xname, &ino); 147 xfs_iunlock(dp, XFS_ILOCK_EXCL); 148 if (error) 149 return error; 150 return xfs_trans_metafile_iget(tp, ino, metafile_type, ipp); 151 } 152 153 /* 154 * Unlock and release resources after committing (or cancelling) a metadata 155 * directory tree operation. The caller retains its reference to @upd->ip 156 * and must release it explicitly. 157 */ 158 static inline void 159 xfs_metadir_teardown( 160 struct xfs_metadir_update *upd, 161 int error) 162 { 163 trace_xfs_metadir_teardown(upd, error); 164 165 if (upd->ppargs) { 166 xfs_parent_finish(upd->dp->i_mount, upd->ppargs); 167 upd->ppargs = NULL; 168 } 169 170 if (upd->ip) { 171 if (upd->ip_locked) 172 xfs_iunlock(upd->ip, XFS_ILOCK_EXCL); 173 upd->ip_locked = false; 174 } 175 176 if (upd->dp_locked) 177 xfs_iunlock(upd->dp, XFS_ILOCK_EXCL); 178 upd->dp_locked = false; 179 } 180 181 /* 182 * Begin the process of creating a metadata file by allocating transactions 183 * and taking whatever resources we're going to need. 184 */ 185 int 186 xfs_metadir_start_create( 187 struct xfs_metadir_update *upd) 188 { 189 struct xfs_mount *mp = upd->dp->i_mount; 190 int error; 191 192 ASSERT(upd->dp != NULL); 193 ASSERT(upd->ip == NULL); 194 ASSERT(xfs_has_metadir(mp)); 195 ASSERT(upd->metafile_type != XFS_METAFILE_UNKNOWN); 196 197 error = xfs_parent_start(mp, &upd->ppargs); 198 if (error) 199 return error; 200 201 /* 202 * If we ever need the ability to create rt metadata files on a 203 * pre-metadir filesystem, we'll need to dqattach the parent here. 204 * Currently we assume that mkfs will create the files and quotacheck 205 * will account for them. 206 */ 207 208 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_create, 209 xfs_create_space_res(mp, MAXNAMELEN), 0, 0, &upd->tp); 210 if (error) 211 goto out_teardown; 212 213 /* 214 * Lock the parent directory if there is one. We can't ijoin it to 215 * the transaction until after the child file has been created. 216 */ 217 xfs_ilock(upd->dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); 218 upd->dp_locked = true; 219 220 trace_xfs_metadir_start_create(upd); 221 return 0; 222 out_teardown: 223 xfs_metadir_teardown(upd, error); 224 return error; 225 } 226 227 /* 228 * Create a metadata inode with the given @mode, and insert it into the 229 * metadata directory tree at the given @upd->path. The path up to the final 230 * component must already exist. The final path component must not exist. 231 * 232 * The new metadata inode will be attached to the update structure @upd->ip, 233 * with the ILOCK held until the caller releases it. 234 * 235 * NOTE: This function may return a new inode to the caller even if it returns 236 * a negative error code. If an inode is passed back, the caller must finish 237 * setting up the inode before releasing it. 238 */ 239 int 240 xfs_metadir_create( 241 struct xfs_metadir_update *upd, 242 umode_t mode) 243 { 244 struct xfs_icreate_args args = { 245 .pip = upd->dp, 246 .mode = mode, 247 }; 248 struct xfs_name xname; 249 struct xfs_dir_update du = { 250 .dp = upd->dp, 251 .name = &xname, 252 .ppargs = upd->ppargs, 253 }; 254 struct xfs_mount *mp = upd->dp->i_mount; 255 xfs_ino_t ino; 256 unsigned int resblks; 257 int error; 258 259 xfs_assert_ilocked(upd->dp, XFS_ILOCK_EXCL); 260 261 /* Check that the name does not already exist in the directory. */ 262 xfs_metadir_set_xname(&xname, upd->path, XFS_DIR3_FT_UNKNOWN); 263 error = xfs_metadir_lookup(upd->tp, upd->dp, &xname, &ino); 264 switch (error) { 265 case -ENOENT: 266 break; 267 case 0: 268 error = -EEXIST; 269 fallthrough; 270 default: 271 return error; 272 } 273 274 /* 275 * A newly created regular or special file just has one directory 276 * entry pointing to them, but a directory also the "." entry 277 * pointing to itself. 278 */ 279 error = xfs_dialloc(&upd->tp, &args, &ino); 280 if (error) 281 return error; 282 error = xfs_icreate(upd->tp, ino, &args, &upd->ip); 283 if (error) 284 return error; 285 du.ip = upd->ip; 286 xfs_metafile_set_iflag(upd->tp, upd->ip, upd->metafile_type); 287 upd->ip_locked = true; 288 289 /* 290 * Join the directory inode to the transaction. We do not do it 291 * earlier because xfs_dialloc rolls the transaction. 292 */ 293 xfs_trans_ijoin(upd->tp, upd->dp, 0); 294 295 /* Create the entry. */ 296 if (S_ISDIR(args.mode)) 297 resblks = xfs_mkdir_space_res(mp, xname.len); 298 else 299 resblks = xfs_create_space_res(mp, xname.len); 300 xname.type = xfs_mode_to_ftype(args.mode); 301 302 trace_xfs_metadir_try_create(upd); 303 304 error = xfs_dir_create_child(upd->tp, resblks, &du); 305 if (error) 306 return error; 307 308 /* Metadir files are not accounted to quota. */ 309 310 trace_xfs_metadir_create(upd); 311 312 return 0; 313 } 314 315 #ifndef __KERNEL__ 316 /* 317 * Begin the process of linking a metadata file by allocating transactions 318 * and locking whatever resources we're going to need. 319 */ 320 int 321 xfs_metadir_start_link( 322 struct xfs_metadir_update *upd) 323 { 324 struct xfs_mount *mp = upd->dp->i_mount; 325 unsigned int resblks; 326 int nospace_error = 0; 327 int error; 328 329 ASSERT(upd->dp != NULL); 330 ASSERT(upd->ip != NULL); 331 ASSERT(xfs_has_metadir(mp)); 332 333 error = xfs_parent_start(mp, &upd->ppargs); 334 if (error) 335 return error; 336 337 resblks = xfs_link_space_res(mp, MAXNAMELEN); 338 error = xfs_trans_alloc_dir(upd->dp, &M_RES(mp)->tr_link, upd->ip, 339 &resblks, &upd->tp, &nospace_error); 340 if (error) 341 goto out_teardown; 342 if (!resblks) { 343 /* We don't allow reservationless updates. */ 344 xfs_trans_cancel(upd->tp); 345 upd->tp = NULL; 346 xfs_iunlock(upd->dp, XFS_ILOCK_EXCL); 347 xfs_iunlock(upd->ip, XFS_ILOCK_EXCL); 348 error = nospace_error; 349 goto out_teardown; 350 } 351 352 upd->dp_locked = true; 353 upd->ip_locked = true; 354 355 trace_xfs_metadir_start_link(upd); 356 return 0; 357 out_teardown: 358 xfs_metadir_teardown(upd, error); 359 return error; 360 } 361 362 /* 363 * Link the metadata directory given by @path to the inode @upd->ip. 364 * The path (up to the final component) must already exist, but the final 365 * component must not already exist. 366 */ 367 int 368 xfs_metadir_link( 369 struct xfs_metadir_update *upd) 370 { 371 struct xfs_name xname; 372 struct xfs_dir_update du = { 373 .dp = upd->dp, 374 .name = &xname, 375 .ip = upd->ip, 376 .ppargs = upd->ppargs, 377 }; 378 struct xfs_mount *mp = upd->dp->i_mount; 379 xfs_ino_t ino; 380 unsigned int resblks; 381 int error; 382 383 xfs_assert_ilocked(upd->dp, XFS_ILOCK_EXCL); 384 xfs_assert_ilocked(upd->ip, XFS_ILOCK_EXCL); 385 386 /* Look up the name in the current directory. */ 387 xfs_metadir_set_xname(&xname, upd->path, 388 xfs_mode_to_ftype(VFS_I(upd->ip)->i_mode)); 389 error = xfs_metadir_lookup(upd->tp, upd->dp, &xname, &ino); 390 switch (error) { 391 case -ENOENT: 392 break; 393 case 0: 394 error = -EEXIST; 395 fallthrough; 396 default: 397 return error; 398 } 399 400 resblks = xfs_link_space_res(mp, xname.len); 401 error = xfs_dir_add_child(upd->tp, resblks, &du); 402 if (error) 403 return error; 404 405 trace_xfs_metadir_link(upd); 406 407 return 0; 408 } 409 #endif /* ! __KERNEL__ */ 410 411 /* Commit a metadir update and unlock/drop all resources. */ 412 int 413 xfs_metadir_commit( 414 struct xfs_metadir_update *upd) 415 { 416 int error; 417 418 trace_xfs_metadir_commit(upd); 419 420 error = xfs_trans_commit(upd->tp); 421 upd->tp = NULL; 422 423 xfs_metadir_teardown(upd, error); 424 return error; 425 } 426 427 /* Cancel a metadir update and unlock/drop all resources. */ 428 void 429 xfs_metadir_cancel( 430 struct xfs_metadir_update *upd, 431 int error) 432 { 433 trace_xfs_metadir_cancel(upd); 434 435 xfs_trans_cancel(upd->tp); 436 upd->tp = NULL; 437 438 xfs_metadir_teardown(upd, error); 439 } 440 441 /* Create a metadata for the last component of the path. */ 442 int 443 xfs_metadir_mkdir( 444 struct xfs_inode *dp, 445 const char *path, 446 struct xfs_inode **ipp) 447 { 448 struct xfs_metadir_update upd = { 449 .dp = dp, 450 .path = path, 451 .metafile_type = XFS_METAFILE_DIR, 452 }; 453 int error; 454 455 if (xfs_is_shutdown(dp->i_mount)) 456 return -EIO; 457 458 /* Allocate a transaction to create the last directory. */ 459 error = xfs_metadir_start_create(&upd); 460 if (error) 461 return error; 462 463 /* Create the subdirectory and take our reference. */ 464 error = xfs_metadir_create(&upd, S_IFDIR); 465 if (error) 466 goto out_cancel; 467 468 error = xfs_metadir_commit(&upd); 469 if (error) 470 goto out_irele; 471 472 xfs_finish_inode_setup(upd.ip); 473 *ipp = upd.ip; 474 return 0; 475 476 out_cancel: 477 xfs_metadir_cancel(&upd, error); 478 out_irele: 479 /* Have to finish setting up the inode to ensure it's deleted. */ 480 if (upd.ip) { 481 xfs_finish_inode_setup(upd.ip); 482 xfs_irele(upd.ip); 483 } 484 return error; 485 } 486