1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2023-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_trans_resv.h" 11 #include "xfs_mount.h" 12 #include "xfs_log_format.h" 13 #include "xfs_trans.h" 14 #include "xfs_inode.h" 15 #include "xfs_metafile.h" 16 #include "xfs_quota.h" 17 #include "xfs_qm.h" 18 #include "xfs_dir2.h" 19 #include "xfs_parent.h" 20 #include "xfs_bmap_btree.h" 21 #include "xfs_trans_space.h" 22 #include "xfs_attr.h" 23 #include "xfs_rtgroup.h" 24 #include "scrub/scrub.h" 25 #include "scrub/common.h" 26 #include "scrub/trace.h" 27 #include "scrub/readdir.h" 28 #include "scrub/repair.h" 29 30 /* 31 * Metadata Directory Tree Paths 32 * ============================= 33 * 34 * A filesystem with metadir enabled expects to find metadata structures 35 * attached to files that are accessible by walking a path down the metadata 36 * directory tree. Given the metadir path and the incore inode storing the 37 * metadata, this scrubber ensures that the ondisk metadir path points to the 38 * ondisk inode represented by the incore inode. 39 */ 40 41 struct xchk_metapath { 42 struct xfs_scrub *sc; 43 44 /* Name for lookup */ 45 struct xfs_name xname; 46 47 /* Directory update for repairs */ 48 struct xfs_dir_update du; 49 50 /* Path down to this metadata file from the parent directory */ 51 const char *path; 52 53 /* Directory parent of the metadata file. */ 54 struct xfs_inode *dp; 55 56 /* Locks held on dp */ 57 unsigned int dp_ilock_flags; 58 59 /* Transaction block reservations */ 60 unsigned int link_resblks; 61 unsigned int unlink_resblks; 62 63 /* Parent pointer updates */ 64 struct xfs_parent_args link_ppargs; 65 struct xfs_parent_args unlink_ppargs; 66 67 /* Scratchpads for removing links */ 68 struct xfs_da_args pptr_args; 69 }; 70 71 /* Release resources tracked in the buffer. */ 72 static inline void 73 xchk_metapath_cleanup( 74 void *buf) 75 { 76 struct xchk_metapath *mpath = buf; 77 78 if (mpath->dp_ilock_flags) 79 xfs_iunlock(mpath->dp, mpath->dp_ilock_flags); 80 kfree(mpath->path); 81 } 82 83 /* Set up a metadir path scan. @path must be dynamically allocated. */ 84 static inline int 85 xchk_setup_metapath_scan( 86 struct xfs_scrub *sc, 87 struct xfs_inode *dp, 88 const char *path, 89 struct xfs_inode *ip) 90 { 91 struct xchk_metapath *mpath; 92 int error; 93 94 if (!path) 95 return -ENOMEM; 96 97 error = xchk_install_live_inode(sc, ip); 98 if (error) { 99 kfree(path); 100 return error; 101 } 102 103 mpath = kzalloc(sizeof(struct xchk_metapath), XCHK_GFP_FLAGS); 104 if (!mpath) { 105 kfree(path); 106 return -ENOMEM; 107 } 108 109 mpath->sc = sc; 110 sc->buf = mpath; 111 sc->buf_cleanup = xchk_metapath_cleanup; 112 113 mpath->dp = dp; 114 mpath->path = path; /* path is now owned by mpath */ 115 116 mpath->xname.name = mpath->path; 117 mpath->xname.len = strlen(mpath->path); 118 mpath->xname.type = xfs_mode_to_ftype(VFS_I(ip)->i_mode); 119 120 return 0; 121 } 122 123 #ifdef CONFIG_XFS_RT 124 /* Scan the /rtgroups directory itself. */ 125 static int 126 xchk_setup_metapath_rtdir( 127 struct xfs_scrub *sc) 128 { 129 if (!sc->mp->m_rtdirip) 130 return -ENOENT; 131 132 return xchk_setup_metapath_scan(sc, sc->mp->m_metadirip, 133 kasprintf(GFP_KERNEL, "rtgroups"), sc->mp->m_rtdirip); 134 } 135 136 /* Scan a rtgroup inode under the /rtgroups directory. */ 137 static int 138 xchk_setup_metapath_rtginode( 139 struct xfs_scrub *sc, 140 enum xfs_rtg_inodes type) 141 { 142 struct xfs_rtgroup *rtg; 143 struct xfs_inode *ip; 144 int error; 145 146 rtg = xfs_rtgroup_get(sc->mp, sc->sm->sm_agno); 147 if (!rtg) 148 return -ENOENT; 149 150 ip = rtg->rtg_inodes[type]; 151 if (!ip) { 152 error = -ENOENT; 153 goto out_put_rtg; 154 } 155 156 error = xchk_setup_metapath_scan(sc, sc->mp->m_rtdirip, 157 xfs_rtginode_path(rtg_rgno(rtg), type), ip); 158 159 out_put_rtg: 160 xfs_rtgroup_put(rtg); 161 return error; 162 } 163 #else 164 # define xchk_setup_metapath_rtdir(...) (-ENOENT) 165 # define xchk_setup_metapath_rtginode(...) (-ENOENT) 166 #endif /* CONFIG_XFS_RT */ 167 168 #ifdef CONFIG_XFS_QUOTA 169 /* Scan the /quota directory itself. */ 170 static int 171 xchk_setup_metapath_quotadir( 172 struct xfs_scrub *sc) 173 { 174 struct xfs_trans *tp; 175 struct xfs_inode *dp = NULL; 176 int error; 177 178 error = xfs_trans_alloc_empty(sc->mp, &tp); 179 if (error) 180 return error; 181 182 error = xfs_dqinode_load_parent(tp, &dp); 183 xfs_trans_cancel(tp); 184 if (error) 185 return error; 186 187 error = xchk_setup_metapath_scan(sc, sc->mp->m_metadirip, 188 kasprintf(GFP_KERNEL, "quota"), dp); 189 xfs_irele(dp); 190 return error; 191 } 192 193 /* Scan a quota inode under the /quota directory. */ 194 static int 195 xchk_setup_metapath_dqinode( 196 struct xfs_scrub *sc, 197 xfs_dqtype_t type) 198 { 199 struct xfs_quotainfo *qi = sc->mp->m_quotainfo; 200 struct xfs_trans *tp = NULL; 201 struct xfs_inode *dp = NULL; 202 struct xfs_inode *ip = NULL; 203 int error; 204 205 if (!qi) 206 return -ENOENT; 207 208 switch (type) { 209 case XFS_DQTYPE_USER: 210 ip = qi->qi_uquotaip; 211 break; 212 case XFS_DQTYPE_GROUP: 213 ip = qi->qi_gquotaip; 214 break; 215 case XFS_DQTYPE_PROJ: 216 ip = qi->qi_pquotaip; 217 break; 218 default: 219 ASSERT(0); 220 return -EINVAL; 221 } 222 if (!ip) 223 return -ENOENT; 224 225 error = xfs_trans_alloc_empty(sc->mp, &tp); 226 if (error) 227 return error; 228 229 error = xfs_dqinode_load_parent(tp, &dp); 230 xfs_trans_cancel(tp); 231 if (error) 232 return error; 233 234 error = xchk_setup_metapath_scan(sc, dp, 235 kstrdup(xfs_dqinode_path(type), GFP_KERNEL), ip); 236 237 xfs_irele(dp); 238 return error; 239 } 240 #else 241 # define xchk_setup_metapath_quotadir(...) (-ENOENT) 242 # define xchk_setup_metapath_dqinode(...) (-ENOENT) 243 #endif /* CONFIG_XFS_QUOTA */ 244 245 int 246 xchk_setup_metapath( 247 struct xfs_scrub *sc) 248 { 249 if (!xfs_has_metadir(sc->mp)) 250 return -ENOENT; 251 if (sc->sm->sm_gen) 252 return -EINVAL; 253 254 switch (sc->sm->sm_ino) { 255 case XFS_SCRUB_METAPATH_PROBE: 256 /* Just probing, nothing else to do. */ 257 if (sc->sm->sm_agno) 258 return -EINVAL; 259 return 0; 260 case XFS_SCRUB_METAPATH_RTDIR: 261 return xchk_setup_metapath_rtdir(sc); 262 case XFS_SCRUB_METAPATH_RTBITMAP: 263 return xchk_setup_metapath_rtginode(sc, XFS_RTGI_BITMAP); 264 case XFS_SCRUB_METAPATH_RTSUMMARY: 265 return xchk_setup_metapath_rtginode(sc, XFS_RTGI_SUMMARY); 266 case XFS_SCRUB_METAPATH_QUOTADIR: 267 return xchk_setup_metapath_quotadir(sc); 268 case XFS_SCRUB_METAPATH_USRQUOTA: 269 return xchk_setup_metapath_dqinode(sc, XFS_DQTYPE_USER); 270 case XFS_SCRUB_METAPATH_GRPQUOTA: 271 return xchk_setup_metapath_dqinode(sc, XFS_DQTYPE_GROUP); 272 case XFS_SCRUB_METAPATH_PRJQUOTA: 273 return xchk_setup_metapath_dqinode(sc, XFS_DQTYPE_PROJ); 274 default: 275 return -ENOENT; 276 } 277 } 278 279 /* 280 * Take the ILOCK on the metadata directory parent and child. We do not know 281 * that the metadata directory is not corrupt, so we lock the parent and try 282 * to lock the child. Returns 0 if successful, or -EINTR to abort the scrub. 283 */ 284 STATIC int 285 xchk_metapath_ilock_both( 286 struct xchk_metapath *mpath) 287 { 288 struct xfs_scrub *sc = mpath->sc; 289 int error = 0; 290 291 while (true) { 292 xfs_ilock(mpath->dp, XFS_ILOCK_EXCL); 293 if (xchk_ilock_nowait(sc, XFS_ILOCK_EXCL)) { 294 mpath->dp_ilock_flags |= XFS_ILOCK_EXCL; 295 return 0; 296 } 297 xfs_iunlock(mpath->dp, XFS_ILOCK_EXCL); 298 299 if (xchk_should_terminate(sc, &error)) 300 return error; 301 302 delay(1); 303 } 304 305 ASSERT(0); 306 return -EINTR; 307 } 308 309 /* Unlock parent and child inodes. */ 310 static inline void 311 xchk_metapath_iunlock( 312 struct xchk_metapath *mpath) 313 { 314 struct xfs_scrub *sc = mpath->sc; 315 316 xchk_iunlock(sc, XFS_ILOCK_EXCL); 317 318 mpath->dp_ilock_flags &= ~XFS_ILOCK_EXCL; 319 xfs_iunlock(mpath->dp, XFS_ILOCK_EXCL); 320 } 321 322 int 323 xchk_metapath( 324 struct xfs_scrub *sc) 325 { 326 struct xchk_metapath *mpath = sc->buf; 327 xfs_ino_t ino = NULLFSINO; 328 int error; 329 330 /* Just probing, nothing else to do. */ 331 if (sc->sm->sm_ino == XFS_SCRUB_METAPATH_PROBE) 332 return 0; 333 334 /* Parent required to do anything else. */ 335 if (mpath->dp == NULL) { 336 xchk_ino_set_corrupt(sc, sc->ip->i_ino); 337 return 0; 338 } 339 340 error = xchk_trans_alloc_empty(sc); 341 if (error) 342 return error; 343 344 error = xchk_metapath_ilock_both(mpath); 345 if (error) 346 goto out_cancel; 347 348 /* Make sure the parent dir has a dirent pointing to this file. */ 349 error = xchk_dir_lookup(sc, mpath->dp, &mpath->xname, &ino); 350 trace_xchk_metapath_lookup(sc, mpath->path, mpath->dp, ino); 351 if (error == -ENOENT) { 352 /* No directory entry at all */ 353 xchk_ino_set_corrupt(sc, sc->ip->i_ino); 354 error = 0; 355 goto out_ilock; 356 } 357 if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error)) 358 goto out_ilock; 359 if (ino != sc->ip->i_ino) { 360 /* Pointing to wrong inode */ 361 xchk_ino_set_corrupt(sc, sc->ip->i_ino); 362 } 363 364 out_ilock: 365 xchk_metapath_iunlock(mpath); 366 out_cancel: 367 xchk_trans_cancel(sc); 368 return error; 369 } 370 371 #ifdef CONFIG_XFS_ONLINE_REPAIR 372 /* Create the dirent represented by the final component of the path. */ 373 STATIC int 374 xrep_metapath_link( 375 struct xchk_metapath *mpath) 376 { 377 struct xfs_scrub *sc = mpath->sc; 378 379 mpath->du.dp = mpath->dp; 380 mpath->du.name = &mpath->xname; 381 mpath->du.ip = sc->ip; 382 383 if (xfs_has_parent(sc->mp)) 384 mpath->du.ppargs = &mpath->link_ppargs; 385 else 386 mpath->du.ppargs = NULL; 387 388 trace_xrep_metapath_link(sc, mpath->path, mpath->dp, sc->ip->i_ino); 389 390 return xfs_dir_add_child(sc->tp, mpath->link_resblks, &mpath->du); 391 } 392 393 /* Remove the dirent at the final component of the path. */ 394 STATIC int 395 xrep_metapath_unlink( 396 struct xchk_metapath *mpath, 397 xfs_ino_t ino, 398 struct xfs_inode *ip) 399 { 400 struct xfs_parent_rec rec; 401 struct xfs_scrub *sc = mpath->sc; 402 struct xfs_mount *mp = sc->mp; 403 int error; 404 405 trace_xrep_metapath_unlink(sc, mpath->path, mpath->dp, ino); 406 407 if (!ip) { 408 /* The child inode isn't allocated. Junk the dirent. */ 409 xfs_trans_log_inode(sc->tp, mpath->dp, XFS_ILOG_CORE); 410 return xfs_dir_removename(sc->tp, mpath->dp, &mpath->xname, 411 ino, mpath->unlink_resblks); 412 } 413 414 mpath->du.dp = mpath->dp; 415 mpath->du.name = &mpath->xname; 416 mpath->du.ip = ip; 417 mpath->du.ppargs = NULL; 418 419 /* Figure out if we're removing a parent pointer too. */ 420 if (xfs_has_parent(mp)) { 421 xfs_inode_to_parent_rec(&rec, ip); 422 error = xfs_parent_lookup(sc->tp, ip, &mpath->xname, &rec, 423 &mpath->pptr_args); 424 switch (error) { 425 case -ENOATTR: 426 break; 427 case 0: 428 mpath->du.ppargs = &mpath->unlink_ppargs; 429 break; 430 default: 431 return error; 432 } 433 } 434 435 return xfs_dir_remove_child(sc->tp, mpath->unlink_resblks, &mpath->du); 436 } 437 438 /* 439 * Try to create a dirent in @mpath->dp with the name @mpath->xname that points 440 * to @sc->ip. Returns: 441 * 442 * -EEXIST and an @alleged_child if the dirent that points to the wrong inode; 443 * 0 if there is now a dirent pointing to @sc->ip; or 444 * A negative errno on error. 445 */ 446 STATIC int 447 xrep_metapath_try_link( 448 struct xchk_metapath *mpath, 449 xfs_ino_t *alleged_child) 450 { 451 struct xfs_scrub *sc = mpath->sc; 452 xfs_ino_t ino; 453 int error; 454 455 /* Allocate transaction, lock inodes, join to transaction. */ 456 error = xchk_trans_alloc(sc, mpath->link_resblks); 457 if (error) 458 return error; 459 460 error = xchk_metapath_ilock_both(mpath); 461 if (error) { 462 xchk_trans_cancel(sc); 463 return error; 464 } 465 xfs_trans_ijoin(sc->tp, mpath->dp, 0); 466 xfs_trans_ijoin(sc->tp, sc->ip, 0); 467 468 error = xchk_dir_lookup(sc, mpath->dp, &mpath->xname, &ino); 469 trace_xrep_metapath_lookup(sc, mpath->path, mpath->dp, ino); 470 if (error == -ENOENT) { 471 /* 472 * There is no dirent in the directory. Create an entry 473 * pointing to @sc->ip. 474 */ 475 error = xrep_metapath_link(mpath); 476 if (error) 477 goto out_cancel; 478 479 error = xrep_trans_commit(sc); 480 xchk_metapath_iunlock(mpath); 481 return error; 482 } 483 if (error) 484 goto out_cancel; 485 486 if (ino == sc->ip->i_ino) { 487 /* The dirent already points to @sc->ip; we're done. */ 488 error = 0; 489 goto out_cancel; 490 } 491 492 /* 493 * The dirent points elsewhere; pass that back so that the caller 494 * can try to remove the dirent. 495 */ 496 *alleged_child = ino; 497 error = -EEXIST; 498 499 out_cancel: 500 xchk_trans_cancel(sc); 501 xchk_metapath_iunlock(mpath); 502 return error; 503 } 504 505 /* 506 * Take the ILOCK on the metadata directory parent and a bad child, if one is 507 * supplied. We do not know that the metadata directory is not corrupt, so we 508 * lock the parent and try to lock the child. Returns 0 if successful, or 509 * -EINTR to abort the repair. The lock state of @dp is not recorded in @mpath. 510 */ 511 STATIC int 512 xchk_metapath_ilock_parent_and_child( 513 struct xchk_metapath *mpath, 514 struct xfs_inode *ip) 515 { 516 struct xfs_scrub *sc = mpath->sc; 517 int error = 0; 518 519 while (true) { 520 xfs_ilock(mpath->dp, XFS_ILOCK_EXCL); 521 if (!ip || xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) 522 return 0; 523 xfs_iunlock(mpath->dp, XFS_ILOCK_EXCL); 524 525 if (xchk_should_terminate(sc, &error)) 526 return error; 527 528 delay(1); 529 } 530 531 ASSERT(0); 532 return -EINTR; 533 } 534 535 /* 536 * Try to remove a dirent in @mpath->dp with the name @mpath->xname that points 537 * to @alleged_child. Returns: 538 * 539 * 0 if there is no longer a dirent; 540 * -EEXIST if the dirent points to @sc->ip; 541 * -EAGAIN and an updated @alleged_child if the dirent points elsewhere; or 542 * A negative errno for any other error. 543 */ 544 STATIC int 545 xrep_metapath_try_unlink( 546 struct xchk_metapath *mpath, 547 xfs_ino_t *alleged_child) 548 { 549 struct xfs_scrub *sc = mpath->sc; 550 struct xfs_inode *ip = NULL; 551 xfs_ino_t ino; 552 int error; 553 554 ASSERT(*alleged_child != sc->ip->i_ino); 555 556 trace_xrep_metapath_try_unlink(sc, mpath->path, mpath->dp, 557 *alleged_child); 558 559 /* 560 * Allocate transaction, grab the alleged child inode, lock inodes, 561 * join to transaction. 562 */ 563 error = xchk_trans_alloc(sc, mpath->unlink_resblks); 564 if (error) 565 return error; 566 567 error = xchk_iget(sc, *alleged_child, &ip); 568 if (error == -EINVAL || error == -ENOENT) { 569 /* inode number is bogus, junk the dirent */ 570 error = 0; 571 } 572 if (error) { 573 xchk_trans_cancel(sc); 574 return error; 575 } 576 577 error = xchk_metapath_ilock_parent_and_child(mpath, ip); 578 if (error) { 579 xchk_trans_cancel(sc); 580 return error; 581 } 582 xfs_trans_ijoin(sc->tp, mpath->dp, 0); 583 if (ip) 584 xfs_trans_ijoin(sc->tp, ip, 0); 585 586 error = xchk_dir_lookup(sc, mpath->dp, &mpath->xname, &ino); 587 trace_xrep_metapath_lookup(sc, mpath->path, mpath->dp, ino); 588 if (error == -ENOENT) { 589 /* 590 * There is no dirent in the directory anymore. We're ready to 591 * try the link operation again. 592 */ 593 error = 0; 594 goto out_cancel; 595 } 596 if (error) 597 goto out_cancel; 598 599 if (ino == sc->ip->i_ino) { 600 /* The dirent already points to @sc->ip; we're done. */ 601 error = -EEXIST; 602 goto out_cancel; 603 } 604 605 /* 606 * The dirent does not point to the alleged child. Update the caller 607 * and signal that we want to be called again. 608 */ 609 if (ino != *alleged_child) { 610 *alleged_child = ino; 611 error = -EAGAIN; 612 goto out_cancel; 613 } 614 615 /* Remove the link to the child. */ 616 error = xrep_metapath_unlink(mpath, ino, ip); 617 if (error) 618 goto out_cancel; 619 620 error = xrep_trans_commit(sc); 621 goto out_unlock; 622 623 out_cancel: 624 xchk_trans_cancel(sc); 625 out_unlock: 626 xfs_iunlock(mpath->dp, XFS_ILOCK_EXCL); 627 if (ip) { 628 xfs_iunlock(ip, XFS_ILOCK_EXCL); 629 xchk_irele(sc, ip); 630 } 631 return error; 632 } 633 634 /* 635 * Make sure the metadata directory path points to the child being examined. 636 * 637 * Repair needs to be able to create a directory structure, create its own 638 * transactions, and take ILOCKs. This function /must/ be called after all 639 * other repairs have completed. 640 */ 641 int 642 xrep_metapath( 643 struct xfs_scrub *sc) 644 { 645 struct xchk_metapath *mpath = sc->buf; 646 struct xfs_mount *mp = sc->mp; 647 int error = 0; 648 649 /* Just probing, nothing to repair. */ 650 if (sc->sm->sm_ino == XFS_SCRUB_METAPATH_PROBE) 651 return 0; 652 653 /* Parent required to do anything else. */ 654 if (mpath->dp == NULL) 655 return -EFSCORRUPTED; 656 657 /* 658 * Make sure the child file actually has an attr fork to receive a new 659 * parent pointer if the fs has parent pointers. 660 */ 661 if (xfs_has_parent(mp)) { 662 error = xfs_attr_add_fork(sc->ip, 663 sizeof(struct xfs_attr_sf_hdr), 1); 664 if (error) 665 return error; 666 } 667 668 /* Compute block reservation required to unlink and link a file. */ 669 mpath->unlink_resblks = xfs_remove_space_res(mp, MAXNAMELEN); 670 mpath->link_resblks = xfs_link_space_res(mp, MAXNAMELEN); 671 672 do { 673 xfs_ino_t alleged_child; 674 675 /* Re-establish the link, or tell us which inode to remove. */ 676 error = xrep_metapath_try_link(mpath, &alleged_child); 677 if (!error) 678 return 0; 679 if (error != -EEXIST) 680 return error; 681 682 /* 683 * Remove an incorrect link to an alleged child, or tell us 684 * which inode to remove. 685 */ 686 do { 687 error = xrep_metapath_try_unlink(mpath, &alleged_child); 688 } while (error == -EAGAIN); 689 if (error == -EEXIST) { 690 /* Link established; we're done. */ 691 error = 0; 692 break; 693 } 694 } while (!error); 695 696 return error; 697 } 698 #endif /* CONFIG_XFS_ONLINE_REPAIR */ 699