diff options
Diffstat (limited to 'net/ceph')
-rw-r--r-- | net/ceph/Kconfig | 1 | ||||
-rw-r--r-- | net/ceph/auth.c | 8 | ||||
-rw-r--r-- | net/ceph/auth_x.c | 8 | ||||
-rw-r--r-- | net/ceph/ceph_common.c | 112 | ||||
-rw-r--r-- | net/ceph/crypto.c | 73 | ||||
-rw-r--r-- | net/ceph/crypto.h | 4 | ||||
-rw-r--r-- | net/ceph/mon_client.c | 2 | ||||
-rw-r--r-- | net/ceph/osd_client.c | 14 |
8 files changed, 198 insertions, 24 deletions
diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig index ad424049b0cf..be683f2d401f 100644 --- a/net/ceph/Kconfig +++ b/net/ceph/Kconfig | |||
@@ -4,6 +4,7 @@ config CEPH_LIB | |||
4 | select LIBCRC32C | 4 | select LIBCRC32C |
5 | select CRYPTO_AES | 5 | select CRYPTO_AES |
6 | select CRYPTO | 6 | select CRYPTO |
7 | select KEYS | ||
7 | default n | 8 | default n |
8 | help | 9 | help |
9 | Choose Y or M here to include cephlib, which provides the | 10 | Choose Y or M here to include cephlib, which provides the |
diff --git a/net/ceph/auth.c b/net/ceph/auth.c index 549c1f43e1d5..b4bf4ac090f1 100644 --- a/net/ceph/auth.c +++ b/net/ceph/auth.c | |||
@@ -35,12 +35,12 @@ static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol) | |||
35 | /* | 35 | /* |
36 | * setup, teardown. | 36 | * setup, teardown. |
37 | */ | 37 | */ |
38 | struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret) | 38 | struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_crypto_key *key) |
39 | { | 39 | { |
40 | struct ceph_auth_client *ac; | 40 | struct ceph_auth_client *ac; |
41 | int ret; | 41 | int ret; |
42 | 42 | ||
43 | dout("auth_init name '%s' secret '%s'\n", name, secret); | 43 | dout("auth_init name '%s'\n", name); |
44 | 44 | ||
45 | ret = -ENOMEM; | 45 | ret = -ENOMEM; |
46 | ac = kzalloc(sizeof(*ac), GFP_NOFS); | 46 | ac = kzalloc(sizeof(*ac), GFP_NOFS); |
@@ -52,8 +52,8 @@ struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret) | |||
52 | ac->name = name; | 52 | ac->name = name; |
53 | else | 53 | else |
54 | ac->name = CEPH_AUTH_NAME_DEFAULT; | 54 | ac->name = CEPH_AUTH_NAME_DEFAULT; |
55 | dout("auth_init name %s secret %s\n", ac->name, secret); | 55 | dout("auth_init name %s\n", ac->name); |
56 | ac->secret = secret; | 56 | ac->key = key; |
57 | return ac; | 57 | return ac; |
58 | 58 | ||
59 | out: | 59 | out: |
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 7fd5dfcf6e18..1587dc6010c6 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c | |||
@@ -662,14 +662,16 @@ int ceph_x_init(struct ceph_auth_client *ac) | |||
662 | goto out; | 662 | goto out; |
663 | 663 | ||
664 | ret = -EINVAL; | 664 | ret = -EINVAL; |
665 | if (!ac->secret) { | 665 | if (!ac->key) { |
666 | pr_err("no secret set (for auth_x protocol)\n"); | 666 | pr_err("no secret set (for auth_x protocol)\n"); |
667 | goto out_nomem; | 667 | goto out_nomem; |
668 | } | 668 | } |
669 | 669 | ||
670 | ret = ceph_crypto_key_unarmor(&xi->secret, ac->secret); | 670 | ret = ceph_crypto_key_clone(&xi->secret, ac->key); |
671 | if (ret) | 671 | if (ret < 0) { |
672 | pr_err("cannot clone key: %d\n", ret); | ||
672 | goto out_nomem; | 673 | goto out_nomem; |
674 | } | ||
673 | 675 | ||
674 | xi->starting = true; | 676 | xi->starting = true; |
675 | xi->ticket_handlers = RB_ROOT; | 677 | xi->ticket_handlers = RB_ROOT; |
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 95f96ab94bba..132963abc266 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -5,6 +5,8 @@ | |||
5 | #include <linux/fs.h> | 5 | #include <linux/fs.h> |
6 | #include <linux/inet.h> | 6 | #include <linux/inet.h> |
7 | #include <linux/in6.h> | 7 | #include <linux/in6.h> |
8 | #include <linux/key.h> | ||
9 | #include <keys/ceph-type.h> | ||
8 | #include <linux/module.h> | 10 | #include <linux/module.h> |
9 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
10 | #include <linux/parser.h> | 12 | #include <linux/parser.h> |
@@ -20,6 +22,7 @@ | |||
20 | #include <linux/ceph/decode.h> | 22 | #include <linux/ceph/decode.h> |
21 | #include <linux/ceph/mon_client.h> | 23 | #include <linux/ceph/mon_client.h> |
22 | #include <linux/ceph/auth.h> | 24 | #include <linux/ceph/auth.h> |
25 | #include "crypto.h" | ||
23 | 26 | ||
24 | 27 | ||
25 | 28 | ||
@@ -117,9 +120,29 @@ int ceph_compare_options(struct ceph_options *new_opt, | |||
117 | if (ret) | 120 | if (ret) |
118 | return ret; | 121 | return ret; |
119 | 122 | ||
120 | ret = strcmp_null(opt1->secret, opt2->secret); | 123 | if (opt1->key && !opt2->key) |
121 | if (ret) | 124 | return -1; |
122 | return ret; | 125 | if (!opt1->key && opt2->key) |
126 | return 1; | ||
127 | if (opt1->key && opt2->key) { | ||
128 | if (opt1->key->type != opt2->key->type) | ||
129 | return -1; | ||
130 | if (opt1->key->created.tv_sec != opt2->key->created.tv_sec) | ||
131 | return -1; | ||
132 | if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec) | ||
133 | return -1; | ||
134 | if (opt1->key->len != opt2->key->len) | ||
135 | return -1; | ||
136 | if (opt1->key->key && !opt2->key->key) | ||
137 | return -1; | ||
138 | if (!opt1->key->key && opt2->key->key) | ||
139 | return 1; | ||
140 | if (opt1->key->key && opt2->key->key) { | ||
141 | ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len); | ||
142 | if (ret) | ||
143 | return ret; | ||
144 | } | ||
145 | } | ||
123 | 146 | ||
124 | /* any matching mon ip implies a match */ | 147 | /* any matching mon ip implies a match */ |
125 | for (i = 0; i < opt1->num_mon; i++) { | 148 | for (i = 0; i < opt1->num_mon; i++) { |
@@ -176,6 +199,7 @@ enum { | |||
176 | Opt_fsid, | 199 | Opt_fsid, |
177 | Opt_name, | 200 | Opt_name, |
178 | Opt_secret, | 201 | Opt_secret, |
202 | Opt_key, | ||
179 | Opt_ip, | 203 | Opt_ip, |
180 | Opt_last_string, | 204 | Opt_last_string, |
181 | /* string args above */ | 205 | /* string args above */ |
@@ -192,6 +216,7 @@ static match_table_t opt_tokens = { | |||
192 | {Opt_fsid, "fsid=%s"}, | 216 | {Opt_fsid, "fsid=%s"}, |
193 | {Opt_name, "name=%s"}, | 217 | {Opt_name, "name=%s"}, |
194 | {Opt_secret, "secret=%s"}, | 218 | {Opt_secret, "secret=%s"}, |
219 | {Opt_key, "key=%s"}, | ||
195 | {Opt_ip, "ip=%s"}, | 220 | {Opt_ip, "ip=%s"}, |
196 | /* string args above */ | 221 | /* string args above */ |
197 | {Opt_noshare, "noshare"}, | 222 | {Opt_noshare, "noshare"}, |
@@ -203,11 +228,56 @@ void ceph_destroy_options(struct ceph_options *opt) | |||
203 | { | 228 | { |
204 | dout("destroy_options %p\n", opt); | 229 | dout("destroy_options %p\n", opt); |
205 | kfree(opt->name); | 230 | kfree(opt->name); |
206 | kfree(opt->secret); | 231 | if (opt->key) { |
232 | ceph_crypto_key_destroy(opt->key); | ||
233 | kfree(opt->key); | ||
234 | } | ||
207 | kfree(opt); | 235 | kfree(opt); |
208 | } | 236 | } |
209 | EXPORT_SYMBOL(ceph_destroy_options); | 237 | EXPORT_SYMBOL(ceph_destroy_options); |
210 | 238 | ||
239 | /* get secret from key store */ | ||
240 | static int get_secret(struct ceph_crypto_key *dst, const char *name) { | ||
241 | struct key *ukey; | ||
242 | int key_err; | ||
243 | int err = 0; | ||
244 | struct ceph_crypto_key *ckey; | ||
245 | |||
246 | ukey = request_key(&key_type_ceph, name, NULL); | ||
247 | if (!ukey || IS_ERR(ukey)) { | ||
248 | /* request_key errors don't map nicely to mount(2) | ||
249 | errors; don't even try, but still printk */ | ||
250 | key_err = PTR_ERR(ukey); | ||
251 | switch (key_err) { | ||
252 | case -ENOKEY: | ||
253 | pr_warning("ceph: Mount failed due to key not found: %s\n", name); | ||
254 | break; | ||
255 | case -EKEYEXPIRED: | ||
256 | pr_warning("ceph: Mount failed due to expired key: %s\n", name); | ||
257 | break; | ||
258 | case -EKEYREVOKED: | ||
259 | pr_warning("ceph: Mount failed due to revoked key: %s\n", name); | ||
260 | break; | ||
261 | default: | ||
262 | pr_warning("ceph: Mount failed due to unknown key error" | ||
263 | " %d: %s\n", key_err, name); | ||
264 | } | ||
265 | err = -EPERM; | ||
266 | goto out; | ||
267 | } | ||
268 | |||
269 | ckey = ukey->payload.data; | ||
270 | err = ceph_crypto_key_clone(dst, ckey); | ||
271 | if (err) | ||
272 | goto out_key; | ||
273 | /* pass through, err is 0 */ | ||
274 | |||
275 | out_key: | ||
276 | key_put(ukey); | ||
277 | out: | ||
278 | return err; | ||
279 | } | ||
280 | |||
211 | int ceph_parse_options(struct ceph_options **popt, char *options, | 281 | int ceph_parse_options(struct ceph_options **popt, char *options, |
212 | const char *dev_name, const char *dev_name_end, | 282 | const char *dev_name, const char *dev_name_end, |
213 | int (*parse_extra_token)(char *c, void *private), | 283 | int (*parse_extra_token)(char *c, void *private), |
@@ -295,9 +365,24 @@ int ceph_parse_options(struct ceph_options **popt, char *options, | |||
295 | GFP_KERNEL); | 365 | GFP_KERNEL); |
296 | break; | 366 | break; |
297 | case Opt_secret: | 367 | case Opt_secret: |
298 | opt->secret = kstrndup(argstr[0].from, | 368 | opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); |
299 | argstr[0].to-argstr[0].from, | 369 | if (!opt->key) { |
300 | GFP_KERNEL); | 370 | err = -ENOMEM; |
371 | goto out; | ||
372 | } | ||
373 | err = ceph_crypto_key_unarmor(opt->key, argstr[0].from); | ||
374 | if (err < 0) | ||
375 | goto out; | ||
376 | break; | ||
377 | case Opt_key: | ||
378 | opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); | ||
379 | if (!opt->key) { | ||
380 | err = -ENOMEM; | ||
381 | goto out; | ||
382 | } | ||
383 | err = get_secret(opt->key, argstr[0].from); | ||
384 | if (err < 0) | ||
385 | goto out; | ||
301 | break; | 386 | break; |
302 | 387 | ||
303 | /* misc */ | 388 | /* misc */ |
@@ -394,8 +479,8 @@ void ceph_destroy_client(struct ceph_client *client) | |||
394 | ceph_osdc_stop(&client->osdc); | 479 | ceph_osdc_stop(&client->osdc); |
395 | 480 | ||
396 | /* | 481 | /* |
397 | * make sure mds and osd connections close out before destroying | 482 | * make sure osd connections close out before destroying the |
398 | * the auth module, which is needed to free those connections' | 483 | * auth module, which is needed to free those connections' |
399 | * ceph_authorizers. | 484 | * ceph_authorizers. |
400 | */ | 485 | */ |
401 | ceph_msgr_flush(); | 486 | ceph_msgr_flush(); |
@@ -496,10 +581,14 @@ static int __init init_ceph_lib(void) | |||
496 | if (ret < 0) | 581 | if (ret < 0) |
497 | goto out; | 582 | goto out; |
498 | 583 | ||
499 | ret = ceph_msgr_init(); | 584 | ret = ceph_crypto_init(); |
500 | if (ret < 0) | 585 | if (ret < 0) |
501 | goto out_debugfs; | 586 | goto out_debugfs; |
502 | 587 | ||
588 | ret = ceph_msgr_init(); | ||
589 | if (ret < 0) | ||
590 | goto out_crypto; | ||
591 | |||
503 | pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", | 592 | pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", |
504 | CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, | 593 | CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, |
505 | CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, | 594 | CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, |
@@ -507,6 +596,8 @@ static int __init init_ceph_lib(void) | |||
507 | 596 | ||
508 | return 0; | 597 | return 0; |
509 | 598 | ||
599 | out_crypto: | ||
600 | ceph_crypto_shutdown(); | ||
510 | out_debugfs: | 601 | out_debugfs: |
511 | ceph_debugfs_cleanup(); | 602 | ceph_debugfs_cleanup(); |
512 | out: | 603 | out: |
@@ -517,6 +608,7 @@ static void __exit exit_ceph_lib(void) | |||
517 | { | 608 | { |
518 | dout("exit_ceph_lib\n"); | 609 | dout("exit_ceph_lib\n"); |
519 | ceph_msgr_exit(); | 610 | ceph_msgr_exit(); |
611 | ceph_crypto_shutdown(); | ||
520 | ceph_debugfs_cleanup(); | 612 | ceph_debugfs_cleanup(); |
521 | } | 613 | } |
522 | 614 | ||
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 7b505b0c983f..5a8009c9e0cd 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c | |||
@@ -5,10 +5,23 @@ | |||
5 | #include <linux/scatterlist.h> | 5 | #include <linux/scatterlist.h> |
6 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
7 | #include <crypto/hash.h> | 7 | #include <crypto/hash.h> |
8 | #include <linux/key-type.h> | ||
8 | 9 | ||
10 | #include <keys/ceph-type.h> | ||
9 | #include <linux/ceph/decode.h> | 11 | #include <linux/ceph/decode.h> |
10 | #include "crypto.h" | 12 | #include "crypto.h" |
11 | 13 | ||
14 | int ceph_crypto_key_clone(struct ceph_crypto_key *dst, | ||
15 | const struct ceph_crypto_key *src) | ||
16 | { | ||
17 | memcpy(dst, src, sizeof(struct ceph_crypto_key)); | ||
18 | dst->key = kmalloc(src->len, GFP_NOFS); | ||
19 | if (!dst->key) | ||
20 | return -ENOMEM; | ||
21 | memcpy(dst->key, src->key, src->len); | ||
22 | return 0; | ||
23 | } | ||
24 | |||
12 | int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end) | 25 | int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end) |
13 | { | 26 | { |
14 | if (*p + sizeof(u16) + sizeof(key->created) + | 27 | if (*p + sizeof(u16) + sizeof(key->created) + |
@@ -410,3 +423,63 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, | |||
410 | return -EINVAL; | 423 | return -EINVAL; |
411 | } | 424 | } |
412 | } | 425 | } |
426 | |||
427 | int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) | ||
428 | { | ||
429 | struct ceph_crypto_key *ckey; | ||
430 | int ret; | ||
431 | void *p; | ||
432 | |||
433 | ret = -EINVAL; | ||
434 | if (datalen <= 0 || datalen > 32767 || !data) | ||
435 | goto err; | ||
436 | |||
437 | ret = key_payload_reserve(key, datalen); | ||
438 | if (ret < 0) | ||
439 | goto err; | ||
440 | |||
441 | ret = -ENOMEM; | ||
442 | ckey = kmalloc(sizeof(*ckey), GFP_KERNEL); | ||
443 | if (!ckey) | ||
444 | goto err; | ||
445 | |||
446 | /* TODO ceph_crypto_key_decode should really take const input */ | ||
447 | p = (void*)data; | ||
448 | ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); | ||
449 | if (ret < 0) | ||
450 | goto err_ckey; | ||
451 | |||
452 | key->payload.data = ckey; | ||
453 | return 0; | ||
454 | |||
455 | err_ckey: | ||
456 | kfree(ckey); | ||
457 | err: | ||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | int ceph_key_match(const struct key *key, const void *description) | ||
462 | { | ||
463 | return strcmp(key->description, description) == 0; | ||
464 | } | ||
465 | |||
466 | void ceph_key_destroy(struct key *key) { | ||
467 | struct ceph_crypto_key *ckey = key->payload.data; | ||
468 | |||
469 | ceph_crypto_key_destroy(ckey); | ||
470 | } | ||
471 | |||
472 | struct key_type key_type_ceph = { | ||
473 | .name = "ceph", | ||
474 | .instantiate = ceph_key_instantiate, | ||
475 | .match = ceph_key_match, | ||
476 | .destroy = ceph_key_destroy, | ||
477 | }; | ||
478 | |||
479 | int ceph_crypto_init(void) { | ||
480 | return register_key_type(&key_type_ceph); | ||
481 | } | ||
482 | |||
483 | void ceph_crypto_shutdown(void) { | ||
484 | unregister_key_type(&key_type_ceph); | ||
485 | } | ||
diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index f9eccace592b..1919d1550d75 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h | |||
@@ -19,6 +19,8 @@ static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key) | |||
19 | kfree(key->key); | 19 | kfree(key->key); |
20 | } | 20 | } |
21 | 21 | ||
22 | extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst, | ||
23 | const struct ceph_crypto_key *src); | ||
22 | extern int ceph_crypto_key_encode(struct ceph_crypto_key *key, | 24 | extern int ceph_crypto_key_encode(struct ceph_crypto_key *key, |
23 | void **p, void *end); | 25 | void **p, void *end); |
24 | extern int ceph_crypto_key_decode(struct ceph_crypto_key *key, | 26 | extern int ceph_crypto_key_decode(struct ceph_crypto_key *key, |
@@ -40,6 +42,8 @@ extern int ceph_encrypt2(struct ceph_crypto_key *secret, | |||
40 | void *dst, size_t *dst_len, | 42 | void *dst, size_t *dst_len, |
41 | const void *src1, size_t src1_len, | 43 | const void *src1, size_t src1_len, |
42 | const void *src2, size_t src2_len); | 44 | const void *src2, size_t src2_len); |
45 | extern int ceph_crypto_init(void); | ||
46 | extern void ceph_crypto_shutdown(void); | ||
43 | 47 | ||
44 | /* armor.c */ | 48 | /* armor.c */ |
45 | extern int ceph_armor(char *dst, const char *src, const char *end); | 49 | extern int ceph_armor(char *dst, const char *src, const char *end); |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 8a079399174a..cbe31fa45508 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -759,7 +759,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) | |||
759 | 759 | ||
760 | /* authentication */ | 760 | /* authentication */ |
761 | monc->auth = ceph_auth_init(cl->options->name, | 761 | monc->auth = ceph_auth_init(cl->options->name, |
762 | cl->options->secret); | 762 | cl->options->key); |
763 | if (IS_ERR(monc->auth)) | 763 | if (IS_ERR(monc->auth)) |
764 | return PTR_ERR(monc->auth); | 764 | return PTR_ERR(monc->auth); |
765 | monc->auth->want_keys = | 765 | monc->auth->want_keys = |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 02212ed50852..50af02737a3d 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -837,8 +837,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, | |||
837 | dout("moving osd to %p lru\n", req->r_osd); | 837 | dout("moving osd to %p lru\n", req->r_osd); |
838 | __move_osd_to_lru(osdc, req->r_osd); | 838 | __move_osd_to_lru(osdc, req->r_osd); |
839 | } | 839 | } |
840 | if (list_empty(&req->r_osd_item) && | 840 | if (list_empty(&req->r_linger_item)) |
841 | list_empty(&req->r_linger_item)) | ||
842 | req->r_osd = NULL; | 841 | req->r_osd = NULL; |
843 | } | 842 | } |
844 | 843 | ||
@@ -883,7 +882,8 @@ static void __unregister_linger_request(struct ceph_osd_client *osdc, | |||
883 | dout("moving osd to %p lru\n", req->r_osd); | 882 | dout("moving osd to %p lru\n", req->r_osd); |
884 | __move_osd_to_lru(osdc, req->r_osd); | 883 | __move_osd_to_lru(osdc, req->r_osd); |
885 | } | 884 | } |
886 | req->r_osd = NULL; | 885 | if (list_empty(&req->r_osd_item)) |
886 | req->r_osd = NULL; | ||
887 | } | 887 | } |
888 | } | 888 | } |
889 | 889 | ||
@@ -917,7 +917,7 @@ EXPORT_SYMBOL(ceph_osdc_set_request_linger); | |||
917 | /* | 917 | /* |
918 | * Pick an osd (the first 'up' osd in the pg), allocate the osd struct | 918 | * Pick an osd (the first 'up' osd in the pg), allocate the osd struct |
919 | * (as needed), and set the request r_osd appropriately. If there is | 919 | * (as needed), and set the request r_osd appropriately. If there is |
920 | * no up osd, set r_osd to NULL. Move the request to the appropiate list | 920 | * no up osd, set r_osd to NULL. Move the request to the appropriate list |
921 | * (unsent, homeless) or leave on in-flight lru. | 921 | * (unsent, homeless) or leave on in-flight lru. |
922 | * | 922 | * |
923 | * Return 0 if unchanged, 1 if changed, or negative on error. | 923 | * Return 0 if unchanged, 1 if changed, or negative on error. |
@@ -1602,11 +1602,11 @@ void handle_watch_notify(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
1602 | cookie, ver, event); | 1602 | cookie, ver, event); |
1603 | if (event) { | 1603 | if (event) { |
1604 | event_work = kmalloc(sizeof(*event_work), GFP_NOIO); | 1604 | event_work = kmalloc(sizeof(*event_work), GFP_NOIO); |
1605 | INIT_WORK(&event_work->work, do_event_work); | ||
1606 | if (!event_work) { | 1605 | if (!event_work) { |
1607 | dout("ERROR: could not allocate event_work\n"); | 1606 | dout("ERROR: could not allocate event_work\n"); |
1608 | goto done_err; | 1607 | goto done_err; |
1609 | } | 1608 | } |
1609 | INIT_WORK(&event_work->work, do_event_work); | ||
1610 | event_work->event = event; | 1610 | event_work->event = event; |
1611 | event_work->ver = ver; | 1611 | event_work->ver = ver; |
1612 | event_work->notify_id = notify_id; | 1612 | event_work->notify_id = notify_id; |
@@ -1672,7 +1672,7 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
1672 | if (req->r_sent == 0) { | 1672 | if (req->r_sent == 0) { |
1673 | rc = __map_request(osdc, req); | 1673 | rc = __map_request(osdc, req); |
1674 | if (rc < 0) | 1674 | if (rc < 0) |
1675 | return rc; | 1675 | goto out_unlock; |
1676 | if (req->r_osd == NULL) { | 1676 | if (req->r_osd == NULL) { |
1677 | dout("send_request %p no up osds in pg\n", req); | 1677 | dout("send_request %p no up osds in pg\n", req); |
1678 | ceph_monc_request_next_osdmap(&osdc->client->monc); | 1678 | ceph_monc_request_next_osdmap(&osdc->client->monc); |
@@ -1689,6 +1689,8 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
1689 | } | 1689 | } |
1690 | } | 1690 | } |
1691 | } | 1691 | } |
1692 | |||
1693 | out_unlock: | ||
1692 | mutex_unlock(&osdc->request_mutex); | 1694 | mutex_unlock(&osdc->request_mutex); |
1693 | up_read(&osdc->map_sem); | 1695 | up_read(&osdc->map_sem); |
1694 | return rc; | 1696 | return rc; |