libceph: remove 'osdtimeout' option
[linux-2.6.git] / net / ceph / ceph_common.c
index 95f96ab..b11448f 100644 (file)
@@ -5,6 +5,8 @@
 #include <linux/fs.h>
 #include <linux/inet.h>
 #include <linux/in6.h>
+#include <linux/key.h>
+#include <keys/ceph-type.h>
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/parser.h>
@@ -20,6 +22,7 @@
 #include <linux/ceph/decode.h>
 #include <linux/ceph/mon_client.h>
 #include <linux/ceph/auth.h>
+#include "crypto.h"
 
 
 
@@ -80,10 +83,7 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
                        return -1;
                }
        } else {
-               pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
                memcpy(&client->fsid, fsid, sizeof(*fsid));
-               ceph_debugfs_client_init(client);
-               client->have_fsid = true;
        }
        return 0;
 }
@@ -117,9 +117,29 @@ int ceph_compare_options(struct ceph_options *new_opt,
        if (ret)
                return ret;
 
-       ret = strcmp_null(opt1->secret, opt2->secret);
-       if (ret)
-               return ret;
+       if (opt1->key && !opt2->key)
+               return -1;
+       if (!opt1->key && opt2->key)
+               return 1;
+       if (opt1->key && opt2->key) {
+               if (opt1->key->type != opt2->key->type)
+                       return -1;
+               if (opt1->key->created.tv_sec != opt2->key->created.tv_sec)
+                       return -1;
+               if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec)
+                       return -1;
+               if (opt1->key->len != opt2->key->len)
+                       return -1;
+               if (opt1->key->key && !opt2->key->key)
+                       return -1;
+               if (!opt1->key->key && opt2->key->key)
+                       return 1;
+               if (opt1->key->key && opt2->key->key) {
+                       ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len);
+                       if (ret)
+                               return ret;
+               }
+       }
 
        /* any matching mon ip implies a match */
        for (i = 0; i < opt1->num_mon; i++) {
@@ -176,10 +196,13 @@ enum {
        Opt_fsid,
        Opt_name,
        Opt_secret,
+       Opt_key,
        Opt_ip,
        Opt_last_string,
        /* string args above */
+       Opt_share,
        Opt_noshare,
+       Opt_crc,
        Opt_nocrc,
 };
 
@@ -192,9 +215,12 @@ static match_table_t opt_tokens = {
        {Opt_fsid, "fsid=%s"},
        {Opt_name, "name=%s"},
        {Opt_secret, "secret=%s"},
+       {Opt_key, "key=%s"},
        {Opt_ip, "ip=%s"},
        /* string args above */
+       {Opt_share, "share"},
        {Opt_noshare, "noshare"},
+       {Opt_crc, "crc"},
        {Opt_nocrc, "nocrc"},
        {-1, NULL}
 };
@@ -203,15 +229,62 @@ void ceph_destroy_options(struct ceph_options *opt)
 {
        dout("destroy_options %p\n", opt);
        kfree(opt->name);
-       kfree(opt->secret);
+       if (opt->key) {
+               ceph_crypto_key_destroy(opt->key);
+               kfree(opt->key);
+       }
+       kfree(opt->mon_addr);
        kfree(opt);
 }
 EXPORT_SYMBOL(ceph_destroy_options);
 
-int ceph_parse_options(struct ceph_options **popt, char *options,
-                      const char *dev_name, const char *dev_name_end,
-                      int (*parse_extra_token)(char *c, void *private),
-                      void *private)
+/* get secret from key store */
+static int get_secret(struct ceph_crypto_key *dst, const char *name) {
+       struct key *ukey;
+       int key_err;
+       int err = 0;
+       struct ceph_crypto_key *ckey;
+
+       ukey = request_key(&key_type_ceph, name, NULL);
+       if (!ukey || IS_ERR(ukey)) {
+               /* request_key errors don't map nicely to mount(2)
+                  errors; don't even try, but still printk */
+               key_err = PTR_ERR(ukey);
+               switch (key_err) {
+               case -ENOKEY:
+                       pr_warning("ceph: Mount failed due to key not found: %s\n", name);
+                       break;
+               case -EKEYEXPIRED:
+                       pr_warning("ceph: Mount failed due to expired key: %s\n", name);
+                       break;
+               case -EKEYREVOKED:
+                       pr_warning("ceph: Mount failed due to revoked key: %s\n", name);
+                       break;
+               default:
+                       pr_warning("ceph: Mount failed due to unknown key error"
+                              " %d: %s\n", key_err, name);
+               }
+               err = -EPERM;
+               goto out;
+       }
+
+       ckey = ukey->payload.data;
+       err = ceph_crypto_key_clone(dst, ckey);
+       if (err)
+               goto out_key;
+       /* pass through, err is 0 */
+
+out_key:
+       key_put(ukey);
+out:
+       return err;
+}
+
+struct ceph_options *
+ceph_parse_options(char *options, const char *dev_name,
+                       const char *dev_name_end,
+                       int (*parse_extra_token)(char *c, void *private),
+                       void *private)
 {
        struct ceph_options *opt;
        const char *c;
@@ -220,7 +293,7 @@ int ceph_parse_options(struct ceph_options **popt, char *options,
 
        opt = kzalloc(sizeof(*opt), GFP_KERNEL);
        if (!opt)
-               return err;
+               return ERR_PTR(-ENOMEM);
        opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr),
                                GFP_KERNEL);
        if (!opt->mon_addr)
@@ -231,7 +304,6 @@ int ceph_parse_options(struct ceph_options **popt, char *options,
 
        /* start with defaults */
        opt->flags = CEPH_OPT_DEFAULT;
-       opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT;
        opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
        opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */
        opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;   /* seconds */
@@ -295,14 +367,29 @@ int ceph_parse_options(struct ceph_options **popt, char *options,
                                              GFP_KERNEL);
                        break;
                case Opt_secret:
-                       opt->secret = kstrndup(argstr[0].from,
-                                               argstr[0].to-argstr[0].from,
-                                               GFP_KERNEL);
+                       opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
+                       if (!opt->key) {
+                               err = -ENOMEM;
+                               goto out;
+                       }
+                       err = ceph_crypto_key_unarmor(opt->key, argstr[0].from);
+                       if (err < 0)
+                               goto out;
+                       break;
+               case Opt_key:
+                       opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
+                       if (!opt->key) {
+                               err = -ENOMEM;
+                               goto out;
+                       }
+                       err = get_secret(opt->key, argstr[0].from);
+                       if (err < 0)
+                               goto out;
                        break;
 
                        /* misc */
                case Opt_osdtimeout:
-                       opt->osd_timeout = intval;
+                       pr_warning("ignoring deprecated osdtimeout option\n");
                        break;
                case Opt_osdkeepalivetimeout:
                        opt->osd_keepalive_timeout = intval;
@@ -314,10 +401,16 @@ int ceph_parse_options(struct ceph_options **popt, char *options,
                        opt->mount_timeout = intval;
                        break;
 
+               case Opt_share:
+                       opt->flags &= ~CEPH_OPT_NOSHARE;
+                       break;
                case Opt_noshare:
                        opt->flags |= CEPH_OPT_NOSHARE;
                        break;
 
+               case Opt_crc:
+                       opt->flags &= ~CEPH_OPT_NOCRC;
+                       break;
                case Opt_nocrc:
                        opt->flags |= CEPH_OPT_NOCRC;
                        break;
@@ -328,12 +421,11 @@ int ceph_parse_options(struct ceph_options **popt, char *options,
        }
 
        /* success */
-       *popt = opt;
-       return 0;
+       return opt;
 
 out:
        ceph_destroy_options(opt);
-       return err;
+       return ERR_PTR(err);
 }
 EXPORT_SYMBOL(ceph_parse_options);
 
@@ -346,9 +438,12 @@ EXPORT_SYMBOL(ceph_client_id);
 /*
  * create a fresh client instance
  */
-struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
+struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private,
+                                      unsigned supported_features,
+                                      unsigned required_features)
 {
        struct ceph_client *client;
+       struct ceph_entity_addr *myaddr = NULL;
        int err = -ENOMEM;
 
        client = kzalloc(sizeof(*client), GFP_KERNEL);
@@ -363,10 +458,18 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
        client->auth_err = 0;
 
        client->extra_mon_dispatch = NULL;
-       client->supported_features = CEPH_FEATURE_SUPPORTED_DEFAULT;
-       client->required_features = CEPH_FEATURE_REQUIRED_DEFAULT;
-
-       client->msgr = NULL;
+       client->supported_features = CEPH_FEATURE_SUPPORTED_DEFAULT |
+               supported_features;
+       client->required_features = CEPH_FEATURE_REQUIRED_DEFAULT |
+               required_features;
+
+       /* msgr */
+       if (ceph_test_opt(client, MYIP))
+               myaddr = &client->options->my_addr;
+       ceph_messenger_init(&client->msgr, myaddr,
+               client->supported_features,
+               client->required_features,
+               ceph_test_opt(client, NOCRC));
 
        /* subsystems */
        err = ceph_monc_init(&client->monc, client);
@@ -390,23 +493,15 @@ void ceph_destroy_client(struct ceph_client *client)
 {
        dout("destroy_client %p\n", client);
 
+       atomic_set(&client->msgr.stopping, 1);
+
        /* unmount */
        ceph_osdc_stop(&client->osdc);
 
-       /*
-        * make sure mds and osd connections close out before destroying
-        * the auth module, which is needed to free those connections'
-        * ceph_authorizers.
-        */
-       ceph_msgr_flush();
-
        ceph_monc_stop(&client->monc);
 
        ceph_debugfs_client_cleanup(client);
 
-       if (client->msgr)
-               ceph_messenger_destroy(client->msgr);
-
        ceph_destroy_options(client->options);
 
        kfree(client);
@@ -428,24 +523,9 @@ static int have_mon_and_osd_map(struct ceph_client *client)
  */
 int __ceph_open_session(struct ceph_client *client, unsigned long started)
 {
-       struct ceph_entity_addr *myaddr = NULL;
        int err;
        unsigned long timeout = client->options->mount_timeout * HZ;
 
-       /* initialize the messenger */
-       if (client->msgr == NULL) {
-               if (ceph_test_opt(client, MYIP))
-                       myaddr = &client->options->my_addr;
-               client->msgr = ceph_messenger_create(myaddr,
-                                       client->supported_features,
-                                       client->required_features);
-               if (IS_ERR(client->msgr)) {
-                       client->msgr = NULL;
-                       return PTR_ERR(client->msgr);
-               }
-               client->msgr->nocrc = ceph_test_opt(client, NOCRC);
-       }
-
        /* open session, and wait for mon and osd maps */
        err = ceph_monc_open_session(&client->monc);
        if (err < 0)
@@ -496,10 +576,14 @@ static int __init init_ceph_lib(void)
        if (ret < 0)
                goto out;
 
-       ret = ceph_msgr_init();
+       ret = ceph_crypto_init();
        if (ret < 0)
                goto out_debugfs;
 
+       ret = ceph_msgr_init();
+       if (ret < 0)
+               goto out_crypto;
+
        pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n",
                CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL,
                CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT,
@@ -507,6 +591,8 @@ static int __init init_ceph_lib(void)
 
        return 0;
 
+out_crypto:
+       ceph_crypto_shutdown();
 out_debugfs:
        ceph_debugfs_cleanup();
 out:
@@ -517,6 +603,7 @@ static void __exit exit_ceph_lib(void)
 {
        dout("exit_ceph_lib\n");
        ceph_msgr_exit();
+       ceph_crypto_shutdown();
        ceph_debugfs_cleanup();
 }