at master 18 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2014 Red Hat, Inc. 4 * All Rights Reserved. 5 */ 6 7#include "xfs.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_sysfs.h" 13#include "xfs_log.h" 14#include "xfs_log_priv.h" 15#include "xfs_mount.h" 16#include "xfs_zones.h" 17 18struct xfs_sysfs_attr { 19 struct attribute attr; 20 ssize_t (*show)(struct kobject *kobject, char *buf); 21 ssize_t (*store)(struct kobject *kobject, const char *buf, 22 size_t count); 23}; 24 25static inline struct xfs_sysfs_attr * 26to_attr(struct attribute *attr) 27{ 28 return container_of(attr, struct xfs_sysfs_attr, attr); 29} 30 31#define XFS_SYSFS_ATTR_RW(name) \ 32 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RW(name) 33#define XFS_SYSFS_ATTR_RO(name) \ 34 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RO(name) 35#define XFS_SYSFS_ATTR_WO(name) \ 36 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_WO(name) 37 38#define ATTR_LIST(name) &xfs_sysfs_attr_##name.attr 39 40STATIC ssize_t 41xfs_sysfs_object_show( 42 struct kobject *kobject, 43 struct attribute *attr, 44 char *buf) 45{ 46 struct xfs_sysfs_attr *xfs_attr = to_attr(attr); 47 48 return xfs_attr->show ? xfs_attr->show(kobject, buf) : 0; 49} 50 51STATIC ssize_t 52xfs_sysfs_object_store( 53 struct kobject *kobject, 54 struct attribute *attr, 55 const char *buf, 56 size_t count) 57{ 58 struct xfs_sysfs_attr *xfs_attr = to_attr(attr); 59 60 return xfs_attr->store ? xfs_attr->store(kobject, buf, count) : 0; 61} 62 63static const struct sysfs_ops xfs_sysfs_ops = { 64 .show = xfs_sysfs_object_show, 65 .store = xfs_sysfs_object_store, 66}; 67 68static struct attribute *xfs_mp_attrs[] = { 69 NULL, 70}; 71ATTRIBUTE_GROUPS(xfs_mp); 72 73static const struct kobj_type xfs_mp_ktype = { 74 .release = xfs_sysfs_release, 75 .sysfs_ops = &xfs_sysfs_ops, 76 .default_groups = xfs_mp_groups, 77}; 78 79#ifdef DEBUG 80/* debug */ 81 82STATIC ssize_t 83bug_on_assert_store( 84 struct kobject *kobject, 85 const char *buf, 86 size_t count) 87{ 88 int ret; 89 int val; 90 91 ret = kstrtoint(buf, 0, &val); 92 if (ret) 93 return ret; 94 95 if (val == 1) 96 xfs_globals.bug_on_assert = true; 97 else if (val == 0) 98 xfs_globals.bug_on_assert = false; 99 else 100 return -EINVAL; 101 102 return count; 103} 104 105STATIC ssize_t 106bug_on_assert_show( 107 struct kobject *kobject, 108 char *buf) 109{ 110 return sysfs_emit(buf, "%d\n", xfs_globals.bug_on_assert); 111} 112XFS_SYSFS_ATTR_RW(bug_on_assert); 113 114STATIC ssize_t 115log_recovery_delay_store( 116 struct kobject *kobject, 117 const char *buf, 118 size_t count) 119{ 120 int ret; 121 int val; 122 123 ret = kstrtoint(buf, 0, &val); 124 if (ret) 125 return ret; 126 127 if (val < 0 || val > 60) 128 return -EINVAL; 129 130 xfs_globals.log_recovery_delay = val; 131 132 return count; 133} 134 135STATIC ssize_t 136log_recovery_delay_show( 137 struct kobject *kobject, 138 char *buf) 139{ 140 return sysfs_emit(buf, "%d\n", xfs_globals.log_recovery_delay); 141} 142XFS_SYSFS_ATTR_RW(log_recovery_delay); 143 144STATIC ssize_t 145mount_delay_store( 146 struct kobject *kobject, 147 const char *buf, 148 size_t count) 149{ 150 int ret; 151 int val; 152 153 ret = kstrtoint(buf, 0, &val); 154 if (ret) 155 return ret; 156 157 if (val < 0 || val > 60) 158 return -EINVAL; 159 160 xfs_globals.mount_delay = val; 161 162 return count; 163} 164 165STATIC ssize_t 166mount_delay_show( 167 struct kobject *kobject, 168 char *buf) 169{ 170 return sysfs_emit(buf, "%d\n", xfs_globals.mount_delay); 171} 172XFS_SYSFS_ATTR_RW(mount_delay); 173 174static ssize_t 175always_cow_store( 176 struct kobject *kobject, 177 const char *buf, 178 size_t count) 179{ 180 ssize_t ret; 181 182 ret = kstrtobool(buf, &xfs_globals.always_cow); 183 if (ret < 0) 184 return ret; 185 return count; 186} 187 188static ssize_t 189always_cow_show( 190 struct kobject *kobject, 191 char *buf) 192{ 193 return sysfs_emit(buf, "%d\n", xfs_globals.always_cow); 194} 195XFS_SYSFS_ATTR_RW(always_cow); 196 197/* 198 * Override how many threads the parallel work queue is allowed to create. 199 * This has to be a debug-only global (instead of an errortag) because one of 200 * the main users of parallel workqueues is mount time quotacheck. 201 */ 202STATIC ssize_t 203pwork_threads_store( 204 struct kobject *kobject, 205 const char *buf, 206 size_t count) 207{ 208 int ret; 209 int val; 210 211 ret = kstrtoint(buf, 0, &val); 212 if (ret) 213 return ret; 214 215 if (val < -1 || val > num_possible_cpus()) 216 return -EINVAL; 217 218 xfs_globals.pwork_threads = val; 219 220 return count; 221} 222 223STATIC ssize_t 224pwork_threads_show( 225 struct kobject *kobject, 226 char *buf) 227{ 228 return sysfs_emit(buf, "%d\n", xfs_globals.pwork_threads); 229} 230XFS_SYSFS_ATTR_RW(pwork_threads); 231 232/* 233 * The "LARP" (Logged extended Attribute Recovery Persistence) debugging knob 234 * sets the XFS_DA_OP_LOGGED flag on all xfs_attr_set operations performed on 235 * V5 filesystems. As a result, the intermediate progress of all setxattr and 236 * removexattr operations are tracked via the log and can be restarted during 237 * recovery. This is useful for testing xattr recovery prior to merging of the 238 * parent pointer feature which requires it to maintain consistency, and may be 239 * enabled for userspace xattrs in the future. 240 */ 241static ssize_t 242larp_store( 243 struct kobject *kobject, 244 const char *buf, 245 size_t count) 246{ 247 ssize_t ret; 248 249 ret = kstrtobool(buf, &xfs_globals.larp); 250 if (ret < 0) 251 return ret; 252 return count; 253} 254 255STATIC ssize_t 256larp_show( 257 struct kobject *kobject, 258 char *buf) 259{ 260 return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.larp); 261} 262XFS_SYSFS_ATTR_RW(larp); 263 264STATIC ssize_t 265bload_leaf_slack_store( 266 struct kobject *kobject, 267 const char *buf, 268 size_t count) 269{ 270 int ret; 271 int val; 272 273 ret = kstrtoint(buf, 0, &val); 274 if (ret) 275 return ret; 276 277 xfs_globals.bload_leaf_slack = val; 278 return count; 279} 280 281STATIC ssize_t 282bload_leaf_slack_show( 283 struct kobject *kobject, 284 char *buf) 285{ 286 return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.bload_leaf_slack); 287} 288XFS_SYSFS_ATTR_RW(bload_leaf_slack); 289 290STATIC ssize_t 291bload_node_slack_store( 292 struct kobject *kobject, 293 const char *buf, 294 size_t count) 295{ 296 int ret; 297 int val; 298 299 ret = kstrtoint(buf, 0, &val); 300 if (ret) 301 return ret; 302 303 xfs_globals.bload_node_slack = val; 304 return count; 305} 306 307STATIC ssize_t 308bload_node_slack_show( 309 struct kobject *kobject, 310 char *buf) 311{ 312 return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.bload_node_slack); 313} 314XFS_SYSFS_ATTR_RW(bload_node_slack); 315 316static struct attribute *xfs_dbg_attrs[] = { 317 ATTR_LIST(bug_on_assert), 318 ATTR_LIST(log_recovery_delay), 319 ATTR_LIST(mount_delay), 320 ATTR_LIST(always_cow), 321 ATTR_LIST(pwork_threads), 322 ATTR_LIST(larp), 323 ATTR_LIST(bload_leaf_slack), 324 ATTR_LIST(bload_node_slack), 325 NULL, 326}; 327ATTRIBUTE_GROUPS(xfs_dbg); 328 329const struct kobj_type xfs_dbg_ktype = { 330 .release = xfs_sysfs_release, 331 .sysfs_ops = &xfs_sysfs_ops, 332 .default_groups = xfs_dbg_groups, 333}; 334 335#endif /* DEBUG */ 336 337/* stats */ 338 339static inline struct xstats * 340to_xstats(struct kobject *kobject) 341{ 342 struct xfs_kobj *kobj = to_kobj(kobject); 343 344 return container_of(kobj, struct xstats, xs_kobj); 345} 346 347STATIC ssize_t 348stats_show( 349 struct kobject *kobject, 350 char *buf) 351{ 352 struct xstats *stats = to_xstats(kobject); 353 354 return xfs_stats_format(stats->xs_stats, buf); 355} 356XFS_SYSFS_ATTR_RO(stats); 357 358STATIC ssize_t 359stats_clear_store( 360 struct kobject *kobject, 361 const char *buf, 362 size_t count) 363{ 364 int ret; 365 int val; 366 struct xstats *stats = to_xstats(kobject); 367 368 ret = kstrtoint(buf, 0, &val); 369 if (ret) 370 return ret; 371 372 if (val != 1) 373 return -EINVAL; 374 375 xfs_stats_clearall(stats->xs_stats); 376 return count; 377} 378XFS_SYSFS_ATTR_WO(stats_clear); 379 380static struct attribute *xfs_stats_attrs[] = { 381 ATTR_LIST(stats), 382 ATTR_LIST(stats_clear), 383 NULL, 384}; 385ATTRIBUTE_GROUPS(xfs_stats); 386 387const struct kobj_type xfs_stats_ktype = { 388 .release = xfs_sysfs_release, 389 .sysfs_ops = &xfs_sysfs_ops, 390 .default_groups = xfs_stats_groups, 391}; 392 393/* xlog */ 394 395static inline struct xlog * 396to_xlog(struct kobject *kobject) 397{ 398 struct xfs_kobj *kobj = to_kobj(kobject); 399 400 return container_of(kobj, struct xlog, l_kobj); 401} 402 403STATIC ssize_t 404log_head_lsn_show( 405 struct kobject *kobject, 406 char *buf) 407{ 408 int cycle; 409 int block; 410 struct xlog *log = to_xlog(kobject); 411 412 spin_lock(&log->l_icloglock); 413 cycle = log->l_curr_cycle; 414 block = log->l_curr_block; 415 spin_unlock(&log->l_icloglock); 416 417 return sysfs_emit(buf, "%d:%d\n", cycle, block); 418} 419XFS_SYSFS_ATTR_RO(log_head_lsn); 420 421STATIC ssize_t 422log_tail_lsn_show( 423 struct kobject *kobject, 424 char *buf) 425{ 426 int cycle; 427 int block; 428 struct xlog *log = to_xlog(kobject); 429 430 xlog_crack_atomic_lsn(&log->l_tail_lsn, &cycle, &block); 431 return sysfs_emit(buf, "%d:%d\n", cycle, block); 432} 433XFS_SYSFS_ATTR_RO(log_tail_lsn); 434 435STATIC ssize_t 436reserve_grant_head_bytes_show( 437 struct kobject *kobject, 438 char *buf) 439{ 440 return sysfs_emit(buf, "%lld\n", 441 atomic64_read(&to_xlog(kobject)->l_reserve_head.grant)); 442} 443XFS_SYSFS_ATTR_RO(reserve_grant_head_bytes); 444 445STATIC ssize_t 446write_grant_head_bytes_show( 447 struct kobject *kobject, 448 char *buf) 449{ 450 return sysfs_emit(buf, "%lld\n", 451 atomic64_read(&to_xlog(kobject)->l_write_head.grant)); 452} 453XFS_SYSFS_ATTR_RO(write_grant_head_bytes); 454 455static struct attribute *xfs_log_attrs[] = { 456 ATTR_LIST(log_head_lsn), 457 ATTR_LIST(log_tail_lsn), 458 ATTR_LIST(reserve_grant_head_bytes), 459 ATTR_LIST(write_grant_head_bytes), 460 NULL, 461}; 462ATTRIBUTE_GROUPS(xfs_log); 463 464const struct kobj_type xfs_log_ktype = { 465 .release = xfs_sysfs_release, 466 .sysfs_ops = &xfs_sysfs_ops, 467 .default_groups = xfs_log_groups, 468}; 469 470/* 471 * Metadata IO error configuration 472 * 473 * The sysfs structure here is: 474 * ...xfs/<dev>/error/<class>/<errno>/<error_attrs> 475 * 476 * where <class> allows us to discriminate between data IO and metadata IO, 477 * and any other future type of IO (e.g. special inode or directory error 478 * handling) we care to support. 479 */ 480static inline struct xfs_error_cfg * 481to_error_cfg(struct kobject *kobject) 482{ 483 struct xfs_kobj *kobj = to_kobj(kobject); 484 return container_of(kobj, struct xfs_error_cfg, kobj); 485} 486 487static inline struct xfs_mount * 488err_to_mp(struct kobject *kobject) 489{ 490 struct xfs_kobj *kobj = to_kobj(kobject); 491 return container_of(kobj, struct xfs_mount, m_error_kobj); 492} 493 494static ssize_t 495max_retries_show( 496 struct kobject *kobject, 497 char *buf) 498{ 499 int retries; 500 struct xfs_error_cfg *cfg = to_error_cfg(kobject); 501 502 if (cfg->max_retries == XFS_ERR_RETRY_FOREVER) 503 retries = -1; 504 else 505 retries = cfg->max_retries; 506 507 return sysfs_emit(buf, "%d\n", retries); 508} 509 510static ssize_t 511max_retries_store( 512 struct kobject *kobject, 513 const char *buf, 514 size_t count) 515{ 516 struct xfs_error_cfg *cfg = to_error_cfg(kobject); 517 int ret; 518 int val; 519 520 ret = kstrtoint(buf, 0, &val); 521 if (ret) 522 return ret; 523 524 if (val < -1) 525 return -EINVAL; 526 527 if (val == -1) 528 cfg->max_retries = XFS_ERR_RETRY_FOREVER; 529 else 530 cfg->max_retries = val; 531 return count; 532} 533XFS_SYSFS_ATTR_RW(max_retries); 534 535static ssize_t 536retry_timeout_seconds_show( 537 struct kobject *kobject, 538 char *buf) 539{ 540 int timeout; 541 struct xfs_error_cfg *cfg = to_error_cfg(kobject); 542 543 if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER) 544 timeout = -1; 545 else 546 timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC; 547 548 return sysfs_emit(buf, "%d\n", timeout); 549} 550 551static ssize_t 552retry_timeout_seconds_store( 553 struct kobject *kobject, 554 const char *buf, 555 size_t count) 556{ 557 struct xfs_error_cfg *cfg = to_error_cfg(kobject); 558 int ret; 559 int val; 560 561 ret = kstrtoint(buf, 0, &val); 562 if (ret) 563 return ret; 564 565 /* 1 day timeout maximum, -1 means infinite */ 566 if (val < -1 || val > 86400) 567 return -EINVAL; 568 569 if (val == -1) 570 cfg->retry_timeout = XFS_ERR_RETRY_FOREVER; 571 else { 572 cfg->retry_timeout = secs_to_jiffies(val); 573 ASSERT(secs_to_jiffies(val) < LONG_MAX); 574 } 575 return count; 576} 577XFS_SYSFS_ATTR_RW(retry_timeout_seconds); 578 579static ssize_t 580fail_at_unmount_show( 581 struct kobject *kobject, 582 char *buf) 583{ 584 struct xfs_mount *mp = err_to_mp(kobject); 585 586 return sysfs_emit(buf, "%d\n", mp->m_fail_unmount); 587} 588 589static ssize_t 590fail_at_unmount_store( 591 struct kobject *kobject, 592 const char *buf, 593 size_t count) 594{ 595 struct xfs_mount *mp = err_to_mp(kobject); 596 int ret; 597 int val; 598 599 ret = kstrtoint(buf, 0, &val); 600 if (ret) 601 return ret; 602 603 if (val < 0 || val > 1) 604 return -EINVAL; 605 606 mp->m_fail_unmount = val; 607 return count; 608} 609XFS_SYSFS_ATTR_RW(fail_at_unmount); 610 611static struct attribute *xfs_error_attrs[] = { 612 ATTR_LIST(max_retries), 613 ATTR_LIST(retry_timeout_seconds), 614 NULL, 615}; 616ATTRIBUTE_GROUPS(xfs_error); 617 618static const struct kobj_type xfs_error_cfg_ktype = { 619 .release = xfs_sysfs_release, 620 .sysfs_ops = &xfs_sysfs_ops, 621 .default_groups = xfs_error_groups, 622}; 623 624static const struct kobj_type xfs_error_ktype = { 625 .release = xfs_sysfs_release, 626 .sysfs_ops = &xfs_sysfs_ops, 627}; 628 629/* 630 * Error initialization tables. These need to be ordered in the same 631 * order as the enums used to index the array. All class init tables need to 632 * define a "default" behaviour as the first entry, all other entries can be 633 * empty. 634 */ 635struct xfs_error_init { 636 char *name; 637 int max_retries; 638 int retry_timeout; /* in seconds */ 639}; 640 641static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = { 642 { .name = "default", 643 .max_retries = XFS_ERR_RETRY_FOREVER, 644 .retry_timeout = XFS_ERR_RETRY_FOREVER, 645 }, 646 { .name = "EIO", 647 .max_retries = XFS_ERR_RETRY_FOREVER, 648 .retry_timeout = XFS_ERR_RETRY_FOREVER, 649 }, 650 { .name = "ENOSPC", 651 .max_retries = XFS_ERR_RETRY_FOREVER, 652 .retry_timeout = XFS_ERR_RETRY_FOREVER, 653 }, 654 { .name = "ENODEV", 655 .max_retries = 0, /* We can't recover from devices disappearing */ 656 .retry_timeout = 0, 657 }, 658}; 659 660static int 661xfs_error_sysfs_init_class( 662 struct xfs_mount *mp, 663 int class, 664 const char *parent_name, 665 struct xfs_kobj *parent_kobj, 666 const struct xfs_error_init init[]) 667{ 668 struct xfs_error_cfg *cfg; 669 int error; 670 int i; 671 672 ASSERT(class < XFS_ERR_CLASS_MAX); 673 674 error = xfs_sysfs_init(parent_kobj, &xfs_error_ktype, 675 &mp->m_error_kobj, parent_name); 676 if (error) 677 return error; 678 679 for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) { 680 cfg = &mp->m_error_cfg[class][i]; 681 error = xfs_sysfs_init(&cfg->kobj, &xfs_error_cfg_ktype, 682 parent_kobj, init[i].name); 683 if (error) 684 goto out_error; 685 686 cfg->max_retries = init[i].max_retries; 687 if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER) 688 cfg->retry_timeout = XFS_ERR_RETRY_FOREVER; 689 else 690 cfg->retry_timeout = 691 secs_to_jiffies(init[i].retry_timeout); 692 } 693 return 0; 694 695out_error: 696 /* unwind the entries that succeeded */ 697 for (i--; i >= 0; i--) { 698 cfg = &mp->m_error_cfg[class][i]; 699 xfs_sysfs_del(&cfg->kobj); 700 } 701 xfs_sysfs_del(parent_kobj); 702 return error; 703} 704 705static inline struct xfs_mount *zoned_to_mp(struct kobject *kobj) 706{ 707 return container_of(to_kobj(kobj), struct xfs_mount, m_zoned_kobj); 708} 709 710static ssize_t 711max_open_zones_show( 712 struct kobject *kobj, 713 char *buf) 714{ 715 /* only report the open zones available for user data */ 716 return sysfs_emit(buf, "%u\n", 717 zoned_to_mp(kobj)->m_max_open_zones - XFS_OPEN_GC_ZONES); 718} 719XFS_SYSFS_ATTR_RO(max_open_zones); 720 721static ssize_t 722zonegc_low_space_store( 723 struct kobject *kobj, 724 const char *buf, 725 size_t count) 726{ 727 int ret; 728 unsigned int val; 729 730 ret = kstrtouint(buf, 0, &val); 731 if (ret) 732 return ret; 733 734 if (val > 100) 735 return -EINVAL; 736 737 zoned_to_mp(kobj)->m_zonegc_low_space = val; 738 739 return count; 740} 741 742static ssize_t 743zonegc_low_space_show( 744 struct kobject *kobj, 745 char *buf) 746{ 747 return sysfs_emit(buf, "%u\n", 748 zoned_to_mp(kobj)->m_zonegc_low_space); 749} 750XFS_SYSFS_ATTR_RW(zonegc_low_space); 751 752static struct attribute *xfs_zoned_attrs[] = { 753 ATTR_LIST(max_open_zones), 754 ATTR_LIST(zonegc_low_space), 755 NULL, 756}; 757ATTRIBUTE_GROUPS(xfs_zoned); 758 759static const struct kobj_type xfs_zoned_ktype = { 760 .release = xfs_sysfs_release, 761 .sysfs_ops = &xfs_sysfs_ops, 762 .default_groups = xfs_zoned_groups, 763}; 764 765int 766xfs_mount_sysfs_init( 767 struct xfs_mount *mp) 768{ 769 int error; 770 771 super_set_sysfs_name_id(mp->m_super); 772 773 /* .../xfs/<dev>/ */ 774 error = xfs_sysfs_init(&mp->m_kobj, &xfs_mp_ktype, 775 NULL, mp->m_super->s_id); 776 if (error) 777 return error; 778 779 /* .../xfs/<dev>/stats/ */ 780 error = xfs_sysfs_init(&mp->m_stats.xs_kobj, &xfs_stats_ktype, 781 &mp->m_kobj, "stats"); 782 if (error) 783 goto out_remove_fsdir; 784 785 /* .../xfs/<dev>/error/ */ 786 error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype, 787 &mp->m_kobj, "error"); 788 if (error) 789 goto out_remove_stats_dir; 790 791 /* .../xfs/<dev>/error/fail_at_unmount */ 792 error = sysfs_create_file(&mp->m_error_kobj.kobject, 793 ATTR_LIST(fail_at_unmount)); 794 795 if (error) 796 goto out_remove_error_dir; 797 798 /* .../xfs/<dev>/error/metadata/ */ 799 error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA, 800 "metadata", &mp->m_error_meta_kobj, 801 xfs_error_meta_init); 802 if (error) 803 goto out_remove_error_dir; 804 805 if (IS_ENABLED(CONFIG_XFS_RT) && xfs_has_zoned(mp)) { 806 /* .../xfs/<dev>/zoned/ */ 807 error = xfs_sysfs_init(&mp->m_zoned_kobj, &xfs_zoned_ktype, 808 &mp->m_kobj, "zoned"); 809 if (error) 810 goto out_remove_error_dir; 811 } 812 813 return 0; 814 815out_remove_error_dir: 816 xfs_sysfs_del(&mp->m_error_kobj); 817out_remove_stats_dir: 818 xfs_sysfs_del(&mp->m_stats.xs_kobj); 819out_remove_fsdir: 820 xfs_sysfs_del(&mp->m_kobj); 821 return error; 822} 823 824void 825xfs_mount_sysfs_del( 826 struct xfs_mount *mp) 827{ 828 struct xfs_error_cfg *cfg; 829 int i, j; 830 831 if (IS_ENABLED(CONFIG_XFS_RT) && xfs_has_zoned(mp)) 832 xfs_sysfs_del(&mp->m_zoned_kobj); 833 834 for (i = 0; i < XFS_ERR_CLASS_MAX; i++) { 835 for (j = 0; j < XFS_ERR_ERRNO_MAX; j++) { 836 cfg = &mp->m_error_cfg[i][j]; 837 838 xfs_sysfs_del(&cfg->kobj); 839 } 840 } 841 xfs_sysfs_del(&mp->m_error_meta_kobj); 842 xfs_sysfs_del(&mp->m_error_kobj); 843 xfs_sysfs_del(&mp->m_stats.xs_kobj); 844 xfs_sysfs_del(&mp->m_kobj); 845} 846 847struct xfs_error_cfg * 848xfs_error_get_cfg( 849 struct xfs_mount *mp, 850 int error_class, 851 int error) 852{ 853 struct xfs_error_cfg *cfg; 854 855 if (error < 0) 856 error = -error; 857 858 switch (error) { 859 case EIO: 860 cfg = &mp->m_error_cfg[error_class][XFS_ERR_EIO]; 861 break; 862 case ENOSPC: 863 cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENOSPC]; 864 break; 865 case ENODEV: 866 cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENODEV]; 867 break; 868 default: 869 cfg = &mp->m_error_cfg[error_class][XFS_ERR_DEFAULT]; 870 break; 871 } 872 873 return cfg; 874}