linux/drivers/staging/lustre/lustre/llite/lproc_llite.c
<<
>>
Prefs
   1/*
   2 * GPL HEADER START
   3 *
   4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 only,
   8 * as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License version 2 for more details (a copy is included
  14 * in the LICENSE file that accompanied this code).
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * version 2 along with this program; If not, see
  18 * http://www.gnu.org/licenses/gpl-2.0.html
  19 *
  20 * GPL HEADER END
  21 */
  22/*
  23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  24 * Use is subject to license terms.
  25 *
  26 * Copyright (c) 2011, 2015, Intel Corporation.
  27 */
  28/*
  29 * This file is part of Lustre, http://www.lustre.org/
  30 * Lustre is a trademark of Sun Microsystems, Inc.
  31 */
  32#define DEBUG_SUBSYSTEM S_LLITE
  33
  34#include "../include/lprocfs_status.h"
  35#include <linux/seq_file.h>
  36#include "../include/obd_support.h"
  37
  38#include "llite_internal.h"
  39#include "vvp_internal.h"
  40
  41/* debugfs llite mount point registration */
  42static struct file_operations ll_rw_extents_stats_fops;
  43static struct file_operations ll_rw_extents_stats_pp_fops;
  44static struct file_operations ll_rw_offset_stats_fops;
  45
  46static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
  47                              char *buf)
  48{
  49        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
  50                                              ll_kobj);
  51        struct obd_statfs osfs;
  52        int rc;
  53
  54        rc = ll_statfs_internal(sbi->ll_sb, &osfs,
  55                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
  56                                OBD_STATFS_NODELAY);
  57        if (!rc)
  58                return sprintf(buf, "%u\n", osfs.os_bsize);
  59
  60        return rc;
  61}
  62LUSTRE_RO_ATTR(blocksize);
  63
  64static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
  65                                char *buf)
  66{
  67        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
  68                                              ll_kobj);
  69        struct obd_statfs osfs;
  70        int rc;
  71
  72        rc = ll_statfs_internal(sbi->ll_sb, &osfs,
  73                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
  74                                OBD_STATFS_NODELAY);
  75        if (!rc) {
  76                __u32 blk_size = osfs.os_bsize >> 10;
  77                __u64 result = osfs.os_blocks;
  78
  79                while (blk_size >>= 1)
  80                        result <<= 1;
  81
  82                rc = sprintf(buf, "%llu\n", result);
  83        }
  84
  85        return rc;
  86}
  87LUSTRE_RO_ATTR(kbytestotal);
  88
  89static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
  90                               char *buf)
  91{
  92        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
  93                                              ll_kobj);
  94        struct obd_statfs osfs;
  95        int rc;
  96
  97        rc = ll_statfs_internal(sbi->ll_sb, &osfs,
  98                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
  99                                OBD_STATFS_NODELAY);
 100        if (!rc) {
 101                __u32 blk_size = osfs.os_bsize >> 10;
 102                __u64 result = osfs.os_bfree;
 103
 104                while (blk_size >>= 1)
 105                        result <<= 1;
 106
 107                rc = sprintf(buf, "%llu\n", result);
 108        }
 109
 110        return rc;
 111}
 112LUSTRE_RO_ATTR(kbytesfree);
 113
 114static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
 115                                char *buf)
 116{
 117        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 118                                              ll_kobj);
 119        struct obd_statfs osfs;
 120        int rc;
 121
 122        rc = ll_statfs_internal(sbi->ll_sb, &osfs,
 123                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
 124                                OBD_STATFS_NODELAY);
 125        if (!rc) {
 126                __u32 blk_size = osfs.os_bsize >> 10;
 127                __u64 result = osfs.os_bavail;
 128
 129                while (blk_size >>= 1)
 130                        result <<= 1;
 131
 132                rc = sprintf(buf, "%llu\n", result);
 133        }
 134
 135        return rc;
 136}
 137LUSTRE_RO_ATTR(kbytesavail);
 138
 139static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
 140                               char *buf)
 141{
 142        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 143                                              ll_kobj);
 144        struct obd_statfs osfs;
 145        int rc;
 146
 147        rc = ll_statfs_internal(sbi->ll_sb, &osfs,
 148                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
 149                                OBD_STATFS_NODELAY);
 150        if (!rc)
 151                return sprintf(buf, "%llu\n", osfs.os_files);
 152
 153        return rc;
 154}
 155LUSTRE_RO_ATTR(filestotal);
 156
 157static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
 158                              char *buf)
 159{
 160        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 161                                              ll_kobj);
 162        struct obd_statfs osfs;
 163        int rc;
 164
 165        rc = ll_statfs_internal(sbi->ll_sb, &osfs,
 166                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
 167                                OBD_STATFS_NODELAY);
 168        if (!rc)
 169                return sprintf(buf, "%llu\n", osfs.os_ffree);
 170
 171        return rc;
 172}
 173LUSTRE_RO_ATTR(filesfree);
 174
 175static ssize_t client_type_show(struct kobject *kobj, struct attribute *attr,
 176                                char *buf)
 177{
 178        return sprintf(buf, "local client\n");
 179}
 180LUSTRE_RO_ATTR(client_type);
 181
 182static ssize_t fstype_show(struct kobject *kobj, struct attribute *attr,
 183                           char *buf)
 184{
 185        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 186                                              ll_kobj);
 187
 188        return sprintf(buf, "%s\n", sbi->ll_sb->s_type->name);
 189}
 190LUSTRE_RO_ATTR(fstype);
 191
 192static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
 193                         char *buf)
 194{
 195        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 196                                              ll_kobj);
 197
 198        return sprintf(buf, "%s\n", sbi->ll_sb_uuid.uuid);
 199}
 200LUSTRE_RO_ATTR(uuid);
 201
 202static int ll_site_stats_seq_show(struct seq_file *m, void *v)
 203{
 204        struct super_block *sb = m->private;
 205
 206        /*
 207         * See description of statistical counters in struct cl_site, and
 208         * struct lu_site.
 209         */
 210        return cl_site_stats_print(lu2cl_site(ll_s2sbi(sb)->ll_site), m);
 211}
 212
 213LPROC_SEQ_FOPS_RO(ll_site_stats);
 214
 215static ssize_t max_read_ahead_mb_show(struct kobject *kobj,
 216                                      struct attribute *attr, char *buf)
 217{
 218        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 219                                              ll_kobj);
 220        long pages_number;
 221        int mult;
 222
 223        spin_lock(&sbi->ll_lock);
 224        pages_number = sbi->ll_ra_info.ra_max_pages;
 225        spin_unlock(&sbi->ll_lock);
 226
 227        mult = 1 << (20 - PAGE_SHIFT);
 228        return lprocfs_read_frac_helper(buf, PAGE_SIZE, pages_number, mult);
 229}
 230
 231static ssize_t max_read_ahead_mb_store(struct kobject *kobj,
 232                                       struct attribute *attr,
 233                                       const char *buffer,
 234                                       size_t count)
 235{
 236        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 237                                              ll_kobj);
 238        int rc;
 239        unsigned long pages_number;
 240
 241        rc = kstrtoul(buffer, 10, &pages_number);
 242        if (rc)
 243                return rc;
 244
 245        pages_number *= 1 << (20 - PAGE_SHIFT); /* MB -> pages */
 246
 247        if (pages_number > totalram_pages / 2) {
 248                CERROR("can't set file readahead more than %lu MB\n",
 249                       totalram_pages >> (20 - PAGE_SHIFT + 1)); /*1/2 of RAM*/
 250                return -ERANGE;
 251        }
 252
 253        spin_lock(&sbi->ll_lock);
 254        sbi->ll_ra_info.ra_max_pages = pages_number;
 255        spin_unlock(&sbi->ll_lock);
 256
 257        return count;
 258}
 259LUSTRE_RW_ATTR(max_read_ahead_mb);
 260
 261static ssize_t max_read_ahead_per_file_mb_show(struct kobject *kobj,
 262                                               struct attribute *attr,
 263                                               char *buf)
 264{
 265        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 266                                              ll_kobj);
 267        long pages_number;
 268        int mult;
 269
 270        spin_lock(&sbi->ll_lock);
 271        pages_number = sbi->ll_ra_info.ra_max_pages_per_file;
 272        spin_unlock(&sbi->ll_lock);
 273
 274        mult = 1 << (20 - PAGE_SHIFT);
 275        return lprocfs_read_frac_helper(buf, PAGE_SIZE, pages_number, mult);
 276}
 277
 278static ssize_t max_read_ahead_per_file_mb_store(struct kobject *kobj,
 279                                                struct attribute *attr,
 280                                                const char *buffer,
 281                                                size_t count)
 282{
 283        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 284                                              ll_kobj);
 285        int rc;
 286        unsigned long pages_number;
 287
 288        rc = kstrtoul(buffer, 10, &pages_number);
 289        if (rc)
 290                return rc;
 291
 292        if (pages_number > sbi->ll_ra_info.ra_max_pages) {
 293                CERROR("can't set file readahead more than max_read_ahead_mb %lu MB\n",
 294                       sbi->ll_ra_info.ra_max_pages);
 295                return -ERANGE;
 296        }
 297
 298        spin_lock(&sbi->ll_lock);
 299        sbi->ll_ra_info.ra_max_pages_per_file = pages_number;
 300        spin_unlock(&sbi->ll_lock);
 301
 302        return count;
 303}
 304LUSTRE_RW_ATTR(max_read_ahead_per_file_mb);
 305
 306static ssize_t max_read_ahead_whole_mb_show(struct kobject *kobj,
 307                                            struct attribute *attr,
 308                                            char *buf)
 309{
 310        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 311                                              ll_kobj);
 312        long pages_number;
 313        int mult;
 314
 315        spin_lock(&sbi->ll_lock);
 316        pages_number = sbi->ll_ra_info.ra_max_read_ahead_whole_pages;
 317        spin_unlock(&sbi->ll_lock);
 318
 319        mult = 1 << (20 - PAGE_SHIFT);
 320        return lprocfs_read_frac_helper(buf, PAGE_SIZE, pages_number, mult);
 321}
 322
 323static ssize_t max_read_ahead_whole_mb_store(struct kobject *kobj,
 324                                             struct attribute *attr,
 325                                             const char  *buffer,
 326                                             size_t count)
 327{
 328        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 329                                              ll_kobj);
 330        int rc;
 331        unsigned long pages_number;
 332
 333        rc = kstrtoul(buffer, 10, &pages_number);
 334        if (rc)
 335                return rc;
 336
 337        /* Cap this at the current max readahead window size, the readahead
 338         * algorithm does this anyway so it's pointless to set it larger.
 339         */
 340        if (pages_number > sbi->ll_ra_info.ra_max_pages_per_file) {
 341                CERROR("can't set max_read_ahead_whole_mb more than max_read_ahead_per_file_mb: %lu\n",
 342                       sbi->ll_ra_info.ra_max_pages_per_file >> (20 - PAGE_SHIFT));
 343                return -ERANGE;
 344        }
 345
 346        spin_lock(&sbi->ll_lock);
 347        sbi->ll_ra_info.ra_max_read_ahead_whole_pages = pages_number;
 348        spin_unlock(&sbi->ll_lock);
 349
 350        return count;
 351}
 352LUSTRE_RW_ATTR(max_read_ahead_whole_mb);
 353
 354static int ll_max_cached_mb_seq_show(struct seq_file *m, void *v)
 355{
 356        struct super_block     *sb    = m->private;
 357        struct ll_sb_info      *sbi   = ll_s2sbi(sb);
 358        struct cl_client_cache *cache = sbi->ll_cache;
 359        int shift = 20 - PAGE_SHIFT;
 360        long max_cached_mb;
 361        long unused_mb;
 362
 363        max_cached_mb = cache->ccc_lru_max >> shift;
 364        unused_mb = atomic_long_read(&cache->ccc_lru_left) >> shift;
 365        seq_printf(m,
 366                   "users: %d\n"
 367                   "max_cached_mb: %ld\n"
 368                   "used_mb: %ld\n"
 369                   "unused_mb: %ld\n"
 370                   "reclaim_count: %u\n",
 371                   atomic_read(&cache->ccc_users),
 372                   max_cached_mb,
 373                   max_cached_mb - unused_mb,
 374                   unused_mb,
 375                   cache->ccc_lru_shrinkers);
 376        return 0;
 377}
 378
 379static ssize_t ll_max_cached_mb_seq_write(struct file *file,
 380                                          const char __user *buffer,
 381                                          size_t count, loff_t *off)
 382{
 383        struct super_block *sb = ((struct seq_file *)file->private_data)->private;
 384        struct ll_sb_info *sbi = ll_s2sbi(sb);
 385        struct cl_client_cache *cache = sbi->ll_cache;
 386        struct lu_env *env;
 387        long diff = 0;
 388        long nrpages = 0;
 389        int refcheck;
 390        long pages_number;
 391        int mult;
 392        long rc;
 393        u64 val;
 394        char kernbuf[128];
 395
 396        if (count >= sizeof(kernbuf))
 397                return -EINVAL;
 398
 399        if (copy_from_user(kernbuf, buffer, count))
 400                return -EFAULT;
 401        kernbuf[count] = 0;
 402
 403        mult = 1 << (20 - PAGE_SHIFT);
 404        buffer += lprocfs_find_named_value(kernbuf, "max_cached_mb:", &count) -
 405                  kernbuf;
 406        rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult);
 407        if (rc)
 408                return rc;
 409
 410        if (val > LONG_MAX)
 411                return -ERANGE;
 412        pages_number = (long)val;
 413
 414        if (pages_number < 0 || pages_number > totalram_pages) {
 415                CERROR("%s: can't set max cache more than %lu MB\n",
 416                       ll_get_fsname(sb, NULL, 0),
 417                       totalram_pages >> (20 - PAGE_SHIFT));
 418                return -ERANGE;
 419        }
 420
 421        spin_lock(&sbi->ll_lock);
 422        diff = pages_number - cache->ccc_lru_max;
 423        spin_unlock(&sbi->ll_lock);
 424
 425        /* easy - add more LRU slots. */
 426        if (diff >= 0) {
 427                atomic_long_add(diff, &cache->ccc_lru_left);
 428                rc = 0;
 429                goto out;
 430        }
 431
 432        env = cl_env_get(&refcheck);
 433        if (IS_ERR(env))
 434                return 0;
 435
 436        diff = -diff;
 437        while (diff > 0) {
 438                long tmp;
 439
 440                /* reduce LRU budget from free slots. */
 441                do {
 442                        long ov, nv;
 443
 444                        ov = atomic_long_read(&cache->ccc_lru_left);
 445                        if (ov == 0)
 446                                break;
 447
 448                        nv = ov > diff ? ov - diff : 0;
 449                        rc = atomic_long_cmpxchg(&cache->ccc_lru_left, ov, nv);
 450                        if (likely(ov == rc)) {
 451                                diff -= ov - nv;
 452                                nrpages += ov - nv;
 453                                break;
 454                        }
 455                } while (1);
 456
 457                if (diff <= 0)
 458                        break;
 459
 460                if (!sbi->ll_dt_exp) { /* being initialized */
 461                        rc = 0;
 462                        goto out;
 463                }
 464
 465                /* difficult - have to ask OSCs to drop LRU slots. */
 466                tmp = diff << 1;
 467                rc = obd_set_info_async(env, sbi->ll_dt_exp,
 468                                        sizeof(KEY_CACHE_LRU_SHRINK),
 469                                        KEY_CACHE_LRU_SHRINK,
 470                                        sizeof(tmp), &tmp, NULL);
 471                if (rc < 0)
 472                        break;
 473        }
 474        cl_env_put(env, &refcheck);
 475
 476out:
 477        if (rc >= 0) {
 478                spin_lock(&sbi->ll_lock);
 479                cache->ccc_lru_max = pages_number;
 480                spin_unlock(&sbi->ll_lock);
 481                rc = count;
 482        } else {
 483                atomic_long_add(nrpages, &cache->ccc_lru_left);
 484        }
 485        return rc;
 486}
 487
 488LPROC_SEQ_FOPS(ll_max_cached_mb);
 489
 490static ssize_t checksum_pages_show(struct kobject *kobj, struct attribute *attr,
 491                                   char *buf)
 492{
 493        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 494                                              ll_kobj);
 495
 496        return sprintf(buf, "%u\n", (sbi->ll_flags & LL_SBI_CHECKSUM) ? 1 : 0);
 497}
 498
 499static ssize_t checksum_pages_store(struct kobject *kobj,
 500                                    struct attribute *attr,
 501                                    const char *buffer,
 502                                    size_t count)
 503{
 504        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 505                                              ll_kobj);
 506        int rc;
 507        unsigned long val;
 508
 509        if (!sbi->ll_dt_exp)
 510                /* Not set up yet */
 511                return -EAGAIN;
 512
 513        rc = kstrtoul(buffer, 10, &val);
 514        if (rc)
 515                return rc;
 516        if (val)
 517                sbi->ll_flags |= LL_SBI_CHECKSUM;
 518        else
 519                sbi->ll_flags &= ~LL_SBI_CHECKSUM;
 520
 521        rc = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM),
 522                                KEY_CHECKSUM, sizeof(val), &val, NULL);
 523        if (rc)
 524                CWARN("Failed to set OSC checksum flags: %d\n", rc);
 525
 526        return count;
 527}
 528LUSTRE_RW_ATTR(checksum_pages);
 529
 530static ssize_t ll_rd_track_id(struct kobject *kobj, char *buf,
 531                              enum stats_track_type type)
 532{
 533        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 534                                              ll_kobj);
 535
 536        if (sbi->ll_stats_track_type == type)
 537                return sprintf(buf, "%d\n", sbi->ll_stats_track_id);
 538        else if (sbi->ll_stats_track_type == STATS_TRACK_ALL)
 539                return sprintf(buf, "0 (all)\n");
 540        else
 541                return sprintf(buf, "untracked\n");
 542}
 543
 544static ssize_t ll_wr_track_id(struct kobject *kobj, const char *buffer,
 545                              size_t count,
 546                              enum stats_track_type type)
 547{
 548        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 549                                              ll_kobj);
 550        int rc;
 551        unsigned long pid;
 552
 553        rc = kstrtoul(buffer, 10, &pid);
 554        if (rc)
 555                return rc;
 556        sbi->ll_stats_track_id = pid;
 557        if (pid == 0)
 558                sbi->ll_stats_track_type = STATS_TRACK_ALL;
 559        else
 560                sbi->ll_stats_track_type = type;
 561        lprocfs_clear_stats(sbi->ll_stats);
 562        return count;
 563}
 564
 565static ssize_t stats_track_pid_show(struct kobject *kobj,
 566                                    struct attribute *attr,
 567                                    char *buf)
 568{
 569        return ll_rd_track_id(kobj, buf, STATS_TRACK_PID);
 570}
 571
 572static ssize_t stats_track_pid_store(struct kobject *kobj,
 573                                     struct attribute *attr,
 574                                     const char *buffer,
 575                                     size_t count)
 576{
 577        return ll_wr_track_id(kobj, buffer, count, STATS_TRACK_PID);
 578}
 579LUSTRE_RW_ATTR(stats_track_pid);
 580
 581static ssize_t stats_track_ppid_show(struct kobject *kobj,
 582                                     struct attribute *attr,
 583                                     char *buf)
 584{
 585        return ll_rd_track_id(kobj, buf, STATS_TRACK_PPID);
 586}
 587
 588static ssize_t stats_track_ppid_store(struct kobject *kobj,
 589                                      struct attribute *attr,
 590                                      const char *buffer,
 591                                      size_t count)
 592{
 593        return ll_wr_track_id(kobj, buffer, count, STATS_TRACK_PPID);
 594}
 595LUSTRE_RW_ATTR(stats_track_ppid);
 596
 597static ssize_t stats_track_gid_show(struct kobject *kobj,
 598                                    struct attribute *attr,
 599                                    char *buf)
 600{
 601        return ll_rd_track_id(kobj, buf, STATS_TRACK_GID);
 602}
 603
 604static ssize_t stats_track_gid_store(struct kobject *kobj,
 605                                     struct attribute *attr,
 606                                     const char *buffer,
 607                                     size_t count)
 608{
 609        return ll_wr_track_id(kobj, buffer, count, STATS_TRACK_GID);
 610}
 611LUSTRE_RW_ATTR(stats_track_gid);
 612
 613static ssize_t statahead_max_show(struct kobject *kobj,
 614                                  struct attribute *attr,
 615                                  char *buf)
 616{
 617        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 618                                              ll_kobj);
 619
 620        return sprintf(buf, "%u\n", sbi->ll_sa_max);
 621}
 622
 623static ssize_t statahead_max_store(struct kobject *kobj,
 624                                   struct attribute *attr,
 625                                   const char *buffer,
 626                                   size_t count)
 627{
 628        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 629                                              ll_kobj);
 630        int rc;
 631        unsigned long val;
 632
 633        rc = kstrtoul(buffer, 10, &val);
 634        if (rc)
 635                return rc;
 636
 637        if (val <= LL_SA_RPC_MAX)
 638                sbi->ll_sa_max = val;
 639        else
 640                CERROR("Bad statahead_max value %lu. Valid values are in the range [0, %d]\n",
 641                       val, LL_SA_RPC_MAX);
 642
 643        return count;
 644}
 645LUSTRE_RW_ATTR(statahead_max);
 646
 647static ssize_t statahead_agl_show(struct kobject *kobj,
 648                                  struct attribute *attr,
 649                                  char *buf)
 650{
 651        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 652                                              ll_kobj);
 653
 654        return sprintf(buf, "%u\n", sbi->ll_flags & LL_SBI_AGL_ENABLED ? 1 : 0);
 655}
 656
 657static ssize_t statahead_agl_store(struct kobject *kobj,
 658                                   struct attribute *attr,
 659                                   const char *buffer,
 660                                   size_t count)
 661{
 662        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 663                                              ll_kobj);
 664        int rc;
 665        unsigned long val;
 666
 667        rc = kstrtoul(buffer, 10, &val);
 668        if (rc)
 669                return rc;
 670
 671        if (val)
 672                sbi->ll_flags |= LL_SBI_AGL_ENABLED;
 673        else
 674                sbi->ll_flags &= ~LL_SBI_AGL_ENABLED;
 675
 676        return count;
 677}
 678LUSTRE_RW_ATTR(statahead_agl);
 679
 680static int ll_statahead_stats_seq_show(struct seq_file *m, void *v)
 681{
 682        struct super_block *sb = m->private;
 683        struct ll_sb_info *sbi = ll_s2sbi(sb);
 684
 685        seq_printf(m,
 686                   "statahead total: %u\n"
 687                   "statahead wrong: %u\n"
 688                   "agl total: %u\n",
 689                   atomic_read(&sbi->ll_sa_total),
 690                   atomic_read(&sbi->ll_sa_wrong),
 691                   atomic_read(&sbi->ll_agl_total));
 692        return 0;
 693}
 694
 695LPROC_SEQ_FOPS_RO(ll_statahead_stats);
 696
 697static ssize_t lazystatfs_show(struct kobject *kobj,
 698                               struct attribute *attr,
 699                               char *buf)
 700{
 701        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 702                                              ll_kobj);
 703
 704        return sprintf(buf, "%u\n", sbi->ll_flags & LL_SBI_LAZYSTATFS ? 1 : 0);
 705}
 706
 707static ssize_t lazystatfs_store(struct kobject *kobj,
 708                                struct attribute *attr,
 709                                const char *buffer,
 710                                size_t count)
 711{
 712        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 713                                              ll_kobj);
 714        int rc;
 715        unsigned long val;
 716
 717        rc = kstrtoul(buffer, 10, &val);
 718        if (rc)
 719                return rc;
 720
 721        if (val)
 722                sbi->ll_flags |= LL_SBI_LAZYSTATFS;
 723        else
 724                sbi->ll_flags &= ~LL_SBI_LAZYSTATFS;
 725
 726        return count;
 727}
 728LUSTRE_RW_ATTR(lazystatfs);
 729
 730static ssize_t max_easize_show(struct kobject *kobj,
 731                               struct attribute *attr,
 732                               char *buf)
 733{
 734        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 735                                              ll_kobj);
 736        unsigned int ealen;
 737        int rc;
 738
 739        rc = ll_get_max_mdsize(sbi, &ealen);
 740        if (rc)
 741                return rc;
 742
 743        return sprintf(buf, "%u\n", ealen);
 744}
 745LUSTRE_RO_ATTR(max_easize);
 746
 747/**
 748 * Get default_easize.
 749 *
 750 * \see client_obd::cl_default_mds_easize
 751 *
 752 * \param[in] kobj      kernel object for sysfs tree
 753 * \param[in] attr      attribute of this kernel object
 754 * \param[in] buf       buffer to write data into
 755 *
 756 * \retval positive     \a count on success
 757 * \retval negative     negated errno on failure
 758 */
 759static ssize_t default_easize_show(struct kobject *kobj,
 760                                   struct attribute *attr,
 761                                   char *buf)
 762{
 763        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 764                                              ll_kobj);
 765        unsigned int ealen;
 766        int rc;
 767
 768        rc = ll_get_default_mdsize(sbi, &ealen);
 769        if (rc)
 770                return rc;
 771
 772        return sprintf(buf, "%u\n", ealen);
 773}
 774
 775/**
 776 * Set default_easize.
 777 *
 778 * Range checking on the passed value is handled by
 779 * ll_set_default_mdsize().
 780 *
 781 * \see client_obd::cl_default_mds_easize
 782 *
 783 * \param[in] kobj      kernel object for sysfs tree
 784 * \param[in] attr      attribute of this kernel object
 785 * \param[in] buffer    string passed from user space
 786 * \param[in] count     \a buffer length
 787 *
 788 * \retval positive     \a count on success
 789 * \retval negative     negated errno on failure
 790 */
 791static ssize_t default_easize_store(struct kobject *kobj,
 792                                    struct attribute *attr,
 793                                    const char *buffer,
 794                                    size_t count)
 795{
 796        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 797                                              ll_kobj);
 798        unsigned long val;
 799        int rc;
 800
 801        rc = kstrtoul(buffer, 10, &val);
 802        if (rc)
 803                return rc;
 804
 805        rc = ll_set_default_mdsize(sbi, val);
 806        if (rc)
 807                return rc;
 808
 809        return count;
 810}
 811LUSTRE_RW_ATTR(default_easize);
 812
 813static int ll_sbi_flags_seq_show(struct seq_file *m, void *v)
 814{
 815        const char *str[] = LL_SBI_FLAGS;
 816        struct super_block *sb = m->private;
 817        int flags = ll_s2sbi(sb)->ll_flags;
 818        int i = 0;
 819
 820        while (flags != 0) {
 821                if (ARRAY_SIZE(str) <= i) {
 822                        CERROR("%s: Revise array LL_SBI_FLAGS to match sbi flags please.\n",
 823                               ll_get_fsname(sb, NULL, 0));
 824                        return -EINVAL;
 825                }
 826
 827                if (flags & 0x1)
 828                        seq_printf(m, "%s ", str[i]);
 829                flags >>= 1;
 830                ++i;
 831        }
 832        seq_puts(m, "\b\n");
 833        return 0;
 834}
 835
 836LPROC_SEQ_FOPS_RO(ll_sbi_flags);
 837
 838static ssize_t xattr_cache_show(struct kobject *kobj,
 839                                struct attribute *attr,
 840                                char *buf)
 841{
 842        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 843                                              ll_kobj);
 844
 845        return sprintf(buf, "%u\n", sbi->ll_xattr_cache_enabled);
 846}
 847
 848static ssize_t xattr_cache_store(struct kobject *kobj,
 849                                 struct attribute *attr,
 850                                 const char *buffer,
 851                                 size_t count)
 852{
 853        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 854                                              ll_kobj);
 855        int rc;
 856        unsigned long val;
 857
 858        rc = kstrtoul(buffer, 10, &val);
 859        if (rc)
 860                return rc;
 861
 862        if (val != 0 && val != 1)
 863                return -ERANGE;
 864
 865        if (val == 1 && !(sbi->ll_flags & LL_SBI_XATTR_CACHE))
 866                return -ENOTSUPP;
 867
 868        sbi->ll_xattr_cache_enabled = val;
 869
 870        return count;
 871}
 872LUSTRE_RW_ATTR(xattr_cache);
 873
 874static int ll_unstable_stats_seq_show(struct seq_file *m, void *v)
 875{
 876        struct super_block     *sb    = m->private;
 877        struct ll_sb_info      *sbi   = ll_s2sbi(sb);
 878        struct cl_client_cache *cache = sbi->ll_cache;
 879        long pages;
 880        int mb;
 881
 882        pages = atomic_long_read(&cache->ccc_unstable_nr);
 883        mb = (pages * PAGE_SIZE) >> 20;
 884
 885        seq_printf(m,
 886                   "unstable_check:     %8d\n"
 887                   "unstable_pages: %12ld\n"
 888                   "unstable_mb:        %8d\n",
 889                   cache->ccc_unstable_check, pages, mb);
 890
 891        return 0;
 892}
 893
 894static ssize_t ll_unstable_stats_seq_write(struct file *file,
 895                                           const char __user *buffer,
 896                                           size_t count, loff_t *off)
 897{
 898        struct super_block *sb = ((struct seq_file *)file->private_data)->private;
 899        struct ll_sb_info *sbi = ll_s2sbi(sb);
 900        char kernbuf[128];
 901        int val, rc;
 902
 903        if (!count)
 904                return 0;
 905        if (count >= sizeof(kernbuf))
 906                return -EINVAL;
 907
 908        if (copy_from_user(kernbuf, buffer, count))
 909                return -EFAULT;
 910        kernbuf[count] = 0;
 911
 912        buffer += lprocfs_find_named_value(kernbuf, "unstable_check:", &count) -
 913                  kernbuf;
 914        rc = lprocfs_write_helper(buffer, count, &val);
 915        if (rc < 0)
 916                return rc;
 917
 918        /* borrow lru lock to set the value */
 919        spin_lock(&sbi->ll_cache->ccc_lru_lock);
 920        sbi->ll_cache->ccc_unstable_check = !!val;
 921        spin_unlock(&sbi->ll_cache->ccc_lru_lock);
 922
 923        return count;
 924}
 925LPROC_SEQ_FOPS(ll_unstable_stats);
 926
 927static ssize_t root_squash_show(struct kobject *kobj, struct attribute *attr,
 928                                char *buf)
 929{
 930        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 931                                              ll_kobj);
 932        struct root_squash_info *squash = &sbi->ll_squash;
 933
 934        return sprintf(buf, "%u:%u\n", squash->rsi_uid, squash->rsi_gid);
 935}
 936
 937static ssize_t root_squash_store(struct kobject *kobj, struct attribute *attr,
 938                                 const char *buffer, size_t count)
 939{
 940        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
 941                                              ll_kobj);
 942        struct root_squash_info *squash = &sbi->ll_squash;
 943
 944        return lprocfs_wr_root_squash(buffer, count, squash,
 945                                      ll_get_fsname(sbi->ll_sb, NULL, 0));
 946}
 947LUSTRE_RW_ATTR(root_squash);
 948
 949static int ll_nosquash_nids_seq_show(struct seq_file *m, void *v)
 950{
 951        struct super_block *sb = m->private;
 952        struct ll_sb_info *sbi = ll_s2sbi(sb);
 953        struct root_squash_info *squash = &sbi->ll_squash;
 954        int len;
 955
 956        down_read(&squash->rsi_sem);
 957        if (!list_empty(&squash->rsi_nosquash_nids)) {
 958                len = cfs_print_nidlist(m->buf + m->count, m->size - m->count,
 959                                        &squash->rsi_nosquash_nids);
 960                m->count += len;
 961                seq_puts(m, "\n");
 962        } else {
 963                seq_puts(m, "NONE\n");
 964        }
 965        up_read(&squash->rsi_sem);
 966
 967        return 0;
 968}
 969
 970static ssize_t ll_nosquash_nids_seq_write(struct file *file,
 971                                          const char __user *buffer,
 972                                          size_t count, loff_t *off)
 973{
 974        struct seq_file *m = file->private_data;
 975        struct super_block *sb = m->private;
 976        struct ll_sb_info *sbi = ll_s2sbi(sb);
 977        struct root_squash_info *squash = &sbi->ll_squash;
 978        int rc;
 979
 980        rc = lprocfs_wr_nosquash_nids(buffer, count, squash,
 981                                      ll_get_fsname(sb, NULL, 0));
 982        if (rc < 0)
 983                return rc;
 984
 985        ll_compute_rootsquash_state(sbi);
 986
 987        return rc;
 988}
 989
 990LPROC_SEQ_FOPS(ll_nosquash_nids);
 991
 992static struct lprocfs_vars lprocfs_llite_obd_vars[] = {
 993        /* { "mntpt_path",   ll_rd_path,             0, 0 }, */
 994        { "site",         &ll_site_stats_fops,    NULL, 0 },
 995        /* { "filegroups",   lprocfs_rd_filegroups,  0, 0 }, */
 996        { "max_cached_mb",    &ll_max_cached_mb_fops, NULL },
 997        { "statahead_stats",  &ll_statahead_stats_fops, NULL, 0 },
 998        { "unstable_stats",   &ll_unstable_stats_fops, NULL },
 999        { "sbi_flags",        &ll_sbi_flags_fops, NULL, 0 },
1000        { .name =               "nosquash_nids",
1001          .fops =               &ll_nosquash_nids_fops          },
1002        { NULL }
1003};
1004
1005#define MAX_STRING_SIZE 128
1006
1007static struct attribute *llite_attrs[] = {
1008        &lustre_attr_blocksize.attr,
1009        &lustre_attr_kbytestotal.attr,
1010        &lustre_attr_kbytesfree.attr,
1011        &lustre_attr_kbytesavail.attr,
1012        &lustre_attr_filestotal.attr,
1013        &lustre_attr_filesfree.attr,
1014        &lustre_attr_client_type.attr,
1015        &lustre_attr_fstype.attr,
1016        &lustre_attr_uuid.attr,
1017        &lustre_attr_max_read_ahead_mb.attr,
1018        &lustre_attr_max_read_ahead_per_file_mb.attr,
1019        &lustre_attr_max_read_ahead_whole_mb.attr,
1020        &lustre_attr_checksum_pages.attr,
1021        &lustre_attr_stats_track_pid.attr,
1022        &lustre_attr_stats_track_ppid.attr,
1023        &lustre_attr_stats_track_gid.attr,
1024        &lustre_attr_statahead_max.attr,
1025        &lustre_attr_statahead_agl.attr,
1026        &lustre_attr_lazystatfs.attr,
1027        &lustre_attr_max_easize.attr,
1028        &lustre_attr_default_easize.attr,
1029        &lustre_attr_xattr_cache.attr,
1030        &lustre_attr_root_squash.attr,
1031        NULL,
1032};
1033
1034static void llite_sb_release(struct kobject *kobj)
1035{
1036        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
1037                                              ll_kobj);
1038        complete(&sbi->ll_kobj_unregister);
1039}
1040
1041static struct kobj_type llite_ktype = {
1042        .default_attrs  = llite_attrs,
1043        .sysfs_ops      = &lustre_sysfs_ops,
1044        .release        = llite_sb_release,
1045};
1046
1047static const struct llite_file_opcode {
1048        __u32       opcode;
1049        __u32       type;
1050        const char *opname;
1051} llite_opcode_table[LPROC_LL_FILE_OPCODES] = {
1052        /* file operation */
1053        { LPROC_LL_DIRTY_HITS,     LPROCFS_TYPE_REGS, "dirty_pages_hits" },
1054        { LPROC_LL_DIRTY_MISSES,   LPROCFS_TYPE_REGS, "dirty_pages_misses" },
1055        { LPROC_LL_READ_BYTES,     LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
1056                                   "read_bytes" },
1057        { LPROC_LL_WRITE_BYTES,    LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
1058                                   "write_bytes" },
1059        { LPROC_LL_BRW_READ,       LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_PAGES,
1060                                   "brw_read" },
1061        { LPROC_LL_BRW_WRITE,      LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_PAGES,
1062                                   "brw_write" },
1063        { LPROC_LL_OSC_READ,       LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
1064                                   "osc_read" },
1065        { LPROC_LL_OSC_WRITE,      LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
1066                                   "osc_write" },
1067        { LPROC_LL_IOCTL,         LPROCFS_TYPE_REGS, "ioctl" },
1068        { LPROC_LL_OPEN,           LPROCFS_TYPE_REGS, "open" },
1069        { LPROC_LL_RELEASE,     LPROCFS_TYPE_REGS, "close" },
1070        { LPROC_LL_MAP,     LPROCFS_TYPE_REGS, "mmap" },
1071        { LPROC_LL_LLSEEK,       LPROCFS_TYPE_REGS, "seek" },
1072        { LPROC_LL_FSYNC,         LPROCFS_TYPE_REGS, "fsync" },
1073        { LPROC_LL_READDIR,     LPROCFS_TYPE_REGS, "readdir" },
1074        /* inode operation */
1075        { LPROC_LL_SETATTR,     LPROCFS_TYPE_REGS, "setattr" },
1076        { LPROC_LL_TRUNC,         LPROCFS_TYPE_REGS, "truncate" },
1077        { LPROC_LL_FLOCK,         LPROCFS_TYPE_REGS, "flock" },
1078        { LPROC_LL_GETATTR,     LPROCFS_TYPE_REGS, "getattr" },
1079        /* dir inode operation */
1080        { LPROC_LL_CREATE,       LPROCFS_TYPE_REGS, "create" },
1081        { LPROC_LL_LINK,           LPROCFS_TYPE_REGS, "link" },
1082        { LPROC_LL_UNLINK,       LPROCFS_TYPE_REGS, "unlink" },
1083        { LPROC_LL_SYMLINK,     LPROCFS_TYPE_REGS, "symlink" },
1084        { LPROC_LL_MKDIR,         LPROCFS_TYPE_REGS, "mkdir" },
1085        { LPROC_LL_RMDIR,         LPROCFS_TYPE_REGS, "rmdir" },
1086        { LPROC_LL_MKNOD,         LPROCFS_TYPE_REGS, "mknod" },
1087        { LPROC_LL_RENAME,       LPROCFS_TYPE_REGS, "rename" },
1088        /* special inode operation */
1089        { LPROC_LL_STAFS,         LPROCFS_TYPE_REGS, "statfs" },
1090        { LPROC_LL_ALLOC_INODE,    LPROCFS_TYPE_REGS, "alloc_inode" },
1091        { LPROC_LL_SETXATTR,       LPROCFS_TYPE_REGS, "setxattr" },
1092        { LPROC_LL_GETXATTR,       LPROCFS_TYPE_REGS, "getxattr" },
1093        { LPROC_LL_GETXATTR_HITS,  LPROCFS_TYPE_REGS, "getxattr_hits" },
1094        { LPROC_LL_LISTXATTR,      LPROCFS_TYPE_REGS, "listxattr" },
1095        { LPROC_LL_REMOVEXATTR,    LPROCFS_TYPE_REGS, "removexattr" },
1096        { LPROC_LL_INODE_PERM,     LPROCFS_TYPE_REGS, "inode_permission" },
1097};
1098
1099void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count)
1100{
1101        if (!sbi->ll_stats)
1102                return;
1103        if (sbi->ll_stats_track_type == STATS_TRACK_ALL)
1104                lprocfs_counter_add(sbi->ll_stats, op, count);
1105        else if (sbi->ll_stats_track_type == STATS_TRACK_PID &&
1106                 sbi->ll_stats_track_id == current->pid)
1107                lprocfs_counter_add(sbi->ll_stats, op, count);
1108        else if (sbi->ll_stats_track_type == STATS_TRACK_PPID &&
1109                 sbi->ll_stats_track_id == current->real_parent->pid)
1110                lprocfs_counter_add(sbi->ll_stats, op, count);
1111        else if (sbi->ll_stats_track_type == STATS_TRACK_GID &&
1112                 sbi->ll_stats_track_id ==
1113                        from_kgid(&init_user_ns, current_gid()))
1114                lprocfs_counter_add(sbi->ll_stats, op, count);
1115}
1116EXPORT_SYMBOL(ll_stats_ops_tally);
1117
1118static const char *ra_stat_string[] = {
1119        [RA_STAT_HIT] = "hits",
1120        [RA_STAT_MISS] = "misses",
1121        [RA_STAT_DISTANT_READPAGE] = "readpage not consecutive",
1122        [RA_STAT_MISS_IN_WINDOW] = "miss inside window",
1123        [RA_STAT_FAILED_GRAB_PAGE] = "failed grab_cache_page",
1124        [RA_STAT_FAILED_MATCH] = "failed lock match",
1125        [RA_STAT_DISCARDED] = "read but discarded",
1126        [RA_STAT_ZERO_LEN] = "zero length file",
1127        [RA_STAT_ZERO_WINDOW] = "zero size window",
1128        [RA_STAT_EOF] = "read-ahead to EOF",
1129        [RA_STAT_MAX_IN_FLIGHT] = "hit max r-a issue",
1130        [RA_STAT_WRONG_GRAB_PAGE] = "wrong page from grab_cache_page",
1131        [RA_STAT_FAILED_REACH_END] = "failed to reach end"
1132};
1133
1134int ldebugfs_register_mountpoint(struct dentry *parent,
1135                                 struct super_block *sb, char *osc, char *mdc)
1136{
1137        struct lustre_sb_info *lsi = s2lsi(sb);
1138        struct ll_sb_info *sbi = ll_s2sbi(sb);
1139        struct obd_device *obd;
1140        struct dentry *dir;
1141        char name[MAX_STRING_SIZE + 1], *ptr;
1142        int err, id, len, rc;
1143
1144        name[MAX_STRING_SIZE] = '\0';
1145
1146        LASSERT(sbi);
1147        LASSERT(mdc);
1148        LASSERT(osc);
1149
1150        /* Get fsname */
1151        len = strlen(lsi->lsi_lmd->lmd_profile);
1152        ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-');
1153        if (ptr && (strcmp(ptr, "-client") == 0))
1154                len -= 7;
1155
1156        /* Mount info */
1157        snprintf(name, MAX_STRING_SIZE, "%.*s-%p", len,
1158                 lsi->lsi_lmd->lmd_profile, sb);
1159
1160        dir = ldebugfs_register(name, parent, NULL, NULL);
1161        if (IS_ERR_OR_NULL(dir)) {
1162                err = dir ? PTR_ERR(dir) : -ENOMEM;
1163                sbi->ll_debugfs_entry = NULL;
1164                return err;
1165        }
1166        sbi->ll_debugfs_entry = dir;
1167
1168        rc = ldebugfs_seq_create(sbi->ll_debugfs_entry, "dump_page_cache", 0444,
1169                                 &vvp_dump_pgcache_file_ops, sbi);
1170        if (rc)
1171                CWARN("Error adding the dump_page_cache file\n");
1172
1173        rc = ldebugfs_seq_create(sbi->ll_debugfs_entry, "extents_stats", 0644,
1174                                 &ll_rw_extents_stats_fops, sbi);
1175        if (rc)
1176                CWARN("Error adding the extent_stats file\n");
1177
1178        rc = ldebugfs_seq_create(sbi->ll_debugfs_entry,
1179                                 "extents_stats_per_process",
1180                                 0644, &ll_rw_extents_stats_pp_fops, sbi);
1181        if (rc)
1182                CWARN("Error adding the extents_stats_per_process file\n");
1183
1184        rc = ldebugfs_seq_create(sbi->ll_debugfs_entry, "offset_stats", 0644,
1185                                 &ll_rw_offset_stats_fops, sbi);
1186        if (rc)
1187                CWARN("Error adding the offset_stats file\n");
1188
1189        /* File operations stats */
1190        sbi->ll_stats = lprocfs_alloc_stats(LPROC_LL_FILE_OPCODES,
1191                                            LPROCFS_STATS_FLAG_NONE);
1192        if (!sbi->ll_stats) {
1193                err = -ENOMEM;
1194                goto out;
1195        }
1196        /* do counter init */
1197        for (id = 0; id < LPROC_LL_FILE_OPCODES; id++) {
1198                __u32 type = llite_opcode_table[id].type;
1199                void *ptr = NULL;
1200
1201                if (type & LPROCFS_TYPE_REGS)
1202                        ptr = "regs";
1203                else if (type & LPROCFS_TYPE_BYTES)
1204                        ptr = "bytes";
1205                else if (type & LPROCFS_TYPE_PAGES)
1206                        ptr = "pages";
1207                lprocfs_counter_init(sbi->ll_stats,
1208                                     llite_opcode_table[id].opcode,
1209                                     (type & LPROCFS_CNTR_AVGMINMAX),
1210                                     llite_opcode_table[id].opname, ptr);
1211        }
1212        err = ldebugfs_register_stats(sbi->ll_debugfs_entry, "stats",
1213                                      sbi->ll_stats);
1214        if (err)
1215                goto out;
1216
1217        sbi->ll_ra_stats = lprocfs_alloc_stats(ARRAY_SIZE(ra_stat_string),
1218                                               LPROCFS_STATS_FLAG_NONE);
1219        if (!sbi->ll_ra_stats) {
1220                err = -ENOMEM;
1221                goto out;
1222        }
1223
1224        for (id = 0; id < ARRAY_SIZE(ra_stat_string); id++)
1225                lprocfs_counter_init(sbi->ll_ra_stats, id, 0,
1226                                     ra_stat_string[id], "pages");
1227
1228        err = ldebugfs_register_stats(sbi->ll_debugfs_entry, "read_ahead_stats",
1229                                      sbi->ll_ra_stats);
1230        if (err)
1231                goto out;
1232
1233        err = ldebugfs_add_vars(sbi->ll_debugfs_entry,
1234                                lprocfs_llite_obd_vars, sb);
1235        if (err)
1236                goto out;
1237
1238        sbi->ll_kobj.kset = llite_kset;
1239        init_completion(&sbi->ll_kobj_unregister);
1240        err = kobject_init_and_add(&sbi->ll_kobj, &llite_ktype, NULL,
1241                                   "%s", name);
1242        if (err)
1243                goto out;
1244
1245        /* MDC info */
1246        obd = class_name2obd(mdc);
1247
1248        err = sysfs_create_link(&sbi->ll_kobj, &obd->obd_kobj,
1249                                obd->obd_type->typ_name);
1250        if (err)
1251                goto out;
1252
1253        /* OSC */
1254        obd = class_name2obd(osc);
1255
1256        err = sysfs_create_link(&sbi->ll_kobj, &obd->obd_kobj,
1257                                obd->obd_type->typ_name);
1258out:
1259        if (err) {
1260                ldebugfs_remove(&sbi->ll_debugfs_entry);
1261                lprocfs_free_stats(&sbi->ll_ra_stats);
1262                lprocfs_free_stats(&sbi->ll_stats);
1263        }
1264        return err;
1265}
1266
1267void ldebugfs_unregister_mountpoint(struct ll_sb_info *sbi)
1268{
1269        if (sbi->ll_debugfs_entry) {
1270                ldebugfs_remove(&sbi->ll_debugfs_entry);
1271                kobject_put(&sbi->ll_kobj);
1272                wait_for_completion(&sbi->ll_kobj_unregister);
1273                lprocfs_free_stats(&sbi->ll_ra_stats);
1274                lprocfs_free_stats(&sbi->ll_stats);
1275        }
1276}
1277
1278#undef MAX_STRING_SIZE
1279
1280#define pct(a, b) (b ? a * 100 / b : 0)
1281
1282static void ll_display_extents_info(struct ll_rw_extents_info *io_extents,
1283                                    struct seq_file *seq, int which)
1284{
1285        unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum;
1286        unsigned long start, end, r, w;
1287        char *unitp = "KMGTPEZY";
1288        int i, units = 10;
1289        struct per_process_info *pp_info = &io_extents->pp_extents[which];
1290
1291        read_cum = 0;
1292        write_cum = 0;
1293        start = 0;
1294
1295        for (i = 0; i < LL_HIST_MAX; i++) {
1296                read_tot += pp_info->pp_r_hist.oh_buckets[i];
1297                write_tot += pp_info->pp_w_hist.oh_buckets[i];
1298        }
1299
1300        for (i = 0; i < LL_HIST_MAX; i++) {
1301                r = pp_info->pp_r_hist.oh_buckets[i];
1302                w = pp_info->pp_w_hist.oh_buckets[i];
1303                read_cum += r;
1304                write_cum += w;
1305                end = 1 << (i + LL_HIST_START - units);
1306                seq_printf(seq, "%4lu%c - %4lu%c%c: %14lu %4lu %4lu  | %14lu %4lu %4lu\n",
1307                           start, *unitp, end, *unitp,
1308                           (i == LL_HIST_MAX - 1) ? '+' : ' ',
1309                           r, pct(r, read_tot), pct(read_cum, read_tot),
1310                           w, pct(w, write_tot), pct(write_cum, write_tot));
1311                start = end;
1312                if (start == 1 << 10) {
1313                        start = 1;
1314                        units += 10;
1315                        unitp++;
1316                }
1317                if (read_cum == read_tot && write_cum == write_tot)
1318                        break;
1319        }
1320}
1321
1322static int ll_rw_extents_stats_pp_seq_show(struct seq_file *seq, void *v)
1323{
1324        struct timespec64 now;
1325        struct ll_sb_info *sbi = seq->private;
1326        struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1327        int k;
1328
1329        ktime_get_real_ts64(&now);
1330
1331        if (!sbi->ll_rw_stats_on) {
1332                seq_printf(seq, "disabled\n"
1333                           "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1334                return 0;
1335        }
1336        seq_printf(seq, "snapshot_time:  %llu.%09lu (secs.usecs)\n",
1337                   (s64)now.tv_sec, (unsigned long)now.tv_nsec);
1338        seq_printf(seq, "%15s %19s       | %20s\n", " ", "read", "write");
1339        seq_printf(seq, "%13s   %14s %4s %4s  | %14s %4s %4s\n",
1340                   "extents", "calls", "%", "cum%",
1341                   "calls", "%", "cum%");
1342        spin_lock(&sbi->ll_pp_extent_lock);
1343        for (k = 0; k < LL_PROCESS_HIST_MAX; k++) {
1344                if (io_extents->pp_extents[k].pid != 0) {
1345                        seq_printf(seq, "\nPID: %d\n",
1346                                   io_extents->pp_extents[k].pid);
1347                        ll_display_extents_info(io_extents, seq, k);
1348                }
1349        }
1350        spin_unlock(&sbi->ll_pp_extent_lock);
1351        return 0;
1352}
1353
1354static ssize_t ll_rw_extents_stats_pp_seq_write(struct file *file,
1355                                                const char __user *buf,
1356                                                size_t len,
1357                                                loff_t *off)
1358{
1359        struct seq_file *seq = file->private_data;
1360        struct ll_sb_info *sbi = seq->private;
1361        struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1362        int i;
1363        int value = 1, rc = 0;
1364
1365        if (len == 0)
1366                return -EINVAL;
1367
1368        rc = lprocfs_write_helper(buf, len, &value);
1369        if (rc < 0 && len < 16) {
1370                char kernbuf[16];
1371
1372                if (copy_from_user(kernbuf, buf, len))
1373                        return -EFAULT;
1374                kernbuf[len] = 0;
1375
1376                if (kernbuf[len - 1] == '\n')
1377                        kernbuf[len - 1] = 0;
1378
1379                if (strcmp(kernbuf, "disabled") == 0 ||
1380                    strcmp(kernbuf, "Disabled") == 0)
1381                        value = 0;
1382        }
1383
1384        if (value == 0)
1385                sbi->ll_rw_stats_on = 0;
1386        else
1387                sbi->ll_rw_stats_on = 1;
1388
1389        spin_lock(&sbi->ll_pp_extent_lock);
1390        for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1391                io_extents->pp_extents[i].pid = 0;
1392                lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
1393                lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist);
1394        }
1395        spin_unlock(&sbi->ll_pp_extent_lock);
1396        return len;
1397}
1398
1399LPROC_SEQ_FOPS(ll_rw_extents_stats_pp);
1400
1401static int ll_rw_extents_stats_seq_show(struct seq_file *seq, void *v)
1402{
1403        struct timespec64 now;
1404        struct ll_sb_info *sbi = seq->private;
1405        struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1406
1407        ktime_get_real_ts64(&now);
1408
1409        if (!sbi->ll_rw_stats_on) {
1410                seq_printf(seq, "disabled\n"
1411                           "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1412                return 0;
1413        }
1414        seq_printf(seq, "snapshot_time:  %llu.%09lu (secs.usecs)\n",
1415                   (u64)now.tv_sec, (unsigned long)now.tv_nsec);
1416
1417        seq_printf(seq, "%15s %19s       | %20s\n", " ", "read", "write");
1418        seq_printf(seq, "%13s   %14s %4s %4s  | %14s %4s %4s\n",
1419                   "extents", "calls", "%", "cum%",
1420                   "calls", "%", "cum%");
1421        spin_lock(&sbi->ll_lock);
1422        ll_display_extents_info(io_extents, seq, LL_PROCESS_HIST_MAX);
1423        spin_unlock(&sbi->ll_lock);
1424
1425        return 0;
1426}
1427
1428static ssize_t ll_rw_extents_stats_seq_write(struct file *file,
1429                                             const char __user *buf,
1430                                             size_t len, loff_t *off)
1431{
1432        struct seq_file *seq = file->private_data;
1433        struct ll_sb_info *sbi = seq->private;
1434        struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1435        int i;
1436        int value = 1, rc = 0;
1437
1438        if (len == 0)
1439                return -EINVAL;
1440
1441        rc = lprocfs_write_helper(buf, len, &value);
1442        if (rc < 0 && len < 16) {
1443                char kernbuf[16];
1444
1445                if (copy_from_user(kernbuf, buf, len))
1446                        return -EFAULT;
1447                kernbuf[len] = 0;
1448
1449                if (kernbuf[len - 1] == '\n')
1450                        kernbuf[len - 1] = 0;
1451
1452                if (strcmp(kernbuf, "disabled") == 0 ||
1453                    strcmp(kernbuf, "Disabled") == 0)
1454                        value = 0;
1455        }
1456
1457        if (value == 0)
1458                sbi->ll_rw_stats_on = 0;
1459        else
1460                sbi->ll_rw_stats_on = 1;
1461
1462        spin_lock(&sbi->ll_pp_extent_lock);
1463        for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) {
1464                io_extents->pp_extents[i].pid = 0;
1465                lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
1466                lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist);
1467        }
1468        spin_unlock(&sbi->ll_pp_extent_lock);
1469
1470        return len;
1471}
1472
1473LPROC_SEQ_FOPS(ll_rw_extents_stats);
1474
1475void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid,
1476                       struct ll_file_data *file, loff_t pos,
1477                       size_t count, int rw)
1478{
1479        int i, cur = -1;
1480        struct ll_rw_process_info *process;
1481        struct ll_rw_process_info *offset;
1482        int *off_count = &sbi->ll_rw_offset_entry_count;
1483        int *process_count = &sbi->ll_offset_process_count;
1484        struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1485
1486        if (!sbi->ll_rw_stats_on)
1487                return;
1488        process = sbi->ll_rw_process_info;
1489        offset = sbi->ll_rw_offset_info;
1490
1491        spin_lock(&sbi->ll_pp_extent_lock);
1492        /* Extent statistics */
1493        for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1494                if (io_extents->pp_extents[i].pid == pid) {
1495                        cur = i;
1496                        break;
1497                }
1498        }
1499
1500        if (cur == -1) {
1501                /* new process */
1502                sbi->ll_extent_process_count =
1503                        (sbi->ll_extent_process_count + 1) % LL_PROCESS_HIST_MAX;
1504                cur = sbi->ll_extent_process_count;
1505                io_extents->pp_extents[cur].pid = pid;
1506                lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_r_hist);
1507                lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_w_hist);
1508        }
1509
1510        for (i = 0; (count >= (1 << LL_HIST_START << i)) &&
1511             (i < (LL_HIST_MAX - 1)); i++)
1512                ;
1513        if (rw == 0) {
1514                io_extents->pp_extents[cur].pp_r_hist.oh_buckets[i]++;
1515                io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_r_hist.oh_buckets[i]++;
1516        } else {
1517                io_extents->pp_extents[cur].pp_w_hist.oh_buckets[i]++;
1518                io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_w_hist.oh_buckets[i]++;
1519        }
1520        spin_unlock(&sbi->ll_pp_extent_lock);
1521
1522        spin_lock(&sbi->ll_process_lock);
1523        /* Offset statistics */
1524        for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1525                if (process[i].rw_pid == pid) {
1526                        if (process[i].rw_last_file != file) {
1527                                process[i].rw_range_start = pos;
1528                                process[i].rw_last_file_pos = pos + count;
1529                                process[i].rw_smallest_extent = count;
1530                                process[i].rw_largest_extent = count;
1531                                process[i].rw_offset = 0;
1532                                process[i].rw_last_file = file;
1533                                spin_unlock(&sbi->ll_process_lock);
1534                                return;
1535                        }
1536                        if (process[i].rw_last_file_pos != pos) {
1537                                *off_count =
1538                                    (*off_count + 1) % LL_OFFSET_HIST_MAX;
1539                                offset[*off_count].rw_op = process[i].rw_op;
1540                                offset[*off_count].rw_pid = pid;
1541                                offset[*off_count].rw_range_start =
1542                                        process[i].rw_range_start;
1543                                offset[*off_count].rw_range_end =
1544                                        process[i].rw_last_file_pos;
1545                                offset[*off_count].rw_smallest_extent =
1546                                        process[i].rw_smallest_extent;
1547                                offset[*off_count].rw_largest_extent =
1548                                        process[i].rw_largest_extent;
1549                                offset[*off_count].rw_offset =
1550                                        process[i].rw_offset;
1551                                process[i].rw_op = rw;
1552                                process[i].rw_range_start = pos;
1553                                process[i].rw_smallest_extent = count;
1554                                process[i].rw_largest_extent = count;
1555                                process[i].rw_offset = pos -
1556                                        process[i].rw_last_file_pos;
1557                        }
1558                        if (process[i].rw_smallest_extent > count)
1559                                process[i].rw_smallest_extent = count;
1560                        if (process[i].rw_largest_extent < count)
1561                                process[i].rw_largest_extent = count;
1562                        process[i].rw_last_file_pos = pos + count;
1563                        spin_unlock(&sbi->ll_process_lock);
1564                        return;
1565                }
1566        }
1567        *process_count = (*process_count + 1) % LL_PROCESS_HIST_MAX;
1568        process[*process_count].rw_pid = pid;
1569        process[*process_count].rw_op = rw;
1570        process[*process_count].rw_range_start = pos;
1571        process[*process_count].rw_last_file_pos = pos + count;
1572        process[*process_count].rw_smallest_extent = count;
1573        process[*process_count].rw_largest_extent = count;
1574        process[*process_count].rw_offset = 0;
1575        process[*process_count].rw_last_file = file;
1576        spin_unlock(&sbi->ll_process_lock);
1577}
1578
1579static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v)
1580{
1581        struct timespec64 now;
1582        struct ll_sb_info *sbi = seq->private;
1583        struct ll_rw_process_info *offset = sbi->ll_rw_offset_info;
1584        struct ll_rw_process_info *process = sbi->ll_rw_process_info;
1585        int i;
1586
1587        ktime_get_real_ts64(&now);
1588
1589        if (!sbi->ll_rw_stats_on) {
1590                seq_printf(seq, "disabled\n"
1591                           "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1592                return 0;
1593        }
1594        spin_lock(&sbi->ll_process_lock);
1595
1596        seq_printf(seq, "snapshot_time:  %llu.%09lu (secs.usecs)\n",
1597                   (s64)now.tv_sec, (unsigned long)now.tv_nsec);
1598        seq_printf(seq, "%3s %10s %14s %14s %17s %17s %14s\n",
1599                   "R/W", "PID", "RANGE START", "RANGE END",
1600                   "SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET");
1601        /* We stored the discontiguous offsets here; print them first */
1602        for (i = 0; i < LL_OFFSET_HIST_MAX; i++) {
1603                if (offset[i].rw_pid != 0)
1604                        seq_printf(seq,
1605                                   "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1606                                   offset[i].rw_op == READ ? 'R' : 'W',
1607                                   offset[i].rw_pid,
1608                                   offset[i].rw_range_start,
1609                                   offset[i].rw_range_end,
1610                                   (unsigned long)offset[i].rw_smallest_extent,
1611                                   (unsigned long)offset[i].rw_largest_extent,
1612                                   offset[i].rw_offset);
1613        }
1614        /* Then print the current offsets for each process */
1615        for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1616                if (process[i].rw_pid != 0)
1617                        seq_printf(seq,
1618                                   "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1619                                   process[i].rw_op == READ ? 'R' : 'W',
1620                                   process[i].rw_pid,
1621                                   process[i].rw_range_start,
1622                                   process[i].rw_last_file_pos,
1623                                   (unsigned long)process[i].rw_smallest_extent,
1624                                   (unsigned long)process[i].rw_largest_extent,
1625                                   process[i].rw_offset);
1626        }
1627        spin_unlock(&sbi->ll_process_lock);
1628
1629        return 0;
1630}
1631
1632static ssize_t ll_rw_offset_stats_seq_write(struct file *file,
1633                                            const char __user *buf,
1634                                            size_t len, loff_t *off)
1635{
1636        struct seq_file *seq = file->private_data;
1637        struct ll_sb_info *sbi = seq->private;
1638        struct ll_rw_process_info *process_info = sbi->ll_rw_process_info;
1639        struct ll_rw_process_info *offset_info = sbi->ll_rw_offset_info;
1640        int value = 1, rc = 0;
1641
1642        if (len == 0)
1643                return -EINVAL;
1644
1645        rc = lprocfs_write_helper(buf, len, &value);
1646
1647        if (rc < 0 && len < 16) {
1648                char kernbuf[16];
1649
1650                if (copy_from_user(kernbuf, buf, len))
1651                        return -EFAULT;
1652                kernbuf[len] = 0;
1653
1654                if (kernbuf[len - 1] == '\n')
1655                        kernbuf[len - 1] = 0;
1656
1657                if (strcmp(kernbuf, "disabled") == 0 ||
1658                    strcmp(kernbuf, "Disabled") == 0)
1659                        value = 0;
1660        }
1661
1662        if (value == 0)
1663                sbi->ll_rw_stats_on = 0;
1664        else
1665                sbi->ll_rw_stats_on = 1;
1666
1667        spin_lock(&sbi->ll_process_lock);
1668        sbi->ll_offset_process_count = 0;
1669        sbi->ll_rw_offset_entry_count = 0;
1670        memset(process_info, 0, sizeof(struct ll_rw_process_info) *
1671               LL_PROCESS_HIST_MAX);
1672        memset(offset_info, 0, sizeof(struct ll_rw_process_info) *
1673               LL_OFFSET_HIST_MAX);
1674        spin_unlock(&sbi->ll_process_lock);
1675
1676        return len;
1677}
1678
1679LPROC_SEQ_FOPS(ll_rw_offset_stats);
1680
1681void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars)
1682{
1683        lvars->obd_vars = lprocfs_llite_obd_vars;
1684}
1685