1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2019 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <darrick.wong@oracle.com> 5 */ 6 #include "xfs_platform.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_mount.h" 13 #include "xfs_inode.h" 14 #include "xfs_trace.h" 15 #include "xfs_health.h" 16 #include "xfs_ag.h" 17 #include "xfs_btree.h" 18 #include "xfs_da_format.h" 19 #include "xfs_da_btree.h" 20 #include "xfs_quota_defs.h" 21 #include "xfs_rtgroup.h" 22 #include "xfs_healthmon.h" 23 24 #include <linux/fserror.h> 25 26 static void 27 xfs_health_unmount_group( 28 struct xfs_group *xg, 29 bool *warn) 30 { 31 unsigned int sick = 0; 32 unsigned int checked = 0; 33 34 xfs_group_measure_sickness(xg, &sick, &checked); 35 if (sick) { 36 trace_xfs_group_unfixed_corruption(xg, sick); 37 *warn = true; 38 } 39 } 40 41 /* 42 * Warn about metadata corruption that we detected but haven't fixed, and 43 * make sure we're not sitting on anything that would get in the way of 44 * recovery. 45 */ 46 void 47 xfs_health_unmount( 48 struct xfs_mount *mp) 49 { 50 struct xfs_perag *pag = NULL; 51 struct xfs_rtgroup *rtg = NULL; 52 unsigned int sick = 0; 53 unsigned int checked = 0; 54 bool warn = false; 55 56 if (xfs_is_shutdown(mp)) 57 return; 58 59 /* Measure AG corruption levels. */ 60 while ((pag = xfs_perag_next(mp, pag))) 61 xfs_health_unmount_group(pag_group(pag), &warn); 62 63 /* Measure realtime group corruption levels. */ 64 while ((rtg = xfs_rtgroup_next(mp, rtg))) 65 xfs_health_unmount_group(rtg_group(rtg), &warn); 66 67 /* 68 * Measure fs corruption and keep the sample around for the warning. 69 * See the note below for why we exempt FS_COUNTERS. 70 */ 71 xfs_fs_measure_sickness(mp, &sick, &checked); 72 if (sick & ~XFS_SICK_FS_COUNTERS) { 73 trace_xfs_fs_unfixed_corruption(mp, sick); 74 warn = true; 75 } 76 77 if (warn) { 78 xfs_warn(mp, 79 "Uncorrected metadata errors detected; please run xfs_repair."); 80 81 /* 82 * We discovered uncorrected metadata problems at some point 83 * during this filesystem mount and have advised the 84 * administrator to run repair once the unmount completes. 85 * 86 * However, we must be careful -- when FSCOUNTERS are flagged 87 * unhealthy, the unmount procedure omits writing the clean 88 * unmount record to the log so that the next mount will run 89 * recovery and recompute the summary counters. In other 90 * words, we leave a dirty log to get the counters fixed. 91 * 92 * Unfortunately, xfs_repair cannot recover dirty logs, so if 93 * there were filesystem problems, FSCOUNTERS was flagged, and 94 * the administrator takes our advice to run xfs_repair, 95 * they'll have to zap the log before repairing structures. 96 * We don't really want to encourage this, so we mark the 97 * FSCOUNTERS healthy so that a subsequent repair run won't see 98 * a dirty log. 99 */ 100 if (sick & XFS_SICK_FS_COUNTERS) 101 xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS); 102 } 103 } 104 105 /* Mark unhealthy per-fs metadata. */ 106 void 107 xfs_fs_mark_sick( 108 struct xfs_mount *mp, 109 unsigned int mask) 110 { 111 unsigned int old_mask; 112 113 ASSERT(!(mask & ~XFS_SICK_FS_ALL)); 114 trace_xfs_fs_mark_sick(mp, mask); 115 116 spin_lock(&mp->m_sb_lock); 117 old_mask = mp->m_fs_sick; 118 mp->m_fs_sick |= mask; 119 spin_unlock(&mp->m_sb_lock); 120 121 fserror_report_metadata(mp->m_super, -EFSCORRUPTED, GFP_NOFS); 122 if (mask) 123 xfs_healthmon_report_fs(mp, XFS_HEALTHMON_SICK, old_mask, mask); 124 } 125 126 /* Mark per-fs metadata as having been checked and found unhealthy by fsck. */ 127 void 128 xfs_fs_mark_corrupt( 129 struct xfs_mount *mp, 130 unsigned int mask) 131 { 132 unsigned int old_mask; 133 134 ASSERT(!(mask & ~XFS_SICK_FS_ALL)); 135 trace_xfs_fs_mark_corrupt(mp, mask); 136 137 spin_lock(&mp->m_sb_lock); 138 old_mask = mp->m_fs_sick; 139 mp->m_fs_sick |= mask; 140 mp->m_fs_checked |= mask; 141 spin_unlock(&mp->m_sb_lock); 142 143 fserror_report_metadata(mp->m_super, -EFSCORRUPTED, GFP_NOFS); 144 if (mask) 145 xfs_healthmon_report_fs(mp, XFS_HEALTHMON_CORRUPT, old_mask, 146 mask); 147 } 148 149 /* Mark a per-fs metadata healed. */ 150 void 151 xfs_fs_mark_healthy( 152 struct xfs_mount *mp, 153 unsigned int mask) 154 { 155 unsigned int old_mask; 156 157 ASSERT(!(mask & ~XFS_SICK_FS_ALL)); 158 trace_xfs_fs_mark_healthy(mp, mask); 159 160 spin_lock(&mp->m_sb_lock); 161 old_mask = mp->m_fs_sick; 162 mp->m_fs_sick &= ~mask; 163 if (!(mp->m_fs_sick & XFS_SICK_FS_PRIMARY)) 164 mp->m_fs_sick &= ~XFS_SICK_FS_SECONDARY; 165 mp->m_fs_checked |= mask; 166 spin_unlock(&mp->m_sb_lock); 167 168 if (mask) 169 xfs_healthmon_report_fs(mp, XFS_HEALTHMON_HEALTHY, old_mask, 170 mask); 171 } 172 173 /* Sample which per-fs metadata are unhealthy. */ 174 void 175 xfs_fs_measure_sickness( 176 struct xfs_mount *mp, 177 unsigned int *sick, 178 unsigned int *checked) 179 { 180 spin_lock(&mp->m_sb_lock); 181 *sick = mp->m_fs_sick; 182 *checked = mp->m_fs_checked; 183 spin_unlock(&mp->m_sb_lock); 184 } 185 186 /* Mark unhealthy per-ag metadata given a raw AG number. */ 187 void 188 xfs_agno_mark_sick( 189 struct xfs_mount *mp, 190 xfs_agnumber_t agno, 191 unsigned int mask) 192 { 193 struct xfs_perag *pag = xfs_perag_get(mp, agno); 194 195 /* per-ag structure not set up yet? */ 196 if (!pag) 197 return; 198 199 xfs_ag_mark_sick(pag, mask); 200 xfs_perag_put(pag); 201 } 202 203 static inline void 204 xfs_group_check_mask( 205 struct xfs_group *xg, 206 unsigned int mask) 207 { 208 if (xg->xg_type == XG_TYPE_AG) 209 ASSERT(!(mask & ~XFS_SICK_AG_ALL)); 210 else 211 ASSERT(!(mask & ~XFS_SICK_RG_ALL)); 212 } 213 214 /* Mark unhealthy per-ag metadata. */ 215 void 216 xfs_group_mark_sick( 217 struct xfs_group *xg, 218 unsigned int mask) 219 { 220 unsigned int old_mask; 221 222 xfs_group_check_mask(xg, mask); 223 trace_xfs_group_mark_sick(xg, mask); 224 225 spin_lock(&xg->xg_state_lock); 226 old_mask = xg->xg_sick; 227 xg->xg_sick |= mask; 228 spin_unlock(&xg->xg_state_lock); 229 230 fserror_report_metadata(xg->xg_mount->m_super, -EFSCORRUPTED, GFP_NOFS); 231 if (mask) 232 xfs_healthmon_report_group(xg, XFS_HEALTHMON_SICK, old_mask, 233 mask); 234 } 235 236 /* 237 * Mark per-group metadata as having been checked and found unhealthy by fsck. 238 */ 239 void 240 xfs_group_mark_corrupt( 241 struct xfs_group *xg, 242 unsigned int mask) 243 { 244 unsigned int old_mask; 245 246 xfs_group_check_mask(xg, mask); 247 trace_xfs_group_mark_corrupt(xg, mask); 248 249 spin_lock(&xg->xg_state_lock); 250 old_mask = xg->xg_sick; 251 xg->xg_sick |= mask; 252 xg->xg_checked |= mask; 253 spin_unlock(&xg->xg_state_lock); 254 255 fserror_report_metadata(xg->xg_mount->m_super, -EFSCORRUPTED, GFP_NOFS); 256 if (mask) 257 xfs_healthmon_report_group(xg, XFS_HEALTHMON_CORRUPT, old_mask, 258 mask); 259 } 260 261 /* 262 * Mark per-group metadata ok. 263 */ 264 void 265 xfs_group_mark_healthy( 266 struct xfs_group *xg, 267 unsigned int mask) 268 { 269 unsigned int old_mask; 270 271 xfs_group_check_mask(xg, mask); 272 trace_xfs_group_mark_healthy(xg, mask); 273 274 spin_lock(&xg->xg_state_lock); 275 old_mask = xg->xg_sick; 276 xg->xg_sick &= ~mask; 277 if (!(xg->xg_sick & XFS_SICK_AG_PRIMARY)) 278 xg->xg_sick &= ~XFS_SICK_AG_SECONDARY; 279 xg->xg_checked |= mask; 280 spin_unlock(&xg->xg_state_lock); 281 282 if (mask) 283 xfs_healthmon_report_group(xg, XFS_HEALTHMON_HEALTHY, old_mask, 284 mask); 285 } 286 287 /* Sample which per-ag metadata are unhealthy. */ 288 void 289 xfs_group_measure_sickness( 290 struct xfs_group *xg, 291 unsigned int *sick, 292 unsigned int *checked) 293 { 294 spin_lock(&xg->xg_state_lock); 295 *sick = xg->xg_sick; 296 *checked = xg->xg_checked; 297 spin_unlock(&xg->xg_state_lock); 298 } 299 300 /* Mark unhealthy per-rtgroup metadata given a raw rt group number. */ 301 void 302 xfs_rgno_mark_sick( 303 struct xfs_mount *mp, 304 xfs_rgnumber_t rgno, 305 unsigned int mask) 306 { 307 struct xfs_rtgroup *rtg = xfs_rtgroup_get(mp, rgno); 308 309 /* per-rtgroup structure not set up yet? */ 310 if (!rtg) 311 return; 312 313 xfs_group_mark_sick(rtg_group(rtg), mask); 314 xfs_rtgroup_put(rtg); 315 } 316 317 static inline void xfs_inode_report_fserror(struct xfs_inode *ip) 318 { 319 /* 320 * Do not report inodes being constructed or freed, or metadata inodes, 321 * to fsnotify. 322 */ 323 if (xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIM) || 324 xfs_is_internal_inode(ip)) { 325 fserror_report_metadata(ip->i_mount->m_super, -EFSCORRUPTED, 326 GFP_NOFS); 327 return; 328 } 329 330 fserror_report_file_metadata(VFS_I(ip), -EFSCORRUPTED, GFP_NOFS); 331 } 332 333 /* Mark the unhealthy parts of an inode. */ 334 void 335 xfs_inode_mark_sick( 336 struct xfs_inode *ip, 337 unsigned int mask) 338 { 339 unsigned int old_mask; 340 341 ASSERT(!(mask & ~XFS_SICK_INO_ALL)); 342 trace_xfs_inode_mark_sick(ip, mask); 343 344 spin_lock(&ip->i_flags_lock); 345 old_mask = ip->i_sick; 346 ip->i_sick |= mask; 347 spin_unlock(&ip->i_flags_lock); 348 349 /* 350 * Keep this inode around so we don't lose the sickness report. Scrub 351 * grabs inodes with DONTCACHE assuming that most inode are ok, which 352 * is not the case here. 353 */ 354 spin_lock(&VFS_I(ip)->i_lock); 355 inode_state_clear(VFS_I(ip), I_DONTCACHE); 356 spin_unlock(&VFS_I(ip)->i_lock); 357 358 xfs_inode_report_fserror(ip); 359 if (mask) 360 xfs_healthmon_report_inode(ip, XFS_HEALTHMON_SICK, old_mask, 361 mask); 362 } 363 364 /* Mark inode metadata as having been checked and found unhealthy by fsck. */ 365 void 366 xfs_inode_mark_corrupt( 367 struct xfs_inode *ip, 368 unsigned int mask) 369 { 370 unsigned int old_mask; 371 372 ASSERT(!(mask & ~XFS_SICK_INO_ALL)); 373 trace_xfs_inode_mark_corrupt(ip, mask); 374 375 spin_lock(&ip->i_flags_lock); 376 old_mask = ip->i_sick; 377 ip->i_sick |= mask; 378 ip->i_checked |= mask; 379 spin_unlock(&ip->i_flags_lock); 380 381 /* 382 * Keep this inode around so we don't lose the sickness report. Scrub 383 * grabs inodes with DONTCACHE assuming that most inode are ok, which 384 * is not the case here. 385 */ 386 spin_lock(&VFS_I(ip)->i_lock); 387 inode_state_clear(VFS_I(ip), I_DONTCACHE); 388 spin_unlock(&VFS_I(ip)->i_lock); 389 390 xfs_inode_report_fserror(ip); 391 if (mask) 392 xfs_healthmon_report_inode(ip, XFS_HEALTHMON_CORRUPT, old_mask, 393 mask); 394 } 395 396 /* Mark parts of an inode healed. */ 397 void 398 xfs_inode_mark_healthy( 399 struct xfs_inode *ip, 400 unsigned int mask) 401 { 402 unsigned int old_mask; 403 404 ASSERT(!(mask & ~XFS_SICK_INO_ALL)); 405 trace_xfs_inode_mark_healthy(ip, mask); 406 407 spin_lock(&ip->i_flags_lock); 408 old_mask = ip->i_sick; 409 ip->i_sick &= ~mask; 410 if (!(ip->i_sick & XFS_SICK_INO_PRIMARY)) 411 ip->i_sick &= ~XFS_SICK_INO_SECONDARY; 412 ip->i_checked |= mask; 413 spin_unlock(&ip->i_flags_lock); 414 415 if (mask) 416 xfs_healthmon_report_inode(ip, XFS_HEALTHMON_HEALTHY, old_mask, 417 mask); 418 } 419 420 /* Sample which parts of an inode are unhealthy. */ 421 void 422 xfs_inode_measure_sickness( 423 struct xfs_inode *ip, 424 unsigned int *sick, 425 unsigned int *checked) 426 { 427 spin_lock(&ip->i_flags_lock); 428 *sick = ip->i_sick; 429 *checked = ip->i_checked; 430 spin_unlock(&ip->i_flags_lock); 431 } 432 433 /* Mappings between internal sick masks and ioctl sick masks. */ 434 435 struct ioctl_sick_map { 436 unsigned int sick_mask; 437 unsigned int ioctl_mask; 438 }; 439 440 #define for_each_sick_map(map, m) \ 441 for ((m) = (map); (m) < (map) + ARRAY_SIZE(map); (m)++) 442 443 static const struct ioctl_sick_map fs_map[] = { 444 { XFS_SICK_FS_COUNTERS, XFS_FSOP_GEOM_SICK_COUNTERS}, 445 { XFS_SICK_FS_UQUOTA, XFS_FSOP_GEOM_SICK_UQUOTA }, 446 { XFS_SICK_FS_GQUOTA, XFS_FSOP_GEOM_SICK_GQUOTA }, 447 { XFS_SICK_FS_PQUOTA, XFS_FSOP_GEOM_SICK_PQUOTA }, 448 { XFS_SICK_FS_QUOTACHECK, XFS_FSOP_GEOM_SICK_QUOTACHECK }, 449 { XFS_SICK_FS_NLINKS, XFS_FSOP_GEOM_SICK_NLINKS }, 450 { XFS_SICK_FS_METADIR, XFS_FSOP_GEOM_SICK_METADIR }, 451 { XFS_SICK_FS_METAPATH, XFS_FSOP_GEOM_SICK_METAPATH }, 452 }; 453 454 static const struct ioctl_sick_map rt_map[] = { 455 { XFS_SICK_RG_BITMAP, XFS_FSOP_GEOM_SICK_RT_BITMAP }, 456 { XFS_SICK_RG_SUMMARY, XFS_FSOP_GEOM_SICK_RT_SUMMARY }, 457 }; 458 459 static inline void 460 xfgeo_health_tick( 461 struct xfs_fsop_geom *geo, 462 unsigned int sick, 463 unsigned int checked, 464 const struct ioctl_sick_map *m) 465 { 466 if (checked & m->sick_mask) 467 geo->checked |= m->ioctl_mask; 468 if (sick & m->sick_mask) 469 geo->sick |= m->ioctl_mask; 470 } 471 472 /* Fill out fs geometry health info. */ 473 void 474 xfs_fsop_geom_health( 475 struct xfs_mount *mp, 476 struct xfs_fsop_geom *geo) 477 { 478 struct xfs_rtgroup *rtg = NULL; 479 const struct ioctl_sick_map *m; 480 unsigned int sick; 481 unsigned int checked; 482 483 geo->sick = 0; 484 geo->checked = 0; 485 486 xfs_fs_measure_sickness(mp, &sick, &checked); 487 for_each_sick_map(fs_map, m) 488 xfgeo_health_tick(geo, sick, checked, m); 489 490 while ((rtg = xfs_rtgroup_next(mp, rtg))) { 491 xfs_group_measure_sickness(rtg_group(rtg), &sick, &checked); 492 for_each_sick_map(rt_map, m) 493 xfgeo_health_tick(geo, sick, checked, m); 494 } 495 } 496 497 /* 498 * Translate XFS_SICK_FS_* into XFS_FSOP_GEOM_SICK_* except for the rt free 499 * space codes, which are sent via the rtgroup events. 500 */ 501 unsigned int 502 xfs_healthmon_fs_mask( 503 unsigned int sick_mask) 504 { 505 const struct ioctl_sick_map *m; 506 unsigned int ioctl_mask = 0; 507 508 for_each_sick_map(fs_map, m) { 509 if (sick_mask & m->sick_mask) 510 ioctl_mask |= m->ioctl_mask; 511 } 512 513 return ioctl_mask; 514 } 515 516 static const struct ioctl_sick_map ag_map[] = { 517 { XFS_SICK_AG_SB, XFS_AG_GEOM_SICK_SB }, 518 { XFS_SICK_AG_AGF, XFS_AG_GEOM_SICK_AGF }, 519 { XFS_SICK_AG_AGFL, XFS_AG_GEOM_SICK_AGFL }, 520 { XFS_SICK_AG_AGI, XFS_AG_GEOM_SICK_AGI }, 521 { XFS_SICK_AG_BNOBT, XFS_AG_GEOM_SICK_BNOBT }, 522 { XFS_SICK_AG_CNTBT, XFS_AG_GEOM_SICK_CNTBT }, 523 { XFS_SICK_AG_INOBT, XFS_AG_GEOM_SICK_INOBT }, 524 { XFS_SICK_AG_FINOBT, XFS_AG_GEOM_SICK_FINOBT }, 525 { XFS_SICK_AG_RMAPBT, XFS_AG_GEOM_SICK_RMAPBT }, 526 { XFS_SICK_AG_REFCNTBT, XFS_AG_GEOM_SICK_REFCNTBT }, 527 { XFS_SICK_AG_INODES, XFS_AG_GEOM_SICK_INODES }, 528 }; 529 530 /* Fill out ag geometry health info. */ 531 void 532 xfs_ag_geom_health( 533 struct xfs_perag *pag, 534 struct xfs_ag_geometry *ageo) 535 { 536 const struct ioctl_sick_map *m; 537 unsigned int sick; 538 unsigned int checked; 539 540 ageo->ag_sick = 0; 541 ageo->ag_checked = 0; 542 543 xfs_group_measure_sickness(pag_group(pag), &sick, &checked); 544 for_each_sick_map(ag_map, m) { 545 if (checked & m->sick_mask) 546 ageo->ag_checked |= m->ioctl_mask; 547 if (sick & m->sick_mask) 548 ageo->ag_sick |= m->ioctl_mask; 549 } 550 } 551 552 /* Translate XFS_SICK_AG_* into XFS_AG_GEOM_SICK_*. */ 553 unsigned int 554 xfs_healthmon_perag_mask( 555 unsigned int sick_mask) 556 { 557 const struct ioctl_sick_map *m; 558 unsigned int ioctl_mask = 0; 559 560 for_each_sick_map(ag_map, m) { 561 if (sick_mask & m->sick_mask) 562 ioctl_mask |= m->ioctl_mask; 563 } 564 565 return ioctl_mask; 566 } 567 568 static const struct ioctl_sick_map rtgroup_map[] = { 569 { XFS_SICK_RG_SUPER, XFS_RTGROUP_GEOM_SICK_SUPER }, 570 { XFS_SICK_RG_BITMAP, XFS_RTGROUP_GEOM_SICK_BITMAP }, 571 { XFS_SICK_RG_SUMMARY, XFS_RTGROUP_GEOM_SICK_SUMMARY }, 572 { XFS_SICK_RG_RMAPBT, XFS_RTGROUP_GEOM_SICK_RMAPBT }, 573 { XFS_SICK_RG_REFCNTBT, XFS_RTGROUP_GEOM_SICK_REFCNTBT }, 574 }; 575 576 /* Fill out rtgroup geometry health info. */ 577 void 578 xfs_rtgroup_geom_health( 579 struct xfs_rtgroup *rtg, 580 struct xfs_rtgroup_geometry *rgeo) 581 { 582 const struct ioctl_sick_map *m; 583 unsigned int sick; 584 unsigned int checked; 585 586 rgeo->rg_sick = 0; 587 rgeo->rg_checked = 0; 588 589 xfs_group_measure_sickness(rtg_group(rtg), &sick, &checked); 590 for_each_sick_map(rtgroup_map, m) { 591 if (checked & m->sick_mask) 592 rgeo->rg_checked |= m->ioctl_mask; 593 if (sick & m->sick_mask) 594 rgeo->rg_sick |= m->ioctl_mask; 595 } 596 } 597 598 /* Translate XFS_SICK_RG_* into XFS_RTGROUP_GEOM_SICK_*. */ 599 unsigned int 600 xfs_healthmon_rtgroup_mask( 601 unsigned int sick_mask) 602 { 603 const struct ioctl_sick_map *m; 604 unsigned int ioctl_mask = 0; 605 606 for_each_sick_map(rtgroup_map, m) { 607 if (sick_mask & m->sick_mask) 608 ioctl_mask |= m->ioctl_mask; 609 } 610 611 return ioctl_mask; 612 } 613 614 static const struct ioctl_sick_map ino_map[] = { 615 { XFS_SICK_INO_CORE, XFS_BS_SICK_INODE }, 616 { XFS_SICK_INO_BMBTD, XFS_BS_SICK_BMBTD }, 617 { XFS_SICK_INO_BMBTA, XFS_BS_SICK_BMBTA }, 618 { XFS_SICK_INO_BMBTC, XFS_BS_SICK_BMBTC }, 619 { XFS_SICK_INO_DIR, XFS_BS_SICK_DIR }, 620 { XFS_SICK_INO_XATTR, XFS_BS_SICK_XATTR }, 621 { XFS_SICK_INO_SYMLINK, XFS_BS_SICK_SYMLINK }, 622 { XFS_SICK_INO_PARENT, XFS_BS_SICK_PARENT }, 623 { XFS_SICK_INO_BMBTD_ZAPPED, XFS_BS_SICK_BMBTD }, 624 { XFS_SICK_INO_BMBTA_ZAPPED, XFS_BS_SICK_BMBTA }, 625 { XFS_SICK_INO_DIR_ZAPPED, XFS_BS_SICK_DIR }, 626 { XFS_SICK_INO_SYMLINK_ZAPPED, XFS_BS_SICK_SYMLINK }, 627 { XFS_SICK_INO_DIRTREE, XFS_BS_SICK_DIRTREE }, 628 }; 629 630 /* Fill out bulkstat health info. */ 631 void 632 xfs_bulkstat_health( 633 struct xfs_inode *ip, 634 struct xfs_bulkstat *bs) 635 { 636 const struct ioctl_sick_map *m; 637 unsigned int sick; 638 unsigned int checked; 639 640 bs->bs_sick = 0; 641 bs->bs_checked = 0; 642 643 xfs_inode_measure_sickness(ip, &sick, &checked); 644 for_each_sick_map(ino_map, m) { 645 if (checked & m->sick_mask) 646 bs->bs_checked |= m->ioctl_mask; 647 if (sick & m->sick_mask) 648 bs->bs_sick |= m->ioctl_mask; 649 } 650 } 651 652 /* Translate XFS_SICK_INO_* into XFS_BS_SICK_*. */ 653 unsigned int 654 xfs_healthmon_inode_mask( 655 unsigned int sick_mask) 656 { 657 const struct ioctl_sick_map *m; 658 unsigned int ioctl_mask = 0; 659 660 for_each_sick_map(ino_map, m) { 661 if (sick_mask & m->sick_mask) 662 ioctl_mask |= m->ioctl_mask; 663 } 664 665 return ioctl_mask; 666 } 667 668 /* Mark a block mapping sick. */ 669 void 670 xfs_bmap_mark_sick( 671 struct xfs_inode *ip, 672 int whichfork) 673 { 674 unsigned int mask; 675 676 switch (whichfork) { 677 case XFS_DATA_FORK: 678 mask = XFS_SICK_INO_BMBTD; 679 break; 680 case XFS_ATTR_FORK: 681 mask = XFS_SICK_INO_BMBTA; 682 break; 683 case XFS_COW_FORK: 684 mask = XFS_SICK_INO_BMBTC; 685 break; 686 default: 687 ASSERT(0); 688 return; 689 } 690 691 xfs_inode_mark_sick(ip, mask); 692 } 693 694 /* Record observations of btree corruption with the health tracking system. */ 695 void 696 xfs_btree_mark_sick( 697 struct xfs_btree_cur *cur) 698 { 699 if (xfs_btree_is_bmap(cur->bc_ops)) { 700 xfs_bmap_mark_sick(cur->bc_ino.ip, cur->bc_ino.whichfork); 701 /* no health state tracking for ephemeral btrees */ 702 } else if (cur->bc_ops->type != XFS_BTREE_TYPE_MEM) { 703 ASSERT(cur->bc_group); 704 ASSERT(cur->bc_ops->sick_mask); 705 xfs_group_mark_sick(cur->bc_group, cur->bc_ops->sick_mask); 706 } 707 } 708 709 /* 710 * Record observations of dir/attr btree corruption with the health tracking 711 * system. 712 */ 713 void 714 xfs_dirattr_mark_sick( 715 struct xfs_inode *ip, 716 int whichfork) 717 { 718 unsigned int mask; 719 720 switch (whichfork) { 721 case XFS_DATA_FORK: 722 mask = XFS_SICK_INO_DIR; 723 break; 724 case XFS_ATTR_FORK: 725 mask = XFS_SICK_INO_XATTR; 726 break; 727 default: 728 ASSERT(0); 729 return; 730 } 731 732 xfs_inode_mark_sick(ip, mask); 733 } 734 735 /* 736 * Record observations of dir/attr btree corruption with the health tracking 737 * system. 738 */ 739 void 740 xfs_da_mark_sick( 741 struct xfs_da_args *args) 742 { 743 xfs_dirattr_mark_sick(args->dp, args->whichfork); 744 } 745