root/net/ceph/ceph_common.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. libceph_compatible
  2. param_get_supported_features
  3. ceph_msg_type_name
  4. ceph_check_fsid
  5. strcmp_null
  6. ceph_compare_options
  7. ceph_kvmalloc
  8. parse_fsid
  9. ceph_destroy_options
  10. get_secret
  11. ceph_parse_options
  12. ceph_print_client_options
  13. ceph_client_addr
  14. ceph_client_gid
  15. ceph_create_client
  16. ceph_destroy_client
  17. ceph_reset_client_addr
  18. have_mon_and_osd_map
  19. __ceph_open_session
  20. ceph_open_session
  21. ceph_wait_for_latest_osdmap
  22. init_ceph_lib
  23. exit_ceph_lib

   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/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, &param_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         /* any matching mon ip implies a match */
 180         for (i = 0; i < opt1->num_mon; i++) {
 181                 if (ceph_monmap_contains(client->monc.monmap,
 182                                  &opt1->mon_addr[i]))
 183                         return 0;
 184         }
 185         return -1;
 186 }
 187 EXPORT_SYMBOL(ceph_compare_options);
 188 
 189 /*
 190  * kvmalloc() doesn't fall back to the vmalloc allocator unless flags are
 191  * compatible with (a superset of) GFP_KERNEL.  This is because while the
 192  * actual pages are allocated with the specified flags, the page table pages
 193  * are always allocated with GFP_KERNEL.  map_vm_area() doesn't even take
 194  * flags because GFP_KERNEL is hard-coded in {p4d,pud,pmd,pte}_alloc().
 195  *
 196  * ceph_kvmalloc() may be called with GFP_KERNEL, GFP_NOFS or GFP_NOIO.
 197  */
 198 void *ceph_kvmalloc(size_t size, gfp_t flags)
 199 {
 200         void *p;
 201 
 202         if ((flags & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS)) {
 203                 p = kvmalloc(size, flags);
 204         } else if ((flags & (__GFP_IO | __GFP_FS)) == __GFP_IO) {
 205                 unsigned int nofs_flag = memalloc_nofs_save();
 206                 p = kvmalloc(size, GFP_KERNEL);
 207                 memalloc_nofs_restore(nofs_flag);
 208         } else {
 209                 unsigned int noio_flag = memalloc_noio_save();
 210                 p = kvmalloc(size, GFP_KERNEL);
 211                 memalloc_noio_restore(noio_flag);
 212         }
 213 
 214         return p;
 215 }
 216 
 217 static int parse_fsid(const char *str, struct ceph_fsid *fsid)
 218 {
 219         int i = 0;
 220         char tmp[3];
 221         int err = -EINVAL;
 222         int d;
 223 
 224         dout("parse_fsid '%s'\n", str);
 225         tmp[2] = 0;
 226         while (*str && i < 16) {
 227                 if (ispunct(*str)) {
 228                         str++;
 229                         continue;
 230                 }
 231                 if (!isxdigit(str[0]) || !isxdigit(str[1]))
 232                         break;
 233                 tmp[0] = str[0];
 234                 tmp[1] = str[1];
 235                 if (sscanf(tmp, "%x", &d) < 1)
 236                         break;
 237                 fsid->fsid[i] = d & 0xff;
 238                 i++;
 239                 str += 2;
 240         }
 241 
 242         if (i == 16)
 243                 err = 0;
 244         dout("parse_fsid ret %d got fsid %pU\n", err, fsid);
 245         return err;
 246 }
 247 
 248 /*
 249  * ceph options
 250  */
 251 enum {
 252         Opt_osdtimeout,
 253         Opt_osdkeepalivetimeout,
 254         Opt_mount_timeout,
 255         Opt_osd_idle_ttl,
 256         Opt_osd_request_timeout,
 257         Opt_last_int,
 258         /* int args above */
 259         Opt_fsid,
 260         Opt_name,
 261         Opt_secret,
 262         Opt_key,
 263         Opt_ip,
 264         Opt_last_string,
 265         /* string args above */
 266         Opt_share,
 267         Opt_noshare,
 268         Opt_crc,
 269         Opt_nocrc,
 270         Opt_cephx_require_signatures,
 271         Opt_nocephx_require_signatures,
 272         Opt_cephx_sign_messages,
 273         Opt_nocephx_sign_messages,
 274         Opt_tcp_nodelay,
 275         Opt_notcp_nodelay,
 276         Opt_abort_on_full,
 277 };
 278 
 279 static match_table_t opt_tokens = {
 280         {Opt_osdtimeout, "osdtimeout=%d"},
 281         {Opt_osdkeepalivetimeout, "osdkeepalive=%d"},
 282         {Opt_mount_timeout, "mount_timeout=%d"},
 283         {Opt_osd_idle_ttl, "osd_idle_ttl=%d"},
 284         {Opt_osd_request_timeout, "osd_request_timeout=%d"},
 285         /* int args above */
 286         {Opt_fsid, "fsid=%s"},
 287         {Opt_name, "name=%s"},
 288         {Opt_secret, "secret=%s"},
 289         {Opt_key, "key=%s"},
 290         {Opt_ip, "ip=%s"},
 291         /* string args above */
 292         {Opt_share, "share"},
 293         {Opt_noshare, "noshare"},
 294         {Opt_crc, "crc"},
 295         {Opt_nocrc, "nocrc"},
 296         {Opt_cephx_require_signatures, "cephx_require_signatures"},
 297         {Opt_nocephx_require_signatures, "nocephx_require_signatures"},
 298         {Opt_cephx_sign_messages, "cephx_sign_messages"},
 299         {Opt_nocephx_sign_messages, "nocephx_sign_messages"},
 300         {Opt_tcp_nodelay, "tcp_nodelay"},
 301         {Opt_notcp_nodelay, "notcp_nodelay"},
 302         {Opt_abort_on_full, "abort_on_full"},
 303         {-1, NULL}
 304 };
 305 
 306 void ceph_destroy_options(struct ceph_options *opt)
 307 {
 308         dout("destroy_options %p\n", opt);
 309         kfree(opt->name);
 310         if (opt->key) {
 311                 ceph_crypto_key_destroy(opt->key);
 312                 kfree(opt->key);
 313         }
 314         kfree(opt->mon_addr);
 315         kfree(opt);
 316 }
 317 EXPORT_SYMBOL(ceph_destroy_options);
 318 
 319 /* get secret from key store */
 320 static int get_secret(struct ceph_crypto_key *dst, const char *name) {
 321         struct key *ukey;
 322         int key_err;
 323         int err = 0;
 324         struct ceph_crypto_key *ckey;
 325 
 326         ukey = request_key(&key_type_ceph, name, NULL);
 327         if (IS_ERR(ukey)) {
 328                 /* request_key errors don't map nicely to mount(2)
 329                    errors; don't even try, but still printk */
 330                 key_err = PTR_ERR(ukey);
 331                 switch (key_err) {
 332                 case -ENOKEY:
 333                         pr_warn("ceph: Mount failed due to key not found: %s\n",
 334                                 name);
 335                         break;
 336                 case -EKEYEXPIRED:
 337                         pr_warn("ceph: Mount failed due to expired key: %s\n",
 338                                 name);
 339                         break;
 340                 case -EKEYREVOKED:
 341                         pr_warn("ceph: Mount failed due to revoked key: %s\n",
 342                                 name);
 343                         break;
 344                 default:
 345                         pr_warn("ceph: Mount failed due to unknown key error %d: %s\n",
 346                                 key_err, name);
 347                 }
 348                 err = -EPERM;
 349                 goto out;
 350         }
 351 
 352         ckey = ukey->payload.data[0];
 353         err = ceph_crypto_key_clone(dst, ckey);
 354         if (err)
 355                 goto out_key;
 356         /* pass through, err is 0 */
 357 
 358 out_key:
 359         key_put(ukey);
 360 out:
 361         return err;
 362 }
 363 
 364 struct ceph_options *
 365 ceph_parse_options(char *options, const char *dev_name,
 366                         const char *dev_name_end,
 367                         int (*parse_extra_token)(char *c, void *private),
 368                         void *private)
 369 {
 370         struct ceph_options *opt;
 371         const char *c;
 372         int err = -ENOMEM;
 373         substring_t argstr[MAX_OPT_ARGS];
 374 
 375         opt = kzalloc(sizeof(*opt), GFP_KERNEL);
 376         if (!opt)
 377                 return ERR_PTR(-ENOMEM);
 378         opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr),
 379                                 GFP_KERNEL);
 380         if (!opt->mon_addr)
 381                 goto out;
 382 
 383         dout("parse_options %p options '%s' dev_name '%s'\n", opt, options,
 384              dev_name);
 385 
 386         /* start with defaults */
 387         opt->flags = CEPH_OPT_DEFAULT;
 388         opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
 389         opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT;
 390         opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;
 391         opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT;
 392 
 393         /* get mon ip(s) */
 394         /* ip1[:port1][,ip2[:port2]...] */
 395         err = ceph_parse_ips(dev_name, dev_name_end, opt->mon_addr,
 396                              CEPH_MAX_MON, &opt->num_mon);
 397         if (err < 0)
 398                 goto out;
 399 
 400         /* parse mount options */
 401         while ((c = strsep(&options, ",")) != NULL) {
 402                 int token, intval;
 403                 if (!*c)
 404                         continue;
 405                 err = -EINVAL;
 406                 token = match_token((char *)c, opt_tokens, argstr);
 407                 if (token < 0 && parse_extra_token) {
 408                         /* extra? */
 409                         err = parse_extra_token((char *)c, private);
 410                         if (err < 0) {
 411                                 pr_err("bad option at '%s'\n", c);
 412                                 goto out;
 413                         }
 414                         continue;
 415                 }
 416                 if (token < Opt_last_int) {
 417                         err = match_int(&argstr[0], &intval);
 418                         if (err < 0) {
 419                                 pr_err("bad option arg (not int) at '%s'\n", c);
 420                                 goto out;
 421                         }
 422                         dout("got int token %d val %d\n", token, intval);
 423                 } else if (token > Opt_last_int && token < Opt_last_string) {
 424                         dout("got string token %d val %s\n", token,
 425                              argstr[0].from);
 426                 } else {
 427                         dout("got token %d\n", token);
 428                 }
 429                 switch (token) {
 430                 case Opt_ip:
 431                         err = ceph_parse_ips(argstr[0].from,
 432                                              argstr[0].to,
 433                                              &opt->my_addr,
 434                                              1, NULL);
 435                         if (err < 0)
 436                                 goto out;
 437                         opt->flags |= CEPH_OPT_MYIP;
 438                         break;
 439 
 440                 case Opt_fsid:
 441                         err = parse_fsid(argstr[0].from, &opt->fsid);
 442                         if (err == 0)
 443                                 opt->flags |= CEPH_OPT_FSID;
 444                         break;
 445                 case Opt_name:
 446                         kfree(opt->name);
 447                         opt->name = kstrndup(argstr[0].from,
 448                                               argstr[0].to-argstr[0].from,
 449                                               GFP_KERNEL);
 450                         if (!opt->name) {
 451                                 err = -ENOMEM;
 452                                 goto out;
 453                         }
 454                         break;
 455                 case Opt_secret:
 456                         ceph_crypto_key_destroy(opt->key);
 457                         kfree(opt->key);
 458 
 459                         opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
 460                         if (!opt->key) {
 461                                 err = -ENOMEM;
 462                                 goto out;
 463                         }
 464                         err = ceph_crypto_key_unarmor(opt->key, argstr[0].from);
 465                         if (err < 0)
 466                                 goto out;
 467                         break;
 468                 case Opt_key:
 469                         ceph_crypto_key_destroy(opt->key);
 470                         kfree(opt->key);
 471 
 472                         opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
 473                         if (!opt->key) {
 474                                 err = -ENOMEM;
 475                                 goto out;
 476                         }
 477                         err = get_secret(opt->key, argstr[0].from);
 478                         if (err < 0)
 479                                 goto out;
 480                         break;
 481 
 482                         /* misc */
 483                 case Opt_osdtimeout:
 484                         pr_warn("ignoring deprecated osdtimeout option\n");
 485                         break;
 486                 case Opt_osdkeepalivetimeout:
 487                         /* 0 isn't well defined right now, reject it */
 488                         if (intval < 1 || intval > INT_MAX / 1000) {
 489                                 pr_err("osdkeepalive out of range\n");
 490                                 err = -EINVAL;
 491                                 goto out;
 492                         }
 493                         opt->osd_keepalive_timeout =
 494                                         msecs_to_jiffies(intval * 1000);
 495                         break;
 496                 case Opt_osd_idle_ttl:
 497                         /* 0 isn't well defined right now, reject it */
 498                         if (intval < 1 || intval > INT_MAX / 1000) {
 499                                 pr_err("osd_idle_ttl out of range\n");
 500                                 err = -EINVAL;
 501                                 goto out;
 502                         }
 503                         opt->osd_idle_ttl = msecs_to_jiffies(intval * 1000);
 504                         break;
 505                 case Opt_mount_timeout:
 506                         /* 0 is "wait forever" (i.e. infinite timeout) */
 507                         if (intval < 0 || intval > INT_MAX / 1000) {
 508                                 pr_err("mount_timeout out of range\n");
 509                                 err = -EINVAL;
 510                                 goto out;
 511                         }
 512                         opt->mount_timeout = msecs_to_jiffies(intval * 1000);
 513                         break;
 514                 case Opt_osd_request_timeout:
 515                         /* 0 is "wait forever" (i.e. infinite timeout) */
 516                         if (intval < 0 || intval > INT_MAX / 1000) {
 517                                 pr_err("osd_request_timeout out of range\n");
 518                                 err = -EINVAL;
 519                                 goto out;
 520                         }
 521                         opt->osd_request_timeout = msecs_to_jiffies(intval * 1000);
 522                         break;
 523 
 524                 case Opt_share:
 525                         opt->flags &= ~CEPH_OPT_NOSHARE;
 526                         break;
 527                 case Opt_noshare:
 528                         opt->flags |= CEPH_OPT_NOSHARE;
 529                         break;
 530 
 531                 case Opt_crc:
 532                         opt->flags &= ~CEPH_OPT_NOCRC;
 533                         break;
 534                 case Opt_nocrc:
 535                         opt->flags |= CEPH_OPT_NOCRC;
 536                         break;
 537 
 538                 case Opt_cephx_require_signatures:
 539                         opt->flags &= ~CEPH_OPT_NOMSGAUTH;
 540                         break;
 541                 case Opt_nocephx_require_signatures:
 542                         opt->flags |= CEPH_OPT_NOMSGAUTH;
 543                         break;
 544                 case Opt_cephx_sign_messages:
 545                         opt->flags &= ~CEPH_OPT_NOMSGSIGN;
 546                         break;
 547                 case Opt_nocephx_sign_messages:
 548                         opt->flags |= CEPH_OPT_NOMSGSIGN;
 549                         break;
 550 
 551                 case Opt_tcp_nodelay:
 552                         opt->flags |= CEPH_OPT_TCP_NODELAY;
 553                         break;
 554                 case Opt_notcp_nodelay:
 555                         opt->flags &= ~CEPH_OPT_TCP_NODELAY;
 556                         break;
 557 
 558                 case Opt_abort_on_full:
 559                         opt->flags |= CEPH_OPT_ABORT_ON_FULL;
 560                         break;
 561 
 562                 default:
 563                         BUG_ON(token);
 564                 }
 565         }
 566 
 567         /* success */
 568         return opt;
 569 
 570 out:
 571         ceph_destroy_options(opt);
 572         return ERR_PTR(err);
 573 }
 574 EXPORT_SYMBOL(ceph_parse_options);
 575 
 576 int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
 577                               bool show_all)
 578 {
 579         struct ceph_options *opt = client->options;
 580         size_t pos = m->count;
 581 
 582         if (opt->name) {
 583                 seq_puts(m, "name=");
 584                 seq_escape(m, opt->name, ", \t\n\\");
 585                 seq_putc(m, ',');
 586         }
 587         if (opt->key)
 588                 seq_puts(m, "secret=<hidden>,");
 589 
 590         if (opt->flags & CEPH_OPT_FSID)
 591                 seq_printf(m, "fsid=%pU,", &opt->fsid);
 592         if (opt->flags & CEPH_OPT_NOSHARE)
 593                 seq_puts(m, "noshare,");
 594         if (opt->flags & CEPH_OPT_NOCRC)
 595                 seq_puts(m, "nocrc,");
 596         if (opt->flags & CEPH_OPT_NOMSGAUTH)
 597                 seq_puts(m, "nocephx_require_signatures,");
 598         if (opt->flags & CEPH_OPT_NOMSGSIGN)
 599                 seq_puts(m, "nocephx_sign_messages,");
 600         if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
 601                 seq_puts(m, "notcp_nodelay,");
 602         if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL))
 603                 seq_puts(m, "abort_on_full,");
 604 
 605         if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
 606                 seq_printf(m, "mount_timeout=%d,",
 607                            jiffies_to_msecs(opt->mount_timeout) / 1000);
 608         if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
 609                 seq_printf(m, "osd_idle_ttl=%d,",
 610                            jiffies_to_msecs(opt->osd_idle_ttl) / 1000);
 611         if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
 612                 seq_printf(m, "osdkeepalivetimeout=%d,",
 613                     jiffies_to_msecs(opt->osd_keepalive_timeout) / 1000);
 614         if (opt->osd_request_timeout != CEPH_OSD_REQUEST_TIMEOUT_DEFAULT)
 615                 seq_printf(m, "osd_request_timeout=%d,",
 616                            jiffies_to_msecs(opt->osd_request_timeout) / 1000);
 617 
 618         /* drop redundant comma */
 619         if (m->count != pos)
 620                 m->count--;
 621 
 622         return 0;
 623 }
 624 EXPORT_SYMBOL(ceph_print_client_options);
 625 
 626 struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client)
 627 {
 628         return &client->msgr.inst.addr;
 629 }
 630 EXPORT_SYMBOL(ceph_client_addr);
 631 
 632 u64 ceph_client_gid(struct ceph_client *client)
 633 {
 634         return client->monc.auth->global_id;
 635 }
 636 EXPORT_SYMBOL(ceph_client_gid);
 637 
 638 /*
 639  * create a fresh client instance
 640  */
 641 struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
 642 {
 643         struct ceph_client *client;
 644         struct ceph_entity_addr *myaddr = NULL;
 645         int err;
 646 
 647         err = wait_for_random_bytes();
 648         if (err < 0)
 649                 return ERR_PTR(err);
 650 
 651         client = kzalloc(sizeof(*client), GFP_KERNEL);
 652         if (client == NULL)
 653                 return ERR_PTR(-ENOMEM);
 654 
 655         client->private = private;
 656         client->options = opt;
 657 
 658         mutex_init(&client->mount_mutex);
 659         init_waitqueue_head(&client->auth_wq);
 660         client->auth_err = 0;
 661 
 662         client->extra_mon_dispatch = NULL;
 663         client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT;
 664         client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT;
 665 
 666         if (!ceph_test_opt(client, NOMSGAUTH))
 667                 client->required_features |= CEPH_FEATURE_MSG_AUTH;
 668 
 669         /* msgr */
 670         if (ceph_test_opt(client, MYIP))
 671                 myaddr = &client->options->my_addr;
 672 
 673         ceph_messenger_init(&client->msgr, myaddr);
 674 
 675         /* subsystems */
 676         err = ceph_monc_init(&client->monc, client);
 677         if (err < 0)
 678                 goto fail;
 679         err = ceph_osdc_init(&client->osdc, client);
 680         if (err < 0)
 681                 goto fail_monc;
 682 
 683         return client;
 684 
 685 fail_monc:
 686         ceph_monc_stop(&client->monc);
 687 fail:
 688         ceph_messenger_fini(&client->msgr);
 689         kfree(client);
 690         return ERR_PTR(err);
 691 }
 692 EXPORT_SYMBOL(ceph_create_client);
 693 
 694 void ceph_destroy_client(struct ceph_client *client)
 695 {
 696         dout("destroy_client %p\n", client);
 697 
 698         atomic_set(&client->msgr.stopping, 1);
 699 
 700         /* unmount */
 701         ceph_osdc_stop(&client->osdc);
 702         ceph_monc_stop(&client->monc);
 703         ceph_messenger_fini(&client->msgr);
 704 
 705         ceph_debugfs_client_cleanup(client);
 706 
 707         ceph_destroy_options(client->options);
 708 
 709         kfree(client);
 710         dout("destroy_client %p done\n", client);
 711 }
 712 EXPORT_SYMBOL(ceph_destroy_client);
 713 
 714 void ceph_reset_client_addr(struct ceph_client *client)
 715 {
 716         ceph_messenger_reset_nonce(&client->msgr);
 717         ceph_monc_reopen_session(&client->monc);
 718         ceph_osdc_reopen_osds(&client->osdc);
 719 }
 720 EXPORT_SYMBOL(ceph_reset_client_addr);
 721 
 722 /*
 723  * true if we have the mon map (and have thus joined the cluster)
 724  */
 725 static bool have_mon_and_osd_map(struct ceph_client *client)
 726 {
 727         return client->monc.monmap && client->monc.monmap->epoch &&
 728                client->osdc.osdmap && client->osdc.osdmap->epoch;
 729 }
 730 
 731 /*
 732  * mount: join the ceph cluster, and open root directory.
 733  */
 734 int __ceph_open_session(struct ceph_client *client, unsigned long started)
 735 {
 736         unsigned long timeout = client->options->mount_timeout;
 737         long err;
 738 
 739         /* open session, and wait for mon and osd maps */
 740         err = ceph_monc_open_session(&client->monc);
 741         if (err < 0)
 742                 return err;
 743 
 744         while (!have_mon_and_osd_map(client)) {
 745                 if (timeout && time_after_eq(jiffies, started + timeout))
 746                         return -ETIMEDOUT;
 747 
 748                 /* wait */
 749                 dout("mount waiting for mon_map\n");
 750                 err = wait_event_interruptible_timeout(client->auth_wq,
 751                         have_mon_and_osd_map(client) || (client->auth_err < 0),
 752                         ceph_timeout_jiffies(timeout));
 753                 if (err < 0)
 754                         return err;
 755                 if (client->auth_err < 0)
 756                         return client->auth_err;
 757         }
 758 
 759         pr_info("client%llu fsid %pU\n", ceph_client_gid(client),
 760                 &client->fsid);
 761         ceph_debugfs_client_init(client);
 762 
 763         return 0;
 764 }
 765 EXPORT_SYMBOL(__ceph_open_session);
 766 
 767 int ceph_open_session(struct ceph_client *client)
 768 {
 769         int ret;
 770         unsigned long started = jiffies;  /* note the start time */
 771 
 772         dout("open_session start\n");
 773         mutex_lock(&client->mount_mutex);
 774 
 775         ret = __ceph_open_session(client, started);
 776 
 777         mutex_unlock(&client->mount_mutex);
 778         return ret;
 779 }
 780 EXPORT_SYMBOL(ceph_open_session);
 781 
 782 int ceph_wait_for_latest_osdmap(struct ceph_client *client,
 783                                 unsigned long timeout)
 784 {
 785         u64 newest_epoch;
 786         int ret;
 787 
 788         ret = ceph_monc_get_version(&client->monc, "osdmap", &newest_epoch);
 789         if (ret)
 790                 return ret;
 791 
 792         if (client->osdc.osdmap->epoch >= newest_epoch)
 793                 return 0;
 794 
 795         ceph_osdc_maybe_request_map(&client->osdc);
 796         return ceph_monc_wait_osdmap(&client->monc, newest_epoch, timeout);
 797 }
 798 EXPORT_SYMBOL(ceph_wait_for_latest_osdmap);
 799 
 800 static int __init init_ceph_lib(void)
 801 {
 802         int ret = 0;
 803 
 804         ceph_debugfs_init();
 805 
 806         ret = ceph_crypto_init();
 807         if (ret < 0)
 808                 goto out_debugfs;
 809 
 810         ret = ceph_msgr_init();
 811         if (ret < 0)
 812                 goto out_crypto;
 813 
 814         ret = ceph_osdc_setup();
 815         if (ret < 0)
 816                 goto out_msgr;
 817 
 818         pr_info("loaded (mon/osd proto %d/%d)\n",
 819                 CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL);
 820 
 821         return 0;
 822 
 823 out_msgr:
 824         ceph_msgr_exit();
 825 out_crypto:
 826         ceph_crypto_shutdown();
 827 out_debugfs:
 828         ceph_debugfs_cleanup();
 829         return ret;
 830 }
 831 
 832 static void __exit exit_ceph_lib(void)
 833 {
 834         dout("exit_ceph_lib\n");
 835         WARN_ON(!ceph_strings_empty());
 836 
 837         ceph_osdc_cleanup();
 838         ceph_msgr_exit();
 839         ceph_crypto_shutdown();
 840         ceph_debugfs_cleanup();
 841 }
 842 
 843 module_init(init_ceph_lib);
 844 module_exit(exit_ceph_lib);
 845 
 846 MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
 847 MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
 848 MODULE_AUTHOR("Patience Warnick <patience@newdream.net>");
 849 MODULE_DESCRIPTION("Ceph core library");
 850 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */