linux/net/ceph/ceph_common.c
<<
>>
Prefs
   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 */
  44bool libceph_compatible(void *data)
  45{
  46        return true;
  47}
  48EXPORT_SYMBOL(libceph_compatible);
  49
  50static 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}
  55static const struct kernel_param_ops param_ops_supported_features = {
  56        .get = param_get_supported_features,
  57};
  58module_param_cb(supported_features, &param_ops_supported_features, NULL,
  59                0444);
  60
  61const 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}
 100EXPORT_SYMBOL(ceph_msg_type_name);
 101
 102/*
 103 * Initially learn our fsid, or verify an fsid matches.
 104 */
 105int 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}
 118EXPORT_SYMBOL(ceph_check_fsid);
 119
 120static 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
 131int 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}
 191EXPORT_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 */
 201void *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
 220static 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 */
 254enum {
 255        Opt_osdkeepalivetimeout,
 256        Opt_mount_timeout,
 257        Opt_osd_idle_ttl,
 258        Opt_osd_request_timeout,
 259        /* int args above */
 260        Opt_fsid,
 261        Opt_name,
 262        Opt_secret,
 263        Opt_key,
 264        Opt_ip,
 265        Opt_crush_location,
 266        Opt_read_from_replica,
 267        Opt_ms_mode,
 268        /* string args above */
 269        Opt_share,
 270        Opt_crc,
 271        Opt_cephx_require_signatures,
 272        Opt_cephx_sign_messages,
 273        Opt_tcp_nodelay,
 274        Opt_abort_on_full,
 275};
 276
 277enum {
 278        Opt_read_from_replica_no,
 279        Opt_read_from_replica_balance,
 280        Opt_read_from_replica_localize,
 281};
 282
 283static const struct constant_table ceph_param_read_from_replica[] = {
 284        {"no",          Opt_read_from_replica_no},
 285        {"balance",     Opt_read_from_replica_balance},
 286        {"localize",    Opt_read_from_replica_localize},
 287        {}
 288};
 289
 290enum ceph_ms_mode {
 291        Opt_ms_mode_legacy,
 292        Opt_ms_mode_crc,
 293        Opt_ms_mode_secure,
 294        Opt_ms_mode_prefer_crc,
 295        Opt_ms_mode_prefer_secure
 296};
 297
 298static const struct constant_table ceph_param_ms_mode[] = {
 299        {"legacy",              Opt_ms_mode_legacy},
 300        {"crc",                 Opt_ms_mode_crc},
 301        {"secure",              Opt_ms_mode_secure},
 302        {"prefer-crc",          Opt_ms_mode_prefer_crc},
 303        {"prefer-secure",       Opt_ms_mode_prefer_secure},
 304        {}
 305};
 306
 307static const struct fs_parameter_spec ceph_parameters[] = {
 308        fsparam_flag    ("abort_on_full",               Opt_abort_on_full),
 309        __fsparam       (NULL, "cephx_require_signatures", Opt_cephx_require_signatures,
 310                         fs_param_neg_with_no|fs_param_deprecated, NULL),
 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_enum    ("read_from_replica",           Opt_read_from_replica,
 323                         ceph_param_read_from_replica),
 324        fsparam_enum    ("ms_mode",                     Opt_ms_mode,
 325                         ceph_param_ms_mode),
 326        fsparam_string  ("secret",                      Opt_secret),
 327        fsparam_flag_no ("share",                       Opt_share),
 328        fsparam_flag_no ("tcp_nodelay",                 Opt_tcp_nodelay),
 329        {}
 330};
 331
 332struct ceph_options *ceph_alloc_options(void)
 333{
 334        struct ceph_options *opt;
 335
 336        opt = kzalloc(sizeof(*opt), GFP_KERNEL);
 337        if (!opt)
 338                return NULL;
 339
 340        opt->crush_locs = RB_ROOT;
 341        opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr),
 342                                GFP_KERNEL);
 343        if (!opt->mon_addr) {
 344                kfree(opt);
 345                return NULL;
 346        }
 347
 348        opt->flags = CEPH_OPT_DEFAULT;
 349        opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
 350        opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT;
 351        opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;
 352        opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT;
 353        opt->read_from_replica = CEPH_READ_FROM_REPLICA_DEFAULT;
 354        opt->con_modes[0] = CEPH_CON_MODE_UNKNOWN;
 355        opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
 356        return opt;
 357}
 358EXPORT_SYMBOL(ceph_alloc_options);
 359
 360void ceph_destroy_options(struct ceph_options *opt)
 361{
 362        dout("destroy_options %p\n", opt);
 363        if (!opt)
 364                return;
 365
 366        ceph_clear_crush_locs(&opt->crush_locs);
 367        kfree(opt->name);
 368        if (opt->key) {
 369                ceph_crypto_key_destroy(opt->key);
 370                kfree(opt->key);
 371        }
 372        kfree(opt->mon_addr);
 373        kfree(opt);
 374}
 375EXPORT_SYMBOL(ceph_destroy_options);
 376
 377/* get secret from key store */
 378static int get_secret(struct ceph_crypto_key *dst, const char *name,
 379                      struct p_log *log)
 380{
 381        struct key *ukey;
 382        int key_err;
 383        int err = 0;
 384        struct ceph_crypto_key *ckey;
 385
 386        ukey = request_key(&key_type_ceph, name, NULL);
 387        if (IS_ERR(ukey)) {
 388                /* request_key errors don't map nicely to mount(2)
 389                   errors; don't even try, but still printk */
 390                key_err = PTR_ERR(ukey);
 391                switch (key_err) {
 392                case -ENOKEY:
 393                        error_plog(log, "Failed due to key not found: %s",
 394                               name);
 395                        break;
 396                case -EKEYEXPIRED:
 397                        error_plog(log, "Failed due to expired key: %s",
 398                               name);
 399                        break;
 400                case -EKEYREVOKED:
 401                        error_plog(log, "Failed due to revoked key: %s",
 402                               name);
 403                        break;
 404                default:
 405                        error_plog(log, "Failed due to key error %d: %s",
 406                               key_err, name);
 407                }
 408                err = -EPERM;
 409                goto out;
 410        }
 411
 412        ckey = ukey->payload.data[0];
 413        err = ceph_crypto_key_clone(dst, ckey);
 414        if (err)
 415                goto out_key;
 416        /* pass through, err is 0 */
 417
 418out_key:
 419        key_put(ukey);
 420out:
 421        return err;
 422}
 423
 424int ceph_parse_mon_ips(const char *buf, size_t len, struct ceph_options *opt,
 425                       struct fc_log *l)
 426{
 427        struct p_log log = {.prefix = "libceph", .log = l};
 428        int ret;
 429
 430        /* ip1[:port1][,ip2[:port2]...] */
 431        ret = ceph_parse_ips(buf, buf + len, opt->mon_addr, CEPH_MAX_MON,
 432                             &opt->num_mon);
 433        if (ret) {
 434                error_plog(&log, "Failed to parse monitor IPs: %d", ret);
 435                return ret;
 436        }
 437
 438        return 0;
 439}
 440EXPORT_SYMBOL(ceph_parse_mon_ips);
 441
 442int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
 443                     struct fc_log *l)
 444{
 445        struct fs_parse_result result;
 446        int token, err;
 447        struct p_log log = {.prefix = "libceph", .log = l};
 448
 449        token = __fs_parse(&log, ceph_parameters, param, &result);
 450        dout("%s fs_parse '%s' token %d\n", __func__, param->key, token);
 451        if (token < 0)
 452                return token;
 453
 454        switch (token) {
 455        case Opt_ip:
 456                err = ceph_parse_ips(param->string,
 457                                     param->string + param->size,
 458                                     &opt->my_addr,
 459                                     1, NULL);
 460                if (err) {
 461                        error_plog(&log, "Failed to parse ip: %d", err);
 462                        return err;
 463                }
 464                opt->flags |= CEPH_OPT_MYIP;
 465                break;
 466
 467        case Opt_fsid:
 468                err = parse_fsid(param->string, &opt->fsid);
 469                if (err) {
 470                        error_plog(&log, "Failed to parse fsid: %d", err);
 471                        return err;
 472                }
 473                opt->flags |= CEPH_OPT_FSID;
 474                break;
 475        case Opt_name:
 476                kfree(opt->name);
 477                opt->name = param->string;
 478                param->string = NULL;
 479                break;
 480        case Opt_secret:
 481                ceph_crypto_key_destroy(opt->key);
 482                kfree(opt->key);
 483
 484                opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
 485                if (!opt->key)
 486                        return -ENOMEM;
 487                err = ceph_crypto_key_unarmor(opt->key, param->string);
 488                if (err) {
 489                        error_plog(&log, "Failed to parse secret: %d", err);
 490                        return err;
 491                }
 492                break;
 493        case Opt_key:
 494                ceph_crypto_key_destroy(opt->key);
 495                kfree(opt->key);
 496
 497                opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
 498                if (!opt->key)
 499                        return -ENOMEM;
 500                return get_secret(opt->key, param->string, &log);
 501        case Opt_crush_location:
 502                ceph_clear_crush_locs(&opt->crush_locs);
 503                err = ceph_parse_crush_location(param->string,
 504                                                &opt->crush_locs);
 505                if (err) {
 506                        error_plog(&log, "Failed to parse CRUSH location: %d",
 507                                   err);
 508                        return err;
 509                }
 510                break;
 511        case Opt_read_from_replica:
 512                switch (result.uint_32) {
 513                case Opt_read_from_replica_no:
 514                        opt->read_from_replica = 0;
 515                        break;
 516                case Opt_read_from_replica_balance:
 517                        opt->read_from_replica = CEPH_OSD_FLAG_BALANCE_READS;
 518                        break;
 519                case Opt_read_from_replica_localize:
 520                        opt->read_from_replica = CEPH_OSD_FLAG_LOCALIZE_READS;
 521                        break;
 522                default:
 523                        BUG();
 524                }
 525                break;
 526        case Opt_ms_mode:
 527                switch (result.uint_32) {
 528                case Opt_ms_mode_legacy:
 529                        opt->con_modes[0] = CEPH_CON_MODE_UNKNOWN;
 530                        opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
 531                        break;
 532                case Opt_ms_mode_crc:
 533                        opt->con_modes[0] = CEPH_CON_MODE_CRC;
 534                        opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
 535                        break;
 536                case Opt_ms_mode_secure:
 537                        opt->con_modes[0] = CEPH_CON_MODE_SECURE;
 538                        opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
 539                        break;
 540                case Opt_ms_mode_prefer_crc:
 541                        opt->con_modes[0] = CEPH_CON_MODE_CRC;
 542                        opt->con_modes[1] = CEPH_CON_MODE_SECURE;
 543                        break;
 544                case Opt_ms_mode_prefer_secure:
 545                        opt->con_modes[0] = CEPH_CON_MODE_SECURE;
 546                        opt->con_modes[1] = CEPH_CON_MODE_CRC;
 547                        break;
 548                default:
 549                        BUG();
 550                }
 551                break;
 552
 553        case Opt_osdkeepalivetimeout:
 554                /* 0 isn't well defined right now, reject it */
 555                if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000)
 556                        goto out_of_range;
 557                opt->osd_keepalive_timeout =
 558                    msecs_to_jiffies(result.uint_32 * 1000);
 559                break;
 560        case Opt_osd_idle_ttl:
 561                /* 0 isn't well defined right now, reject it */
 562                if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000)
 563                        goto out_of_range;
 564                opt->osd_idle_ttl = msecs_to_jiffies(result.uint_32 * 1000);
 565                break;
 566        case Opt_mount_timeout:
 567                /* 0 is "wait forever" (i.e. infinite timeout) */
 568                if (result.uint_32 > INT_MAX / 1000)
 569                        goto out_of_range;
 570                opt->mount_timeout = msecs_to_jiffies(result.uint_32 * 1000);
 571                break;
 572        case Opt_osd_request_timeout:
 573                /* 0 is "wait forever" (i.e. infinite timeout) */
 574                if (result.uint_32 > INT_MAX / 1000)
 575                        goto out_of_range;
 576                opt->osd_request_timeout =
 577                    msecs_to_jiffies(result.uint_32 * 1000);
 578                break;
 579
 580        case Opt_share:
 581                if (!result.negated)
 582                        opt->flags &= ~CEPH_OPT_NOSHARE;
 583                else
 584                        opt->flags |= CEPH_OPT_NOSHARE;
 585                break;
 586        case Opt_crc:
 587                if (!result.negated)
 588                        opt->flags &= ~CEPH_OPT_NOCRC;
 589                else
 590                        opt->flags |= CEPH_OPT_NOCRC;
 591                break;
 592        case Opt_cephx_require_signatures:
 593                if (!result.negated)
 594                        warn_plog(&log, "Ignoring cephx_require_signatures");
 595                else
 596                        warn_plog(&log, "Ignoring nocephx_require_signatures, use nocephx_sign_messages");
 597                break;
 598        case Opt_cephx_sign_messages:
 599                if (!result.negated)
 600                        opt->flags &= ~CEPH_OPT_NOMSGSIGN;
 601                else
 602                        opt->flags |= CEPH_OPT_NOMSGSIGN;
 603                break;
 604        case Opt_tcp_nodelay:
 605                if (!result.negated)
 606                        opt->flags |= CEPH_OPT_TCP_NODELAY;
 607                else
 608                        opt->flags &= ~CEPH_OPT_TCP_NODELAY;
 609                break;
 610
 611        case Opt_abort_on_full:
 612                opt->flags |= CEPH_OPT_ABORT_ON_FULL;
 613                break;
 614
 615        default:
 616                BUG();
 617        }
 618
 619        return 0;
 620
 621out_of_range:
 622        return inval_plog(&log, "%s out of range", param->key);
 623}
 624EXPORT_SYMBOL(ceph_parse_param);
 625
 626int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
 627                              bool show_all)
 628{
 629        struct ceph_options *opt = client->options;
 630        size_t pos = m->count;
 631        struct rb_node *n;
 632
 633        if (opt->name) {
 634                seq_puts(m, "name=");
 635                seq_escape(m, opt->name, ", \t\n\\");
 636                seq_putc(m, ',');
 637        }
 638        if (opt->key)
 639                seq_puts(m, "secret=<hidden>,");
 640
 641        if (!RB_EMPTY_ROOT(&opt->crush_locs)) {
 642                seq_puts(m, "crush_location=");
 643                for (n = rb_first(&opt->crush_locs); ; ) {
 644                        struct crush_loc_node *loc =
 645                            rb_entry(n, struct crush_loc_node, cl_node);
 646
 647                        seq_printf(m, "%s:%s", loc->cl_loc.cl_type_name,
 648                                   loc->cl_loc.cl_name);
 649                        n = rb_next(n);
 650                        if (!n)
 651                                break;
 652
 653                        seq_putc(m, '|');
 654                }
 655                seq_putc(m, ',');
 656        }
 657        if (opt->read_from_replica == CEPH_OSD_FLAG_BALANCE_READS) {
 658                seq_puts(m, "read_from_replica=balance,");
 659        } else if (opt->read_from_replica == CEPH_OSD_FLAG_LOCALIZE_READS) {
 660                seq_puts(m, "read_from_replica=localize,");
 661        }
 662        if (opt->con_modes[0] != CEPH_CON_MODE_UNKNOWN) {
 663                if (opt->con_modes[0] == CEPH_CON_MODE_CRC &&
 664                    opt->con_modes[1] == CEPH_CON_MODE_UNKNOWN) {
 665                        seq_puts(m, "ms_mode=crc,");
 666                } else if (opt->con_modes[0] == CEPH_CON_MODE_SECURE &&
 667                           opt->con_modes[1] == CEPH_CON_MODE_UNKNOWN) {
 668                        seq_puts(m, "ms_mode=secure,");
 669                } else if (opt->con_modes[0] == CEPH_CON_MODE_CRC &&
 670                           opt->con_modes[1] == CEPH_CON_MODE_SECURE) {
 671                        seq_puts(m, "ms_mode=prefer-crc,");
 672                } else if (opt->con_modes[0] == CEPH_CON_MODE_SECURE &&
 673                           opt->con_modes[1] == CEPH_CON_MODE_CRC) {
 674                        seq_puts(m, "ms_mode=prefer-secure,");
 675                }
 676        }
 677
 678        if (opt->flags & CEPH_OPT_FSID)
 679                seq_printf(m, "fsid=%pU,", &opt->fsid);
 680        if (opt->flags & CEPH_OPT_NOSHARE)
 681                seq_puts(m, "noshare,");
 682        if (opt->flags & CEPH_OPT_NOCRC)
 683                seq_puts(m, "nocrc,");
 684        if (opt->flags & CEPH_OPT_NOMSGSIGN)
 685                seq_puts(m, "nocephx_sign_messages,");
 686        if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
 687                seq_puts(m, "notcp_nodelay,");
 688        if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL))
 689                seq_puts(m, "abort_on_full,");
 690
 691        if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
 692                seq_printf(m, "mount_timeout=%d,",
 693                           jiffies_to_msecs(opt->mount_timeout) / 1000);
 694        if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
 695                seq_printf(m, "osd_idle_ttl=%d,",
 696                           jiffies_to_msecs(opt->osd_idle_ttl) / 1000);
 697        if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
 698                seq_printf(m, "osdkeepalivetimeout=%d,",
 699                    jiffies_to_msecs(opt->osd_keepalive_timeout) / 1000);
 700        if (opt->osd_request_timeout != CEPH_OSD_REQUEST_TIMEOUT_DEFAULT)
 701                seq_printf(m, "osd_request_timeout=%d,",
 702                           jiffies_to_msecs(opt->osd_request_timeout) / 1000);
 703
 704        /* drop redundant comma */
 705        if (m->count != pos)
 706                m->count--;
 707
 708        return 0;
 709}
 710EXPORT_SYMBOL(ceph_print_client_options);
 711
 712struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client)
 713{
 714        return &client->msgr.inst.addr;
 715}
 716EXPORT_SYMBOL(ceph_client_addr);
 717
 718u64 ceph_client_gid(struct ceph_client *client)
 719{
 720        return client->monc.auth->global_id;
 721}
 722EXPORT_SYMBOL(ceph_client_gid);
 723
 724/*
 725 * create a fresh client instance
 726 */
 727struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
 728{
 729        struct ceph_client *client;
 730        struct ceph_entity_addr *myaddr = NULL;
 731        int err;
 732
 733        err = wait_for_random_bytes();
 734        if (err < 0)
 735                return ERR_PTR(err);
 736
 737        client = kzalloc(sizeof(*client), GFP_KERNEL);
 738        if (client == NULL)
 739                return ERR_PTR(-ENOMEM);
 740
 741        client->private = private;
 742        client->options = opt;
 743
 744        mutex_init(&client->mount_mutex);
 745        init_waitqueue_head(&client->auth_wq);
 746        client->auth_err = 0;
 747
 748        client->extra_mon_dispatch = NULL;
 749        client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT;
 750        client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT;
 751
 752        if (!ceph_test_opt(client, NOMSGSIGN))
 753                client->required_features |= CEPH_FEATURE_MSG_AUTH;
 754
 755        /* msgr */
 756        if (ceph_test_opt(client, MYIP))
 757                myaddr = &client->options->my_addr;
 758
 759        ceph_messenger_init(&client->msgr, myaddr);
 760
 761        /* subsystems */
 762        err = ceph_monc_init(&client->monc, client);
 763        if (err < 0)
 764                goto fail;
 765        err = ceph_osdc_init(&client->osdc, client);
 766        if (err < 0)
 767                goto fail_monc;
 768
 769        return client;
 770
 771fail_monc:
 772        ceph_monc_stop(&client->monc);
 773fail:
 774        ceph_messenger_fini(&client->msgr);
 775        kfree(client);
 776        return ERR_PTR(err);
 777}
 778EXPORT_SYMBOL(ceph_create_client);
 779
 780void ceph_destroy_client(struct ceph_client *client)
 781{
 782        dout("destroy_client %p\n", client);
 783
 784        atomic_set(&client->msgr.stopping, 1);
 785
 786        /* unmount */
 787        ceph_osdc_stop(&client->osdc);
 788        ceph_monc_stop(&client->monc);
 789        ceph_messenger_fini(&client->msgr);
 790
 791        ceph_debugfs_client_cleanup(client);
 792
 793        ceph_destroy_options(client->options);
 794
 795        kfree(client);
 796        dout("destroy_client %p done\n", client);
 797}
 798EXPORT_SYMBOL(ceph_destroy_client);
 799
 800void ceph_reset_client_addr(struct ceph_client *client)
 801{
 802        ceph_messenger_reset_nonce(&client->msgr);
 803        ceph_monc_reopen_session(&client->monc);
 804        ceph_osdc_reopen_osds(&client->osdc);
 805}
 806EXPORT_SYMBOL(ceph_reset_client_addr);
 807
 808/*
 809 * true if we have the mon map (and have thus joined the cluster)
 810 */
 811static bool have_mon_and_osd_map(struct ceph_client *client)
 812{
 813        return client->monc.monmap && client->monc.monmap->epoch &&
 814               client->osdc.osdmap && client->osdc.osdmap->epoch;
 815}
 816
 817/*
 818 * mount: join the ceph cluster, and open root directory.
 819 */
 820int __ceph_open_session(struct ceph_client *client, unsigned long started)
 821{
 822        unsigned long timeout = client->options->mount_timeout;
 823        long err;
 824
 825        /* open session, and wait for mon and osd maps */
 826        err = ceph_monc_open_session(&client->monc);
 827        if (err < 0)
 828                return err;
 829
 830        while (!have_mon_and_osd_map(client)) {
 831                if (timeout && time_after_eq(jiffies, started + timeout))
 832                        return -ETIMEDOUT;
 833
 834                /* wait */
 835                dout("mount waiting for mon_map\n");
 836                err = wait_event_interruptible_timeout(client->auth_wq,
 837                        have_mon_and_osd_map(client) || (client->auth_err < 0),
 838                        ceph_timeout_jiffies(timeout));
 839                if (err < 0)
 840                        return err;
 841                if (client->auth_err < 0)
 842                        return client->auth_err;
 843        }
 844
 845        pr_info("client%llu fsid %pU\n", ceph_client_gid(client),
 846                &client->fsid);
 847        ceph_debugfs_client_init(client);
 848
 849        return 0;
 850}
 851EXPORT_SYMBOL(__ceph_open_session);
 852
 853int ceph_open_session(struct ceph_client *client)
 854{
 855        int ret;
 856        unsigned long started = jiffies;  /* note the start time */
 857
 858        dout("open_session start\n");
 859        mutex_lock(&client->mount_mutex);
 860
 861        ret = __ceph_open_session(client, started);
 862
 863        mutex_unlock(&client->mount_mutex);
 864        return ret;
 865}
 866EXPORT_SYMBOL(ceph_open_session);
 867
 868int ceph_wait_for_latest_osdmap(struct ceph_client *client,
 869                                unsigned long timeout)
 870{
 871        u64 newest_epoch;
 872        int ret;
 873
 874        ret = ceph_monc_get_version(&client->monc, "osdmap", &newest_epoch);
 875        if (ret)
 876                return ret;
 877
 878        if (client->osdc.osdmap->epoch >= newest_epoch)
 879                return 0;
 880
 881        ceph_osdc_maybe_request_map(&client->osdc);
 882        return ceph_monc_wait_osdmap(&client->monc, newest_epoch, timeout);
 883}
 884EXPORT_SYMBOL(ceph_wait_for_latest_osdmap);
 885
 886static int __init init_ceph_lib(void)
 887{
 888        int ret = 0;
 889
 890        ceph_debugfs_init();
 891
 892        ret = ceph_crypto_init();
 893        if (ret < 0)
 894                goto out_debugfs;
 895
 896        ret = ceph_msgr_init();
 897        if (ret < 0)
 898                goto out_crypto;
 899
 900        ret = ceph_osdc_setup();
 901        if (ret < 0)
 902                goto out_msgr;
 903
 904        pr_info("loaded (mon/osd proto %d/%d)\n",
 905                CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL);
 906
 907        return 0;
 908
 909out_msgr:
 910        ceph_msgr_exit();
 911out_crypto:
 912        ceph_crypto_shutdown();
 913out_debugfs:
 914        ceph_debugfs_cleanup();
 915        return ret;
 916}
 917
 918static void __exit exit_ceph_lib(void)
 919{
 920        dout("exit_ceph_lib\n");
 921        WARN_ON(!ceph_strings_empty());
 922
 923        ceph_osdc_cleanup();
 924        ceph_msgr_exit();
 925        ceph_crypto_shutdown();
 926        ceph_debugfs_cleanup();
 927}
 928
 929module_init(init_ceph_lib);
 930module_exit(exit_ceph_lib);
 931
 932MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
 933MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
 934MODULE_AUTHOR("Patience Warnick <patience@newdream.net>");
 935MODULE_DESCRIPTION("Ceph core library");
 936MODULE_LICENSE("GPL");
 937