linux/drivers/staging/lustre/lustre/osc/lproc_osc.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.sun.com/software/products/lustre/docs/GPLv2.pdf
  19 *
  20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  21 * CA 95054 USA or visit www.sun.com if you need additional information or
  22 * have any questions.
  23 *
  24 * GPL HEADER END
  25 */
  26/*
  27 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  28 * Use is subject to license terms.
  29 *
  30 * Copyright (c) 2011, 2012, Intel Corporation.
  31 */
  32/*
  33 * This file is part of Lustre, http://www.lustre.org/
  34 * Lustre is a trademark of Sun Microsystems, Inc.
  35 */
  36#define DEBUG_SUBSYSTEM S_CLASS
  37
  38#include <linux/statfs.h>
  39#include "../include/obd_cksum.h"
  40#include "../include/obd_class.h"
  41#include "../include/lprocfs_status.h"
  42#include <linux/seq_file.h>
  43#include "osc_internal.h"
  44
  45static int osc_active_seq_show(struct seq_file *m, void *v)
  46{
  47        struct obd_device *dev = m->private;
  48
  49        LPROCFS_CLIMP_CHECK(dev);
  50        seq_printf(m, "%d\n", !dev->u.cli.cl_import->imp_deactive);
  51        LPROCFS_CLIMP_EXIT(dev);
  52
  53        return 0;
  54}
  55
  56static ssize_t osc_active_seq_write(struct file *file,
  57                                const char __user *buffer,
  58                                size_t count, loff_t *off)
  59{
  60        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
  61        int val, rc;
  62
  63        rc = lprocfs_write_helper(buffer, count, &val);
  64        if (rc)
  65                return rc;
  66        if (val < 0 || val > 1)
  67                return -ERANGE;
  68
  69        /* opposite senses */
  70        if (dev->u.cli.cl_import->imp_deactive == val)
  71                rc = ptlrpc_set_import_active(dev->u.cli.cl_import, val);
  72        else
  73                CDEBUG(D_CONFIG, "activate %d: ignoring repeat request\n", val);
  74
  75        return count;
  76}
  77LPROC_SEQ_FOPS(osc_active);
  78
  79static int osc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v)
  80{
  81        struct obd_device *dev = m->private;
  82        struct client_obd *cli = &dev->u.cli;
  83
  84        client_obd_list_lock(&cli->cl_loi_list_lock);
  85        seq_printf(m, "%u\n", cli->cl_max_rpcs_in_flight);
  86        client_obd_list_unlock(&cli->cl_loi_list_lock);
  87
  88        return 0;
  89}
  90
  91static ssize_t osc_max_rpcs_in_flight_seq_write(struct file *file,
  92                        const char __user *buffer,
  93                        size_t count, loff_t *off)
  94{
  95        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
  96        struct client_obd *cli = &dev->u.cli;
  97        struct ptlrpc_request_pool *pool = cli->cl_import->imp_rq_pool;
  98        int val, rc;
  99
 100        rc = lprocfs_write_helper(buffer, count, &val);
 101        if (rc)
 102                return rc;
 103
 104        if (val < 1 || val > OSC_MAX_RIF_MAX)
 105                return -ERANGE;
 106
 107        LPROCFS_CLIMP_CHECK(dev);
 108        if (pool && val > cli->cl_max_rpcs_in_flight)
 109                pool->prp_populate(pool, val-cli->cl_max_rpcs_in_flight);
 110
 111        client_obd_list_lock(&cli->cl_loi_list_lock);
 112        cli->cl_max_rpcs_in_flight = val;
 113        client_obd_list_unlock(&cli->cl_loi_list_lock);
 114
 115        LPROCFS_CLIMP_EXIT(dev);
 116        return count;
 117}
 118LPROC_SEQ_FOPS(osc_max_rpcs_in_flight);
 119
 120static int osc_max_dirty_mb_seq_show(struct seq_file *m, void *v)
 121{
 122        struct obd_device *dev = m->private;
 123        struct client_obd *cli = &dev->u.cli;
 124        long val;
 125        int mult;
 126
 127        client_obd_list_lock(&cli->cl_loi_list_lock);
 128        val = cli->cl_dirty_max;
 129        client_obd_list_unlock(&cli->cl_loi_list_lock);
 130
 131        mult = 1 << 20;
 132        return lprocfs_seq_read_frac_helper(m, val, mult);
 133}
 134
 135static ssize_t osc_max_dirty_mb_seq_write(struct file *file,
 136                                const char __user *buffer,
 137                                size_t count, loff_t *off)
 138{
 139        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
 140        struct client_obd *cli = &dev->u.cli;
 141        int pages_number, mult, rc;
 142
 143        mult = 1 << (20 - PAGE_CACHE_SHIFT);
 144        rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
 145        if (rc)
 146                return rc;
 147
 148        if (pages_number <= 0 ||
 149            pages_number > OSC_MAX_DIRTY_MB_MAX << (20 - PAGE_CACHE_SHIFT) ||
 150            pages_number > totalram_pages / 4) /* 1/4 of RAM */
 151                return -ERANGE;
 152
 153        client_obd_list_lock(&cli->cl_loi_list_lock);
 154        cli->cl_dirty_max = (u32)(pages_number << PAGE_CACHE_SHIFT);
 155        osc_wake_cache_waiters(cli);
 156        client_obd_list_unlock(&cli->cl_loi_list_lock);
 157
 158        return count;
 159}
 160LPROC_SEQ_FOPS(osc_max_dirty_mb);
 161
 162static int osc_cached_mb_seq_show(struct seq_file *m, void *v)
 163{
 164        struct obd_device *dev = m->private;
 165        struct client_obd *cli = &dev->u.cli;
 166        int shift = 20 - PAGE_CACHE_SHIFT;
 167
 168        seq_printf(m,
 169                   "used_mb: %d\n"
 170                   "busy_cnt: %d\n",
 171                   (atomic_read(&cli->cl_lru_in_list) +
 172                    atomic_read(&cli->cl_lru_busy)) >> shift,
 173                   atomic_read(&cli->cl_lru_busy));
 174
 175        return 0;
 176}
 177
 178/* shrink the number of caching pages to a specific number */
 179static ssize_t osc_cached_mb_seq_write(struct file *file,
 180                                       const char __user *buffer,
 181                                       size_t count, loff_t *off)
 182{
 183        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
 184        struct client_obd *cli = &dev->u.cli;
 185        int pages_number, mult, rc;
 186        char kernbuf[128];
 187
 188        if (count >= sizeof(kernbuf))
 189                return -EINVAL;
 190
 191        if (copy_from_user(kernbuf, buffer, count))
 192                return -EFAULT;
 193        kernbuf[count] = 0;
 194
 195        mult = 1 << (20 - PAGE_CACHE_SHIFT);
 196        buffer += lprocfs_find_named_value(kernbuf, "used_mb:", &count) -
 197                  kernbuf;
 198        rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
 199        if (rc)
 200                return rc;
 201
 202        if (pages_number < 0)
 203                return -ERANGE;
 204
 205        rc = atomic_read(&cli->cl_lru_in_list) - pages_number;
 206        if (rc > 0)
 207                (void)osc_lru_shrink(cli, rc);
 208
 209        return count;
 210}
 211LPROC_SEQ_FOPS(osc_cached_mb);
 212
 213static int osc_cur_dirty_bytes_seq_show(struct seq_file *m, void *v)
 214{
 215        struct obd_device *dev = m->private;
 216        struct client_obd *cli = &dev->u.cli;
 217
 218        client_obd_list_lock(&cli->cl_loi_list_lock);
 219        seq_printf(m, "%lu\n", cli->cl_dirty);
 220        client_obd_list_unlock(&cli->cl_loi_list_lock);
 221
 222        return 0;
 223}
 224LPROC_SEQ_FOPS_RO(osc_cur_dirty_bytes);
 225
 226static int osc_cur_grant_bytes_seq_show(struct seq_file *m, void *v)
 227{
 228        struct obd_device *dev = m->private;
 229        struct client_obd *cli = &dev->u.cli;
 230
 231        client_obd_list_lock(&cli->cl_loi_list_lock);
 232        seq_printf(m, "%lu\n", cli->cl_avail_grant);
 233        client_obd_list_unlock(&cli->cl_loi_list_lock);
 234
 235        return 0;
 236}
 237
 238static ssize_t osc_cur_grant_bytes_seq_write(struct file *file,
 239                                const char __user *buffer,
 240                                size_t count, loff_t *off)
 241{
 242        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
 243        struct client_obd *cli = &obd->u.cli;
 244        int             rc;
 245        __u64         val;
 246
 247        if (obd == NULL)
 248                return 0;
 249
 250        rc = lprocfs_write_u64_helper(buffer, count, &val);
 251        if (rc)
 252                return rc;
 253
 254        /* this is only for shrinking grant */
 255        client_obd_list_lock(&cli->cl_loi_list_lock);
 256        if (val >= cli->cl_avail_grant) {
 257                client_obd_list_unlock(&cli->cl_loi_list_lock);
 258                return 0;
 259        }
 260        client_obd_list_unlock(&cli->cl_loi_list_lock);
 261
 262        LPROCFS_CLIMP_CHECK(obd);
 263        if (cli->cl_import->imp_state == LUSTRE_IMP_FULL)
 264                rc = osc_shrink_grant_to_target(cli, val);
 265        LPROCFS_CLIMP_EXIT(obd);
 266        if (rc)
 267                return rc;
 268        return count;
 269}
 270LPROC_SEQ_FOPS(osc_cur_grant_bytes);
 271
 272static int osc_cur_lost_grant_bytes_seq_show(struct seq_file *m, void *v)
 273{
 274        struct obd_device *dev = m->private;
 275        struct client_obd *cli = &dev->u.cli;
 276
 277        client_obd_list_lock(&cli->cl_loi_list_lock);
 278        seq_printf(m, "%lu\n", cli->cl_lost_grant);
 279        client_obd_list_unlock(&cli->cl_loi_list_lock);
 280
 281        return 0;
 282}
 283LPROC_SEQ_FOPS_RO(osc_cur_lost_grant_bytes);
 284
 285static int osc_grant_shrink_interval_seq_show(struct seq_file *m, void *v)
 286{
 287        struct obd_device *obd = m->private;
 288
 289        if (obd == NULL)
 290                return 0;
 291        seq_printf(m, "%d\n", obd->u.cli.cl_grant_shrink_interval);
 292        return 0;
 293}
 294
 295static ssize_t osc_grant_shrink_interval_seq_write(struct file *file,
 296                                const char __user *buffer,
 297                                size_t count, loff_t *off)
 298{
 299        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
 300        int val, rc;
 301
 302        if (obd == NULL)
 303                return 0;
 304
 305        rc = lprocfs_write_helper(buffer, count, &val);
 306        if (rc)
 307                return rc;
 308
 309        if (val <= 0)
 310                return -ERANGE;
 311
 312        obd->u.cli.cl_grant_shrink_interval = val;
 313
 314        return count;
 315}
 316LPROC_SEQ_FOPS(osc_grant_shrink_interval);
 317
 318static int osc_checksum_seq_show(struct seq_file *m, void *v)
 319{
 320        struct obd_device *obd = m->private;
 321
 322        if (obd == NULL)
 323                return 0;
 324
 325        seq_printf(m, "%d\n", obd->u.cli.cl_checksum ? 1 : 0);
 326        return 0;
 327}
 328
 329static ssize_t osc_checksum_seq_write(struct file *file,
 330                                const char __user *buffer,
 331                                size_t count, loff_t *off)
 332{
 333        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
 334        int val, rc;
 335
 336        if (obd == NULL)
 337                return 0;
 338
 339        rc = lprocfs_write_helper(buffer, count, &val);
 340        if (rc)
 341                return rc;
 342
 343        obd->u.cli.cl_checksum = (val ? 1 : 0);
 344
 345        return count;
 346}
 347LPROC_SEQ_FOPS(osc_checksum);
 348
 349static int osc_checksum_type_seq_show(struct seq_file *m, void *v)
 350{
 351        struct obd_device *obd = m->private;
 352        int i;
 353        DECLARE_CKSUM_NAME;
 354
 355        if (obd == NULL)
 356                return 0;
 357
 358        for (i = 0; i < ARRAY_SIZE(cksum_name); i++) {
 359                if (((1 << i) & obd->u.cli.cl_supp_cksum_types) == 0)
 360                        continue;
 361                if (obd->u.cli.cl_cksum_type == (1 << i))
 362                        seq_printf(m, "[%s] ", cksum_name[i]);
 363                else
 364                        seq_printf(m, "%s ", cksum_name[i]);
 365        }
 366        seq_putc(m, '\n');
 367        return 0;
 368}
 369
 370static ssize_t osc_checksum_type_seq_write(struct file *file,
 371                                const char __user *buffer,
 372                                size_t count, loff_t *off)
 373{
 374        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
 375        int i;
 376        DECLARE_CKSUM_NAME;
 377        char kernbuf[10];
 378
 379        if (obd == NULL)
 380                return 0;
 381
 382        if (count > sizeof(kernbuf) - 1)
 383                return -EINVAL;
 384        if (copy_from_user(kernbuf, buffer, count))
 385                return -EFAULT;
 386        if (count > 0 && kernbuf[count - 1] == '\n')
 387                kernbuf[count - 1] = '\0';
 388        else
 389                kernbuf[count] = '\0';
 390
 391        for (i = 0; i < ARRAY_SIZE(cksum_name); i++) {
 392                if (((1 << i) & obd->u.cli.cl_supp_cksum_types) == 0)
 393                        continue;
 394                if (!strcmp(kernbuf, cksum_name[i])) {
 395                       obd->u.cli.cl_cksum_type = 1 << i;
 396                       return count;
 397                }
 398        }
 399        return -EINVAL;
 400}
 401LPROC_SEQ_FOPS(osc_checksum_type);
 402
 403static int osc_resend_count_seq_show(struct seq_file *m, void *v)
 404{
 405        struct obd_device *obd = m->private;
 406
 407        seq_printf(m, "%u\n", atomic_read(&obd->u.cli.cl_resends));
 408        return 0;
 409}
 410
 411static ssize_t osc_resend_count_seq_write(struct file *file,
 412                                const char __user *buffer,
 413                                size_t count, loff_t *off)
 414{
 415        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
 416        int val, rc;
 417
 418        rc = lprocfs_write_helper(buffer, count, &val);
 419        if (rc)
 420                return rc;
 421
 422        if (val < 0)
 423               return -EINVAL;
 424
 425        atomic_set(&obd->u.cli.cl_resends, val);
 426
 427        return count;
 428}
 429LPROC_SEQ_FOPS(osc_resend_count);
 430
 431static int osc_contention_seconds_seq_show(struct seq_file *m, void *v)
 432{
 433        struct obd_device *obd = m->private;
 434        struct osc_device *od  = obd2osc_dev(obd);
 435
 436        seq_printf(m, "%u\n", od->od_contention_time);
 437        return 0;
 438}
 439
 440static ssize_t osc_contention_seconds_seq_write(struct file *file,
 441                                        const char __user *buffer,
 442                                        size_t count, loff_t *off)
 443{
 444        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
 445        struct osc_device *od  = obd2osc_dev(obd);
 446
 447        return lprocfs_write_helper(buffer, count, &od->od_contention_time) ?:
 448                count;
 449}
 450LPROC_SEQ_FOPS(osc_contention_seconds);
 451
 452static int osc_lockless_truncate_seq_show(struct seq_file *m, void *v)
 453{
 454        struct obd_device *obd = m->private;
 455        struct osc_device *od  = obd2osc_dev(obd);
 456
 457        seq_printf(m, "%u\n", od->od_lockless_truncate);
 458        return 0;
 459}
 460
 461static ssize_t osc_lockless_truncate_seq_write(struct file *file,
 462                                        const char __user *buffer,
 463                                        size_t count, loff_t *off)
 464{
 465        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
 466        struct osc_device *od  = obd2osc_dev(obd);
 467
 468        return lprocfs_write_helper(buffer, count, &od->od_lockless_truncate) ?:
 469                count;
 470}
 471LPROC_SEQ_FOPS(osc_lockless_truncate);
 472
 473static int osc_destroys_in_flight_seq_show(struct seq_file *m, void *v)
 474{
 475        struct obd_device *obd = m->private;
 476
 477        seq_printf(m, "%u\n", atomic_read(&obd->u.cli.cl_destroy_in_flight));
 478        return 0;
 479}
 480LPROC_SEQ_FOPS_RO(osc_destroys_in_flight);
 481
 482static int osc_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *v)
 483{
 484        return lprocfs_obd_rd_max_pages_per_rpc(m, m->private);
 485}
 486
 487static ssize_t osc_obd_max_pages_per_rpc_seq_write(struct file *file,
 488                                const char __user *buffer,
 489                                size_t count, loff_t *off)
 490{
 491        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
 492        struct client_obd *cli = &dev->u.cli;
 493        struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
 494        int chunk_mask, rc;
 495        __u64 val;
 496
 497        rc = lprocfs_write_u64_helper(buffer, count, &val);
 498        if (rc)
 499                return rc;
 500
 501        /* if the max_pages is specified in bytes, convert to pages */
 502        if (val >= ONE_MB_BRW_SIZE)
 503                val >>= PAGE_CACHE_SHIFT;
 504
 505        LPROCFS_CLIMP_CHECK(dev);
 506
 507        chunk_mask = ~((1 << (cli->cl_chunkbits - PAGE_CACHE_SHIFT)) - 1);
 508        /* max_pages_per_rpc must be chunk aligned */
 509        val = (val + ~chunk_mask) & chunk_mask;
 510        if (val == 0 || val > ocd->ocd_brw_size >> PAGE_CACHE_SHIFT) {
 511                LPROCFS_CLIMP_EXIT(dev);
 512                return -ERANGE;
 513        }
 514        client_obd_list_lock(&cli->cl_loi_list_lock);
 515        cli->cl_max_pages_per_rpc = val;
 516        client_obd_list_unlock(&cli->cl_loi_list_lock);
 517
 518        LPROCFS_CLIMP_EXIT(dev);
 519        return count;
 520}
 521LPROC_SEQ_FOPS(osc_obd_max_pages_per_rpc);
 522
 523LPROC_SEQ_FOPS_RO_TYPE(osc, uuid);
 524LPROC_SEQ_FOPS_RO_TYPE(osc, connect_flags);
 525LPROC_SEQ_FOPS_RO_TYPE(osc, blksize);
 526LPROC_SEQ_FOPS_RO_TYPE(osc, kbytestotal);
 527LPROC_SEQ_FOPS_RO_TYPE(osc, kbytesfree);
 528LPROC_SEQ_FOPS_RO_TYPE(osc, kbytesavail);
 529LPROC_SEQ_FOPS_RO_TYPE(osc, filestotal);
 530LPROC_SEQ_FOPS_RO_TYPE(osc, filesfree);
 531LPROC_SEQ_FOPS_RO_TYPE(osc, server_uuid);
 532LPROC_SEQ_FOPS_RO_TYPE(osc, conn_uuid);
 533LPROC_SEQ_FOPS_RO_TYPE(osc, timeouts);
 534LPROC_SEQ_FOPS_RO_TYPE(osc, state);
 535
 536LPROC_SEQ_FOPS_WR_ONLY(osc, ping);
 537
 538LPROC_SEQ_FOPS_RW_TYPE(osc, import);
 539LPROC_SEQ_FOPS_RW_TYPE(osc, pinger_recov);
 540
 541static struct lprocfs_vars lprocfs_osc_obd_vars[] = {
 542        { "uuid",            &osc_uuid_fops,    NULL, 0 },
 543        { "ping",            &osc_ping_fops,    NULL, 0222 },
 544        { "connect_flags",   &osc_connect_flags_fops, NULL, 0 },
 545        { "blocksize",       &osc_blksize_fops,     NULL, 0 },
 546        { "kbytestotal",     &osc_kbytestotal_fops, NULL, 0 },
 547        { "kbytesfree",      &osc_kbytesfree_fops,  NULL, 0 },
 548        { "kbytesavail",     &osc_kbytesavail_fops, NULL, 0 },
 549        { "filestotal",      &osc_filestotal_fops,  NULL, 0 },
 550        { "filesfree",       &osc_filesfree_fops,   NULL, 0 },
 551        /*{ "filegroups",      lprocfs_rd_filegroups,  NULL, 0 },*/
 552        { "ost_server_uuid", &osc_server_uuid_fops, NULL, 0 },
 553        { "ost_conn_uuid",   &osc_conn_uuid_fops, NULL, 0 },
 554        { "active",          &osc_active_fops, NULL },
 555        { "max_pages_per_rpc", &osc_obd_max_pages_per_rpc_fops, NULL },
 556        { "max_rpcs_in_flight", &osc_max_rpcs_in_flight_fops, NULL },
 557        { "destroys_in_flight", &osc_destroys_in_flight_fops, NULL, 0 },
 558        { "max_dirty_mb",    &osc_max_dirty_mb_fops, NULL },
 559        { "osc_cached_mb",   &osc_cached_mb_fops, NULL },
 560        { "cur_dirty_bytes", &osc_cur_dirty_bytes_fops, NULL, 0 },
 561        { "cur_grant_bytes", &osc_cur_grant_bytes_fops, NULL },
 562        { "cur_lost_grant_bytes", &osc_cur_lost_grant_bytes_fops, NULL, 0},
 563        { "grant_shrink_interval", &osc_grant_shrink_interval_fops, NULL },
 564        { "checksums",       &osc_checksum_fops, NULL },
 565        { "checksum_type",   &osc_checksum_type_fops, NULL },
 566        { "resend_count",    &osc_resend_count_fops, NULL},
 567        { "timeouts",        &osc_timeouts_fops, NULL, 0 },
 568        { "contention_seconds", &osc_contention_seconds_fops, NULL },
 569        { "lockless_truncate",  &osc_lockless_truncate_fops, NULL },
 570        { "import",             &osc_import_fops, NULL },
 571        { "state",              &osc_state_fops, NULL, 0 },
 572        { "pinger_recov",       &osc_pinger_recov_fops, NULL },
 573        { NULL }
 574};
 575
 576LPROC_SEQ_FOPS_RO_TYPE(osc, numrefs);
 577static struct lprocfs_vars lprocfs_osc_module_vars[] = {
 578        { "num_refs",   &osc_numrefs_fops,     NULL, 0 },
 579        { NULL }
 580};
 581
 582#define pct(a, b) (b ? a * 100 / b : 0)
 583
 584static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v)
 585{
 586        struct timeval now;
 587        struct obd_device *dev = seq->private;
 588        struct client_obd *cli = &dev->u.cli;
 589        unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum;
 590        int i;
 591
 592        do_gettimeofday(&now);
 593
 594        client_obd_list_lock(&cli->cl_loi_list_lock);
 595
 596        seq_printf(seq, "snapshot_time:  %lu.%lu (secs.usecs)\n",
 597                   now.tv_sec, (unsigned long)now.tv_usec);
 598        seq_printf(seq, "read RPCs in flight:  %d\n",
 599                   cli->cl_r_in_flight);
 600        seq_printf(seq, "write RPCs in flight: %d\n",
 601                   cli->cl_w_in_flight);
 602        seq_printf(seq, "pending write pages:  %d\n",
 603                   atomic_read(&cli->cl_pending_w_pages));
 604        seq_printf(seq, "pending read pages:   %d\n",
 605                   atomic_read(&cli->cl_pending_r_pages));
 606
 607        seq_puts(seq, "\n\t\t\tread\t\t\twrite\n");
 608        seq_puts(seq, "pages per rpc     rpcs   % cum % |");
 609        seq_puts(seq, "       rpcs   % cum %\n");
 610
 611        read_tot = lprocfs_oh_sum(&cli->cl_read_page_hist);
 612        write_tot = lprocfs_oh_sum(&cli->cl_write_page_hist);
 613
 614        read_cum = 0;
 615        write_cum = 0;
 616        for (i = 0; i < OBD_HIST_MAX; i++) {
 617                unsigned long r = cli->cl_read_page_hist.oh_buckets[i];
 618                unsigned long w = cli->cl_write_page_hist.oh_buckets[i];
 619                read_cum += r;
 620                write_cum += w;
 621                seq_printf(seq, "%d:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
 622                                 1 << i, r, pct(r, read_tot),
 623                                 pct(read_cum, read_tot), w,
 624                                 pct(w, write_tot),
 625                                 pct(write_cum, write_tot));
 626                if (read_cum == read_tot && write_cum == write_tot)
 627                        break;
 628        }
 629
 630        seq_puts(seq, "\n\t\t\tread\t\t\twrite\n");
 631        seq_puts(seq, "rpcs in flight   rpcs   % cum % |");
 632        seq_puts(seq, "       rpcs   % cum %\n");
 633
 634        read_tot = lprocfs_oh_sum(&cli->cl_read_rpc_hist);
 635        write_tot = lprocfs_oh_sum(&cli->cl_write_rpc_hist);
 636
 637        read_cum = 0;
 638        write_cum = 0;
 639        for (i = 0; i < OBD_HIST_MAX; i++) {
 640                unsigned long r = cli->cl_read_rpc_hist.oh_buckets[i];
 641                unsigned long w = cli->cl_write_rpc_hist.oh_buckets[i];
 642                read_cum += r;
 643                write_cum += w;
 644                seq_printf(seq, "%d:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
 645                                 i, r, pct(r, read_tot),
 646                                 pct(read_cum, read_tot), w,
 647                                 pct(w, write_tot),
 648                                 pct(write_cum, write_tot));
 649                if (read_cum == read_tot && write_cum == write_tot)
 650                        break;
 651        }
 652
 653        seq_puts(seq, "\n\t\t\tread\t\t\twrite\n");
 654        seq_puts(seq, "offset           rpcs   % cum % |");
 655        seq_puts(seq, "       rpcs   % cum %\n");
 656
 657        read_tot = lprocfs_oh_sum(&cli->cl_read_offset_hist);
 658        write_tot = lprocfs_oh_sum(&cli->cl_write_offset_hist);
 659
 660        read_cum = 0;
 661        write_cum = 0;
 662        for (i = 0; i < OBD_HIST_MAX; i++) {
 663                unsigned long r = cli->cl_read_offset_hist.oh_buckets[i];
 664                unsigned long w = cli->cl_write_offset_hist.oh_buckets[i];
 665                read_cum += r;
 666                write_cum += w;
 667                seq_printf(seq, "%d:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
 668                           (i == 0) ? 0 : 1 << (i - 1),
 669                           r, pct(r, read_tot), pct(read_cum, read_tot),
 670                           w, pct(w, write_tot), pct(write_cum, write_tot));
 671                if (read_cum == read_tot && write_cum == write_tot)
 672                        break;
 673        }
 674
 675        client_obd_list_unlock(&cli->cl_loi_list_lock);
 676
 677        return 0;
 678}
 679#undef pct
 680
 681static ssize_t osc_rpc_stats_seq_write(struct file *file,
 682                                const char __user *buf,
 683                                size_t len, loff_t *off)
 684{
 685        struct seq_file *seq = file->private_data;
 686        struct obd_device *dev = seq->private;
 687        struct client_obd *cli = &dev->u.cli;
 688
 689        lprocfs_oh_clear(&cli->cl_read_rpc_hist);
 690        lprocfs_oh_clear(&cli->cl_write_rpc_hist);
 691        lprocfs_oh_clear(&cli->cl_read_page_hist);
 692        lprocfs_oh_clear(&cli->cl_write_page_hist);
 693        lprocfs_oh_clear(&cli->cl_read_offset_hist);
 694        lprocfs_oh_clear(&cli->cl_write_offset_hist);
 695
 696        return len;
 697}
 698
 699LPROC_SEQ_FOPS(osc_rpc_stats);
 700
 701static int osc_stats_seq_show(struct seq_file *seq, void *v)
 702{
 703        struct timeval now;
 704        struct obd_device *dev = seq->private;
 705        struct osc_stats *stats = &obd2osc_dev(dev)->od_stats;
 706
 707        do_gettimeofday(&now);
 708
 709        seq_printf(seq, "snapshot_time:  %lu.%lu (secs.usecs)\n",
 710                   now.tv_sec, (unsigned long)now.tv_usec);
 711        seq_printf(seq, "lockless_write_bytes\t\t%llu\n",
 712                   stats->os_lockless_writes);
 713        seq_printf(seq, "lockless_read_bytes\t\t%llu\n",
 714                   stats->os_lockless_reads);
 715        seq_printf(seq, "lockless_truncate\t\t%llu\n",
 716                   stats->os_lockless_truncates);
 717        return 0;
 718}
 719
 720static ssize_t osc_stats_seq_write(struct file *file,
 721                                const char __user *buf,
 722                                size_t len, loff_t *off)
 723{
 724        struct seq_file *seq = file->private_data;
 725        struct obd_device *dev = seq->private;
 726        struct osc_stats *stats = &obd2osc_dev(dev)->od_stats;
 727
 728        memset(stats, 0, sizeof(*stats));
 729        return len;
 730}
 731
 732LPROC_SEQ_FOPS(osc_stats);
 733
 734int lproc_osc_attach_seqstat(struct obd_device *dev)
 735{
 736        int rc;
 737
 738        rc = lprocfs_seq_create(dev->obd_proc_entry, "osc_stats", 0644,
 739                                &osc_stats_fops, dev);
 740        if (rc == 0)
 741                rc = lprocfs_obd_seq_create(dev, "rpc_stats", 0644,
 742                                            &osc_rpc_stats_fops, dev);
 743
 744        return rc;
 745}
 746
 747void lprocfs_osc_init_vars(struct lprocfs_static_vars *lvars)
 748{
 749        lvars->module_vars = lprocfs_osc_module_vars;
 750        lvars->obd_vars    = lprocfs_osc_obd_vars;
 751}
 752