Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.14-rc3 634 lines 13 kB view raw
1/* 2 * Copyright (c) 2014 Red Hat, Inc. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19#include "xfs.h" 20#include "xfs_shared.h" 21#include "xfs_format.h" 22#include "xfs_log_format.h" 23#include "xfs_trans_resv.h" 24#include "xfs_sysfs.h" 25#include "xfs_log.h" 26#include "xfs_log_priv.h" 27#include "xfs_stats.h" 28#include "xfs_mount.h" 29 30struct xfs_sysfs_attr { 31 struct attribute attr; 32 ssize_t (*show)(struct kobject *kobject, char *buf); 33 ssize_t (*store)(struct kobject *kobject, const char *buf, 34 size_t count); 35}; 36 37static inline struct xfs_sysfs_attr * 38to_attr(struct attribute *attr) 39{ 40 return container_of(attr, struct xfs_sysfs_attr, attr); 41} 42 43#define XFS_SYSFS_ATTR_RW(name) \ 44 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RW(name) 45#define XFS_SYSFS_ATTR_RO(name) \ 46 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RO(name) 47#define XFS_SYSFS_ATTR_WO(name) \ 48 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_WO(name) 49 50#define ATTR_LIST(name) &xfs_sysfs_attr_##name.attr 51 52STATIC ssize_t 53xfs_sysfs_object_show( 54 struct kobject *kobject, 55 struct attribute *attr, 56 char *buf) 57{ 58 struct xfs_sysfs_attr *xfs_attr = to_attr(attr); 59 60 return xfs_attr->show ? xfs_attr->show(kobject, buf) : 0; 61} 62 63STATIC ssize_t 64xfs_sysfs_object_store( 65 struct kobject *kobject, 66 struct attribute *attr, 67 const char *buf, 68 size_t count) 69{ 70 struct xfs_sysfs_attr *xfs_attr = to_attr(attr); 71 72 return xfs_attr->store ? xfs_attr->store(kobject, buf, count) : 0; 73} 74 75static const struct sysfs_ops xfs_sysfs_ops = { 76 .show = xfs_sysfs_object_show, 77 .store = xfs_sysfs_object_store, 78}; 79 80/* 81 * xfs_mount kobject. The mp kobject also serves as the per-mount parent object 82 * that is identified by the fsname under sysfs. 83 */ 84 85static inline struct xfs_mount * 86to_mp(struct kobject *kobject) 87{ 88 struct xfs_kobj *kobj = to_kobj(kobject); 89 90 return container_of(kobj, struct xfs_mount, m_kobj); 91} 92 93static struct attribute *xfs_mp_attrs[] = { 94 NULL, 95}; 96 97struct kobj_type xfs_mp_ktype = { 98 .release = xfs_sysfs_release, 99 .sysfs_ops = &xfs_sysfs_ops, 100 .default_attrs = xfs_mp_attrs, 101}; 102 103#ifdef DEBUG 104/* debug */ 105 106STATIC ssize_t 107bug_on_assert_store( 108 struct kobject *kobject, 109 const char *buf, 110 size_t count) 111{ 112 int ret; 113 int val; 114 115 ret = kstrtoint(buf, 0, &val); 116 if (ret) 117 return ret; 118 119 if (val == 1) 120 xfs_globals.bug_on_assert = true; 121 else if (val == 0) 122 xfs_globals.bug_on_assert = false; 123 else 124 return -EINVAL; 125 126 return count; 127} 128 129STATIC ssize_t 130bug_on_assert_show( 131 struct kobject *kobject, 132 char *buf) 133{ 134 return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.bug_on_assert ? 1 : 0); 135} 136XFS_SYSFS_ATTR_RW(bug_on_assert); 137 138STATIC ssize_t 139log_recovery_delay_store( 140 struct kobject *kobject, 141 const char *buf, 142 size_t count) 143{ 144 int ret; 145 int val; 146 147 ret = kstrtoint(buf, 0, &val); 148 if (ret) 149 return ret; 150 151 if (val < 0 || val > 60) 152 return -EINVAL; 153 154 xfs_globals.log_recovery_delay = val; 155 156 return count; 157} 158 159STATIC ssize_t 160log_recovery_delay_show( 161 struct kobject *kobject, 162 char *buf) 163{ 164 return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.log_recovery_delay); 165} 166XFS_SYSFS_ATTR_RW(log_recovery_delay); 167 168static struct attribute *xfs_dbg_attrs[] = { 169 ATTR_LIST(bug_on_assert), 170 ATTR_LIST(log_recovery_delay), 171 NULL, 172}; 173 174struct kobj_type xfs_dbg_ktype = { 175 .release = xfs_sysfs_release, 176 .sysfs_ops = &xfs_sysfs_ops, 177 .default_attrs = xfs_dbg_attrs, 178}; 179 180#endif /* DEBUG */ 181 182/* stats */ 183 184static inline struct xstats * 185to_xstats(struct kobject *kobject) 186{ 187 struct xfs_kobj *kobj = to_kobj(kobject); 188 189 return container_of(kobj, struct xstats, xs_kobj); 190} 191 192STATIC ssize_t 193stats_show( 194 struct kobject *kobject, 195 char *buf) 196{ 197 struct xstats *stats = to_xstats(kobject); 198 199 return xfs_stats_format(stats->xs_stats, buf); 200} 201XFS_SYSFS_ATTR_RO(stats); 202 203STATIC ssize_t 204stats_clear_store( 205 struct kobject *kobject, 206 const char *buf, 207 size_t count) 208{ 209 int ret; 210 int val; 211 struct xstats *stats = to_xstats(kobject); 212 213 ret = kstrtoint(buf, 0, &val); 214 if (ret) 215 return ret; 216 217 if (val != 1) 218 return -EINVAL; 219 220 xfs_stats_clearall(stats->xs_stats); 221 return count; 222} 223XFS_SYSFS_ATTR_WO(stats_clear); 224 225static struct attribute *xfs_stats_attrs[] = { 226 ATTR_LIST(stats), 227 ATTR_LIST(stats_clear), 228 NULL, 229}; 230 231struct kobj_type xfs_stats_ktype = { 232 .release = xfs_sysfs_release, 233 .sysfs_ops = &xfs_sysfs_ops, 234 .default_attrs = xfs_stats_attrs, 235}; 236 237/* xlog */ 238 239static inline struct xlog * 240to_xlog(struct kobject *kobject) 241{ 242 struct xfs_kobj *kobj = to_kobj(kobject); 243 244 return container_of(kobj, struct xlog, l_kobj); 245} 246 247STATIC ssize_t 248log_head_lsn_show( 249 struct kobject *kobject, 250 char *buf) 251{ 252 int cycle; 253 int block; 254 struct xlog *log = to_xlog(kobject); 255 256 spin_lock(&log->l_icloglock); 257 cycle = log->l_curr_cycle; 258 block = log->l_curr_block; 259 spin_unlock(&log->l_icloglock); 260 261 return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block); 262} 263XFS_SYSFS_ATTR_RO(log_head_lsn); 264 265STATIC ssize_t 266log_tail_lsn_show( 267 struct kobject *kobject, 268 char *buf) 269{ 270 int cycle; 271 int block; 272 struct xlog *log = to_xlog(kobject); 273 274 xlog_crack_atomic_lsn(&log->l_tail_lsn, &cycle, &block); 275 return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block); 276} 277XFS_SYSFS_ATTR_RO(log_tail_lsn); 278 279STATIC ssize_t 280reserve_grant_head_show( 281 struct kobject *kobject, 282 char *buf) 283 284{ 285 int cycle; 286 int bytes; 287 struct xlog *log = to_xlog(kobject); 288 289 xlog_crack_grant_head(&log->l_reserve_head.grant, &cycle, &bytes); 290 return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes); 291} 292XFS_SYSFS_ATTR_RO(reserve_grant_head); 293 294STATIC ssize_t 295write_grant_head_show( 296 struct kobject *kobject, 297 char *buf) 298{ 299 int cycle; 300 int bytes; 301 struct xlog *log = to_xlog(kobject); 302 303 xlog_crack_grant_head(&log->l_write_head.grant, &cycle, &bytes); 304 return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes); 305} 306XFS_SYSFS_ATTR_RO(write_grant_head); 307 308static struct attribute *xfs_log_attrs[] = { 309 ATTR_LIST(log_head_lsn), 310 ATTR_LIST(log_tail_lsn), 311 ATTR_LIST(reserve_grant_head), 312 ATTR_LIST(write_grant_head), 313 NULL, 314}; 315 316struct kobj_type xfs_log_ktype = { 317 .release = xfs_sysfs_release, 318 .sysfs_ops = &xfs_sysfs_ops, 319 .default_attrs = xfs_log_attrs, 320}; 321 322/* 323 * Metadata IO error configuration 324 * 325 * The sysfs structure here is: 326 * ...xfs/<dev>/error/<class>/<errno>/<error_attrs> 327 * 328 * where <class> allows us to discriminate between data IO and metadata IO, 329 * and any other future type of IO (e.g. special inode or directory error 330 * handling) we care to support. 331 */ 332static inline struct xfs_error_cfg * 333to_error_cfg(struct kobject *kobject) 334{ 335 struct xfs_kobj *kobj = to_kobj(kobject); 336 return container_of(kobj, struct xfs_error_cfg, kobj); 337} 338 339static inline struct xfs_mount * 340err_to_mp(struct kobject *kobject) 341{ 342 struct xfs_kobj *kobj = to_kobj(kobject); 343 return container_of(kobj, struct xfs_mount, m_error_kobj); 344} 345 346static ssize_t 347max_retries_show( 348 struct kobject *kobject, 349 char *buf) 350{ 351 int retries; 352 struct xfs_error_cfg *cfg = to_error_cfg(kobject); 353 354 if (cfg->max_retries == XFS_ERR_RETRY_FOREVER) 355 retries = -1; 356 else 357 retries = cfg->max_retries; 358 359 return snprintf(buf, PAGE_SIZE, "%d\n", retries); 360} 361 362static ssize_t 363max_retries_store( 364 struct kobject *kobject, 365 const char *buf, 366 size_t count) 367{ 368 struct xfs_error_cfg *cfg = to_error_cfg(kobject); 369 int ret; 370 int val; 371 372 ret = kstrtoint(buf, 0, &val); 373 if (ret) 374 return ret; 375 376 if (val < -1) 377 return -EINVAL; 378 379 if (val == -1) 380 cfg->max_retries = XFS_ERR_RETRY_FOREVER; 381 else 382 cfg->max_retries = val; 383 return count; 384} 385XFS_SYSFS_ATTR_RW(max_retries); 386 387static ssize_t 388retry_timeout_seconds_show( 389 struct kobject *kobject, 390 char *buf) 391{ 392 int timeout; 393 struct xfs_error_cfg *cfg = to_error_cfg(kobject); 394 395 if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER) 396 timeout = -1; 397 else 398 timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC; 399 400 return snprintf(buf, PAGE_SIZE, "%d\n", timeout); 401} 402 403static ssize_t 404retry_timeout_seconds_store( 405 struct kobject *kobject, 406 const char *buf, 407 size_t count) 408{ 409 struct xfs_error_cfg *cfg = to_error_cfg(kobject); 410 int ret; 411 int val; 412 413 ret = kstrtoint(buf, 0, &val); 414 if (ret) 415 return ret; 416 417 /* 1 day timeout maximum, -1 means infinite */ 418 if (val < -1 || val > 86400) 419 return -EINVAL; 420 421 if (val == -1) 422 cfg->retry_timeout = XFS_ERR_RETRY_FOREVER; 423 else { 424 cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC); 425 ASSERT(msecs_to_jiffies(val * MSEC_PER_SEC) < LONG_MAX); 426 } 427 return count; 428} 429XFS_SYSFS_ATTR_RW(retry_timeout_seconds); 430 431static ssize_t 432fail_at_unmount_show( 433 struct kobject *kobject, 434 char *buf) 435{ 436 struct xfs_mount *mp = err_to_mp(kobject); 437 438 return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_unmount); 439} 440 441static ssize_t 442fail_at_unmount_store( 443 struct kobject *kobject, 444 const char *buf, 445 size_t count) 446{ 447 struct xfs_mount *mp = err_to_mp(kobject); 448 int ret; 449 int val; 450 451 ret = kstrtoint(buf, 0, &val); 452 if (ret) 453 return ret; 454 455 if (val < 0 || val > 1) 456 return -EINVAL; 457 458 mp->m_fail_unmount = val; 459 return count; 460} 461XFS_SYSFS_ATTR_RW(fail_at_unmount); 462 463static struct attribute *xfs_error_attrs[] = { 464 ATTR_LIST(max_retries), 465 ATTR_LIST(retry_timeout_seconds), 466 NULL, 467}; 468 469 470static struct kobj_type xfs_error_cfg_ktype = { 471 .release = xfs_sysfs_release, 472 .sysfs_ops = &xfs_sysfs_ops, 473 .default_attrs = xfs_error_attrs, 474}; 475 476static struct kobj_type xfs_error_ktype = { 477 .release = xfs_sysfs_release, 478 .sysfs_ops = &xfs_sysfs_ops, 479}; 480 481/* 482 * Error initialization tables. These need to be ordered in the same 483 * order as the enums used to index the array. All class init tables need to 484 * define a "default" behaviour as the first entry, all other entries can be 485 * empty. 486 */ 487struct xfs_error_init { 488 char *name; 489 int max_retries; 490 int retry_timeout; /* in seconds */ 491}; 492 493static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = { 494 { .name = "default", 495 .max_retries = XFS_ERR_RETRY_FOREVER, 496 .retry_timeout = XFS_ERR_RETRY_FOREVER, 497 }, 498 { .name = "EIO", 499 .max_retries = XFS_ERR_RETRY_FOREVER, 500 .retry_timeout = XFS_ERR_RETRY_FOREVER, 501 }, 502 { .name = "ENOSPC", 503 .max_retries = XFS_ERR_RETRY_FOREVER, 504 .retry_timeout = XFS_ERR_RETRY_FOREVER, 505 }, 506 { .name = "ENODEV", 507 .max_retries = 0, /* We can't recover from devices disappearing */ 508 .retry_timeout = 0, 509 }, 510}; 511 512static int 513xfs_error_sysfs_init_class( 514 struct xfs_mount *mp, 515 int class, 516 const char *parent_name, 517 struct xfs_kobj *parent_kobj, 518 const struct xfs_error_init init[]) 519{ 520 struct xfs_error_cfg *cfg; 521 int error; 522 int i; 523 524 ASSERT(class < XFS_ERR_CLASS_MAX); 525 526 error = xfs_sysfs_init(parent_kobj, &xfs_error_ktype, 527 &mp->m_error_kobj, parent_name); 528 if (error) 529 return error; 530 531 for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) { 532 cfg = &mp->m_error_cfg[class][i]; 533 error = xfs_sysfs_init(&cfg->kobj, &xfs_error_cfg_ktype, 534 parent_kobj, init[i].name); 535 if (error) 536 goto out_error; 537 538 cfg->max_retries = init[i].max_retries; 539 if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER) 540 cfg->retry_timeout = XFS_ERR_RETRY_FOREVER; 541 else 542 cfg->retry_timeout = msecs_to_jiffies( 543 init[i].retry_timeout * MSEC_PER_SEC); 544 } 545 return 0; 546 547out_error: 548 /* unwind the entries that succeeded */ 549 for (i--; i >= 0; i--) { 550 cfg = &mp->m_error_cfg[class][i]; 551 xfs_sysfs_del(&cfg->kobj); 552 } 553 xfs_sysfs_del(parent_kobj); 554 return error; 555} 556 557int 558xfs_error_sysfs_init( 559 struct xfs_mount *mp) 560{ 561 int error; 562 563 /* .../xfs/<dev>/error/ */ 564 error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype, 565 &mp->m_kobj, "error"); 566 if (error) 567 return error; 568 569 error = sysfs_create_file(&mp->m_error_kobj.kobject, 570 ATTR_LIST(fail_at_unmount)); 571 572 if (error) 573 goto out_error; 574 575 /* .../xfs/<dev>/error/metadata/ */ 576 error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA, 577 "metadata", &mp->m_error_meta_kobj, 578 xfs_error_meta_init); 579 if (error) 580 goto out_error; 581 582 return 0; 583 584out_error: 585 xfs_sysfs_del(&mp->m_error_kobj); 586 return error; 587} 588 589void 590xfs_error_sysfs_del( 591 struct xfs_mount *mp) 592{ 593 struct xfs_error_cfg *cfg; 594 int i, j; 595 596 for (i = 0; i < XFS_ERR_CLASS_MAX; i++) { 597 for (j = 0; j < XFS_ERR_ERRNO_MAX; j++) { 598 cfg = &mp->m_error_cfg[i][j]; 599 600 xfs_sysfs_del(&cfg->kobj); 601 } 602 } 603 xfs_sysfs_del(&mp->m_error_meta_kobj); 604 xfs_sysfs_del(&mp->m_error_kobj); 605} 606 607struct xfs_error_cfg * 608xfs_error_get_cfg( 609 struct xfs_mount *mp, 610 int error_class, 611 int error) 612{ 613 struct xfs_error_cfg *cfg; 614 615 if (error < 0) 616 error = -error; 617 618 switch (error) { 619 case EIO: 620 cfg = &mp->m_error_cfg[error_class][XFS_ERR_EIO]; 621 break; 622 case ENOSPC: 623 cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENOSPC]; 624 break; 625 case ENODEV: 626 cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENODEV]; 627 break; 628 default: 629 cfg = &mp->m_error_cfg[error_class][XFS_ERR_DEFAULT]; 630 break; 631 } 632 633 return cfg; 634}