linux/fs/xfs/xfs_sysfs.c
<<
>>
Prefs
   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
  93#ifdef DEBUG
  94
  95STATIC ssize_t
  96fail_writes_store(
  97        struct kobject          *kobject,
  98        const char              *buf,
  99        size_t                  count)
 100{
 101        struct xfs_mount        *mp = to_mp(kobject);
 102        int                     ret;
 103        int                     val;
 104
 105        ret = kstrtoint(buf, 0, &val);
 106        if (ret)
 107                return ret;
 108
 109        if (val == 1)
 110                mp->m_fail_writes = true;
 111        else if (val == 0)
 112                mp->m_fail_writes = false;
 113        else
 114                return -EINVAL;
 115
 116        return count;
 117}
 118
 119STATIC ssize_t
 120fail_writes_show(
 121        struct kobject          *kobject,
 122        char                    *buf)
 123{
 124        struct xfs_mount        *mp = to_mp(kobject);
 125
 126        return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_writes ? 1 : 0);
 127}
 128XFS_SYSFS_ATTR_RW(fail_writes);
 129
 130#endif /* DEBUG */
 131
 132static struct attribute *xfs_mp_attrs[] = {
 133#ifdef DEBUG
 134        ATTR_LIST(fail_writes),
 135#endif
 136        NULL,
 137};
 138
 139struct kobj_type xfs_mp_ktype = {
 140        .release = xfs_sysfs_release,
 141        .sysfs_ops = &xfs_sysfs_ops,
 142        .default_attrs = xfs_mp_attrs,
 143};
 144
 145#ifdef DEBUG
 146/* debug */
 147
 148STATIC ssize_t
 149log_recovery_delay_store(
 150        struct kobject  *kobject,
 151        const char      *buf,
 152        size_t          count)
 153{
 154        int             ret;
 155        int             val;
 156
 157        ret = kstrtoint(buf, 0, &val);
 158        if (ret)
 159                return ret;
 160
 161        if (val < 0 || val > 60)
 162                return -EINVAL;
 163
 164        xfs_globals.log_recovery_delay = val;
 165
 166        return count;
 167}
 168
 169STATIC ssize_t
 170log_recovery_delay_show(
 171        struct kobject  *kobject,
 172        char            *buf)
 173{
 174        return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.log_recovery_delay);
 175}
 176XFS_SYSFS_ATTR_RW(log_recovery_delay);
 177
 178static struct attribute *xfs_dbg_attrs[] = {
 179        ATTR_LIST(log_recovery_delay),
 180        NULL,
 181};
 182
 183struct kobj_type xfs_dbg_ktype = {
 184        .release = xfs_sysfs_release,
 185        .sysfs_ops = &xfs_sysfs_ops,
 186        .default_attrs = xfs_dbg_attrs,
 187};
 188
 189#endif /* DEBUG */
 190
 191/* stats */
 192
 193static inline struct xstats *
 194to_xstats(struct kobject *kobject)
 195{
 196        struct xfs_kobj *kobj = to_kobj(kobject);
 197
 198        return container_of(kobj, struct xstats, xs_kobj);
 199}
 200
 201STATIC ssize_t
 202stats_show(
 203        struct kobject  *kobject,
 204        char            *buf)
 205{
 206        struct xstats   *stats = to_xstats(kobject);
 207
 208        return xfs_stats_format(stats->xs_stats, buf);
 209}
 210XFS_SYSFS_ATTR_RO(stats);
 211
 212STATIC ssize_t
 213stats_clear_store(
 214        struct kobject  *kobject,
 215        const char      *buf,
 216        size_t          count)
 217{
 218        int             ret;
 219        int             val;
 220        struct xstats   *stats = to_xstats(kobject);
 221
 222        ret = kstrtoint(buf, 0, &val);
 223        if (ret)
 224                return ret;
 225
 226        if (val != 1)
 227                return -EINVAL;
 228
 229        xfs_stats_clearall(stats->xs_stats);
 230        return count;
 231}
 232XFS_SYSFS_ATTR_WO(stats_clear);
 233
 234static struct attribute *xfs_stats_attrs[] = {
 235        ATTR_LIST(stats),
 236        ATTR_LIST(stats_clear),
 237        NULL,
 238};
 239
 240struct kobj_type xfs_stats_ktype = {
 241        .release = xfs_sysfs_release,
 242        .sysfs_ops = &xfs_sysfs_ops,
 243        .default_attrs = xfs_stats_attrs,
 244};
 245
 246/* xlog */
 247
 248static inline struct xlog *
 249to_xlog(struct kobject *kobject)
 250{
 251        struct xfs_kobj *kobj = to_kobj(kobject);
 252
 253        return container_of(kobj, struct xlog, l_kobj);
 254}
 255
 256STATIC ssize_t
 257log_head_lsn_show(
 258        struct kobject  *kobject,
 259        char            *buf)
 260{
 261        int cycle;
 262        int block;
 263        struct xlog *log = to_xlog(kobject);
 264
 265        spin_lock(&log->l_icloglock);
 266        cycle = log->l_curr_cycle;
 267        block = log->l_curr_block;
 268        spin_unlock(&log->l_icloglock);
 269
 270        return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block);
 271}
 272XFS_SYSFS_ATTR_RO(log_head_lsn);
 273
 274STATIC ssize_t
 275log_tail_lsn_show(
 276        struct kobject  *kobject,
 277        char            *buf)
 278{
 279        int cycle;
 280        int block;
 281        struct xlog *log = to_xlog(kobject);
 282
 283        xlog_crack_atomic_lsn(&log->l_tail_lsn, &cycle, &block);
 284        return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block);
 285}
 286XFS_SYSFS_ATTR_RO(log_tail_lsn);
 287
 288STATIC ssize_t
 289reserve_grant_head_show(
 290        struct kobject  *kobject,
 291        char            *buf)
 292
 293{
 294        int cycle;
 295        int bytes;
 296        struct xlog *log = to_xlog(kobject);
 297
 298        xlog_crack_grant_head(&log->l_reserve_head.grant, &cycle, &bytes);
 299        return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes);
 300}
 301XFS_SYSFS_ATTR_RO(reserve_grant_head);
 302
 303STATIC ssize_t
 304write_grant_head_show(
 305        struct kobject  *kobject,
 306        char            *buf)
 307{
 308        int cycle;
 309        int bytes;
 310        struct xlog *log = to_xlog(kobject);
 311
 312        xlog_crack_grant_head(&log->l_write_head.grant, &cycle, &bytes);
 313        return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes);
 314}
 315XFS_SYSFS_ATTR_RO(write_grant_head);
 316
 317#ifdef DEBUG
 318STATIC ssize_t
 319log_badcrc_factor_store(
 320        struct kobject  *kobject,
 321        const char      *buf,
 322        size_t          count)
 323{
 324        struct xlog     *log = to_xlog(kobject);
 325        int             ret;
 326        uint32_t        val;
 327
 328        ret = kstrtouint(buf, 0, &val);
 329        if (ret)
 330                return ret;
 331
 332        log->l_badcrc_factor = val;
 333
 334        return count;
 335}
 336
 337STATIC ssize_t
 338log_badcrc_factor_show(
 339        struct kobject  *kobject,
 340        char            *buf)
 341{
 342        struct xlog     *log = to_xlog(kobject);
 343
 344        return snprintf(buf, PAGE_SIZE, "%d\n", log->l_badcrc_factor);
 345}
 346
 347XFS_SYSFS_ATTR_RW(log_badcrc_factor);
 348#endif  /* DEBUG */
 349
 350static struct attribute *xfs_log_attrs[] = {
 351        ATTR_LIST(log_head_lsn),
 352        ATTR_LIST(log_tail_lsn),
 353        ATTR_LIST(reserve_grant_head),
 354        ATTR_LIST(write_grant_head),
 355#ifdef DEBUG
 356        ATTR_LIST(log_badcrc_factor),
 357#endif
 358        NULL,
 359};
 360
 361struct kobj_type xfs_log_ktype = {
 362        .release = xfs_sysfs_release,
 363        .sysfs_ops = &xfs_sysfs_ops,
 364        .default_attrs = xfs_log_attrs,
 365};
 366
 367/*
 368 * Metadata IO error configuration
 369 *
 370 * The sysfs structure here is:
 371 *      ...xfs/<dev>/error/<class>/<errno>/<error_attrs>
 372 *
 373 * where <class> allows us to discriminate between data IO and metadata IO,
 374 * and any other future type of IO (e.g. special inode or directory error
 375 * handling) we care to support.
 376 */
 377static inline struct xfs_error_cfg *
 378to_error_cfg(struct kobject *kobject)
 379{
 380        struct xfs_kobj *kobj = to_kobj(kobject);
 381        return container_of(kobj, struct xfs_error_cfg, kobj);
 382}
 383
 384static inline struct xfs_mount *
 385err_to_mp(struct kobject *kobject)
 386{
 387        struct xfs_kobj *kobj = to_kobj(kobject);
 388        return container_of(kobj, struct xfs_mount, m_error_kobj);
 389}
 390
 391static ssize_t
 392max_retries_show(
 393        struct kobject  *kobject,
 394        char            *buf)
 395{
 396        struct xfs_error_cfg *cfg = to_error_cfg(kobject);
 397
 398        return snprintf(buf, PAGE_SIZE, "%d\n", cfg->max_retries);
 399}
 400
 401static ssize_t
 402max_retries_store(
 403        struct kobject  *kobject,
 404        const char      *buf,
 405        size_t          count)
 406{
 407        struct xfs_error_cfg *cfg = to_error_cfg(kobject);
 408        int             ret;
 409        int             val;
 410
 411        ret = kstrtoint(buf, 0, &val);
 412        if (ret)
 413                return ret;
 414
 415        if (val < -1)
 416                return -EINVAL;
 417
 418        cfg->max_retries = val;
 419        return count;
 420}
 421XFS_SYSFS_ATTR_RW(max_retries);
 422
 423static ssize_t
 424retry_timeout_seconds_show(
 425        struct kobject  *kobject,
 426        char            *buf)
 427{
 428        struct xfs_error_cfg *cfg = to_error_cfg(kobject);
 429
 430        return snprintf(buf, PAGE_SIZE, "%ld\n",
 431                        jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC);
 432}
 433
 434static ssize_t
 435retry_timeout_seconds_store(
 436        struct kobject  *kobject,
 437        const char      *buf,
 438        size_t          count)
 439{
 440        struct xfs_error_cfg *cfg = to_error_cfg(kobject);
 441        int             ret;
 442        int             val;
 443
 444        ret = kstrtoint(buf, 0, &val);
 445        if (ret)
 446                return ret;
 447
 448        /* 1 day timeout maximum */
 449        if (val < 0 || val > 86400)
 450                return -EINVAL;
 451
 452        cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);
 453        return count;
 454}
 455XFS_SYSFS_ATTR_RW(retry_timeout_seconds);
 456
 457static ssize_t
 458fail_at_unmount_show(
 459        struct kobject  *kobject,
 460        char            *buf)
 461{
 462        struct xfs_mount        *mp = err_to_mp(kobject);
 463
 464        return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_unmount);
 465}
 466
 467static ssize_t
 468fail_at_unmount_store(
 469        struct kobject  *kobject,
 470        const char      *buf,
 471        size_t          count)
 472{
 473        struct xfs_mount        *mp = err_to_mp(kobject);
 474        int             ret;
 475        int             val;
 476
 477        ret = kstrtoint(buf, 0, &val);
 478        if (ret)
 479                return ret;
 480
 481        if (val < 0 || val > 1)
 482                return -EINVAL;
 483
 484        mp->m_fail_unmount = val;
 485        return count;
 486}
 487XFS_SYSFS_ATTR_RW(fail_at_unmount);
 488
 489static struct attribute *xfs_error_attrs[] = {
 490        ATTR_LIST(max_retries),
 491        ATTR_LIST(retry_timeout_seconds),
 492        NULL,
 493};
 494
 495
 496struct kobj_type xfs_error_cfg_ktype = {
 497        .release = xfs_sysfs_release,
 498        .sysfs_ops = &xfs_sysfs_ops,
 499        .default_attrs = xfs_error_attrs,
 500};
 501
 502struct kobj_type xfs_error_ktype = {
 503        .release = xfs_sysfs_release,
 504        .sysfs_ops = &xfs_sysfs_ops,
 505};
 506
 507/*
 508 * Error initialization tables. These need to be ordered in the same
 509 * order as the enums used to index the array. All class init tables need to
 510 * define a "default" behaviour as the first entry, all other entries can be
 511 * empty.
 512 */
 513struct xfs_error_init {
 514        char            *name;
 515        int             max_retries;
 516        int             retry_timeout;  /* in seconds */
 517};
 518
 519static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {
 520        { .name = "default",
 521          .max_retries = XFS_ERR_RETRY_FOREVER,
 522          .retry_timeout = 0,
 523        },
 524        { .name = "EIO",
 525          .max_retries = XFS_ERR_RETRY_FOREVER,
 526          .retry_timeout = 0,
 527        },
 528        { .name = "ENOSPC",
 529          .max_retries = XFS_ERR_RETRY_FOREVER,
 530          .retry_timeout = 0,
 531        },
 532        { .name = "ENODEV",
 533          .max_retries = 0,
 534        },
 535};
 536
 537static int
 538xfs_error_sysfs_init_class(
 539        struct xfs_mount        *mp,
 540        int                     class,
 541        const char              *parent_name,
 542        struct xfs_kobj         *parent_kobj,
 543        const struct xfs_error_init init[])
 544{
 545        struct xfs_error_cfg    *cfg;
 546        int                     error;
 547        int                     i;
 548
 549        ASSERT(class < XFS_ERR_CLASS_MAX);
 550
 551        error = xfs_sysfs_init(parent_kobj, &xfs_error_ktype,
 552                                &mp->m_error_kobj, parent_name);
 553        if (error)
 554                return error;
 555
 556        for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) {
 557                cfg = &mp->m_error_cfg[class][i];
 558                error = xfs_sysfs_init(&cfg->kobj, &xfs_error_cfg_ktype,
 559                                        parent_kobj, init[i].name);
 560                if (error)
 561                        goto out_error;
 562
 563                cfg->max_retries = init[i].max_retries;
 564                cfg->retry_timeout = msecs_to_jiffies(
 565                                        init[i].retry_timeout * MSEC_PER_SEC);
 566        }
 567        return 0;
 568
 569out_error:
 570        /* unwind the entries that succeeded */
 571        for (i--; i >= 0; i--) {
 572                cfg = &mp->m_error_cfg[class][i];
 573                xfs_sysfs_del(&cfg->kobj);
 574        }
 575        xfs_sysfs_del(parent_kobj);
 576        return error;
 577}
 578
 579int
 580xfs_error_sysfs_init(
 581        struct xfs_mount        *mp)
 582{
 583        int                     error;
 584
 585        /* .../xfs/<dev>/error/ */
 586        error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype,
 587                                &mp->m_kobj, "error");
 588        if (error)
 589                return error;
 590
 591        error = sysfs_create_file(&mp->m_error_kobj.kobject,
 592                                  ATTR_LIST(fail_at_unmount));
 593
 594        if (error)
 595                goto out_error;
 596
 597        /* .../xfs/<dev>/error/metadata/ */
 598        error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA,
 599                                "metadata", &mp->m_error_meta_kobj,
 600                                xfs_error_meta_init);
 601        if (error)
 602                goto out_error;
 603
 604        return 0;
 605
 606out_error:
 607        xfs_sysfs_del(&mp->m_error_kobj);
 608        return error;
 609}
 610
 611void
 612xfs_error_sysfs_del(
 613        struct xfs_mount        *mp)
 614{
 615        struct xfs_error_cfg    *cfg;
 616        int                     i, j;
 617
 618        for (i = 0; i < XFS_ERR_CLASS_MAX; i++) {
 619                for (j = 0; j < XFS_ERR_ERRNO_MAX; j++) {
 620                        cfg = &mp->m_error_cfg[i][j];
 621
 622                        xfs_sysfs_del(&cfg->kobj);
 623                }
 624        }
 625        xfs_sysfs_del(&mp->m_error_meta_kobj);
 626        xfs_sysfs_del(&mp->m_error_kobj);
 627}
 628
 629struct xfs_error_cfg *
 630xfs_error_get_cfg(
 631        struct xfs_mount        *mp,
 632        int                     error_class,
 633        int                     error)
 634{
 635        struct xfs_error_cfg    *cfg;
 636
 637        switch (error) {
 638        case EIO:
 639                cfg = &mp->m_error_cfg[error_class][XFS_ERR_EIO];
 640                break;
 641        case ENOSPC:
 642                cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENOSPC];
 643                break;
 644        case ENODEV:
 645                cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENODEV];
 646                break;
 647        default:
 648                cfg = &mp->m_error_cfg[error_class][XFS_ERR_DEFAULT];
 649                break;
 650        }
 651
 652        return cfg;
 653}
 654