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 39#include "../include/obd_support.h" 40#include "../include/obd.h" 41#include "../include/lprocfs_status.h" 42#include "../include/lustre/lustre_idl.h" 43#include "../include/lustre_net.h" 44#include "../include/obd_class.h" 45#include "ptlrpc_internal.h" 46 47 48struct ll_rpc_opcode { 49 __u32 opcode; 50 const char *opname; 51} ll_rpc_opcode_table[LUSTRE_MAX_OPCODES] = { 52 { OST_REPLY, "ost_reply" }, 53 { OST_GETATTR, "ost_getattr" }, 54 { OST_SETATTR, "ost_setattr" }, 55 { OST_READ, "ost_read" }, 56 { OST_WRITE, "ost_write" }, 57 { OST_CREATE , "ost_create" }, 58 { OST_DESTROY, "ost_destroy" }, 59 { OST_GET_INFO, "ost_get_info" }, 60 { OST_CONNECT, "ost_connect" }, 61 { OST_DISCONNECT, "ost_disconnect" }, 62 { OST_PUNCH, "ost_punch" }, 63 { OST_OPEN, "ost_open" }, 64 { OST_CLOSE, "ost_close" }, 65 { OST_STATFS, "ost_statfs" }, 66 { 14, NULL }, /* formerly OST_SAN_READ */ 67 { 15, NULL }, /* formerly OST_SAN_WRITE */ 68 { OST_SYNC, "ost_sync" }, 69 { OST_SET_INFO, "ost_set_info" }, 70 { OST_QUOTACHECK, "ost_quotacheck" }, 71 { OST_QUOTACTL, "ost_quotactl" }, 72 { OST_QUOTA_ADJUST_QUNIT, "ost_quota_adjust_qunit" }, 73 { MDS_GETATTR, "mds_getattr" }, 74 { MDS_GETATTR_NAME, "mds_getattr_lock" }, 75 { MDS_CLOSE, "mds_close" }, 76 { MDS_REINT, "mds_reint" }, 77 { MDS_READPAGE, "mds_readpage" }, 78 { MDS_CONNECT, "mds_connect" }, 79 { MDS_DISCONNECT, "mds_disconnect" }, 80 { MDS_GETSTATUS, "mds_getstatus" }, 81 { MDS_STATFS, "mds_statfs" }, 82 { MDS_PIN, "mds_pin" }, 83 { MDS_UNPIN, "mds_unpin" }, 84 { MDS_SYNC, "mds_sync" }, 85 { MDS_DONE_WRITING, "mds_done_writing" }, 86 { MDS_SET_INFO, "mds_set_info" }, 87 { MDS_QUOTACHECK, "mds_quotacheck" }, 88 { MDS_QUOTACTL, "mds_quotactl" }, 89 { MDS_GETXATTR, "mds_getxattr" }, 90 { MDS_SETXATTR, "mds_setxattr" }, 91 { MDS_WRITEPAGE, "mds_writepage" }, 92 { MDS_IS_SUBDIR, "mds_is_subdir" }, 93 { MDS_GET_INFO, "mds_get_info" }, 94 { MDS_HSM_STATE_GET, "mds_hsm_state_get" }, 95 { MDS_HSM_STATE_SET, "mds_hsm_state_set" }, 96 { MDS_HSM_ACTION, "mds_hsm_action" }, 97 { MDS_HSM_PROGRESS, "mds_hsm_progress" }, 98 { MDS_HSM_REQUEST, "mds_hsm_request" }, 99 { MDS_HSM_CT_REGISTER, "mds_hsm_ct_register" }, 100 { MDS_HSM_CT_UNREGISTER, "mds_hsm_ct_unregister" }, 101 { MDS_SWAP_LAYOUTS, "mds_swap_layouts" }, 102 { LDLM_ENQUEUE, "ldlm_enqueue" }, 103 { LDLM_CONVERT, "ldlm_convert" }, 104 { LDLM_CANCEL, "ldlm_cancel" }, 105 { LDLM_BL_CALLBACK, "ldlm_bl_callback" }, 106 { LDLM_CP_CALLBACK, "ldlm_cp_callback" }, 107 { LDLM_GL_CALLBACK, "ldlm_gl_callback" }, 108 { LDLM_SET_INFO, "ldlm_set_info" }, 109 { MGS_CONNECT, "mgs_connect" }, 110 { MGS_DISCONNECT, "mgs_disconnect" }, 111 { MGS_EXCEPTION, "mgs_exception" }, 112 { MGS_TARGET_REG, "mgs_target_reg" }, 113 { MGS_TARGET_DEL, "mgs_target_del" }, 114 { MGS_SET_INFO, "mgs_set_info" }, 115 { MGS_CONFIG_READ, "mgs_config_read" }, 116 { OBD_PING, "obd_ping" }, 117 { OBD_LOG_CANCEL, "llog_cancel" }, 118 { OBD_QC_CALLBACK, "obd_quota_callback" }, 119 { OBD_IDX_READ, "dt_index_read" }, 120 { LLOG_ORIGIN_HANDLE_CREATE, "llog_origin_handle_open" }, 121 { LLOG_ORIGIN_HANDLE_NEXT_BLOCK, "llog_origin_handle_next_block" }, 122 { LLOG_ORIGIN_HANDLE_READ_HEADER, "llog_origin_handle_read_header" }, 123 { LLOG_ORIGIN_HANDLE_WRITE_REC, "llog_origin_handle_write_rec" }, 124 { LLOG_ORIGIN_HANDLE_CLOSE, "llog_origin_handle_close" }, 125 { LLOG_ORIGIN_CONNECT, "llog_origin_connect" }, 126 { LLOG_CATINFO, "llog_catinfo" }, 127 { LLOG_ORIGIN_HANDLE_PREV_BLOCK, "llog_origin_handle_prev_block" }, 128 { LLOG_ORIGIN_HANDLE_DESTROY, "llog_origin_handle_destroy" }, 129 { QUOTA_DQACQ, "quota_acquire" }, 130 { QUOTA_DQREL, "quota_release" }, 131 { SEQ_QUERY, "seq_query" }, 132 { SEC_CTX_INIT, "sec_ctx_init" }, 133 { SEC_CTX_INIT_CONT, "sec_ctx_init_cont" }, 134 { SEC_CTX_FINI, "sec_ctx_fini" }, 135 { FLD_QUERY, "fld_query" }, 136 { UPDATE_OBJ, "update_obj" }, 137}; 138 139struct ll_eopcode { 140 __u32 opcode; 141 const char *opname; 142} ll_eopcode_table[EXTRA_LAST_OPC] = { 143 { LDLM_GLIMPSE_ENQUEUE, "ldlm_glimpse_enqueue" }, 144 { LDLM_PLAIN_ENQUEUE, "ldlm_plain_enqueue" }, 145 { LDLM_EXTENT_ENQUEUE, "ldlm_extent_enqueue" }, 146 { LDLM_FLOCK_ENQUEUE, "ldlm_flock_enqueue" }, 147 { LDLM_IBITS_ENQUEUE, "ldlm_ibits_enqueue" }, 148 { MDS_REINT_SETATTR, "mds_reint_setattr" }, 149 { MDS_REINT_CREATE, "mds_reint_create" }, 150 { MDS_REINT_LINK, "mds_reint_link" }, 151 { MDS_REINT_UNLINK, "mds_reint_unlink" }, 152 { MDS_REINT_RENAME, "mds_reint_rename" }, 153 { MDS_REINT_OPEN, "mds_reint_open" }, 154 { MDS_REINT_SETXATTR, "mds_reint_setxattr" }, 155 { BRW_READ_BYTES, "read_bytes" }, 156 { BRW_WRITE_BYTES, "write_bytes" }, 157}; 158 159const char *ll_opcode2str(__u32 opcode) 160{ 161 /* When one of the assertions below fail, chances are that: 162 * 1) A new opcode was added in include/lustre/lustre_idl.h, 163 * but is missing from the table above. 164 * or 2) The opcode space was renumbered or rearranged, 165 * and the opcode_offset() function in 166 * ptlrpc_internal.h needs to be modified. 167 */ 168 __u32 offset = opcode_offset(opcode); 169 LASSERTF(offset < LUSTRE_MAX_OPCODES, 170 "offset %u >= LUSTRE_MAX_OPCODES %u\n", 171 offset, LUSTRE_MAX_OPCODES); 172 LASSERTF(ll_rpc_opcode_table[offset].opcode == opcode, 173 "ll_rpc_opcode_table[%u].opcode %u != opcode %u\n", 174 offset, ll_rpc_opcode_table[offset].opcode, opcode); 175 return ll_rpc_opcode_table[offset].opname; 176} 177 178const char* ll_eopcode2str(__u32 opcode) 179{ 180 LASSERT(ll_eopcode_table[opcode].opcode == opcode); 181 return ll_eopcode_table[opcode].opname; 182} 183#if defined (CONFIG_PROC_FS) 184void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir, 185 char *name, struct proc_dir_entry **procroot_ret, 186 struct lprocfs_stats **stats_ret) 187{ 188 struct proc_dir_entry *svc_procroot; 189 struct lprocfs_stats *svc_stats; 190 int i, rc; 191 unsigned int svc_counter_config = LPROCFS_CNTR_AVGMINMAX | 192 LPROCFS_CNTR_STDDEV; 193 194 LASSERT(*procroot_ret == NULL); 195 LASSERT(*stats_ret == NULL); 196 197 svc_stats = lprocfs_alloc_stats(EXTRA_MAX_OPCODES+LUSTRE_MAX_OPCODES, 198 0); 199 if (svc_stats == NULL) 200 return; 201 202 if (dir) { 203 svc_procroot = lprocfs_register(dir, root, NULL, NULL); 204 if (IS_ERR(svc_procroot)) { 205 lprocfs_free_stats(&svc_stats); 206 return; 207 } 208 } else { 209 svc_procroot = root; 210 } 211 212 lprocfs_counter_init(svc_stats, PTLRPC_REQWAIT_CNTR, 213 svc_counter_config, "req_waittime", "usec"); 214 lprocfs_counter_init(svc_stats, PTLRPC_REQQDEPTH_CNTR, 215 svc_counter_config, "req_qdepth", "reqs"); 216 lprocfs_counter_init(svc_stats, PTLRPC_REQACTIVE_CNTR, 217 svc_counter_config, "req_active", "reqs"); 218 lprocfs_counter_init(svc_stats, PTLRPC_TIMEOUT, 219 svc_counter_config, "req_timeout", "sec"); 220 lprocfs_counter_init(svc_stats, PTLRPC_REQBUF_AVAIL_CNTR, 221 svc_counter_config, "reqbuf_avail", "bufs"); 222 for (i = 0; i < EXTRA_LAST_OPC; i++) { 223 char *units; 224 225 switch (i) { 226 case BRW_WRITE_BYTES: 227 case BRW_READ_BYTES: 228 units = "bytes"; 229 break; 230 default: 231 units = "reqs"; 232 break; 233 } 234 lprocfs_counter_init(svc_stats, PTLRPC_LAST_CNTR + i, 235 svc_counter_config, 236 ll_eopcode2str(i), units); 237 } 238 for (i = 0; i < LUSTRE_MAX_OPCODES; i++) { 239 __u32 opcode = ll_rpc_opcode_table[i].opcode; 240 lprocfs_counter_init(svc_stats, 241 EXTRA_MAX_OPCODES + i, svc_counter_config, 242 ll_opcode2str(opcode), "usec"); 243 } 244 245 rc = lprocfs_register_stats(svc_procroot, name, svc_stats); 246 if (rc < 0) { 247 if (dir) 248 lprocfs_remove(&svc_procroot); 249 lprocfs_free_stats(&svc_stats); 250 } else { 251 if (dir) 252 *procroot_ret = svc_procroot; 253 *stats_ret = svc_stats; 254 } 255} 256 257static int 258ptlrpc_lprocfs_req_history_len_seq_show(struct seq_file *m, void *v) 259{ 260 struct ptlrpc_service *svc = m->private; 261 struct ptlrpc_service_part *svcpt; 262 int total = 0; 263 int i; 264 265 ptlrpc_service_for_each_part(svcpt, i, svc) 266 total += svcpt->scp_hist_nrqbds; 267 268 return seq_printf(m, "%d\n", total); 269} 270LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_req_history_len); 271 272static int 273ptlrpc_lprocfs_req_history_max_seq_show(struct seq_file *m, void *n) 274{ 275 struct ptlrpc_service *svc = m->private; 276 struct ptlrpc_service_part *svcpt; 277 int total = 0; 278 int i; 279 280 ptlrpc_service_for_each_part(svcpt, i, svc) 281 total += svc->srv_hist_nrqbds_cpt_max; 282 283 return seq_printf(m, "%d\n", total); 284} 285 286static ssize_t 287ptlrpc_lprocfs_req_history_max_seq_write(struct file *file, const char *buffer, 288 size_t count, loff_t *off) 289{ 290 struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; 291 int bufpages; 292 int val; 293 int rc; 294 295 rc = lprocfs_write_helper(buffer, count, &val); 296 if (rc < 0) 297 return rc; 298 299 if (val < 0) 300 return -ERANGE; 301 302 /* This sanity check is more of an insanity check; we can still 303 * hose a kernel by allowing the request history to grow too 304 * far. */ 305 bufpages = (svc->srv_buf_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 306 if (val > totalram_pages / (2 * bufpages)) 307 return -ERANGE; 308 309 spin_lock(&svc->srv_lock); 310 311 if (val == 0) 312 svc->srv_hist_nrqbds_cpt_max = 0; 313 else 314 svc->srv_hist_nrqbds_cpt_max = max(1, (val / svc->srv_ncpts)); 315 316 spin_unlock(&svc->srv_lock); 317 318 return count; 319} 320LPROC_SEQ_FOPS(ptlrpc_lprocfs_req_history_max); 321 322static int 323ptlrpc_lprocfs_threads_min_seq_show(struct seq_file *m, void *n) 324{ 325 struct ptlrpc_service *svc = m->private; 326 327 return seq_printf(m, "%d\n", 328 svc->srv_nthrs_cpt_init * svc->srv_ncpts); 329} 330 331static ssize_t 332ptlrpc_lprocfs_threads_min_seq_write(struct file *file, const char *buffer, 333 size_t count, loff_t *off) 334{ 335 struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; 336 int val; 337 int rc = lprocfs_write_helper(buffer, count, &val); 338 339 if (rc < 0) 340 return rc; 341 342 if (val / svc->srv_ncpts < PTLRPC_NTHRS_INIT) 343 return -ERANGE; 344 345 spin_lock(&svc->srv_lock); 346 if (val > svc->srv_nthrs_cpt_limit * svc->srv_ncpts) { 347 spin_unlock(&svc->srv_lock); 348 return -ERANGE; 349 } 350 351 svc->srv_nthrs_cpt_init = val / svc->srv_ncpts; 352 353 spin_unlock(&svc->srv_lock); 354 355 return count; 356} 357LPROC_SEQ_FOPS(ptlrpc_lprocfs_threads_min); 358 359static int 360ptlrpc_lprocfs_threads_started_seq_show(struct seq_file *m, void *n) 361{ 362 struct ptlrpc_service *svc = m->private; 363 struct ptlrpc_service_part *svcpt; 364 int total = 0; 365 int i; 366 367 ptlrpc_service_for_each_part(svcpt, i, svc) 368 total += svcpt->scp_nthrs_running; 369 370 return seq_printf(m, "%d\n", total); 371} 372LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_threads_started); 373 374static int 375ptlrpc_lprocfs_threads_max_seq_show(struct seq_file *m, void *n) 376{ 377 struct ptlrpc_service *svc = m->private; 378 379 return seq_printf(m, "%d\n", 380 svc->srv_nthrs_cpt_limit * svc->srv_ncpts); 381} 382 383static ssize_t 384ptlrpc_lprocfs_threads_max_seq_write(struct file *file, const char *buffer, 385 size_t count, loff_t *off) 386{ 387 struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; 388 int val; 389 int rc = lprocfs_write_helper(buffer, count, &val); 390 391 if (rc < 0) 392 return rc; 393 394 if (val / svc->srv_ncpts < PTLRPC_NTHRS_INIT) 395 return -ERANGE; 396 397 spin_lock(&svc->srv_lock); 398 if (val < svc->srv_nthrs_cpt_init * svc->srv_ncpts) { 399 spin_unlock(&svc->srv_lock); 400 return -ERANGE; 401 } 402 403 svc->srv_nthrs_cpt_limit = val / svc->srv_ncpts; 404 405 spin_unlock(&svc->srv_lock); 406 407 return count; 408} 409LPROC_SEQ_FOPS(ptlrpc_lprocfs_threads_max); 410 411/** 412 * \addtogoup nrs 413 * @{ 414 */ 415extern struct nrs_core nrs_core; 416 417/** 418 * Translates \e ptlrpc_nrs_pol_state values to human-readable strings. 419 * 420 * \param[in] state The policy state 421 */ 422static const char *nrs_state2str(enum ptlrpc_nrs_pol_state state) 423{ 424 switch (state) { 425 default: 426 LBUG(); 427 case NRS_POL_STATE_INVALID: 428 return "invalid"; 429 case NRS_POL_STATE_STOPPED: 430 return "stopped"; 431 case NRS_POL_STATE_STOPPING: 432 return "stopping"; 433 case NRS_POL_STATE_STARTING: 434 return "starting"; 435 case NRS_POL_STATE_STARTED: 436 return "started"; 437 } 438} 439 440/** 441 * Obtains status information for \a policy. 442 * 443 * Information is copied in \a info. 444 * 445 * \param[in] policy The policy 446 * \param[out] info Holds returned status information 447 */ 448void nrs_policy_get_info_locked(struct ptlrpc_nrs_policy *policy, 449 struct ptlrpc_nrs_pol_info *info) 450{ 451 LASSERT(policy != NULL); 452 LASSERT(info != NULL); 453 assert_spin_locked(&policy->pol_nrs->nrs_lock); 454 455 memcpy(info->pi_name, policy->pol_desc->pd_name, NRS_POL_NAME_MAX); 456 457 info->pi_fallback = !!(policy->pol_flags & PTLRPC_NRS_FL_FALLBACK); 458 info->pi_state = policy->pol_state; 459 /** 460 * XXX: These are accessed without holding 461 * ptlrpc_service_part::scp_req_lock. 462 */ 463 info->pi_req_queued = policy->pol_req_queued; 464 info->pi_req_started = policy->pol_req_started; 465} 466 467/** 468 * Reads and prints policy status information for all policies of a PTLRPC 469 * service. 470 */ 471static int ptlrpc_lprocfs_nrs_seq_show(struct seq_file *m, void *n) 472{ 473 struct ptlrpc_service *svc = m->private; 474 struct ptlrpc_service_part *svcpt; 475 struct ptlrpc_nrs *nrs; 476 struct ptlrpc_nrs_policy *policy; 477 struct ptlrpc_nrs_pol_info *infos; 478 struct ptlrpc_nrs_pol_info tmp; 479 unsigned num_pols; 480 unsigned pol_idx = 0; 481 bool hp = false; 482 int i; 483 int rc = 0; 484 485 /** 486 * Serialize NRS core lprocfs operations with policy registration/ 487 * unregistration. 488 */ 489 mutex_lock(&nrs_core.nrs_mutex); 490 491 /** 492 * Use the first service partition's regular NRS head in order to obtain 493 * the number of policies registered with NRS heads of this service. All 494 * service partitions will have the same number of policies. 495 */ 496 nrs = nrs_svcpt2nrs(svc->srv_parts[0], false); 497 498 spin_lock(&nrs->nrs_lock); 499 num_pols = svc->srv_parts[0]->scp_nrs_reg.nrs_num_pols; 500 spin_unlock(&nrs->nrs_lock); 501 502 OBD_ALLOC(infos, num_pols * sizeof(*infos)); 503 if (infos == NULL) { 504 rc = -ENOMEM; 505 goto out; 506 } 507again: 508 509 ptlrpc_service_for_each_part(svcpt, i, svc) { 510 nrs = nrs_svcpt2nrs(svcpt, hp); 511 spin_lock(&nrs->nrs_lock); 512 513 pol_idx = 0; 514 515 list_for_each_entry(policy, &nrs->nrs_policy_list, 516 pol_list) { 517 LASSERT(pol_idx < num_pols); 518 519 nrs_policy_get_info_locked(policy, &tmp); 520 /** 521 * Copy values when handling the first service 522 * partition. 523 */ 524 if (i == 0) { 525 memcpy(infos[pol_idx].pi_name, tmp.pi_name, 526 NRS_POL_NAME_MAX); 527 memcpy(&infos[pol_idx].pi_state, &tmp.pi_state, 528 sizeof(tmp.pi_state)); 529 infos[pol_idx].pi_fallback = tmp.pi_fallback; 530 /** 531 * For the rest of the service partitions 532 * sanity-check the values we get. 533 */ 534 } else { 535 LASSERT(strncmp(infos[pol_idx].pi_name, 536 tmp.pi_name, 537 NRS_POL_NAME_MAX) == 0); 538 /** 539 * Not asserting ptlrpc_nrs_pol_info::pi_state, 540 * because it may be different between 541 * instances of the same policy in different 542 * service partitions. 543 */ 544 LASSERT(infos[pol_idx].pi_fallback == 545 tmp.pi_fallback); 546 } 547 548 infos[pol_idx].pi_req_queued += tmp.pi_req_queued; 549 infos[pol_idx].pi_req_started += tmp.pi_req_started; 550 551 pol_idx++; 552 } 553 spin_unlock(&nrs->nrs_lock); 554 } 555 556 /** 557 * Policy status information output is in YAML format. 558 * For example: 559 * 560 * regular_requests: 561 * - name: fifo 562 * state: started 563 * fallback: yes 564 * queued: 0 565 * active: 0 566 * 567 * - name: crrn 568 * state: started 569 * fallback: no 570 * queued: 2015 571 * active: 384 572 * 573 * high_priority_requests: 574 * - name: fifo 575 * state: started 576 * fallback: yes 577 * queued: 0 578 * active: 2 579 * 580 * - name: crrn 581 * state: stopped 582 * fallback: no 583 * queued: 0 584 * active: 0 585 */ 586 seq_printf(m, "%s\n", 587 !hp ? "\nregular_requests:" : "high_priority_requests:"); 588 589 for (pol_idx = 0; pol_idx < num_pols; pol_idx++) { 590 seq_printf(m, " - name: %s\n" 591 " state: %s\n" 592 " fallback: %s\n" 593 " queued: %-20d\n" 594 " active: %-20d\n\n", 595 infos[pol_idx].pi_name, 596 nrs_state2str(infos[pol_idx].pi_state), 597 infos[pol_idx].pi_fallback ? "yes" : "no", 598 (int)infos[pol_idx].pi_req_queued, 599 (int)infos[pol_idx].pi_req_started); 600 } 601 602 if (!hp && nrs_svc_has_hp(svc)) { 603 memset(infos, 0, num_pols * sizeof(*infos)); 604 605 /** 606 * Redo the processing for the service's HP NRS heads' policies. 607 */ 608 hp = true; 609 goto again; 610 } 611 612out: 613 if (infos) 614 OBD_FREE(infos, num_pols * sizeof(*infos)); 615 616 mutex_unlock(&nrs_core.nrs_mutex); 617 618 return rc; 619} 620 621/** 622 * The longest valid command string is the maximum policy name size, plus the 623 * length of the " reg" substring 624 */ 625#define LPROCFS_NRS_WR_MAX_CMD (NRS_POL_NAME_MAX + sizeof(" reg") - 1) 626 627/** 628 * Starts and stops a given policy on a PTLRPC service. 629 * 630 * Commands consist of the policy name, followed by an optional [reg|hp] token; 631 * if the optional token is omitted, the operation is performed on both the 632 * regular and high-priority (if the service has one) NRS head. 633 */ 634static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file, 635 const char __user *buffer, 636 size_t count, loff_t *off) 637{ 638 struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; 639 enum ptlrpc_nrs_queue_type queue = PTLRPC_NRS_QUEUE_BOTH; 640 char *cmd; 641 char *cmd_copy = NULL; 642 char *token; 643 int rc = 0; 644 645 if (count >= LPROCFS_NRS_WR_MAX_CMD) { 646 rc = -EINVAL; 647 goto out; 648 } 649 650 OBD_ALLOC(cmd, LPROCFS_NRS_WR_MAX_CMD); 651 if (cmd == NULL) { 652 rc = -ENOMEM; 653 goto out; 654 } 655 /** 656 * strsep() modifies its argument, so keep a copy 657 */ 658 cmd_copy = cmd; 659 660 if (copy_from_user(cmd, buffer, count)) { 661 rc = -EFAULT; 662 goto out; 663 } 664 665 cmd[count] = '\0'; 666 667 token = strsep(&cmd, " "); 668 669 if (strlen(token) > NRS_POL_NAME_MAX - 1) { 670 rc = -EINVAL; 671 goto out; 672 } 673 674 /** 675 * No [reg|hp] token has been specified 676 */ 677 if (cmd == NULL) 678 goto default_queue; 679 680 /** 681 * The second token is either NULL, or an optional [reg|hp] string 682 */ 683 if (strcmp(cmd, "reg") == 0) 684 queue = PTLRPC_NRS_QUEUE_REG; 685 else if (strcmp(cmd, "hp") == 0) 686 queue = PTLRPC_NRS_QUEUE_HP; 687 else { 688 rc = -EINVAL; 689 goto out; 690 } 691 692default_queue: 693 694 if (queue == PTLRPC_NRS_QUEUE_HP && !nrs_svc_has_hp(svc)) { 695 rc = -ENODEV; 696 goto out; 697 } 698 else if (queue == PTLRPC_NRS_QUEUE_BOTH && !nrs_svc_has_hp(svc)) 699 queue = PTLRPC_NRS_QUEUE_REG; 700 701 /** 702 * Serialize NRS core lprocfs operations with policy registration/ 703 * unregistration. 704 */ 705 mutex_lock(&nrs_core.nrs_mutex); 706 707 rc = ptlrpc_nrs_policy_control(svc, queue, token, PTLRPC_NRS_CTL_START, 708 false, NULL); 709 710 mutex_unlock(&nrs_core.nrs_mutex); 711out: 712 if (cmd_copy) 713 OBD_FREE(cmd_copy, LPROCFS_NRS_WR_MAX_CMD); 714 715 return rc < 0 ? rc : count; 716} 717LPROC_SEQ_FOPS(ptlrpc_lprocfs_nrs); 718 719/** @} nrs */ 720 721struct ptlrpc_srh_iterator { 722 int srhi_idx; 723 __u64 srhi_seq; 724 struct ptlrpc_request *srhi_req; 725}; 726 727int 728ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part *svcpt, 729 struct ptlrpc_srh_iterator *srhi, 730 __u64 seq) 731{ 732 struct list_head *e; 733 struct ptlrpc_request *req; 734 735 if (srhi->srhi_req != NULL && 736 srhi->srhi_seq > svcpt->scp_hist_seq_culled && 737 srhi->srhi_seq <= seq) { 738 /* If srhi_req was set previously, hasn't been culled and 739 * we're searching for a seq on or after it (i.e. more 740 * recent), search from it onwards. 741 * Since the service history is LRU (i.e. culled reqs will 742 * be near the head), we shouldn't have to do long 743 * re-scans */ 744 LASSERTF(srhi->srhi_seq == srhi->srhi_req->rq_history_seq, 745 "%s:%d: seek seq %llu, request seq %llu\n", 746 svcpt->scp_service->srv_name, svcpt->scp_cpt, 747 srhi->srhi_seq, srhi->srhi_req->rq_history_seq); 748 LASSERTF(!list_empty(&svcpt->scp_hist_reqs), 749 "%s:%d: seek offset %llu, request seq %llu, " 750 "last culled %llu\n", 751 svcpt->scp_service->srv_name, svcpt->scp_cpt, 752 seq, srhi->srhi_seq, svcpt->scp_hist_seq_culled); 753 e = &srhi->srhi_req->rq_history_list; 754 } else { 755 /* search from start */ 756 e = svcpt->scp_hist_reqs.next; 757 } 758 759 while (e != &svcpt->scp_hist_reqs) { 760 req = list_entry(e, struct ptlrpc_request, rq_history_list); 761 762 if (req->rq_history_seq >= seq) { 763 srhi->srhi_seq = req->rq_history_seq; 764 srhi->srhi_req = req; 765 return 0; 766 } 767 e = e->next; 768 } 769 770 return -ENOENT; 771} 772 773/* 774 * ptlrpc history sequence is used as "position" of seq_file, in some case, 775 * seq_read() will increase "position" to indicate reading the next 776 * element, however, low bits of history sequence are reserved for CPT id 777 * (check the details from comments before ptlrpc_req_add_history), which 778 * means seq_read() might change CPT id of history sequence and never 779 * finish reading of requests on a CPT. To make it work, we have to shift 780 * CPT id to high bits and timestamp to low bits, so seq_read() will only 781 * increase timestamp which can correctly indicate the next position. 782 */ 783 784/* convert seq_file pos to cpt */ 785#define PTLRPC_REQ_POS2CPT(svc, pos) \ 786 ((svc)->srv_cpt_bits == 0 ? 0 : \ 787 (__u64)(pos) >> (64 - (svc)->srv_cpt_bits)) 788 789/* make up seq_file pos from cpt */ 790#define PTLRPC_REQ_CPT2POS(svc, cpt) \ 791 ((svc)->srv_cpt_bits == 0 ? 0 : \ 792 (cpt) << (64 - (svc)->srv_cpt_bits)) 793 794/* convert sequence to position */ 795#define PTLRPC_REQ_SEQ2POS(svc, seq) \ 796 ((svc)->srv_cpt_bits == 0 ? (seq) : \ 797 ((seq) >> (svc)->srv_cpt_bits) | \ 798 ((seq) << (64 - (svc)->srv_cpt_bits))) 799 800/* convert position to sequence */ 801#define PTLRPC_REQ_POS2SEQ(svc, pos) \ 802 ((svc)->srv_cpt_bits == 0 ? (pos) : \ 803 ((__u64)(pos) << (svc)->srv_cpt_bits) | \ 804 ((__u64)(pos) >> (64 - (svc)->srv_cpt_bits))) 805 806static void * 807ptlrpc_lprocfs_svc_req_history_start(struct seq_file *s, loff_t *pos) 808{ 809 struct ptlrpc_service *svc = s->private; 810 struct ptlrpc_service_part *svcpt; 811 struct ptlrpc_srh_iterator *srhi; 812 unsigned int cpt; 813 int rc; 814 int i; 815 816 if (sizeof(loff_t) != sizeof(__u64)) { /* can't support */ 817 CWARN("Failed to read request history because size of loff_t " 818 "%d can't match size of u64\n", (int)sizeof(loff_t)); 819 return NULL; 820 } 821 822 OBD_ALLOC(srhi, sizeof(*srhi)); 823 if (srhi == NULL) 824 return NULL; 825 826 srhi->srhi_seq = 0; 827 srhi->srhi_req = NULL; 828 829 cpt = PTLRPC_REQ_POS2CPT(svc, *pos); 830 831 ptlrpc_service_for_each_part(svcpt, i, svc) { 832 if (i < cpt) /* skip */ 833 continue; 834 if (i > cpt) /* make up the lowest position for this CPT */ 835 *pos = PTLRPC_REQ_CPT2POS(svc, i); 836 837 spin_lock(&svcpt->scp_lock); 838 rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, 839 PTLRPC_REQ_POS2SEQ(svc, *pos)); 840 spin_unlock(&svcpt->scp_lock); 841 if (rc == 0) { 842 *pos = PTLRPC_REQ_SEQ2POS(svc, srhi->srhi_seq); 843 srhi->srhi_idx = i; 844 return srhi; 845 } 846 } 847 848 OBD_FREE(srhi, sizeof(*srhi)); 849 return NULL; 850} 851 852static void 853ptlrpc_lprocfs_svc_req_history_stop(struct seq_file *s, void *iter) 854{ 855 struct ptlrpc_srh_iterator *srhi = iter; 856 857 if (srhi != NULL) 858 OBD_FREE(srhi, sizeof(*srhi)); 859} 860 861static void * 862ptlrpc_lprocfs_svc_req_history_next(struct seq_file *s, 863 void *iter, loff_t *pos) 864{ 865 struct ptlrpc_service *svc = s->private; 866 struct ptlrpc_srh_iterator *srhi = iter; 867 struct ptlrpc_service_part *svcpt; 868 __u64 seq; 869 int rc; 870 int i; 871 872 for (i = srhi->srhi_idx; i < svc->srv_ncpts; i++) { 873 svcpt = svc->srv_parts[i]; 874 875 if (i > srhi->srhi_idx) { /* reset iterator for a new CPT */ 876 srhi->srhi_req = NULL; 877 seq = srhi->srhi_seq = 0; 878 } else { /* the next sequence */ 879 seq = srhi->srhi_seq + (1 << svc->srv_cpt_bits); 880 } 881 882 spin_lock(&svcpt->scp_lock); 883 rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, seq); 884 spin_unlock(&svcpt->scp_lock); 885 if (rc == 0) { 886 *pos = PTLRPC_REQ_SEQ2POS(svc, srhi->srhi_seq); 887 srhi->srhi_idx = i; 888 return srhi; 889 } 890 } 891 892 OBD_FREE(srhi, sizeof(*srhi)); 893 return NULL; 894} 895 896/* common ost/mdt so_req_printer */ 897void target_print_req(void *seq_file, struct ptlrpc_request *req) 898{ 899 /* Called holding srv_lock with irqs disabled. 900 * Print specific req contents and a newline. 901 * CAVEAT EMPTOR: check request message length before printing!!! 902 * You might have received any old crap so you must be just as 903 * careful here as the service's request parser!!! */ 904 struct seq_file *sf = seq_file; 905 906 switch (req->rq_phase) { 907 case RQ_PHASE_NEW: 908 /* still awaiting a service thread's attention, or rejected 909 * because the generic request message didn't unpack */ 910 seq_printf(sf, "<not swabbed>\n"); 911 break; 912 case RQ_PHASE_INTERPRET: 913 /* being handled, so basic msg swabbed, and opc is valid 914 * but racing with mds_handle() */ 915 case RQ_PHASE_COMPLETE: 916 /* been handled by mds_handle() reply state possibly still 917 * volatile */ 918 seq_printf(sf, "opc %d\n", lustre_msg_get_opc(req->rq_reqmsg)); 919 break; 920 default: 921 DEBUG_REQ(D_ERROR, req, "bad phase %d", req->rq_phase); 922 } 923} 924EXPORT_SYMBOL(target_print_req); 925 926static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter) 927{ 928 struct ptlrpc_service *svc = s->private; 929 struct ptlrpc_srh_iterator *srhi = iter; 930 struct ptlrpc_service_part *svcpt; 931 struct ptlrpc_request *req; 932 int rc; 933 934 LASSERT(srhi->srhi_idx < svc->srv_ncpts); 935 936 svcpt = svc->srv_parts[srhi->srhi_idx]; 937 938 spin_lock(&svcpt->scp_lock); 939 940 rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, srhi->srhi_seq); 941 942 if (rc == 0) { 943 req = srhi->srhi_req; 944 945 /* Print common req fields. 946 * CAVEAT EMPTOR: we're racing with the service handler 947 * here. The request could contain any old crap, so you 948 * must be just as careful as the service's request 949 * parser. Currently I only print stuff here I know is OK 950 * to look at coz it was set up in request_in_callback()!!! */ 951 seq_printf(s, "%lld:%s:%s:x%llu:%d:%s:%ld:%lds(%+lds) ", 952 req->rq_history_seq, libcfs_nid2str(req->rq_self), 953 libcfs_id2str(req->rq_peer), req->rq_xid, 954 req->rq_reqlen, ptlrpc_rqphase2str(req), 955 req->rq_arrival_time.tv_sec, 956 req->rq_sent - req->rq_arrival_time.tv_sec, 957 req->rq_sent - req->rq_deadline); 958 if (svc->srv_ops.so_req_printer == NULL) 959 seq_printf(s, "\n"); 960 else 961 svc->srv_ops.so_req_printer(s, srhi->srhi_req); 962 } 963 964 spin_unlock(&svcpt->scp_lock); 965 return rc; 966} 967 968static int 969ptlrpc_lprocfs_svc_req_history_open(struct inode *inode, struct file *file) 970{ 971 static struct seq_operations sops = { 972 .start = ptlrpc_lprocfs_svc_req_history_start, 973 .stop = ptlrpc_lprocfs_svc_req_history_stop, 974 .next = ptlrpc_lprocfs_svc_req_history_next, 975 .show = ptlrpc_lprocfs_svc_req_history_show, 976 }; 977 struct seq_file *seqf; 978 int rc; 979 980 rc = seq_open(file, &sops); 981 if (rc) 982 return rc; 983 984 seqf = file->private_data; 985 seqf->private = PDE_DATA(inode); 986 return 0; 987} 988 989/* See also lprocfs_rd_timeouts */ 990static int ptlrpc_lprocfs_timeouts_seq_show(struct seq_file *m, void *n) 991{ 992 struct ptlrpc_service *svc = m->private; 993 struct ptlrpc_service_part *svcpt; 994 struct dhms ts; 995 time_t worstt; 996 unsigned int cur; 997 unsigned int worst; 998 int i; 999 1000 if (AT_OFF) { 1001 seq_printf(m, "adaptive timeouts off, using obd_timeout %u\n", 1002 obd_timeout); 1003 return 0; 1004 } 1005 1006 ptlrpc_service_for_each_part(svcpt, i, svc) { 1007 cur = at_get(&svcpt->scp_at_estimate); 1008 worst = svcpt->scp_at_estimate.at_worst_ever; 1009 worstt = svcpt->scp_at_estimate.at_worst_time; 1010 s2dhms(&ts, get_seconds() - worstt); 1011 1012 seq_printf(m, "%10s : cur %3u worst %3u (at %ld, " 1013 DHMS_FMT" ago) ", "service", 1014 cur, worst, worstt, DHMS_VARS(&ts)); 1015 1016 lprocfs_at_hist_helper(m, &svcpt->scp_at_estimate); 1017 } 1018 1019 return 0; 1020} 1021LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_timeouts); 1022 1023static int ptlrpc_lprocfs_hp_ratio_seq_show(struct seq_file *m, void *v) 1024{ 1025 struct ptlrpc_service *svc = m->private; 1026 return seq_printf(m, "%d", svc->srv_hpreq_ratio); 1027} 1028 1029static ssize_t ptlrpc_lprocfs_hp_ratio_seq_write(struct file *file, 1030 const char *buffer, 1031 size_t count, 1032 loff_t *off) 1033{ 1034 struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; 1035 int rc; 1036 int val; 1037 1038 rc = lprocfs_write_helper(buffer, count, &val); 1039 if (rc < 0) 1040 return rc; 1041 1042 if (val < 0) 1043 return -ERANGE; 1044 1045 spin_lock(&svc->srv_lock); 1046 svc->srv_hpreq_ratio = val; 1047 spin_unlock(&svc->srv_lock); 1048 1049 return count; 1050} 1051LPROC_SEQ_FOPS(ptlrpc_lprocfs_hp_ratio); 1052 1053void ptlrpc_lprocfs_register_service(struct proc_dir_entry *entry, 1054 struct ptlrpc_service *svc) 1055{ 1056 struct lprocfs_vars lproc_vars[] = { 1057 {.name = "high_priority_ratio", 1058 .fops = &ptlrpc_lprocfs_hp_ratio_fops, 1059 .data = svc}, 1060 {.name = "req_buffer_history_len", 1061 .fops = &ptlrpc_lprocfs_req_history_len_fops, 1062 .data = svc}, 1063 {.name = "req_buffer_history_max", 1064 .fops = &ptlrpc_lprocfs_req_history_max_fops, 1065 .data = svc}, 1066 {.name = "threads_min", 1067 .fops = &ptlrpc_lprocfs_threads_min_fops, 1068 .data = svc}, 1069 {.name = "threads_max", 1070 .fops = &ptlrpc_lprocfs_threads_max_fops, 1071 .data = svc}, 1072 {.name = "threads_started", 1073 .fops = &ptlrpc_lprocfs_threads_started_fops, 1074 .data = svc}, 1075 {.name = "timeouts", 1076 .fops = &ptlrpc_lprocfs_timeouts_fops, 1077 .data = svc}, 1078 {.name = "nrs_policies", 1079 .fops = &ptlrpc_lprocfs_nrs_fops, 1080 .data = svc}, 1081 {NULL} 1082 }; 1083 static struct file_operations req_history_fops = { 1084 .owner = THIS_MODULE, 1085 .open = ptlrpc_lprocfs_svc_req_history_open, 1086 .read = seq_read, 1087 .llseek = seq_lseek, 1088 .release = lprocfs_seq_release, 1089 }; 1090 1091 int rc; 1092 1093 ptlrpc_lprocfs_register(entry, svc->srv_name, 1094 "stats", &svc->srv_procroot, 1095 &svc->srv_stats); 1096 1097 if (svc->srv_procroot == NULL) 1098 return; 1099 1100 lprocfs_add_vars(svc->srv_procroot, lproc_vars, NULL); 1101 1102 rc = lprocfs_seq_create(svc->srv_procroot, "req_history", 1103 0400, &req_history_fops, svc); 1104 if (rc) 1105 CWARN("Error adding the req_history file\n"); 1106} 1107 1108void ptlrpc_lprocfs_register_obd(struct obd_device *obddev) 1109{ 1110 ptlrpc_lprocfs_register(obddev->obd_proc_entry, NULL, "stats", 1111 &obddev->obd_svc_procroot, 1112 &obddev->obd_svc_stats); 1113} 1114EXPORT_SYMBOL(ptlrpc_lprocfs_register_obd); 1115 1116void ptlrpc_lprocfs_rpc_sent(struct ptlrpc_request *req, long amount) 1117{ 1118 struct lprocfs_stats *svc_stats; 1119 __u32 op = lustre_msg_get_opc(req->rq_reqmsg); 1120 int opc = opcode_offset(op); 1121 1122 svc_stats = req->rq_import->imp_obd->obd_svc_stats; 1123 if (svc_stats == NULL || opc <= 0) 1124 return; 1125 LASSERT(opc < LUSTRE_MAX_OPCODES); 1126 if (!(op == LDLM_ENQUEUE || op == MDS_REINT)) 1127 lprocfs_counter_add(svc_stats, opc + EXTRA_MAX_OPCODES, amount); 1128} 1129 1130void ptlrpc_lprocfs_brw(struct ptlrpc_request *req, int bytes) 1131{ 1132 struct lprocfs_stats *svc_stats; 1133 int idx; 1134 1135 if (!req->rq_import) 1136 return; 1137 svc_stats = req->rq_import->imp_obd->obd_svc_stats; 1138 if (!svc_stats) 1139 return; 1140 idx = lustre_msg_get_opc(req->rq_reqmsg); 1141 switch (idx) { 1142 case OST_READ: 1143 idx = BRW_READ_BYTES + PTLRPC_LAST_CNTR; 1144 break; 1145 case OST_WRITE: 1146 idx = BRW_WRITE_BYTES + PTLRPC_LAST_CNTR; 1147 break; 1148 default: 1149 LASSERTF(0, "unsupported opcode %u\n", idx); 1150 break; 1151 } 1152 1153 lprocfs_counter_add(svc_stats, idx, bytes); 1154} 1155 1156EXPORT_SYMBOL(ptlrpc_lprocfs_brw); 1157 1158void ptlrpc_lprocfs_unregister_service(struct ptlrpc_service *svc) 1159{ 1160 if (svc->srv_procroot != NULL) 1161 lprocfs_remove(&svc->srv_procroot); 1162 1163 if (svc->srv_stats) 1164 lprocfs_free_stats(&svc->srv_stats); 1165} 1166 1167void ptlrpc_lprocfs_unregister_obd(struct obd_device *obd) 1168{ 1169 if (obd->obd_svc_procroot) 1170 lprocfs_remove(&obd->obd_svc_procroot); 1171 1172 if (obd->obd_svc_stats) 1173 lprocfs_free_stats(&obd->obd_svc_stats); 1174} 1175EXPORT_SYMBOL(ptlrpc_lprocfs_unregister_obd); 1176 1177 1178#define BUFLEN (UUID_MAX + 5) 1179 1180int lprocfs_wr_evict_client(struct file *file, const char *buffer, 1181 size_t count, loff_t *off) 1182{ 1183 struct obd_device *obd = ((struct seq_file *)file->private_data)->private; 1184 char *kbuf; 1185 char *tmpbuf; 1186 1187 OBD_ALLOC(kbuf, BUFLEN); 1188 if (kbuf == NULL) 1189 return -ENOMEM; 1190 1191 /* 1192 * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1 1193 * bytes into kbuf, to ensure that the string is NUL-terminated. 1194 * UUID_MAX should include a trailing NUL already. 1195 */ 1196 if (copy_from_user(kbuf, buffer, 1197 min_t(unsigned long, BUFLEN - 1, count))) { 1198 count = -EFAULT; 1199 goto out; 1200 } 1201 tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count)); 1202 /* Kludge code(deadlock situation): the lprocfs lock has been held 1203 * since the client is evicted by writing client's 1204 * uuid/nid to procfs "evict_client" entry. However, 1205 * obd_export_evict_by_uuid() will call lprocfs_remove() to destroy 1206 * the proc entries under the being destroyed export{}, so I have 1207 * to drop the lock at first here. 1208 * - jay, jxiong@clusterfs.com */ 1209 class_incref(obd, __func__, current); 1210 1211 if (strncmp(tmpbuf, "nid:", 4) == 0) 1212 obd_export_evict_by_nid(obd, tmpbuf + 4); 1213 else if (strncmp(tmpbuf, "uuid:", 5) == 0) 1214 obd_export_evict_by_uuid(obd, tmpbuf + 5); 1215 else 1216 obd_export_evict_by_uuid(obd, tmpbuf); 1217 1218 class_decref(obd, __func__, current); 1219 1220out: 1221 OBD_FREE(kbuf, BUFLEN); 1222 return count; 1223} 1224EXPORT_SYMBOL(lprocfs_wr_evict_client); 1225 1226#undef BUFLEN 1227 1228int lprocfs_wr_ping(struct file *file, const char *buffer, 1229 size_t count, loff_t *off) 1230{ 1231 struct obd_device *obd = ((struct seq_file *)file->private_data)->private; 1232 struct ptlrpc_request *req; 1233 int rc; 1234 1235 LPROCFS_CLIMP_CHECK(obd); 1236 req = ptlrpc_prep_ping(obd->u.cli.cl_import); 1237 LPROCFS_CLIMP_EXIT(obd); 1238 if (req == NULL) 1239 return -ENOMEM; 1240 1241 req->rq_send_state = LUSTRE_IMP_FULL; 1242 1243 rc = ptlrpc_queue_wait(req); 1244 1245 ptlrpc_req_finished(req); 1246 if (rc >= 0) 1247 return count; 1248 return rc; 1249} 1250EXPORT_SYMBOL(lprocfs_wr_ping); 1251 1252/* Write the connection UUID to this file to attempt to connect to that node. 1253 * The connection UUID is a node's primary NID. For example, 1254 * "echo connection=192.168.0.1@tcp0::instance > .../import". 1255 */ 1256int lprocfs_wr_import(struct file *file, const char *buffer, 1257 size_t count, loff_t *off) 1258{ 1259 struct obd_device *obd = ((struct seq_file *)file->private_data)->private; 1260 struct obd_import *imp = obd->u.cli.cl_import; 1261 char *kbuf = NULL; 1262 char *uuid; 1263 char *ptr; 1264 int do_reconn = 1; 1265 const char prefix[] = "connection="; 1266 const int prefix_len = sizeof(prefix) - 1; 1267 1268 if (count > PAGE_CACHE_SIZE - 1 || count <= prefix_len) 1269 return -EINVAL; 1270 1271 OBD_ALLOC(kbuf, count + 1); 1272 if (kbuf == NULL) 1273 return -ENOMEM; 1274 1275 if (copy_from_user(kbuf, buffer, count)) { 1276 count = -EFAULT; 1277 goto out; 1278 } 1279 1280 kbuf[count] = 0; 1281 1282 /* only support connection=uuid::instance now */ 1283 if (strncmp(prefix, kbuf, prefix_len) != 0) { 1284 count = -EINVAL; 1285 goto out; 1286 } 1287 1288 uuid = kbuf + prefix_len; 1289 ptr = strstr(uuid, "::"); 1290 if (ptr) { 1291 __u32 inst; 1292 char *endptr; 1293 1294 *ptr = 0; 1295 do_reconn = 0; 1296 ptr += strlen("::"); 1297 inst = simple_strtol(ptr, &endptr, 10); 1298 if (*endptr) { 1299 CERROR("config: wrong instance # %s\n", ptr); 1300 } else if (inst != imp->imp_connect_data.ocd_instance) { 1301 CDEBUG(D_INFO, "IR: %s is connecting to an obsoleted " 1302 "target(%u/%u), reconnecting...\n", 1303 imp->imp_obd->obd_name, 1304 imp->imp_connect_data.ocd_instance, inst); 1305 do_reconn = 1; 1306 } else { 1307 CDEBUG(D_INFO, "IR: %s has already been connecting to " 1308 "new target(%u)\n", 1309 imp->imp_obd->obd_name, inst); 1310 } 1311 } 1312 1313 if (do_reconn) 1314 ptlrpc_recover_import(imp, uuid, 1); 1315 1316out: 1317 OBD_FREE(kbuf, count + 1); 1318 return count; 1319} 1320EXPORT_SYMBOL(lprocfs_wr_import); 1321 1322int lprocfs_rd_pinger_recov(struct seq_file *m, void *n) 1323{ 1324 struct obd_device *obd = m->private; 1325 struct obd_import *imp = obd->u.cli.cl_import; 1326 int rc; 1327 1328 LPROCFS_CLIMP_CHECK(obd); 1329 rc = seq_printf(m, "%d\n", !imp->imp_no_pinger_recover); 1330 LPROCFS_CLIMP_EXIT(obd); 1331 1332 return rc; 1333} 1334EXPORT_SYMBOL(lprocfs_rd_pinger_recov); 1335 1336int lprocfs_wr_pinger_recov(struct file *file, const char *buffer, 1337 size_t count, loff_t *off) 1338{ 1339 struct obd_device *obd = ((struct seq_file *)file->private_data)->private; 1340 struct client_obd *cli = &obd->u.cli; 1341 struct obd_import *imp = cli->cl_import; 1342 int rc, val; 1343 1344 rc = lprocfs_write_helper(buffer, count, &val); 1345 if (rc < 0) 1346 return rc; 1347 1348 if (val != 0 && val != 1) 1349 return -ERANGE; 1350 1351 LPROCFS_CLIMP_CHECK(obd); 1352 spin_lock(&imp->imp_lock); 1353 imp->imp_no_pinger_recover = !val; 1354 spin_unlock(&imp->imp_lock); 1355 LPROCFS_CLIMP_EXIT(obd); 1356 1357 return count; 1358 1359} 1360EXPORT_SYMBOL(lprocfs_wr_pinger_recov); 1361 1362#endif /* CONFIG_PROC_FS */ 1363