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