1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/ceph/ceph_debug.h> 4 #include <linux/backing-dev.h> 5 #include <linux/ctype.h> 6 #include <linux/fs.h> 7 #include <linux/inet.h> 8 #include <linux/in6.h> 9 #include <linux/key.h> 10 #include <keys/ceph-type.h> 11 #include <linux/module.h> 12 #include <linux/mount.h> 13 #include <linux/nsproxy.h> 14 #include <linux/fs_parser.h> 15 #include <linux/sched.h> 16 #include <linux/sched/mm.h> 17 #include <linux/seq_file.h> 18 #include <linux/slab.h> 19 #include <linux/statfs.h> 20 #include <linux/string.h> 21 #include <linux/vmalloc.h> 22 23 24 #include <linux/ceph/ceph_features.h> 25 #include <linux/ceph/libceph.h> 26 #include <linux/ceph/debugfs.h> 27 #include <linux/ceph/decode.h> 28 #include <linux/ceph/mon_client.h> 29 #include <linux/ceph/auth.h> 30 #include "crypto.h" 31 32 33 /* 34 * Module compatibility interface. For now it doesn't do anything, 35 * but its existence signals a certain level of functionality. 36 * 37 * The data buffer is used to pass information both to and from 38 * libceph. The return value indicates whether libceph determines 39 * it is compatible with the caller (from another kernel module), 40 * given the provided data. 41 * 42 * The data pointer can be null. 43 */ 44 bool libceph_compatible(void *data) 45 { 46 return true; 47 } 48 EXPORT_SYMBOL(libceph_compatible); 49 50 static int param_get_supported_features(char *buffer, 51 const struct kernel_param *kp) 52 { 53 return sprintf(buffer, "0x%llx", CEPH_FEATURES_SUPPORTED_DEFAULT); 54 } 55 static const struct kernel_param_ops param_ops_supported_features = { 56 .get = param_get_supported_features, 57 }; 58 module_param_cb(supported_features, ¶m_ops_supported_features, NULL, 59 0444); 60 61 const char *ceph_msg_type_name(int type) 62 { 63 switch (type) { 64 case CEPH_MSG_SHUTDOWN: return "shutdown"; 65 case CEPH_MSG_PING: return "ping"; 66 case CEPH_MSG_AUTH: return "auth"; 67 case CEPH_MSG_AUTH_REPLY: return "auth_reply"; 68 case CEPH_MSG_MON_MAP: return "mon_map"; 69 case CEPH_MSG_MON_GET_MAP: return "mon_get_map"; 70 case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe"; 71 case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack"; 72 case CEPH_MSG_STATFS: return "statfs"; 73 case CEPH_MSG_STATFS_REPLY: return "statfs_reply"; 74 case CEPH_MSG_MON_GET_VERSION: return "mon_get_version"; 75 case CEPH_MSG_MON_GET_VERSION_REPLY: return "mon_get_version_reply"; 76 case CEPH_MSG_MDS_MAP: return "mds_map"; 77 case CEPH_MSG_FS_MAP_USER: return "fs_map_user"; 78 case CEPH_MSG_CLIENT_SESSION: return "client_session"; 79 case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect"; 80 case CEPH_MSG_CLIENT_REQUEST: return "client_request"; 81 case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward"; 82 case CEPH_MSG_CLIENT_REPLY: return "client_reply"; 83 case CEPH_MSG_CLIENT_CAPS: return "client_caps"; 84 case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release"; 85 case CEPH_MSG_CLIENT_QUOTA: return "client_quota"; 86 case CEPH_MSG_CLIENT_SNAP: return "client_snap"; 87 case CEPH_MSG_CLIENT_LEASE: return "client_lease"; 88 case CEPH_MSG_POOLOP_REPLY: return "poolop_reply"; 89 case CEPH_MSG_POOLOP: return "poolop"; 90 case CEPH_MSG_MON_COMMAND: return "mon_command"; 91 case CEPH_MSG_MON_COMMAND_ACK: return "mon_command_ack"; 92 case CEPH_MSG_OSD_MAP: return "osd_map"; 93 case CEPH_MSG_OSD_OP: return "osd_op"; 94 case CEPH_MSG_OSD_OPREPLY: return "osd_opreply"; 95 case CEPH_MSG_WATCH_NOTIFY: return "watch_notify"; 96 case CEPH_MSG_OSD_BACKOFF: return "osd_backoff"; 97 default: return "unknown"; 98 } 99 } 100 EXPORT_SYMBOL(ceph_msg_type_name); 101 102 /* 103 * Initially learn our fsid, or verify an fsid matches. 104 */ 105 int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) 106 { 107 if (client->have_fsid) { 108 if (ceph_fsid_compare(&client->fsid, fsid)) { 109 pr_err("bad fsid, had %pU got %pU", 110 &client->fsid, fsid); 111 return -1; 112 } 113 } else { 114 memcpy(&client->fsid, fsid, sizeof(*fsid)); 115 } 116 return 0; 117 } 118 EXPORT_SYMBOL(ceph_check_fsid); 119 120 static int strcmp_null(const char *s1, const char *s2) 121 { 122 if (!s1 && !s2) 123 return 0; 124 if (s1 && !s2) 125 return -1; 126 if (!s1 && s2) 127 return 1; 128 return strcmp(s1, s2); 129 } 130 131 int ceph_compare_options(struct ceph_options *new_opt, 132 struct ceph_client *client) 133 { 134 struct ceph_options *opt1 = new_opt; 135 struct ceph_options *opt2 = client->options; 136 int ofs = offsetof(struct ceph_options, mon_addr); 137 int i; 138 int ret; 139 140 /* 141 * Don't bother comparing options if network namespaces don't 142 * match. 143 */ 144 if (!net_eq(current->nsproxy->net_ns, read_pnet(&client->msgr.net))) 145 return -1; 146 147 ret = memcmp(opt1, opt2, ofs); 148 if (ret) 149 return ret; 150 151 ret = strcmp_null(opt1->name, opt2->name); 152 if (ret) 153 return ret; 154 155 if (opt1->key && !opt2->key) 156 return -1; 157 if (!opt1->key && opt2->key) 158 return 1; 159 if (opt1->key && opt2->key) { 160 if (opt1->key->type != opt2->key->type) 161 return -1; 162 if (opt1->key->created.tv_sec != opt2->key->created.tv_sec) 163 return -1; 164 if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec) 165 return -1; 166 if (opt1->key->len != opt2->key->len) 167 return -1; 168 if (opt1->key->key && !opt2->key->key) 169 return -1; 170 if (!opt1->key->key && opt2->key->key) 171 return 1; 172 if (opt1->key->key && opt2->key->key) { 173 ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len); 174 if (ret) 175 return ret; 176 } 177 } 178 179 ret = ceph_compare_crush_locs(&opt1->crush_locs, &opt2->crush_locs); 180 if (ret) 181 return ret; 182 183 /* any matching mon ip implies a match */ 184 for (i = 0; i < opt1->num_mon; i++) { 185 if (ceph_monmap_contains(client->monc.monmap, 186 &opt1->mon_addr[i])) 187 return 0; 188 } 189 return -1; 190 } 191 EXPORT_SYMBOL(ceph_compare_options); 192 193 /* 194 * kvmalloc() doesn't fall back to the vmalloc allocator unless flags are 195 * compatible with (a superset of) GFP_KERNEL. This is because while the 196 * actual pages are allocated with the specified flags, the page table pages 197 * are always allocated with GFP_KERNEL. 198 * 199 * ceph_kvmalloc() may be called with GFP_KERNEL, GFP_NOFS or GFP_NOIO. 200 */ 201 void *ceph_kvmalloc(size_t size, gfp_t flags) 202 { 203 void *p; 204 205 if ((flags & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS)) { 206 p = kvmalloc(size, flags); 207 } else if ((flags & (__GFP_IO | __GFP_FS)) == __GFP_IO) { 208 unsigned int nofs_flag = memalloc_nofs_save(); 209 p = kvmalloc(size, GFP_KERNEL); 210 memalloc_nofs_restore(nofs_flag); 211 } else { 212 unsigned int noio_flag = memalloc_noio_save(); 213 p = kvmalloc(size, GFP_KERNEL); 214 memalloc_noio_restore(noio_flag); 215 } 216 217 return p; 218 } 219 220 static int parse_fsid(const char *str, struct ceph_fsid *fsid) 221 { 222 int i = 0; 223 char tmp[3]; 224 int err = -EINVAL; 225 int d; 226 227 dout("parse_fsid '%s'\n", str); 228 tmp[2] = 0; 229 while (*str && i < 16) { 230 if (ispunct(*str)) { 231 str++; 232 continue; 233 } 234 if (!isxdigit(str[0]) || !isxdigit(str[1])) 235 break; 236 tmp[0] = str[0]; 237 tmp[1] = str[1]; 238 if (sscanf(tmp, "%x", &d) < 1) 239 break; 240 fsid->fsid[i] = d & 0xff; 241 i++; 242 str += 2; 243 } 244 245 if (i == 16) 246 err = 0; 247 dout("parse_fsid ret %d got fsid %pU\n", err, fsid); 248 return err; 249 } 250 251 /* 252 * ceph options 253 */ 254 enum { 255 Opt_osdtimeout, 256 Opt_osdkeepalivetimeout, 257 Opt_mount_timeout, 258 Opt_osd_idle_ttl, 259 Opt_osd_request_timeout, 260 /* int args above */ 261 Opt_fsid, 262 Opt_name, 263 Opt_secret, 264 Opt_key, 265 Opt_ip, 266 Opt_crush_location, 267 Opt_read_from_replica, 268 Opt_ms_mode, 269 /* string args above */ 270 Opt_share, 271 Opt_crc, 272 Opt_cephx_require_signatures, 273 Opt_cephx_sign_messages, 274 Opt_tcp_nodelay, 275 Opt_abort_on_full, 276 }; 277 278 enum { 279 Opt_read_from_replica_no, 280 Opt_read_from_replica_balance, 281 Opt_read_from_replica_localize, 282 }; 283 284 static const struct constant_table ceph_param_read_from_replica[] = { 285 {"no", Opt_read_from_replica_no}, 286 {"balance", Opt_read_from_replica_balance}, 287 {"localize", Opt_read_from_replica_localize}, 288 {} 289 }; 290 291 enum ceph_ms_mode { 292 Opt_ms_mode_legacy, 293 Opt_ms_mode_crc, 294 Opt_ms_mode_secure, 295 Opt_ms_mode_prefer_crc, 296 Opt_ms_mode_prefer_secure 297 }; 298 299 static const struct constant_table ceph_param_ms_mode[] = { 300 {"legacy", Opt_ms_mode_legacy}, 301 {"crc", Opt_ms_mode_crc}, 302 {"secure", Opt_ms_mode_secure}, 303 {"prefer-crc", Opt_ms_mode_prefer_crc}, 304 {"prefer-secure", Opt_ms_mode_prefer_secure}, 305 {} 306 }; 307 308 static const struct fs_parameter_spec ceph_parameters[] = { 309 fsparam_flag ("abort_on_full", Opt_abort_on_full), 310 fsparam_flag_no ("cephx_require_signatures", Opt_cephx_require_signatures), 311 fsparam_flag_no ("cephx_sign_messages", Opt_cephx_sign_messages), 312 fsparam_flag_no ("crc", Opt_crc), 313 fsparam_string ("crush_location", Opt_crush_location), 314 fsparam_string ("fsid", Opt_fsid), 315 fsparam_string ("ip", Opt_ip), 316 fsparam_string ("key", Opt_key), 317 fsparam_u32 ("mount_timeout", Opt_mount_timeout), 318 fsparam_string ("name", Opt_name), 319 fsparam_u32 ("osd_idle_ttl", Opt_osd_idle_ttl), 320 fsparam_u32 ("osd_request_timeout", Opt_osd_request_timeout), 321 fsparam_u32 ("osdkeepalive", Opt_osdkeepalivetimeout), 322 __fsparam (fs_param_is_s32, "osdtimeout", Opt_osdtimeout, 323 fs_param_deprecated, NULL), 324 fsparam_enum ("read_from_replica", Opt_read_from_replica, 325 ceph_param_read_from_replica), 326 fsparam_enum ("ms_mode", Opt_ms_mode, 327 ceph_param_ms_mode), 328 fsparam_string ("secret", Opt_secret), 329 fsparam_flag_no ("share", Opt_share), 330 fsparam_flag_no ("tcp_nodelay", Opt_tcp_nodelay), 331 {} 332 }; 333 334 struct ceph_options *ceph_alloc_options(void) 335 { 336 struct ceph_options *opt; 337 338 opt = kzalloc(sizeof(*opt), GFP_KERNEL); 339 if (!opt) 340 return NULL; 341 342 opt->crush_locs = RB_ROOT; 343 opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr), 344 GFP_KERNEL); 345 if (!opt->mon_addr) { 346 kfree(opt); 347 return NULL; 348 } 349 350 opt->flags = CEPH_OPT_DEFAULT; 351 opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; 352 opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; 353 opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; 354 opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT; 355 opt->read_from_replica = CEPH_READ_FROM_REPLICA_DEFAULT; 356 opt->con_modes[0] = CEPH_CON_MODE_UNKNOWN; 357 opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN; 358 return opt; 359 } 360 EXPORT_SYMBOL(ceph_alloc_options); 361 362 void ceph_destroy_options(struct ceph_options *opt) 363 { 364 dout("destroy_options %p\n", opt); 365 if (!opt) 366 return; 367 368 ceph_clear_crush_locs(&opt->crush_locs); 369 kfree(opt->name); 370 if (opt->key) { 371 ceph_crypto_key_destroy(opt->key); 372 kfree(opt->key); 373 } 374 kfree(opt->mon_addr); 375 kfree(opt); 376 } 377 EXPORT_SYMBOL(ceph_destroy_options); 378 379 /* get secret from key store */ 380 static int get_secret(struct ceph_crypto_key *dst, const char *name, 381 struct p_log *log) 382 { 383 struct key *ukey; 384 int key_err; 385 int err = 0; 386 struct ceph_crypto_key *ckey; 387 388 ukey = request_key(&key_type_ceph, name, NULL); 389 if (IS_ERR(ukey)) { 390 /* request_key errors don't map nicely to mount(2) 391 errors; don't even try, but still printk */ 392 key_err = PTR_ERR(ukey); 393 switch (key_err) { 394 case -ENOKEY: 395 error_plog(log, "Failed due to key not found: %s", 396 name); 397 break; 398 case -EKEYEXPIRED: 399 error_plog(log, "Failed due to expired key: %s", 400 name); 401 break; 402 case -EKEYREVOKED: 403 error_plog(log, "Failed due to revoked key: %s", 404 name); 405 break; 406 default: 407 error_plog(log, "Failed due to key error %d: %s", 408 key_err, name); 409 } 410 err = -EPERM; 411 goto out; 412 } 413 414 ckey = ukey->payload.data[0]; 415 err = ceph_crypto_key_clone(dst, ckey); 416 if (err) 417 goto out_key; 418 /* pass through, err is 0 */ 419 420 out_key: 421 key_put(ukey); 422 out: 423 return err; 424 } 425 426 int ceph_parse_mon_ips(const char *buf, size_t len, struct ceph_options *opt, 427 struct fc_log *l) 428 { 429 struct p_log log = {.prefix = "libceph", .log = l}; 430 int ret; 431 432 /* ip1[:port1][,ip2[:port2]...] */ 433 ret = ceph_parse_ips(buf, buf + len, opt->mon_addr, CEPH_MAX_MON, 434 &opt->num_mon); 435 if (ret) { 436 error_plog(&log, "Failed to parse monitor IPs: %d", ret); 437 return ret; 438 } 439 440 return 0; 441 } 442 EXPORT_SYMBOL(ceph_parse_mon_ips); 443 444 int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt, 445 struct fc_log *l) 446 { 447 struct fs_parse_result result; 448 int token, err; 449 struct p_log log = {.prefix = "libceph", .log = l}; 450 451 token = __fs_parse(&log, ceph_parameters, param, &result); 452 dout("%s fs_parse '%s' token %d\n", __func__, param->key, token); 453 if (token < 0) 454 return token; 455 456 switch (token) { 457 case Opt_ip: 458 err = ceph_parse_ips(param->string, 459 param->string + param->size, 460 &opt->my_addr, 461 1, NULL); 462 if (err) { 463 error_plog(&log, "Failed to parse ip: %d", err); 464 return err; 465 } 466 opt->flags |= CEPH_OPT_MYIP; 467 break; 468 469 case Opt_fsid: 470 err = parse_fsid(param->string, &opt->fsid); 471 if (err) { 472 error_plog(&log, "Failed to parse fsid: %d", err); 473 return err; 474 } 475 opt->flags |= CEPH_OPT_FSID; 476 break; 477 case Opt_name: 478 kfree(opt->name); 479 opt->name = param->string; 480 param->string = NULL; 481 break; 482 case Opt_secret: 483 ceph_crypto_key_destroy(opt->key); 484 kfree(opt->key); 485 486 opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); 487 if (!opt->key) 488 return -ENOMEM; 489 err = ceph_crypto_key_unarmor(opt->key, param->string); 490 if (err) { 491 error_plog(&log, "Failed to parse secret: %d", err); 492 return err; 493 } 494 break; 495 case Opt_key: 496 ceph_crypto_key_destroy(opt->key); 497 kfree(opt->key); 498 499 opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); 500 if (!opt->key) 501 return -ENOMEM; 502 return get_secret(opt->key, param->string, &log); 503 case Opt_crush_location: 504 ceph_clear_crush_locs(&opt->crush_locs); 505 err = ceph_parse_crush_location(param->string, 506 &opt->crush_locs); 507 if (err) { 508 error_plog(&log, "Failed to parse CRUSH location: %d", 509 err); 510 return err; 511 } 512 break; 513 case Opt_read_from_replica: 514 switch (result.uint_32) { 515 case Opt_read_from_replica_no: 516 opt->read_from_replica = 0; 517 break; 518 case Opt_read_from_replica_balance: 519 opt->read_from_replica = CEPH_OSD_FLAG_BALANCE_READS; 520 break; 521 case Opt_read_from_replica_localize: 522 opt->read_from_replica = CEPH_OSD_FLAG_LOCALIZE_READS; 523 break; 524 default: 525 BUG(); 526 } 527 break; 528 case Opt_ms_mode: 529 switch (result.uint_32) { 530 case Opt_ms_mode_legacy: 531 opt->con_modes[0] = CEPH_CON_MODE_UNKNOWN; 532 opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN; 533 break; 534 case Opt_ms_mode_crc: 535 opt->con_modes[0] = CEPH_CON_MODE_CRC; 536 opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN; 537 break; 538 case Opt_ms_mode_secure: 539 opt->con_modes[0] = CEPH_CON_MODE_SECURE; 540 opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN; 541 break; 542 case Opt_ms_mode_prefer_crc: 543 opt->con_modes[0] = CEPH_CON_MODE_CRC; 544 opt->con_modes[1] = CEPH_CON_MODE_SECURE; 545 break; 546 case Opt_ms_mode_prefer_secure: 547 opt->con_modes[0] = CEPH_CON_MODE_SECURE; 548 opt->con_modes[1] = CEPH_CON_MODE_CRC; 549 break; 550 default: 551 BUG(); 552 } 553 break; 554 555 case Opt_osdtimeout: 556 warn_plog(&log, "Ignoring osdtimeout"); 557 break; 558 case Opt_osdkeepalivetimeout: 559 /* 0 isn't well defined right now, reject it */ 560 if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000) 561 goto out_of_range; 562 opt->osd_keepalive_timeout = 563 msecs_to_jiffies(result.uint_32 * 1000); 564 break; 565 case Opt_osd_idle_ttl: 566 /* 0 isn't well defined right now, reject it */ 567 if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000) 568 goto out_of_range; 569 opt->osd_idle_ttl = msecs_to_jiffies(result.uint_32 * 1000); 570 break; 571 case Opt_mount_timeout: 572 /* 0 is "wait forever" (i.e. infinite timeout) */ 573 if (result.uint_32 > INT_MAX / 1000) 574 goto out_of_range; 575 opt->mount_timeout = msecs_to_jiffies(result.uint_32 * 1000); 576 break; 577 case Opt_osd_request_timeout: 578 /* 0 is "wait forever" (i.e. infinite timeout) */ 579 if (result.uint_32 > INT_MAX / 1000) 580 goto out_of_range; 581 opt->osd_request_timeout = 582 msecs_to_jiffies(result.uint_32 * 1000); 583 break; 584 585 case Opt_share: 586 if (!result.negated) 587 opt->flags &= ~CEPH_OPT_NOSHARE; 588 else 589 opt->flags |= CEPH_OPT_NOSHARE; 590 break; 591 case Opt_crc: 592 if (!result.negated) 593 opt->flags &= ~CEPH_OPT_NOCRC; 594 else 595 opt->flags |= CEPH_OPT_NOCRC; 596 break; 597 case Opt_cephx_require_signatures: 598 if (!result.negated) 599 opt->flags &= ~CEPH_OPT_NOMSGAUTH; 600 else 601 opt->flags |= CEPH_OPT_NOMSGAUTH; 602 break; 603 case Opt_cephx_sign_messages: 604 if (!result.negated) 605 opt->flags &= ~CEPH_OPT_NOMSGSIGN; 606 else 607 opt->flags |= CEPH_OPT_NOMSGSIGN; 608 break; 609 case Opt_tcp_nodelay: 610 if (!result.negated) 611 opt->flags |= CEPH_OPT_TCP_NODELAY; 612 else 613 opt->flags &= ~CEPH_OPT_TCP_NODELAY; 614 break; 615 616 case Opt_abort_on_full: 617 opt->flags |= CEPH_OPT_ABORT_ON_FULL; 618 break; 619 620 default: 621 BUG(); 622 } 623 624 return 0; 625 626 out_of_range: 627 return inval_plog(&log, "%s out of range", param->key); 628 } 629 EXPORT_SYMBOL(ceph_parse_param); 630 631 int ceph_print_client_options(struct seq_file *m, struct ceph_client *client, 632 bool show_all) 633 { 634 struct ceph_options *opt = client->options; 635 size_t pos = m->count; 636 struct rb_node *n; 637 638 if (opt->name) { 639 seq_puts(m, "name="); 640 seq_escape(m, opt->name, ", \t\n\\"); 641 seq_putc(m, ','); 642 } 643 if (opt->key) 644 seq_puts(m, "secret=<hidden>,"); 645 646 if (!RB_EMPTY_ROOT(&opt->crush_locs)) { 647 seq_puts(m, "crush_location="); 648 for (n = rb_first(&opt->crush_locs); ; ) { 649 struct crush_loc_node *loc = 650 rb_entry(n, struct crush_loc_node, cl_node); 651 652 seq_printf(m, "%s:%s", loc->cl_loc.cl_type_name, 653 loc->cl_loc.cl_name); 654 n = rb_next(n); 655 if (!n) 656 break; 657 658 seq_putc(m, '|'); 659 } 660 seq_putc(m, ','); 661 } 662 if (opt->read_from_replica == CEPH_OSD_FLAG_BALANCE_READS) { 663 seq_puts(m, "read_from_replica=balance,"); 664 } else if (opt->read_from_replica == CEPH_OSD_FLAG_LOCALIZE_READS) { 665 seq_puts(m, "read_from_replica=localize,"); 666 } 667 if (opt->con_modes[0] != CEPH_CON_MODE_UNKNOWN) { 668 if (opt->con_modes[0] == CEPH_CON_MODE_CRC && 669 opt->con_modes[1] == CEPH_CON_MODE_UNKNOWN) { 670 seq_puts(m, "ms_mode=crc,"); 671 } else if (opt->con_modes[0] == CEPH_CON_MODE_SECURE && 672 opt->con_modes[1] == CEPH_CON_MODE_UNKNOWN) { 673 seq_puts(m, "ms_mode=secure,"); 674 } else if (opt->con_modes[0] == CEPH_CON_MODE_CRC && 675 opt->con_modes[1] == CEPH_CON_MODE_SECURE) { 676 seq_puts(m, "ms_mode=prefer-crc,"); 677 } else if (opt->con_modes[0] == CEPH_CON_MODE_SECURE && 678 opt->con_modes[1] == CEPH_CON_MODE_CRC) { 679 seq_puts(m, "ms_mode=prefer-secure,"); 680 } 681 } 682 683 if (opt->flags & CEPH_OPT_FSID) 684 seq_printf(m, "fsid=%pU,", &opt->fsid); 685 if (opt->flags & CEPH_OPT_NOSHARE) 686 seq_puts(m, "noshare,"); 687 if (opt->flags & CEPH_OPT_NOCRC) 688 seq_puts(m, "nocrc,"); 689 if (opt->flags & CEPH_OPT_NOMSGAUTH) 690 seq_puts(m, "nocephx_require_signatures,"); 691 if (opt->flags & CEPH_OPT_NOMSGSIGN) 692 seq_puts(m, "nocephx_sign_messages,"); 693 if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0) 694 seq_puts(m, "notcp_nodelay,"); 695 if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL)) 696 seq_puts(m, "abort_on_full,"); 697 698 if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT) 699 seq_printf(m, "mount_timeout=%d,", 700 jiffies_to_msecs(opt->mount_timeout) / 1000); 701 if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT) 702 seq_printf(m, "osd_idle_ttl=%d,", 703 jiffies_to_msecs(opt->osd_idle_ttl) / 1000); 704 if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT) 705 seq_printf(m, "osdkeepalivetimeout=%d,", 706 jiffies_to_msecs(opt->osd_keepalive_timeout) / 1000); 707 if (opt->osd_request_timeout != CEPH_OSD_REQUEST_TIMEOUT_DEFAULT) 708 seq_printf(m, "osd_request_timeout=%d,", 709 jiffies_to_msecs(opt->osd_request_timeout) / 1000); 710 711 /* drop redundant comma */ 712 if (m->count != pos) 713 m->count--; 714 715 return 0; 716 } 717 EXPORT_SYMBOL(ceph_print_client_options); 718 719 struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client) 720 { 721 return &client->msgr.inst.addr; 722 } 723 EXPORT_SYMBOL(ceph_client_addr); 724 725 u64 ceph_client_gid(struct ceph_client *client) 726 { 727 return client->monc.auth->global_id; 728 } 729 EXPORT_SYMBOL(ceph_client_gid); 730 731 /* 732 * create a fresh client instance 733 */ 734 struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private) 735 { 736 struct ceph_client *client; 737 struct ceph_entity_addr *myaddr = NULL; 738 int err; 739 740 err = wait_for_random_bytes(); 741 if (err < 0) 742 return ERR_PTR(err); 743 744 client = kzalloc(sizeof(*client), GFP_KERNEL); 745 if (client == NULL) 746 return ERR_PTR(-ENOMEM); 747 748 client->private = private; 749 client->options = opt; 750 751 mutex_init(&client->mount_mutex); 752 init_waitqueue_head(&client->auth_wq); 753 client->auth_err = 0; 754 755 client->extra_mon_dispatch = NULL; 756 client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT; 757 client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT; 758 759 if (!ceph_test_opt(client, NOMSGAUTH)) 760 client->required_features |= CEPH_FEATURE_MSG_AUTH; 761 762 /* msgr */ 763 if (ceph_test_opt(client, MYIP)) 764 myaddr = &client->options->my_addr; 765 766 ceph_messenger_init(&client->msgr, myaddr); 767 768 /* subsystems */ 769 err = ceph_monc_init(&client->monc, client); 770 if (err < 0) 771 goto fail; 772 err = ceph_osdc_init(&client->osdc, client); 773 if (err < 0) 774 goto fail_monc; 775 776 return client; 777 778 fail_monc: 779 ceph_monc_stop(&client->monc); 780 fail: 781 ceph_messenger_fini(&client->msgr); 782 kfree(client); 783 return ERR_PTR(err); 784 } 785 EXPORT_SYMBOL(ceph_create_client); 786 787 void ceph_destroy_client(struct ceph_client *client) 788 { 789 dout("destroy_client %p\n", client); 790 791 atomic_set(&client->msgr.stopping, 1); 792 793 /* unmount */ 794 ceph_osdc_stop(&client->osdc); 795 ceph_monc_stop(&client->monc); 796 ceph_messenger_fini(&client->msgr); 797 798 ceph_debugfs_client_cleanup(client); 799 800 ceph_destroy_options(client->options); 801 802 kfree(client); 803 dout("destroy_client %p done\n", client); 804 } 805 EXPORT_SYMBOL(ceph_destroy_client); 806 807 void ceph_reset_client_addr(struct ceph_client *client) 808 { 809 ceph_messenger_reset_nonce(&client->msgr); 810 ceph_monc_reopen_session(&client->monc); 811 ceph_osdc_reopen_osds(&client->osdc); 812 } 813 EXPORT_SYMBOL(ceph_reset_client_addr); 814 815 /* 816 * true if we have the mon map (and have thus joined the cluster) 817 */ 818 static bool have_mon_and_osd_map(struct ceph_client *client) 819 { 820 return client->monc.monmap && client->monc.monmap->epoch && 821 client->osdc.osdmap && client->osdc.osdmap->epoch; 822 } 823 824 /* 825 * mount: join the ceph cluster, and open root directory. 826 */ 827 int __ceph_open_session(struct ceph_client *client, unsigned long started) 828 { 829 unsigned long timeout = client->options->mount_timeout; 830 long err; 831 832 /* open session, and wait for mon and osd maps */ 833 err = ceph_monc_open_session(&client->monc); 834 if (err < 0) 835 return err; 836 837 while (!have_mon_and_osd_map(client)) { 838 if (timeout && time_after_eq(jiffies, started + timeout)) 839 return -ETIMEDOUT; 840 841 /* wait */ 842 dout("mount waiting for mon_map\n"); 843 err = wait_event_interruptible_timeout(client->auth_wq, 844 have_mon_and_osd_map(client) || (client->auth_err < 0), 845 ceph_timeout_jiffies(timeout)); 846 if (err < 0) 847 return err; 848 if (client->auth_err < 0) 849 return client->auth_err; 850 } 851 852 pr_info("client%llu fsid %pU\n", ceph_client_gid(client), 853 &client->fsid); 854 ceph_debugfs_client_init(client); 855 856 return 0; 857 } 858 EXPORT_SYMBOL(__ceph_open_session); 859 860 int ceph_open_session(struct ceph_client *client) 861 { 862 int ret; 863 unsigned long started = jiffies; /* note the start time */ 864 865 dout("open_session start\n"); 866 mutex_lock(&client->mount_mutex); 867 868 ret = __ceph_open_session(client, started); 869 870 mutex_unlock(&client->mount_mutex); 871 return ret; 872 } 873 EXPORT_SYMBOL(ceph_open_session); 874 875 int ceph_wait_for_latest_osdmap(struct ceph_client *client, 876 unsigned long timeout) 877 { 878 u64 newest_epoch; 879 int ret; 880 881 ret = ceph_monc_get_version(&client->monc, "osdmap", &newest_epoch); 882 if (ret) 883 return ret; 884 885 if (client->osdc.osdmap->epoch >= newest_epoch) 886 return 0; 887 888 ceph_osdc_maybe_request_map(&client->osdc); 889 return ceph_monc_wait_osdmap(&client->monc, newest_epoch, timeout); 890 } 891 EXPORT_SYMBOL(ceph_wait_for_latest_osdmap); 892 893 static int __init init_ceph_lib(void) 894 { 895 int ret = 0; 896 897 ceph_debugfs_init(); 898 899 ret = ceph_crypto_init(); 900 if (ret < 0) 901 goto out_debugfs; 902 903 ret = ceph_msgr_init(); 904 if (ret < 0) 905 goto out_crypto; 906 907 ret = ceph_osdc_setup(); 908 if (ret < 0) 909 goto out_msgr; 910 911 pr_info("loaded (mon/osd proto %d/%d)\n", 912 CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL); 913 914 return 0; 915 916 out_msgr: 917 ceph_msgr_exit(); 918 out_crypto: 919 ceph_crypto_shutdown(); 920 out_debugfs: 921 ceph_debugfs_cleanup(); 922 return ret; 923 } 924 925 static void __exit exit_ceph_lib(void) 926 { 927 dout("exit_ceph_lib\n"); 928 WARN_ON(!ceph_strings_empty()); 929 930 ceph_osdc_cleanup(); 931 ceph_msgr_exit(); 932 ceph_crypto_shutdown(); 933 ceph_debugfs_cleanup(); 934 } 935 936 module_init(init_ceph_lib); 937 module_exit(exit_ceph_lib); 938 939 MODULE_AUTHOR("Sage Weil <sage@newdream.net>"); 940 MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>"); 941 MODULE_AUTHOR("Patience Warnick <patience@newdream.net>"); 942 MODULE_DESCRIPTION("Ceph core library"); 943 MODULE_LICENSE("GPL"); 944