1 2 #include <linux/ceph/ceph_debug.h> 3 #include <linux/backing-dev.h> 4 #include <linux/ctype.h> 5 #include <linux/fs.h> 6 #include <linux/inet.h> 7 #include <linux/in6.h> 8 #include <linux/key.h> 9 #include <keys/ceph-type.h> 10 #include <linux/module.h> 11 #include <linux/mount.h> 12 #include <linux/nsproxy.h> 13 #include <linux/parser.h> 14 #include <linux/sched.h> 15 #include <linux/seq_file.h> 16 #include <linux/slab.h> 17 #include <linux/statfs.h> 18 #include <linux/string.h> 19 #include <linux/vmalloc.h> 20 21 22 #include <linux/ceph/ceph_features.h> 23 #include <linux/ceph/libceph.h> 24 #include <linux/ceph/debugfs.h> 25 #include <linux/ceph/decode.h> 26 #include <linux/ceph/mon_client.h> 27 #include <linux/ceph/auth.h> 28 #include "crypto.h" 29 30 31 /* 32 * Module compatibility interface. For now it doesn't do anything, 33 * but its existence signals a certain level of functionality. 34 * 35 * The data buffer is used to pass information both to and from 36 * libceph. The return value indicates whether libceph determines 37 * it is compatible with the caller (from another kernel module), 38 * given the provided data. 39 * 40 * The data pointer can be null. 41 */ 42 bool libceph_compatible(void *data) 43 { 44 return true; 45 } 46 EXPORT_SYMBOL(libceph_compatible); 47 48 static int param_get_supported_features(char *buffer, 49 const struct kernel_param *kp) 50 { 51 return sprintf(buffer, "0x%llx", CEPH_FEATURES_SUPPORTED_DEFAULT); 52 } 53 static const struct kernel_param_ops param_ops_supported_features = { 54 .get = param_get_supported_features, 55 }; 56 module_param_cb(supported_features, ¶m_ops_supported_features, NULL, 57 S_IRUGO); 58 59 /* 60 * find filename portion of a path (/foo/bar/baz -> baz) 61 */ 62 const char *ceph_file_part(const char *s, int len) 63 { 64 const char *e = s + len; 65 66 while (e != s && *(e-1) != '/') 67 e--; 68 return e; 69 } 70 EXPORT_SYMBOL(ceph_file_part); 71 72 const char *ceph_msg_type_name(int type) 73 { 74 switch (type) { 75 case CEPH_MSG_SHUTDOWN: return "shutdown"; 76 case CEPH_MSG_PING: return "ping"; 77 case CEPH_MSG_AUTH: return "auth"; 78 case CEPH_MSG_AUTH_REPLY: return "auth_reply"; 79 case CEPH_MSG_MON_MAP: return "mon_map"; 80 case CEPH_MSG_MON_GET_MAP: return "mon_get_map"; 81 case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe"; 82 case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack"; 83 case CEPH_MSG_STATFS: return "statfs"; 84 case CEPH_MSG_STATFS_REPLY: return "statfs_reply"; 85 case CEPH_MSG_MON_GET_VERSION: return "mon_get_version"; 86 case CEPH_MSG_MON_GET_VERSION_REPLY: return "mon_get_version_reply"; 87 case CEPH_MSG_MDS_MAP: return "mds_map"; 88 case CEPH_MSG_CLIENT_SESSION: return "client_session"; 89 case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect"; 90 case CEPH_MSG_CLIENT_REQUEST: return "client_request"; 91 case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward"; 92 case CEPH_MSG_CLIENT_REPLY: return "client_reply"; 93 case CEPH_MSG_CLIENT_CAPS: return "client_caps"; 94 case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release"; 95 case CEPH_MSG_CLIENT_SNAP: return "client_snap"; 96 case CEPH_MSG_CLIENT_LEASE: return "client_lease"; 97 case CEPH_MSG_OSD_MAP: return "osd_map"; 98 case CEPH_MSG_OSD_OP: return "osd_op"; 99 case CEPH_MSG_OSD_OPREPLY: return "osd_opreply"; 100 case CEPH_MSG_WATCH_NOTIFY: return "watch_notify"; 101 default: return "unknown"; 102 } 103 } 104 EXPORT_SYMBOL(ceph_msg_type_name); 105 106 /* 107 * Initially learn our fsid, or verify an fsid matches. 108 */ 109 int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) 110 { 111 if (client->have_fsid) { 112 if (ceph_fsid_compare(&client->fsid, fsid)) { 113 pr_err("bad fsid, had %pU got %pU", 114 &client->fsid, fsid); 115 return -1; 116 } 117 } else { 118 memcpy(&client->fsid, fsid, sizeof(*fsid)); 119 } 120 return 0; 121 } 122 EXPORT_SYMBOL(ceph_check_fsid); 123 124 static int strcmp_null(const char *s1, const char *s2) 125 { 126 if (!s1 && !s2) 127 return 0; 128 if (s1 && !s2) 129 return -1; 130 if (!s1 && s2) 131 return 1; 132 return strcmp(s1, s2); 133 } 134 135 int ceph_compare_options(struct ceph_options *new_opt, 136 struct ceph_client *client) 137 { 138 struct ceph_options *opt1 = new_opt; 139 struct ceph_options *opt2 = client->options; 140 int ofs = offsetof(struct ceph_options, mon_addr); 141 int i; 142 int ret; 143 144 /* 145 * Don't bother comparing options if network namespaces don't 146 * match. 147 */ 148 if (!net_eq(current->nsproxy->net_ns, read_pnet(&client->msgr.net))) 149 return -1; 150 151 ret = memcmp(opt1, opt2, ofs); 152 if (ret) 153 return ret; 154 155 ret = strcmp_null(opt1->name, opt2->name); 156 if (ret) 157 return ret; 158 159 if (opt1->key && !opt2->key) 160 return -1; 161 if (!opt1->key && opt2->key) 162 return 1; 163 if (opt1->key && opt2->key) { 164 if (opt1->key->type != opt2->key->type) 165 return -1; 166 if (opt1->key->created.tv_sec != opt2->key->created.tv_sec) 167 return -1; 168 if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec) 169 return -1; 170 if (opt1->key->len != opt2->key->len) 171 return -1; 172 if (opt1->key->key && !opt2->key->key) 173 return -1; 174 if (!opt1->key->key && opt2->key->key) 175 return 1; 176 if (opt1->key->key && opt2->key->key) { 177 ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len); 178 if (ret) 179 return ret; 180 } 181 } 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 void *ceph_kvmalloc(size_t size, gfp_t flags) 194 { 195 if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { 196 void *ptr = kmalloc(size, flags | __GFP_NOWARN); 197 if (ptr) 198 return ptr; 199 } 200 201 return __vmalloc(size, flags, PAGE_KERNEL); 202 } 203 204 205 static int parse_fsid(const char *str, struct ceph_fsid *fsid) 206 { 207 int i = 0; 208 char tmp[3]; 209 int err = -EINVAL; 210 int d; 211 212 dout("parse_fsid '%s'\n", str); 213 tmp[2] = 0; 214 while (*str && i < 16) { 215 if (ispunct(*str)) { 216 str++; 217 continue; 218 } 219 if (!isxdigit(str[0]) || !isxdigit(str[1])) 220 break; 221 tmp[0] = str[0]; 222 tmp[1] = str[1]; 223 if (sscanf(tmp, "%x", &d) < 1) 224 break; 225 fsid->fsid[i] = d & 0xff; 226 i++; 227 str += 2; 228 } 229 230 if (i == 16) 231 err = 0; 232 dout("parse_fsid ret %d got fsid %pU", err, fsid); 233 return err; 234 } 235 236 /* 237 * ceph options 238 */ 239 enum { 240 Opt_osdtimeout, 241 Opt_osdkeepalivetimeout, 242 Opt_mount_timeout, 243 Opt_osd_idle_ttl, 244 Opt_osd_request_timeout, 245 Opt_last_int, 246 /* int args above */ 247 Opt_fsid, 248 Opt_name, 249 Opt_secret, 250 Opt_key, 251 Opt_ip, 252 Opt_last_string, 253 /* string args above */ 254 Opt_share, 255 Opt_noshare, 256 Opt_crc, 257 Opt_nocrc, 258 Opt_cephx_require_signatures, 259 Opt_nocephx_require_signatures, 260 Opt_cephx_sign_messages, 261 Opt_nocephx_sign_messages, 262 Opt_tcp_nodelay, 263 Opt_notcp_nodelay, 264 }; 265 266 static match_table_t opt_tokens = { 267 {Opt_osdtimeout, "osdtimeout=%d"}, 268 {Opt_osdkeepalivetimeout, "osdkeepalive=%d"}, 269 {Opt_mount_timeout, "mount_timeout=%d"}, 270 {Opt_osd_idle_ttl, "osd_idle_ttl=%d"}, 271 {Opt_osd_request_timeout, "osd_request_timeout=%d"}, 272 /* int args above */ 273 {Opt_fsid, "fsid=%s"}, 274 {Opt_name, "name=%s"}, 275 {Opt_secret, "secret=%s"}, 276 {Opt_key, "key=%s"}, 277 {Opt_ip, "ip=%s"}, 278 /* string args above */ 279 {Opt_share, "share"}, 280 {Opt_noshare, "noshare"}, 281 {Opt_crc, "crc"}, 282 {Opt_nocrc, "nocrc"}, 283 {Opt_cephx_require_signatures, "cephx_require_signatures"}, 284 {Opt_nocephx_require_signatures, "nocephx_require_signatures"}, 285 {Opt_cephx_sign_messages, "cephx_sign_messages"}, 286 {Opt_nocephx_sign_messages, "nocephx_sign_messages"}, 287 {Opt_tcp_nodelay, "tcp_nodelay"}, 288 {Opt_notcp_nodelay, "notcp_nodelay"}, 289 {-1, NULL} 290 }; 291 292 void ceph_destroy_options(struct ceph_options *opt) 293 { 294 dout("destroy_options %p\n", opt); 295 kfree(opt->name); 296 if (opt->key) { 297 ceph_crypto_key_destroy(opt->key); 298 kfree(opt->key); 299 } 300 kfree(opt->mon_addr); 301 kfree(opt); 302 } 303 EXPORT_SYMBOL(ceph_destroy_options); 304 305 /* get secret from key store */ 306 static int get_secret(struct ceph_crypto_key *dst, const char *name) { 307 struct key *ukey; 308 int key_err; 309 int err = 0; 310 struct ceph_crypto_key *ckey; 311 312 ukey = request_key(&key_type_ceph, name, NULL); 313 if (!ukey || IS_ERR(ukey)) { 314 /* request_key errors don't map nicely to mount(2) 315 errors; don't even try, but still printk */ 316 key_err = PTR_ERR(ukey); 317 switch (key_err) { 318 case -ENOKEY: 319 pr_warn("ceph: Mount failed due to key not found: %s\n", 320 name); 321 break; 322 case -EKEYEXPIRED: 323 pr_warn("ceph: Mount failed due to expired key: %s\n", 324 name); 325 break; 326 case -EKEYREVOKED: 327 pr_warn("ceph: Mount failed due to revoked key: %s\n", 328 name); 329 break; 330 default: 331 pr_warn("ceph: Mount failed due to unknown key error %d: %s\n", 332 key_err, name); 333 } 334 err = -EPERM; 335 goto out; 336 } 337 338 ckey = ukey->payload.data[0]; 339 err = ceph_crypto_key_clone(dst, ckey); 340 if (err) 341 goto out_key; 342 /* pass through, err is 0 */ 343 344 out_key: 345 key_put(ukey); 346 out: 347 return err; 348 } 349 350 struct ceph_options * 351 ceph_parse_options(char *options, const char *dev_name, 352 const char *dev_name_end, 353 int (*parse_extra_token)(char *c, void *private), 354 void *private) 355 { 356 struct ceph_options *opt; 357 const char *c; 358 int err = -ENOMEM; 359 substring_t argstr[MAX_OPT_ARGS]; 360 361 opt = kzalloc(sizeof(*opt), GFP_KERNEL); 362 if (!opt) 363 return ERR_PTR(-ENOMEM); 364 opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr), 365 GFP_KERNEL); 366 if (!opt->mon_addr) 367 goto out; 368 369 dout("parse_options %p options '%s' dev_name '%s'\n", opt, options, 370 dev_name); 371 372 /* start with defaults */ 373 opt->flags = CEPH_OPT_DEFAULT; 374 opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; 375 opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; 376 opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; 377 opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT; 378 379 /* get mon ip(s) */ 380 /* ip1[:port1][,ip2[:port2]...] */ 381 err = ceph_parse_ips(dev_name, dev_name_end, opt->mon_addr, 382 CEPH_MAX_MON, &opt->num_mon); 383 if (err < 0) 384 goto out; 385 386 /* parse mount options */ 387 while ((c = strsep(&options, ",")) != NULL) { 388 int token, intval, ret; 389 if (!*c) 390 continue; 391 err = -EINVAL; 392 token = match_token((char *)c, opt_tokens, argstr); 393 if (token < 0 && parse_extra_token) { 394 /* extra? */ 395 err = parse_extra_token((char *)c, private); 396 if (err < 0) { 397 pr_err("bad option at '%s'\n", c); 398 goto out; 399 } 400 continue; 401 } 402 if (token < Opt_last_int) { 403 ret = match_int(&argstr[0], &intval); 404 if (ret < 0) { 405 pr_err("bad mount option arg (not int) " 406 "at '%s'\n", c); 407 continue; 408 } 409 dout("got int token %d val %d\n", token, intval); 410 } else if (token > Opt_last_int && token < Opt_last_string) { 411 dout("got string token %d val %s\n", token, 412 argstr[0].from); 413 } else { 414 dout("got token %d\n", token); 415 } 416 switch (token) { 417 case Opt_ip: 418 err = ceph_parse_ips(argstr[0].from, 419 argstr[0].to, 420 &opt->my_addr, 421 1, NULL); 422 if (err < 0) 423 goto out; 424 opt->flags |= CEPH_OPT_MYIP; 425 break; 426 427 case Opt_fsid: 428 err = parse_fsid(argstr[0].from, &opt->fsid); 429 if (err == 0) 430 opt->flags |= CEPH_OPT_FSID; 431 break; 432 case Opt_name: 433 opt->name = kstrndup(argstr[0].from, 434 argstr[0].to-argstr[0].from, 435 GFP_KERNEL); 436 break; 437 case Opt_secret: 438 opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); 439 if (!opt->key) { 440 err = -ENOMEM; 441 goto out; 442 } 443 err = ceph_crypto_key_unarmor(opt->key, argstr[0].from); 444 if (err < 0) 445 goto out; 446 break; 447 case Opt_key: 448 opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); 449 if (!opt->key) { 450 err = -ENOMEM; 451 goto out; 452 } 453 err = get_secret(opt->key, argstr[0].from); 454 if (err < 0) 455 goto out; 456 break; 457 458 /* misc */ 459 case Opt_osdtimeout: 460 pr_warn("ignoring deprecated osdtimeout option\n"); 461 break; 462 case Opt_osdkeepalivetimeout: 463 /* 0 isn't well defined right now, reject it */ 464 if (intval < 1 || intval > INT_MAX / 1000) { 465 pr_err("osdkeepalive out of range\n"); 466 err = -EINVAL; 467 goto out; 468 } 469 opt->osd_keepalive_timeout = 470 msecs_to_jiffies(intval * 1000); 471 break; 472 case Opt_osd_idle_ttl: 473 /* 0 isn't well defined right now, reject it */ 474 if (intval < 1 || intval > INT_MAX / 1000) { 475 pr_err("osd_idle_ttl out of range\n"); 476 err = -EINVAL; 477 goto out; 478 } 479 opt->osd_idle_ttl = msecs_to_jiffies(intval * 1000); 480 break; 481 case Opt_mount_timeout: 482 /* 0 is "wait forever" (i.e. infinite timeout) */ 483 if (intval < 0 || intval > INT_MAX / 1000) { 484 pr_err("mount_timeout out of range\n"); 485 err = -EINVAL; 486 goto out; 487 } 488 opt->mount_timeout = msecs_to_jiffies(intval * 1000); 489 break; 490 case Opt_osd_request_timeout: 491 /* 0 is "wait forever" (i.e. infinite timeout) */ 492 if (intval < 0 || intval > INT_MAX / 1000) { 493 pr_err("osd_request_timeout out of range\n"); 494 err = -EINVAL; 495 goto out; 496 } 497 opt->osd_request_timeout = msecs_to_jiffies(intval * 1000); 498 break; 499 500 case Opt_share: 501 opt->flags &= ~CEPH_OPT_NOSHARE; 502 break; 503 case Opt_noshare: 504 opt->flags |= CEPH_OPT_NOSHARE; 505 break; 506 507 case Opt_crc: 508 opt->flags &= ~CEPH_OPT_NOCRC; 509 break; 510 case Opt_nocrc: 511 opt->flags |= CEPH_OPT_NOCRC; 512 break; 513 514 case Opt_cephx_require_signatures: 515 opt->flags &= ~CEPH_OPT_NOMSGAUTH; 516 break; 517 case Opt_nocephx_require_signatures: 518 opt->flags |= CEPH_OPT_NOMSGAUTH; 519 break; 520 case Opt_cephx_sign_messages: 521 opt->flags &= ~CEPH_OPT_NOMSGSIGN; 522 break; 523 case Opt_nocephx_sign_messages: 524 opt->flags |= CEPH_OPT_NOMSGSIGN; 525 break; 526 527 case Opt_tcp_nodelay: 528 opt->flags |= CEPH_OPT_TCP_NODELAY; 529 break; 530 case Opt_notcp_nodelay: 531 opt->flags &= ~CEPH_OPT_TCP_NODELAY; 532 break; 533 534 default: 535 BUG_ON(token); 536 } 537 } 538 539 /* success */ 540 return opt; 541 542 out: 543 ceph_destroy_options(opt); 544 return ERR_PTR(err); 545 } 546 EXPORT_SYMBOL(ceph_parse_options); 547 548 int ceph_print_client_options(struct seq_file *m, struct ceph_client *client) 549 { 550 struct ceph_options *opt = client->options; 551 size_t pos = m->count; 552 553 if (opt->name) { 554 seq_puts(m, "name="); 555 seq_escape(m, opt->name, ", \t\n\\"); 556 seq_putc(m, ','); 557 } 558 if (opt->key) 559 seq_puts(m, "secret=<hidden>,"); 560 561 if (opt->flags & CEPH_OPT_FSID) 562 seq_printf(m, "fsid=%pU,", &opt->fsid); 563 if (opt->flags & CEPH_OPT_NOSHARE) 564 seq_puts(m, "noshare,"); 565 if (opt->flags & CEPH_OPT_NOCRC) 566 seq_puts(m, "nocrc,"); 567 if (opt->flags & CEPH_OPT_NOMSGAUTH) 568 seq_puts(m, "nocephx_require_signatures,"); 569 if (opt->flags & CEPH_OPT_NOMSGSIGN) 570 seq_puts(m, "nocephx_sign_messages,"); 571 if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0) 572 seq_puts(m, "notcp_nodelay,"); 573 574 if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT) 575 seq_printf(m, "mount_timeout=%d,", 576 jiffies_to_msecs(opt->mount_timeout) / 1000); 577 if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT) 578 seq_printf(m, "osd_idle_ttl=%d,", 579 jiffies_to_msecs(opt->osd_idle_ttl) / 1000); 580 if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT) 581 seq_printf(m, "osdkeepalivetimeout=%d,", 582 jiffies_to_msecs(opt->osd_keepalive_timeout) / 1000); 583 if (opt->osd_request_timeout != CEPH_OSD_REQUEST_TIMEOUT_DEFAULT) 584 seq_printf(m, "osd_request_timeout=%d,", 585 jiffies_to_msecs(opt->osd_request_timeout) / 1000); 586 587 /* drop redundant comma */ 588 if (m->count != pos) 589 m->count--; 590 591 return 0; 592 } 593 EXPORT_SYMBOL(ceph_print_client_options); 594 595 struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client) 596 { 597 return &client->msgr.inst.addr; 598 } 599 EXPORT_SYMBOL(ceph_client_addr); 600 601 u64 ceph_client_gid(struct ceph_client *client) 602 { 603 return client->monc.auth->global_id; 604 } 605 EXPORT_SYMBOL(ceph_client_gid); 606 607 /* 608 * create a fresh client instance 609 */ 610 struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private) 611 { 612 struct ceph_client *client; 613 struct ceph_entity_addr *myaddr = NULL; 614 int err = -ENOMEM; 615 616 client = kzalloc(sizeof(*client), GFP_KERNEL); 617 if (client == NULL) 618 return ERR_PTR(-ENOMEM); 619 620 client->private = private; 621 client->options = opt; 622 623 mutex_init(&client->mount_mutex); 624 init_waitqueue_head(&client->auth_wq); 625 client->auth_err = 0; 626 627 client->extra_mon_dispatch = NULL; 628 client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT; 629 client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT; 630 631 if (!ceph_test_opt(client, NOMSGAUTH)) 632 client->required_features |= CEPH_FEATURE_MSG_AUTH; 633 634 /* msgr */ 635 if (ceph_test_opt(client, MYIP)) 636 myaddr = &client->options->my_addr; 637 638 ceph_messenger_init(&client->msgr, myaddr); 639 640 /* subsystems */ 641 err = ceph_monc_init(&client->monc, client); 642 if (err < 0) 643 goto fail; 644 err = ceph_osdc_init(&client->osdc, client); 645 if (err < 0) 646 goto fail_monc; 647 648 return client; 649 650 fail_monc: 651 ceph_monc_stop(&client->monc); 652 fail: 653 ceph_messenger_fini(&client->msgr); 654 kfree(client); 655 return ERR_PTR(err); 656 } 657 EXPORT_SYMBOL(ceph_create_client); 658 659 void ceph_destroy_client(struct ceph_client *client) 660 { 661 dout("destroy_client %p\n", client); 662 663 atomic_set(&client->msgr.stopping, 1); 664 665 /* unmount */ 666 ceph_osdc_stop(&client->osdc); 667 ceph_monc_stop(&client->monc); 668 ceph_messenger_fini(&client->msgr); 669 670 ceph_debugfs_client_cleanup(client); 671 672 ceph_destroy_options(client->options); 673 674 kfree(client); 675 dout("destroy_client %p done\n", client); 676 } 677 EXPORT_SYMBOL(ceph_destroy_client); 678 679 /* 680 * true if we have the mon map (and have thus joined the cluster) 681 */ 682 static bool have_mon_and_osd_map(struct ceph_client *client) 683 { 684 return client->monc.monmap && client->monc.monmap->epoch && 685 client->osdc.osdmap && client->osdc.osdmap->epoch; 686 } 687 688 /* 689 * mount: join the ceph cluster, and open root directory. 690 */ 691 int __ceph_open_session(struct ceph_client *client, unsigned long started) 692 { 693 unsigned long timeout = client->options->mount_timeout; 694 long err; 695 696 /* open session, and wait for mon and osd maps */ 697 err = ceph_monc_open_session(&client->monc); 698 if (err < 0) 699 return err; 700 701 while (!have_mon_and_osd_map(client)) { 702 if (timeout && time_after_eq(jiffies, started + timeout)) 703 return -ETIMEDOUT; 704 705 /* wait */ 706 dout("mount waiting for mon_map\n"); 707 err = wait_event_interruptible_timeout(client->auth_wq, 708 have_mon_and_osd_map(client) || (client->auth_err < 0), 709 ceph_timeout_jiffies(timeout)); 710 if (err < 0) 711 return err; 712 if (client->auth_err < 0) 713 return client->auth_err; 714 } 715 716 pr_info("client%llu fsid %pU\n", ceph_client_gid(client), 717 &client->fsid); 718 ceph_debugfs_client_init(client); 719 720 return 0; 721 } 722 EXPORT_SYMBOL(__ceph_open_session); 723 724 725 int ceph_open_session(struct ceph_client *client) 726 { 727 int ret; 728 unsigned long started = jiffies; /* note the start time */ 729 730 dout("open_session start\n"); 731 mutex_lock(&client->mount_mutex); 732 733 ret = __ceph_open_session(client, started); 734 735 mutex_unlock(&client->mount_mutex); 736 return ret; 737 } 738 EXPORT_SYMBOL(ceph_open_session); 739 740 741 static int __init init_ceph_lib(void) 742 { 743 int ret = 0; 744 745 ret = ceph_debugfs_init(); 746 if (ret < 0) 747 goto out; 748 749 ret = ceph_crypto_init(); 750 if (ret < 0) 751 goto out_debugfs; 752 753 ret = ceph_msgr_init(); 754 if (ret < 0) 755 goto out_crypto; 756 757 ret = ceph_osdc_setup(); 758 if (ret < 0) 759 goto out_msgr; 760 761 pr_info("loaded (mon/osd proto %d/%d)\n", 762 CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL); 763 764 return 0; 765 766 out_msgr: 767 ceph_msgr_exit(); 768 out_crypto: 769 ceph_crypto_shutdown(); 770 out_debugfs: 771 ceph_debugfs_cleanup(); 772 out: 773 return ret; 774 } 775 776 static void __exit exit_ceph_lib(void) 777 { 778 dout("exit_ceph_lib\n"); 779 WARN_ON(!ceph_strings_empty()); 780 781 ceph_osdc_cleanup(); 782 ceph_msgr_exit(); 783 ceph_crypto_shutdown(); 784 ceph_debugfs_cleanup(); 785 } 786 787 module_init(init_ceph_lib); 788 module_exit(exit_ceph_lib); 789 790 MODULE_AUTHOR("Sage Weil <sage@newdream.net>"); 791 MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>"); 792 MODULE_AUTHOR("Patience Warnick <patience@newdream.net>"); 793 MODULE_DESCRIPTION("Ceph core library"); 794 MODULE_LICENSE("GPL"); 795