0001
0002
0003 #include <linux/ceph/ceph_debug.h>
0004 #include <linux/backing-dev.h>
0005 #include <linux/ctype.h>
0006 #include <linux/fs.h>
0007 #include <linux/inet.h>
0008 #include <linux/in6.h>
0009 #include <linux/key.h>
0010 #include <keys/ceph-type.h>
0011 #include <linux/module.h>
0012 #include <linux/mount.h>
0013 #include <linux/nsproxy.h>
0014 #include <linux/fs_parser.h>
0015 #include <linux/sched.h>
0016 #include <linux/sched/mm.h>
0017 #include <linux/seq_file.h>
0018 #include <linux/slab.h>
0019 #include <linux/statfs.h>
0020 #include <linux/string.h>
0021 #include <linux/vmalloc.h>
0022
0023
0024 #include <linux/ceph/ceph_features.h>
0025 #include <linux/ceph/libceph.h>
0026 #include <linux/ceph/debugfs.h>
0027 #include <linux/ceph/decode.h>
0028 #include <linux/ceph/mon_client.h>
0029 #include <linux/ceph/auth.h>
0030 #include "crypto.h"
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 bool libceph_compatible(void *data)
0045 {
0046 return true;
0047 }
0048 EXPORT_SYMBOL(libceph_compatible);
0049
0050 static int param_get_supported_features(char *buffer,
0051 const struct kernel_param *kp)
0052 {
0053 return sprintf(buffer, "0x%llx", CEPH_FEATURES_SUPPORTED_DEFAULT);
0054 }
0055 static const struct kernel_param_ops param_ops_supported_features = {
0056 .get = param_get_supported_features,
0057 };
0058 module_param_cb(supported_features, ¶m_ops_supported_features, NULL,
0059 0444);
0060
0061 const char *ceph_msg_type_name(int type)
0062 {
0063 switch (type) {
0064 case CEPH_MSG_SHUTDOWN: return "shutdown";
0065 case CEPH_MSG_PING: return "ping";
0066 case CEPH_MSG_AUTH: return "auth";
0067 case CEPH_MSG_AUTH_REPLY: return "auth_reply";
0068 case CEPH_MSG_MON_MAP: return "mon_map";
0069 case CEPH_MSG_MON_GET_MAP: return "mon_get_map";
0070 case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe";
0071 case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack";
0072 case CEPH_MSG_STATFS: return "statfs";
0073 case CEPH_MSG_STATFS_REPLY: return "statfs_reply";
0074 case CEPH_MSG_MON_GET_VERSION: return "mon_get_version";
0075 case CEPH_MSG_MON_GET_VERSION_REPLY: return "mon_get_version_reply";
0076 case CEPH_MSG_MDS_MAP: return "mds_map";
0077 case CEPH_MSG_FS_MAP_USER: return "fs_map_user";
0078 case CEPH_MSG_CLIENT_SESSION: return "client_session";
0079 case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect";
0080 case CEPH_MSG_CLIENT_REQUEST: return "client_request";
0081 case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward";
0082 case CEPH_MSG_CLIENT_REPLY: return "client_reply";
0083 case CEPH_MSG_CLIENT_CAPS: return "client_caps";
0084 case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release";
0085 case CEPH_MSG_CLIENT_QUOTA: return "client_quota";
0086 case CEPH_MSG_CLIENT_SNAP: return "client_snap";
0087 case CEPH_MSG_CLIENT_LEASE: return "client_lease";
0088 case CEPH_MSG_POOLOP_REPLY: return "poolop_reply";
0089 case CEPH_MSG_POOLOP: return "poolop";
0090 case CEPH_MSG_MON_COMMAND: return "mon_command";
0091 case CEPH_MSG_MON_COMMAND_ACK: return "mon_command_ack";
0092 case CEPH_MSG_OSD_MAP: return "osd_map";
0093 case CEPH_MSG_OSD_OP: return "osd_op";
0094 case CEPH_MSG_OSD_OPREPLY: return "osd_opreply";
0095 case CEPH_MSG_WATCH_NOTIFY: return "watch_notify";
0096 case CEPH_MSG_OSD_BACKOFF: return "osd_backoff";
0097 default: return "unknown";
0098 }
0099 }
0100 EXPORT_SYMBOL(ceph_msg_type_name);
0101
0102
0103
0104
0105 int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
0106 {
0107 if (client->have_fsid) {
0108 if (ceph_fsid_compare(&client->fsid, fsid)) {
0109 pr_err("bad fsid, had %pU got %pU",
0110 &client->fsid, fsid);
0111 return -1;
0112 }
0113 } else {
0114 memcpy(&client->fsid, fsid, sizeof(*fsid));
0115 }
0116 return 0;
0117 }
0118 EXPORT_SYMBOL(ceph_check_fsid);
0119
0120 static int strcmp_null(const char *s1, const char *s2)
0121 {
0122 if (!s1 && !s2)
0123 return 0;
0124 if (s1 && !s2)
0125 return -1;
0126 if (!s1 && s2)
0127 return 1;
0128 return strcmp(s1, s2);
0129 }
0130
0131 int ceph_compare_options(struct ceph_options *new_opt,
0132 struct ceph_client *client)
0133 {
0134 struct ceph_options *opt1 = new_opt;
0135 struct ceph_options *opt2 = client->options;
0136 int ofs = offsetof(struct ceph_options, mon_addr);
0137 int i;
0138 int ret;
0139
0140
0141
0142
0143
0144 if (!net_eq(current->nsproxy->net_ns, read_pnet(&client->msgr.net)))
0145 return -1;
0146
0147 ret = memcmp(opt1, opt2, ofs);
0148 if (ret)
0149 return ret;
0150
0151 ret = strcmp_null(opt1->name, opt2->name);
0152 if (ret)
0153 return ret;
0154
0155 if (opt1->key && !opt2->key)
0156 return -1;
0157 if (!opt1->key && opt2->key)
0158 return 1;
0159 if (opt1->key && opt2->key) {
0160 if (opt1->key->type != opt2->key->type)
0161 return -1;
0162 if (opt1->key->created.tv_sec != opt2->key->created.tv_sec)
0163 return -1;
0164 if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec)
0165 return -1;
0166 if (opt1->key->len != opt2->key->len)
0167 return -1;
0168 if (opt1->key->key && !opt2->key->key)
0169 return -1;
0170 if (!opt1->key->key && opt2->key->key)
0171 return 1;
0172 if (opt1->key->key && opt2->key->key) {
0173 ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len);
0174 if (ret)
0175 return ret;
0176 }
0177 }
0178
0179 ret = ceph_compare_crush_locs(&opt1->crush_locs, &opt2->crush_locs);
0180 if (ret)
0181 return ret;
0182
0183
0184 for (i = 0; i < opt1->num_mon; i++) {
0185 if (ceph_monmap_contains(client->monc.monmap,
0186 &opt1->mon_addr[i]))
0187 return 0;
0188 }
0189 return -1;
0190 }
0191 EXPORT_SYMBOL(ceph_compare_options);
0192
0193 int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid)
0194 {
0195 int i = 0;
0196 char tmp[3];
0197 int err = -EINVAL;
0198 int d;
0199
0200 dout("%s '%s'\n", __func__, str);
0201 tmp[2] = 0;
0202 while (*str && i < 16) {
0203 if (ispunct(*str)) {
0204 str++;
0205 continue;
0206 }
0207 if (!isxdigit(str[0]) || !isxdigit(str[1]))
0208 break;
0209 tmp[0] = str[0];
0210 tmp[1] = str[1];
0211 if (sscanf(tmp, "%x", &d) < 1)
0212 break;
0213 fsid->fsid[i] = d & 0xff;
0214 i++;
0215 str += 2;
0216 }
0217
0218 if (i == 16)
0219 err = 0;
0220 dout("%s ret %d got fsid %pU\n", __func__, err, fsid);
0221 return err;
0222 }
0223 EXPORT_SYMBOL(ceph_parse_fsid);
0224
0225
0226
0227
0228 enum {
0229 Opt_osdkeepalivetimeout,
0230 Opt_mount_timeout,
0231 Opt_osd_idle_ttl,
0232 Opt_osd_request_timeout,
0233
0234 Opt_fsid,
0235 Opt_name,
0236 Opt_secret,
0237 Opt_key,
0238 Opt_ip,
0239 Opt_crush_location,
0240 Opt_read_from_replica,
0241 Opt_ms_mode,
0242
0243 Opt_share,
0244 Opt_crc,
0245 Opt_cephx_require_signatures,
0246 Opt_cephx_sign_messages,
0247 Opt_tcp_nodelay,
0248 Opt_abort_on_full,
0249 Opt_rxbounce,
0250 };
0251
0252 enum {
0253 Opt_read_from_replica_no,
0254 Opt_read_from_replica_balance,
0255 Opt_read_from_replica_localize,
0256 };
0257
0258 static const struct constant_table ceph_param_read_from_replica[] = {
0259 {"no", Opt_read_from_replica_no},
0260 {"balance", Opt_read_from_replica_balance},
0261 {"localize", Opt_read_from_replica_localize},
0262 {}
0263 };
0264
0265 enum ceph_ms_mode {
0266 Opt_ms_mode_legacy,
0267 Opt_ms_mode_crc,
0268 Opt_ms_mode_secure,
0269 Opt_ms_mode_prefer_crc,
0270 Opt_ms_mode_prefer_secure
0271 };
0272
0273 static const struct constant_table ceph_param_ms_mode[] = {
0274 {"legacy", Opt_ms_mode_legacy},
0275 {"crc", Opt_ms_mode_crc},
0276 {"secure", Opt_ms_mode_secure},
0277 {"prefer-crc", Opt_ms_mode_prefer_crc},
0278 {"prefer-secure", Opt_ms_mode_prefer_secure},
0279 {}
0280 };
0281
0282 static const struct fs_parameter_spec ceph_parameters[] = {
0283 fsparam_flag ("abort_on_full", Opt_abort_on_full),
0284 __fsparam (NULL, "cephx_require_signatures", Opt_cephx_require_signatures,
0285 fs_param_neg_with_no|fs_param_deprecated, NULL),
0286 fsparam_flag_no ("cephx_sign_messages", Opt_cephx_sign_messages),
0287 fsparam_flag_no ("crc", Opt_crc),
0288 fsparam_string ("crush_location", Opt_crush_location),
0289 fsparam_string ("fsid", Opt_fsid),
0290 fsparam_string ("ip", Opt_ip),
0291 fsparam_string ("key", Opt_key),
0292 fsparam_u32 ("mount_timeout", Opt_mount_timeout),
0293 fsparam_string ("name", Opt_name),
0294 fsparam_u32 ("osd_idle_ttl", Opt_osd_idle_ttl),
0295 fsparam_u32 ("osd_request_timeout", Opt_osd_request_timeout),
0296 fsparam_u32 ("osdkeepalive", Opt_osdkeepalivetimeout),
0297 fsparam_enum ("read_from_replica", Opt_read_from_replica,
0298 ceph_param_read_from_replica),
0299 fsparam_flag ("rxbounce", Opt_rxbounce),
0300 fsparam_enum ("ms_mode", Opt_ms_mode,
0301 ceph_param_ms_mode),
0302 fsparam_string ("secret", Opt_secret),
0303 fsparam_flag_no ("share", Opt_share),
0304 fsparam_flag_no ("tcp_nodelay", Opt_tcp_nodelay),
0305 {}
0306 };
0307
0308 struct ceph_options *ceph_alloc_options(void)
0309 {
0310 struct ceph_options *opt;
0311
0312 opt = kzalloc(sizeof(*opt), GFP_KERNEL);
0313 if (!opt)
0314 return NULL;
0315
0316 opt->crush_locs = RB_ROOT;
0317 opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr),
0318 GFP_KERNEL);
0319 if (!opt->mon_addr) {
0320 kfree(opt);
0321 return NULL;
0322 }
0323
0324 opt->flags = CEPH_OPT_DEFAULT;
0325 opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
0326 opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT;
0327 opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;
0328 opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT;
0329 opt->read_from_replica = CEPH_READ_FROM_REPLICA_DEFAULT;
0330 opt->con_modes[0] = CEPH_CON_MODE_UNKNOWN;
0331 opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
0332 return opt;
0333 }
0334 EXPORT_SYMBOL(ceph_alloc_options);
0335
0336 void ceph_destroy_options(struct ceph_options *opt)
0337 {
0338 dout("destroy_options %p\n", opt);
0339 if (!opt)
0340 return;
0341
0342 ceph_clear_crush_locs(&opt->crush_locs);
0343 kfree(opt->name);
0344 if (opt->key) {
0345 ceph_crypto_key_destroy(opt->key);
0346 kfree(opt->key);
0347 }
0348 kfree(opt->mon_addr);
0349 kfree(opt);
0350 }
0351 EXPORT_SYMBOL(ceph_destroy_options);
0352
0353
0354 static int get_secret(struct ceph_crypto_key *dst, const char *name,
0355 struct p_log *log)
0356 {
0357 struct key *ukey;
0358 int key_err;
0359 int err = 0;
0360 struct ceph_crypto_key *ckey;
0361
0362 ukey = request_key(&key_type_ceph, name, NULL);
0363 if (IS_ERR(ukey)) {
0364
0365
0366 key_err = PTR_ERR(ukey);
0367 switch (key_err) {
0368 case -ENOKEY:
0369 error_plog(log, "Failed due to key not found: %s",
0370 name);
0371 break;
0372 case -EKEYEXPIRED:
0373 error_plog(log, "Failed due to expired key: %s",
0374 name);
0375 break;
0376 case -EKEYREVOKED:
0377 error_plog(log, "Failed due to revoked key: %s",
0378 name);
0379 break;
0380 default:
0381 error_plog(log, "Failed due to key error %d: %s",
0382 key_err, name);
0383 }
0384 err = -EPERM;
0385 goto out;
0386 }
0387
0388 ckey = ukey->payload.data[0];
0389 err = ceph_crypto_key_clone(dst, ckey);
0390 if (err)
0391 goto out_key;
0392
0393
0394 out_key:
0395 key_put(ukey);
0396 out:
0397 return err;
0398 }
0399
0400 int ceph_parse_mon_ips(const char *buf, size_t len, struct ceph_options *opt,
0401 struct fc_log *l, char delim)
0402 {
0403 struct p_log log = {.prefix = "libceph", .log = l};
0404 int ret;
0405
0406
0407 ret = ceph_parse_ips(buf, buf + len, opt->mon_addr, CEPH_MAX_MON,
0408 &opt->num_mon, delim);
0409 if (ret) {
0410 error_plog(&log, "Failed to parse monitor IPs: %d", ret);
0411 return ret;
0412 }
0413
0414 return 0;
0415 }
0416 EXPORT_SYMBOL(ceph_parse_mon_ips);
0417
0418 int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
0419 struct fc_log *l)
0420 {
0421 struct fs_parse_result result;
0422 int token, err;
0423 struct p_log log = {.prefix = "libceph", .log = l};
0424
0425 token = __fs_parse(&log, ceph_parameters, param, &result);
0426 dout("%s fs_parse '%s' token %d\n", __func__, param->key, token);
0427 if (token < 0)
0428 return token;
0429
0430 switch (token) {
0431 case Opt_ip:
0432 err = ceph_parse_ips(param->string,
0433 param->string + param->size,
0434 &opt->my_addr, 1, NULL, ',');
0435 if (err) {
0436 error_plog(&log, "Failed to parse ip: %d", err);
0437 return err;
0438 }
0439 opt->flags |= CEPH_OPT_MYIP;
0440 break;
0441
0442 case Opt_fsid:
0443 err = ceph_parse_fsid(param->string, &opt->fsid);
0444 if (err) {
0445 error_plog(&log, "Failed to parse fsid: %d", err);
0446 return err;
0447 }
0448 opt->flags |= CEPH_OPT_FSID;
0449 break;
0450 case Opt_name:
0451 kfree(opt->name);
0452 opt->name = param->string;
0453 param->string = NULL;
0454 break;
0455 case Opt_secret:
0456 ceph_crypto_key_destroy(opt->key);
0457 kfree(opt->key);
0458
0459 opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
0460 if (!opt->key)
0461 return -ENOMEM;
0462 err = ceph_crypto_key_unarmor(opt->key, param->string);
0463 if (err) {
0464 error_plog(&log, "Failed to parse secret: %d", err);
0465 return err;
0466 }
0467 break;
0468 case Opt_key:
0469 ceph_crypto_key_destroy(opt->key);
0470 kfree(opt->key);
0471
0472 opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
0473 if (!opt->key)
0474 return -ENOMEM;
0475 return get_secret(opt->key, param->string, &log);
0476 case Opt_crush_location:
0477 ceph_clear_crush_locs(&opt->crush_locs);
0478 err = ceph_parse_crush_location(param->string,
0479 &opt->crush_locs);
0480 if (err) {
0481 error_plog(&log, "Failed to parse CRUSH location: %d",
0482 err);
0483 return err;
0484 }
0485 break;
0486 case Opt_read_from_replica:
0487 switch (result.uint_32) {
0488 case Opt_read_from_replica_no:
0489 opt->read_from_replica = 0;
0490 break;
0491 case Opt_read_from_replica_balance:
0492 opt->read_from_replica = CEPH_OSD_FLAG_BALANCE_READS;
0493 break;
0494 case Opt_read_from_replica_localize:
0495 opt->read_from_replica = CEPH_OSD_FLAG_LOCALIZE_READS;
0496 break;
0497 default:
0498 BUG();
0499 }
0500 break;
0501 case Opt_ms_mode:
0502 switch (result.uint_32) {
0503 case Opt_ms_mode_legacy:
0504 opt->con_modes[0] = CEPH_CON_MODE_UNKNOWN;
0505 opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
0506 break;
0507 case Opt_ms_mode_crc:
0508 opt->con_modes[0] = CEPH_CON_MODE_CRC;
0509 opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
0510 break;
0511 case Opt_ms_mode_secure:
0512 opt->con_modes[0] = CEPH_CON_MODE_SECURE;
0513 opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
0514 break;
0515 case Opt_ms_mode_prefer_crc:
0516 opt->con_modes[0] = CEPH_CON_MODE_CRC;
0517 opt->con_modes[1] = CEPH_CON_MODE_SECURE;
0518 break;
0519 case Opt_ms_mode_prefer_secure:
0520 opt->con_modes[0] = CEPH_CON_MODE_SECURE;
0521 opt->con_modes[1] = CEPH_CON_MODE_CRC;
0522 break;
0523 default:
0524 BUG();
0525 }
0526 break;
0527
0528 case Opt_osdkeepalivetimeout:
0529
0530 if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000)
0531 goto out_of_range;
0532 opt->osd_keepalive_timeout =
0533 msecs_to_jiffies(result.uint_32 * 1000);
0534 break;
0535 case Opt_osd_idle_ttl:
0536
0537 if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000)
0538 goto out_of_range;
0539 opt->osd_idle_ttl = msecs_to_jiffies(result.uint_32 * 1000);
0540 break;
0541 case Opt_mount_timeout:
0542
0543 if (result.uint_32 > INT_MAX / 1000)
0544 goto out_of_range;
0545 opt->mount_timeout = msecs_to_jiffies(result.uint_32 * 1000);
0546 break;
0547 case Opt_osd_request_timeout:
0548
0549 if (result.uint_32 > INT_MAX / 1000)
0550 goto out_of_range;
0551 opt->osd_request_timeout =
0552 msecs_to_jiffies(result.uint_32 * 1000);
0553 break;
0554
0555 case Opt_share:
0556 if (!result.negated)
0557 opt->flags &= ~CEPH_OPT_NOSHARE;
0558 else
0559 opt->flags |= CEPH_OPT_NOSHARE;
0560 break;
0561 case Opt_crc:
0562 if (!result.negated)
0563 opt->flags &= ~CEPH_OPT_NOCRC;
0564 else
0565 opt->flags |= CEPH_OPT_NOCRC;
0566 break;
0567 case Opt_cephx_require_signatures:
0568 if (!result.negated)
0569 warn_plog(&log, "Ignoring cephx_require_signatures");
0570 else
0571 warn_plog(&log, "Ignoring nocephx_require_signatures, use nocephx_sign_messages");
0572 break;
0573 case Opt_cephx_sign_messages:
0574 if (!result.negated)
0575 opt->flags &= ~CEPH_OPT_NOMSGSIGN;
0576 else
0577 opt->flags |= CEPH_OPT_NOMSGSIGN;
0578 break;
0579 case Opt_tcp_nodelay:
0580 if (!result.negated)
0581 opt->flags |= CEPH_OPT_TCP_NODELAY;
0582 else
0583 opt->flags &= ~CEPH_OPT_TCP_NODELAY;
0584 break;
0585
0586 case Opt_abort_on_full:
0587 opt->flags |= CEPH_OPT_ABORT_ON_FULL;
0588 break;
0589 case Opt_rxbounce:
0590 opt->flags |= CEPH_OPT_RXBOUNCE;
0591 break;
0592
0593 default:
0594 BUG();
0595 }
0596
0597 return 0;
0598
0599 out_of_range:
0600 return inval_plog(&log, "%s out of range", param->key);
0601 }
0602 EXPORT_SYMBOL(ceph_parse_param);
0603
0604 int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
0605 bool show_all)
0606 {
0607 struct ceph_options *opt = client->options;
0608 size_t pos = m->count;
0609 struct rb_node *n;
0610
0611 if (opt->name) {
0612 seq_puts(m, "name=");
0613 seq_escape(m, opt->name, ", \t\n\\");
0614 seq_putc(m, ',');
0615 }
0616 if (opt->key)
0617 seq_puts(m, "secret=<hidden>,");
0618
0619 if (!RB_EMPTY_ROOT(&opt->crush_locs)) {
0620 seq_puts(m, "crush_location=");
0621 for (n = rb_first(&opt->crush_locs); ; ) {
0622 struct crush_loc_node *loc =
0623 rb_entry(n, struct crush_loc_node, cl_node);
0624
0625 seq_printf(m, "%s:%s", loc->cl_loc.cl_type_name,
0626 loc->cl_loc.cl_name);
0627 n = rb_next(n);
0628 if (!n)
0629 break;
0630
0631 seq_putc(m, '|');
0632 }
0633 seq_putc(m, ',');
0634 }
0635 if (opt->read_from_replica == CEPH_OSD_FLAG_BALANCE_READS) {
0636 seq_puts(m, "read_from_replica=balance,");
0637 } else if (opt->read_from_replica == CEPH_OSD_FLAG_LOCALIZE_READS) {
0638 seq_puts(m, "read_from_replica=localize,");
0639 }
0640 if (opt->con_modes[0] != CEPH_CON_MODE_UNKNOWN) {
0641 if (opt->con_modes[0] == CEPH_CON_MODE_CRC &&
0642 opt->con_modes[1] == CEPH_CON_MODE_UNKNOWN) {
0643 seq_puts(m, "ms_mode=crc,");
0644 } else if (opt->con_modes[0] == CEPH_CON_MODE_SECURE &&
0645 opt->con_modes[1] == CEPH_CON_MODE_UNKNOWN) {
0646 seq_puts(m, "ms_mode=secure,");
0647 } else if (opt->con_modes[0] == CEPH_CON_MODE_CRC &&
0648 opt->con_modes[1] == CEPH_CON_MODE_SECURE) {
0649 seq_puts(m, "ms_mode=prefer-crc,");
0650 } else if (opt->con_modes[0] == CEPH_CON_MODE_SECURE &&
0651 opt->con_modes[1] == CEPH_CON_MODE_CRC) {
0652 seq_puts(m, "ms_mode=prefer-secure,");
0653 }
0654 }
0655
0656 if (opt->flags & CEPH_OPT_FSID)
0657 seq_printf(m, "fsid=%pU,", &opt->fsid);
0658 if (opt->flags & CEPH_OPT_NOSHARE)
0659 seq_puts(m, "noshare,");
0660 if (opt->flags & CEPH_OPT_NOCRC)
0661 seq_puts(m, "nocrc,");
0662 if (opt->flags & CEPH_OPT_NOMSGSIGN)
0663 seq_puts(m, "nocephx_sign_messages,");
0664 if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
0665 seq_puts(m, "notcp_nodelay,");
0666 if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL))
0667 seq_puts(m, "abort_on_full,");
0668 if (opt->flags & CEPH_OPT_RXBOUNCE)
0669 seq_puts(m, "rxbounce,");
0670
0671 if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
0672 seq_printf(m, "mount_timeout=%d,",
0673 jiffies_to_msecs(opt->mount_timeout) / 1000);
0674 if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
0675 seq_printf(m, "osd_idle_ttl=%d,",
0676 jiffies_to_msecs(opt->osd_idle_ttl) / 1000);
0677 if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
0678 seq_printf(m, "osdkeepalivetimeout=%d,",
0679 jiffies_to_msecs(opt->osd_keepalive_timeout) / 1000);
0680 if (opt->osd_request_timeout != CEPH_OSD_REQUEST_TIMEOUT_DEFAULT)
0681 seq_printf(m, "osd_request_timeout=%d,",
0682 jiffies_to_msecs(opt->osd_request_timeout) / 1000);
0683
0684
0685 if (m->count != pos)
0686 m->count--;
0687
0688 return 0;
0689 }
0690 EXPORT_SYMBOL(ceph_print_client_options);
0691
0692 struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client)
0693 {
0694 return &client->msgr.inst.addr;
0695 }
0696 EXPORT_SYMBOL(ceph_client_addr);
0697
0698 u64 ceph_client_gid(struct ceph_client *client)
0699 {
0700 return client->monc.auth->global_id;
0701 }
0702 EXPORT_SYMBOL(ceph_client_gid);
0703
0704
0705
0706
0707 struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
0708 {
0709 struct ceph_client *client;
0710 struct ceph_entity_addr *myaddr = NULL;
0711 int err;
0712
0713 err = wait_for_random_bytes();
0714 if (err < 0)
0715 return ERR_PTR(err);
0716
0717 client = kzalloc(sizeof(*client), GFP_KERNEL);
0718 if (client == NULL)
0719 return ERR_PTR(-ENOMEM);
0720
0721 client->private = private;
0722 client->options = opt;
0723
0724 mutex_init(&client->mount_mutex);
0725 init_waitqueue_head(&client->auth_wq);
0726 client->auth_err = 0;
0727
0728 client->extra_mon_dispatch = NULL;
0729 client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT;
0730 client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT;
0731
0732 if (!ceph_test_opt(client, NOMSGSIGN))
0733 client->required_features |= CEPH_FEATURE_MSG_AUTH;
0734
0735
0736 if (ceph_test_opt(client, MYIP))
0737 myaddr = &client->options->my_addr;
0738
0739 ceph_messenger_init(&client->msgr, myaddr);
0740
0741
0742 err = ceph_monc_init(&client->monc, client);
0743 if (err < 0)
0744 goto fail;
0745 err = ceph_osdc_init(&client->osdc, client);
0746 if (err < 0)
0747 goto fail_monc;
0748
0749 return client;
0750
0751 fail_monc:
0752 ceph_monc_stop(&client->monc);
0753 fail:
0754 ceph_messenger_fini(&client->msgr);
0755 kfree(client);
0756 return ERR_PTR(err);
0757 }
0758 EXPORT_SYMBOL(ceph_create_client);
0759
0760 void ceph_destroy_client(struct ceph_client *client)
0761 {
0762 dout("destroy_client %p\n", client);
0763
0764 atomic_set(&client->msgr.stopping, 1);
0765
0766
0767 ceph_osdc_stop(&client->osdc);
0768 ceph_monc_stop(&client->monc);
0769 ceph_messenger_fini(&client->msgr);
0770
0771 ceph_debugfs_client_cleanup(client);
0772
0773 ceph_destroy_options(client->options);
0774
0775 kfree(client);
0776 dout("destroy_client %p done\n", client);
0777 }
0778 EXPORT_SYMBOL(ceph_destroy_client);
0779
0780 void ceph_reset_client_addr(struct ceph_client *client)
0781 {
0782 ceph_messenger_reset_nonce(&client->msgr);
0783 ceph_monc_reopen_session(&client->monc);
0784 ceph_osdc_reopen_osds(&client->osdc);
0785 }
0786 EXPORT_SYMBOL(ceph_reset_client_addr);
0787
0788
0789
0790
0791 static bool have_mon_and_osd_map(struct ceph_client *client)
0792 {
0793 return client->monc.monmap && client->monc.monmap->epoch &&
0794 client->osdc.osdmap && client->osdc.osdmap->epoch;
0795 }
0796
0797
0798
0799
0800 int __ceph_open_session(struct ceph_client *client, unsigned long started)
0801 {
0802 unsigned long timeout = client->options->mount_timeout;
0803 long err;
0804
0805
0806 err = ceph_monc_open_session(&client->monc);
0807 if (err < 0)
0808 return err;
0809
0810 while (!have_mon_and_osd_map(client)) {
0811 if (timeout && time_after_eq(jiffies, started + timeout))
0812 return -ETIMEDOUT;
0813
0814
0815 dout("mount waiting for mon_map\n");
0816 err = wait_event_interruptible_timeout(client->auth_wq,
0817 have_mon_and_osd_map(client) || (client->auth_err < 0),
0818 ceph_timeout_jiffies(timeout));
0819 if (err < 0)
0820 return err;
0821 if (client->auth_err < 0)
0822 return client->auth_err;
0823 }
0824
0825 pr_info("client%llu fsid %pU\n", ceph_client_gid(client),
0826 &client->fsid);
0827 ceph_debugfs_client_init(client);
0828
0829 return 0;
0830 }
0831 EXPORT_SYMBOL(__ceph_open_session);
0832
0833 int ceph_open_session(struct ceph_client *client)
0834 {
0835 int ret;
0836 unsigned long started = jiffies;
0837
0838 dout("open_session start\n");
0839 mutex_lock(&client->mount_mutex);
0840
0841 ret = __ceph_open_session(client, started);
0842
0843 mutex_unlock(&client->mount_mutex);
0844 return ret;
0845 }
0846 EXPORT_SYMBOL(ceph_open_session);
0847
0848 int ceph_wait_for_latest_osdmap(struct ceph_client *client,
0849 unsigned long timeout)
0850 {
0851 u64 newest_epoch;
0852 int ret;
0853
0854 ret = ceph_monc_get_version(&client->monc, "osdmap", &newest_epoch);
0855 if (ret)
0856 return ret;
0857
0858 if (client->osdc.osdmap->epoch >= newest_epoch)
0859 return 0;
0860
0861 ceph_osdc_maybe_request_map(&client->osdc);
0862 return ceph_monc_wait_osdmap(&client->monc, newest_epoch, timeout);
0863 }
0864 EXPORT_SYMBOL(ceph_wait_for_latest_osdmap);
0865
0866 static int __init init_ceph_lib(void)
0867 {
0868 int ret = 0;
0869
0870 ceph_debugfs_init();
0871
0872 ret = ceph_crypto_init();
0873 if (ret < 0)
0874 goto out_debugfs;
0875
0876 ret = ceph_msgr_init();
0877 if (ret < 0)
0878 goto out_crypto;
0879
0880 ret = ceph_osdc_setup();
0881 if (ret < 0)
0882 goto out_msgr;
0883
0884 pr_info("loaded (mon/osd proto %d/%d)\n",
0885 CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL);
0886
0887 return 0;
0888
0889 out_msgr:
0890 ceph_msgr_exit();
0891 out_crypto:
0892 ceph_crypto_shutdown();
0893 out_debugfs:
0894 ceph_debugfs_cleanup();
0895 return ret;
0896 }
0897
0898 static void __exit exit_ceph_lib(void)
0899 {
0900 dout("exit_ceph_lib\n");
0901 WARN_ON(!ceph_strings_empty());
0902
0903 ceph_osdc_cleanup();
0904 ceph_msgr_exit();
0905 ceph_crypto_shutdown();
0906 ceph_debugfs_cleanup();
0907 }
0908
0909 module_init(init_ceph_lib);
0910 module_exit(exit_ceph_lib);
0911
0912 MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
0913 MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
0914 MODULE_AUTHOR("Patience Warnick <patience@newdream.net>");
0915 MODULE_DESCRIPTION("Ceph core library");
0916 MODULE_LICENSE("GPL");