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