1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2017-2023 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_quota.h" 16 #include "xfs_qm.h" 17 #include "xfs_scrub.h" 18 #include "xfs_buf_mem.h" 19 #include "xfs_rmap.h" 20 #include "xfs_exchrange.h" 21 #include "xfs_exchmaps.h" 22 #include "scrub/scrub.h" 23 #include "scrub/common.h" 24 #include "scrub/trace.h" 25 #include "scrub/repair.h" 26 #include "scrub/health.h" 27 #include "scrub/stats.h" 28 #include "scrub/xfile.h" 29 #include "scrub/tempfile.h" 30 #include "scrub/orphanage.h" 31 32 /* 33 * Online Scrub and Repair 34 * 35 * Traditionally, XFS (the kernel driver) did not know how to check or 36 * repair on-disk data structures. That task was left to the xfs_check 37 * and xfs_repair tools, both of which require taking the filesystem 38 * offline for a thorough but time consuming examination. Online 39 * scrub & repair, on the other hand, enables us to check the metadata 40 * for obvious errors while carefully stepping around the filesystem's 41 * ongoing operations, locking rules, etc. 42 * 43 * Given that most XFS metadata consist of records stored in a btree, 44 * most of the checking functions iterate the btree blocks themselves 45 * looking for irregularities. When a record block is encountered, each 46 * record can be checked for obviously bad values. Record values can 47 * also be cross-referenced against other btrees to look for potential 48 * misunderstandings between pieces of metadata. 49 * 50 * It is expected that the checkers responsible for per-AG metadata 51 * structures will lock the AG headers (AGI, AGF, AGFL), iterate the 52 * metadata structure, and perform any relevant cross-referencing before 53 * unlocking the AG and returning the results to userspace. These 54 * scrubbers must not keep an AG locked for too long to avoid tying up 55 * the block and inode allocators. 56 * 57 * Block maps and b-trees rooted in an inode present a special challenge 58 * because they can involve extents from any AG. The general scrubber 59 * structure of lock -> check -> xref -> unlock still holds, but AG 60 * locking order rules /must/ be obeyed to avoid deadlocks. The 61 * ordering rule, of course, is that we must lock in increasing AG 62 * order. Helper functions are provided to track which AG headers we've 63 * already locked. If we detect an imminent locking order violation, we 64 * can signal a potential deadlock, in which case the scrubber can jump 65 * out to the top level, lock all the AGs in order, and retry the scrub. 66 * 67 * For file data (directories, extended attributes, symlinks) scrub, we 68 * can simply lock the inode and walk the data. For btree data 69 * (directories and attributes) we follow the same btree-scrubbing 70 * strategy outlined previously to check the records. 71 * 72 * We use a bit of trickery with transactions to avoid buffer deadlocks 73 * if there is a cycle in the metadata. The basic problem is that 74 * travelling down a btree involves locking the current buffer at each 75 * tree level. If a pointer should somehow point back to a buffer that 76 * we've already examined, we will deadlock due to the second buffer 77 * locking attempt. Note however that grabbing a buffer in transaction 78 * context links the locked buffer to the transaction. If we try to 79 * re-grab the buffer in the context of the same transaction, we avoid 80 * the second lock attempt and continue. Between the verifier and the 81 * scrubber, something will notice that something is amiss and report 82 * the corruption. Therefore, each scrubber will allocate an empty 83 * transaction, attach buffers to it, and cancel the transaction at the 84 * end of the scrub run. Cancelling a non-dirty transaction simply 85 * unlocks the buffers. 86 * 87 * There are four pieces of data that scrub can communicate to 88 * userspace. The first is the error code (errno), which can be used to 89 * communicate operational errors in performing the scrub. There are 90 * also three flags that can be set in the scrub context. If the data 91 * structure itself is corrupt, the CORRUPT flag will be set. If 92 * the metadata is correct but otherwise suboptimal, the PREEN flag 93 * will be set. 94 * 95 * We perform secondary validation of filesystem metadata by 96 * cross-referencing every record with all other available metadata. 97 * For example, for block mapping extents, we verify that there are no 98 * records in the free space and inode btrees corresponding to that 99 * space extent and that there is a corresponding entry in the reverse 100 * mapping btree. Inconsistent metadata is noted by setting the 101 * XCORRUPT flag; btree query function errors are noted by setting the 102 * XFAIL flag and deleting the cursor to prevent further attempts to 103 * cross-reference with a defective btree. 104 * 105 * If a piece of metadata proves corrupt or suboptimal, the userspace 106 * program can ask the kernel to apply some tender loving care (TLC) to 107 * the metadata object by setting the REPAIR flag and re-calling the 108 * scrub ioctl. "Corruption" is defined by metadata violating the 109 * on-disk specification; operations cannot continue if the violation is 110 * left untreated. It is possible for XFS to continue if an object is 111 * "suboptimal", however performance may be degraded. Repairs are 112 * usually performed by rebuilding the metadata entirely out of 113 * redundant metadata. Optimizing, on the other hand, can sometimes be 114 * done without rebuilding entire structures. 115 * 116 * Generally speaking, the repair code has the following code structure: 117 * Lock -> scrub -> repair -> commit -> re-lock -> re-scrub -> unlock. 118 * The first check helps us figure out if we need to rebuild or simply 119 * optimize the structure so that the rebuild knows what to do. The 120 * second check evaluates the completeness of the repair; that is what 121 * is reported to userspace. 122 * 123 * A quick note on symbol prefixes: 124 * - "xfs_" are general XFS symbols. 125 * - "xchk_" are symbols related to metadata checking. 126 * - "xrep_" are symbols related to metadata repair. 127 * - "xfs_scrub_" are symbols that tie online fsck to the rest of XFS. 128 */ 129 130 /* 131 * Scrub probe -- userspace uses this to probe if we're willing to scrub 132 * or repair a given mountpoint. This will be used by xfs_scrub to 133 * probe the kernel's abilities to scrub (and repair) the metadata. We 134 * do this by validating the ioctl inputs from userspace, preparing the 135 * filesystem for a scrub (or a repair) operation, and immediately 136 * returning to userspace. Userspace can use the returned errno and 137 * structure state to decide (in broad terms) if scrub/repair are 138 * supported by the running kernel. 139 */ 140 static int 141 xchk_probe( 142 struct xfs_scrub *sc) 143 { 144 int error = 0; 145 146 if (xchk_should_terminate(sc, &error)) 147 return error; 148 149 return 0; 150 } 151 152 /* Scrub setup and teardown */ 153 154 #define FSGATES_MASK (XCHK_FSGATES_ALL | XREP_FSGATES_ALL) 155 static inline void 156 xchk_fsgates_disable( 157 struct xfs_scrub *sc) 158 { 159 if (!(sc->flags & FSGATES_MASK)) 160 return; 161 162 trace_xchk_fsgates_disable(sc, sc->flags & FSGATES_MASK); 163 164 if (sc->flags & XCHK_FSGATES_DRAIN) 165 xfs_drain_wait_disable(); 166 167 if (sc->flags & XCHK_FSGATES_QUOTA) 168 xfs_dqtrx_hook_disable(); 169 170 if (sc->flags & XCHK_FSGATES_DIRENTS) 171 xfs_dir_hook_disable(); 172 173 if (sc->flags & XCHK_FSGATES_RMAP) 174 xfs_rmap_hook_disable(); 175 176 sc->flags &= ~FSGATES_MASK; 177 } 178 #undef FSGATES_MASK 179 180 /* Free all the resources and finish the transactions. */ 181 STATIC int 182 xchk_teardown( 183 struct xfs_scrub *sc, 184 int error) 185 { 186 xchk_ag_free(sc, &sc->sa); 187 if (sc->tp) { 188 if (error == 0 && (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)) 189 error = xfs_trans_commit(sc->tp); 190 else 191 xfs_trans_cancel(sc->tp); 192 sc->tp = NULL; 193 } 194 if (sc->ip) { 195 if (sc->ilock_flags) 196 xchk_iunlock(sc, sc->ilock_flags); 197 xchk_irele(sc, sc->ip); 198 sc->ip = NULL; 199 } 200 if (sc->flags & XCHK_HAVE_FREEZE_PROT) { 201 sc->flags &= ~XCHK_HAVE_FREEZE_PROT; 202 mnt_drop_write_file(sc->file); 203 } 204 if (sc->xmbtp) { 205 xmbuf_free(sc->xmbtp); 206 sc->xmbtp = NULL; 207 } 208 if (sc->xfile) { 209 xfile_destroy(sc->xfile); 210 sc->xfile = NULL; 211 } 212 if (sc->buf) { 213 if (sc->buf_cleanup) 214 sc->buf_cleanup(sc->buf); 215 kvfree(sc->buf); 216 sc->buf_cleanup = NULL; 217 sc->buf = NULL; 218 } 219 220 xrep_tempfile_rele(sc); 221 xrep_orphanage_rele(sc); 222 xchk_fsgates_disable(sc); 223 return error; 224 } 225 226 /* Scrubbing dispatch. */ 227 228 static const struct xchk_meta_ops meta_scrub_ops[] = { 229 [XFS_SCRUB_TYPE_PROBE] = { /* ioctl presence test */ 230 .type = ST_NONE, 231 .setup = xchk_setup_fs, 232 .scrub = xchk_probe, 233 .repair = xrep_probe, 234 }, 235 [XFS_SCRUB_TYPE_SB] = { /* superblock */ 236 .type = ST_PERAG, 237 .setup = xchk_setup_agheader, 238 .scrub = xchk_superblock, 239 .repair = xrep_superblock, 240 }, 241 [XFS_SCRUB_TYPE_AGF] = { /* agf */ 242 .type = ST_PERAG, 243 .setup = xchk_setup_agheader, 244 .scrub = xchk_agf, 245 .repair = xrep_agf, 246 }, 247 [XFS_SCRUB_TYPE_AGFL]= { /* agfl */ 248 .type = ST_PERAG, 249 .setup = xchk_setup_agheader, 250 .scrub = xchk_agfl, 251 .repair = xrep_agfl, 252 }, 253 [XFS_SCRUB_TYPE_AGI] = { /* agi */ 254 .type = ST_PERAG, 255 .setup = xchk_setup_agheader, 256 .scrub = xchk_agi, 257 .repair = xrep_agi, 258 }, 259 [XFS_SCRUB_TYPE_BNOBT] = { /* bnobt */ 260 .type = ST_PERAG, 261 .setup = xchk_setup_ag_allocbt, 262 .scrub = xchk_allocbt, 263 .repair = xrep_allocbt, 264 .repair_eval = xrep_revalidate_allocbt, 265 }, 266 [XFS_SCRUB_TYPE_CNTBT] = { /* cntbt */ 267 .type = ST_PERAG, 268 .setup = xchk_setup_ag_allocbt, 269 .scrub = xchk_allocbt, 270 .repair = xrep_allocbt, 271 .repair_eval = xrep_revalidate_allocbt, 272 }, 273 [XFS_SCRUB_TYPE_INOBT] = { /* inobt */ 274 .type = ST_PERAG, 275 .setup = xchk_setup_ag_iallocbt, 276 .scrub = xchk_iallocbt, 277 .repair = xrep_iallocbt, 278 .repair_eval = xrep_revalidate_iallocbt, 279 }, 280 [XFS_SCRUB_TYPE_FINOBT] = { /* finobt */ 281 .type = ST_PERAG, 282 .setup = xchk_setup_ag_iallocbt, 283 .scrub = xchk_iallocbt, 284 .has = xfs_has_finobt, 285 .repair = xrep_iallocbt, 286 .repair_eval = xrep_revalidate_iallocbt, 287 }, 288 [XFS_SCRUB_TYPE_RMAPBT] = { /* rmapbt */ 289 .type = ST_PERAG, 290 .setup = xchk_setup_ag_rmapbt, 291 .scrub = xchk_rmapbt, 292 .has = xfs_has_rmapbt, 293 .repair = xrep_rmapbt, 294 }, 295 [XFS_SCRUB_TYPE_REFCNTBT] = { /* refcountbt */ 296 .type = ST_PERAG, 297 .setup = xchk_setup_ag_refcountbt, 298 .scrub = xchk_refcountbt, 299 .has = xfs_has_reflink, 300 .repair = xrep_refcountbt, 301 }, 302 [XFS_SCRUB_TYPE_INODE] = { /* inode record */ 303 .type = ST_INODE, 304 .setup = xchk_setup_inode, 305 .scrub = xchk_inode, 306 .repair = xrep_inode, 307 }, 308 [XFS_SCRUB_TYPE_BMBTD] = { /* inode data fork */ 309 .type = ST_INODE, 310 .setup = xchk_setup_inode_bmap, 311 .scrub = xchk_bmap_data, 312 .repair = xrep_bmap_data, 313 }, 314 [XFS_SCRUB_TYPE_BMBTA] = { /* inode attr fork */ 315 .type = ST_INODE, 316 .setup = xchk_setup_inode_bmap, 317 .scrub = xchk_bmap_attr, 318 .repair = xrep_bmap_attr, 319 }, 320 [XFS_SCRUB_TYPE_BMBTC] = { /* inode CoW fork */ 321 .type = ST_INODE, 322 .setup = xchk_setup_inode_bmap, 323 .scrub = xchk_bmap_cow, 324 .repair = xrep_bmap_cow, 325 }, 326 [XFS_SCRUB_TYPE_DIR] = { /* directory */ 327 .type = ST_INODE, 328 .setup = xchk_setup_directory, 329 .scrub = xchk_directory, 330 .repair = xrep_directory, 331 }, 332 [XFS_SCRUB_TYPE_XATTR] = { /* extended attributes */ 333 .type = ST_INODE, 334 .setup = xchk_setup_xattr, 335 .scrub = xchk_xattr, 336 .repair = xrep_xattr, 337 }, 338 [XFS_SCRUB_TYPE_SYMLINK] = { /* symbolic link */ 339 .type = ST_INODE, 340 .setup = xchk_setup_symlink, 341 .scrub = xchk_symlink, 342 .repair = xrep_notsupported, 343 }, 344 [XFS_SCRUB_TYPE_PARENT] = { /* parent pointers */ 345 .type = ST_INODE, 346 .setup = xchk_setup_parent, 347 .scrub = xchk_parent, 348 .repair = xrep_parent, 349 }, 350 [XFS_SCRUB_TYPE_RTBITMAP] = { /* realtime bitmap */ 351 .type = ST_FS, 352 .setup = xchk_setup_rtbitmap, 353 .scrub = xchk_rtbitmap, 354 .repair = xrep_rtbitmap, 355 }, 356 [XFS_SCRUB_TYPE_RTSUM] = { /* realtime summary */ 357 .type = ST_FS, 358 .setup = xchk_setup_rtsummary, 359 .scrub = xchk_rtsummary, 360 .repair = xrep_rtsummary, 361 }, 362 [XFS_SCRUB_TYPE_UQUOTA] = { /* user quota */ 363 .type = ST_FS, 364 .setup = xchk_setup_quota, 365 .scrub = xchk_quota, 366 .repair = xrep_quota, 367 }, 368 [XFS_SCRUB_TYPE_GQUOTA] = { /* group quota */ 369 .type = ST_FS, 370 .setup = xchk_setup_quota, 371 .scrub = xchk_quota, 372 .repair = xrep_quota, 373 }, 374 [XFS_SCRUB_TYPE_PQUOTA] = { /* project quota */ 375 .type = ST_FS, 376 .setup = xchk_setup_quota, 377 .scrub = xchk_quota, 378 .repair = xrep_quota, 379 }, 380 [XFS_SCRUB_TYPE_FSCOUNTERS] = { /* fs summary counters */ 381 .type = ST_FS, 382 .setup = xchk_setup_fscounters, 383 .scrub = xchk_fscounters, 384 .repair = xrep_fscounters, 385 }, 386 [XFS_SCRUB_TYPE_QUOTACHECK] = { /* quota counters */ 387 .type = ST_FS, 388 .setup = xchk_setup_quotacheck, 389 .scrub = xchk_quotacheck, 390 .repair = xrep_quotacheck, 391 }, 392 [XFS_SCRUB_TYPE_NLINKS] = { /* inode link counts */ 393 .type = ST_FS, 394 .setup = xchk_setup_nlinks, 395 .scrub = xchk_nlinks, 396 .repair = xrep_nlinks, 397 }, 398 [XFS_SCRUB_TYPE_HEALTHY] = { /* fs healthy; clean all reminders */ 399 .type = ST_FS, 400 .setup = xchk_setup_fs, 401 .scrub = xchk_health_record, 402 .repair = xrep_notsupported, 403 }, 404 }; 405 406 static int 407 xchk_validate_inputs( 408 struct xfs_mount *mp, 409 struct xfs_scrub_metadata *sm) 410 { 411 int error; 412 const struct xchk_meta_ops *ops; 413 414 error = -EINVAL; 415 /* Check our inputs. */ 416 sm->sm_flags &= ~XFS_SCRUB_FLAGS_OUT; 417 if (sm->sm_flags & ~XFS_SCRUB_FLAGS_IN) 418 goto out; 419 /* sm_reserved[] must be zero */ 420 if (memchr_inv(sm->sm_reserved, 0, sizeof(sm->sm_reserved))) 421 goto out; 422 423 error = -ENOENT; 424 /* Do we know about this type of metadata? */ 425 if (sm->sm_type >= XFS_SCRUB_TYPE_NR) 426 goto out; 427 ops = &meta_scrub_ops[sm->sm_type]; 428 if (ops->setup == NULL || ops->scrub == NULL) 429 goto out; 430 /* Does this fs even support this type of metadata? */ 431 if (ops->has && !ops->has(mp)) 432 goto out; 433 434 error = -EINVAL; 435 /* restricting fields must be appropriate for type */ 436 switch (ops->type) { 437 case ST_NONE: 438 case ST_FS: 439 if (sm->sm_ino || sm->sm_gen || sm->sm_agno) 440 goto out; 441 break; 442 case ST_PERAG: 443 if (sm->sm_ino || sm->sm_gen || 444 sm->sm_agno >= mp->m_sb.sb_agcount) 445 goto out; 446 break; 447 case ST_INODE: 448 if (sm->sm_agno || (sm->sm_gen && !sm->sm_ino)) 449 goto out; 450 break; 451 default: 452 goto out; 453 } 454 455 /* No rebuild without repair. */ 456 if ((sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD) && 457 !(sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)) 458 return -EINVAL; 459 460 /* 461 * We only want to repair read-write v5+ filesystems. Defer the check 462 * for ops->repair until after our scrub confirms that we need to 463 * perform repairs so that we avoid failing due to not supporting 464 * repairing an object that doesn't need repairs. 465 */ 466 if (sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) { 467 error = -EOPNOTSUPP; 468 if (!xfs_has_crc(mp)) 469 goto out; 470 471 error = -EROFS; 472 if (xfs_is_readonly(mp)) 473 goto out; 474 } 475 476 error = 0; 477 out: 478 return error; 479 } 480 481 #ifdef CONFIG_XFS_ONLINE_REPAIR 482 static inline void xchk_postmortem(struct xfs_scrub *sc) 483 { 484 /* 485 * Userspace asked us to repair something, we repaired it, rescanned 486 * it, and the rescan says it's still broken. Scream about this in 487 * the system logs. 488 */ 489 if ((sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) && 490 (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT | 491 XFS_SCRUB_OFLAG_XCORRUPT))) 492 xrep_failure(sc->mp); 493 } 494 #else 495 static inline void xchk_postmortem(struct xfs_scrub *sc) 496 { 497 /* 498 * Userspace asked us to scrub something, it's broken, and we have no 499 * way of fixing it. Scream in the logs. 500 */ 501 if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT | 502 XFS_SCRUB_OFLAG_XCORRUPT)) 503 xfs_alert_ratelimited(sc->mp, 504 "Corruption detected during scrub."); 505 } 506 #endif /* CONFIG_XFS_ONLINE_REPAIR */ 507 508 /* Dispatch metadata scrubbing. */ 509 int 510 xfs_scrub_metadata( 511 struct file *file, 512 struct xfs_scrub_metadata *sm) 513 { 514 struct xchk_stats_run run = { }; 515 struct xfs_scrub *sc; 516 struct xfs_mount *mp = XFS_I(file_inode(file))->i_mount; 517 u64 check_start; 518 int error = 0; 519 520 BUILD_BUG_ON(sizeof(meta_scrub_ops) != 521 (sizeof(struct xchk_meta_ops) * XFS_SCRUB_TYPE_NR)); 522 523 trace_xchk_start(XFS_I(file_inode(file)), sm, error); 524 525 /* Forbidden if we are shut down or mounted norecovery. */ 526 error = -ESHUTDOWN; 527 if (xfs_is_shutdown(mp)) 528 goto out; 529 error = -ENOTRECOVERABLE; 530 if (xfs_has_norecovery(mp)) 531 goto out; 532 533 error = xchk_validate_inputs(mp, sm); 534 if (error) 535 goto out; 536 537 xfs_warn_mount(mp, XFS_OPSTATE_WARNED_SCRUB, 538 "EXPERIMENTAL online scrub feature in use. Use at your own risk!"); 539 540 sc = kzalloc(sizeof(struct xfs_scrub), XCHK_GFP_FLAGS); 541 if (!sc) { 542 error = -ENOMEM; 543 goto out; 544 } 545 546 sc->mp = mp; 547 sc->file = file; 548 sc->sm = sm; 549 sc->ops = &meta_scrub_ops[sm->sm_type]; 550 sc->sick_mask = xchk_health_mask_for_scrub_type(sm->sm_type); 551 retry_op: 552 /* 553 * When repairs are allowed, prevent freezing or readonly remount while 554 * scrub is running with a real transaction. 555 */ 556 if (sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) { 557 error = mnt_want_write_file(sc->file); 558 if (error) 559 goto out_sc; 560 561 sc->flags |= XCHK_HAVE_FREEZE_PROT; 562 } 563 564 /* Set up for the operation. */ 565 error = sc->ops->setup(sc); 566 if (error == -EDEADLOCK && !(sc->flags & XCHK_TRY_HARDER)) 567 goto try_harder; 568 if (error == -ECHRNG && !(sc->flags & XCHK_NEED_DRAIN)) 569 goto need_drain; 570 if (error) 571 goto out_teardown; 572 573 /* Scrub for errors. */ 574 check_start = xchk_stats_now(); 575 if ((sc->flags & XREP_ALREADY_FIXED) && sc->ops->repair_eval != NULL) 576 error = sc->ops->repair_eval(sc); 577 else 578 error = sc->ops->scrub(sc); 579 run.scrub_ns += xchk_stats_elapsed_ns(check_start); 580 if (error == -EDEADLOCK && !(sc->flags & XCHK_TRY_HARDER)) 581 goto try_harder; 582 if (error == -ECHRNG && !(sc->flags & XCHK_NEED_DRAIN)) 583 goto need_drain; 584 if (error || (sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)) 585 goto out_teardown; 586 587 xchk_update_health(sc); 588 589 if (xchk_could_repair(sc)) { 590 /* 591 * If userspace asked for a repair but it wasn't necessary, 592 * report that back to userspace. 593 */ 594 if (!xrep_will_attempt(sc)) { 595 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED; 596 goto out_nofix; 597 } 598 599 /* 600 * If it's broken, userspace wants us to fix it, and we haven't 601 * already tried to fix it, then attempt a repair. 602 */ 603 error = xrep_attempt(sc, &run); 604 if (error == -EAGAIN) { 605 /* 606 * Either the repair function succeeded or it couldn't 607 * get all the resources it needs; either way, we go 608 * back to the beginning and call the scrub function. 609 */ 610 error = xchk_teardown(sc, 0); 611 if (error) { 612 xrep_failure(mp); 613 goto out_sc; 614 } 615 goto retry_op; 616 } 617 } 618 619 out_nofix: 620 xchk_postmortem(sc); 621 out_teardown: 622 error = xchk_teardown(sc, error); 623 out_sc: 624 if (error != -ENOENT) 625 xchk_stats_merge(mp, sm, &run); 626 kfree(sc); 627 out: 628 trace_xchk_done(XFS_I(file_inode(file)), sm, error); 629 if (error == -EFSCORRUPTED || error == -EFSBADCRC) { 630 sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT; 631 error = 0; 632 } 633 return error; 634 need_drain: 635 error = xchk_teardown(sc, 0); 636 if (error) 637 goto out_sc; 638 sc->flags |= XCHK_NEED_DRAIN; 639 run.retries++; 640 goto retry_op; 641 try_harder: 642 /* 643 * Scrubbers return -EDEADLOCK to mean 'try harder'. Tear down 644 * everything we hold, then set up again with preparation for 645 * worst-case scenarios. 646 */ 647 error = xchk_teardown(sc, 0); 648 if (error) 649 goto out_sc; 650 sc->flags |= XCHK_TRY_HARDER; 651 run.retries++; 652 goto retry_op; 653 } 654