diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/ceph/auth_x.c | 76 | ||||
| -rw-r--r-- | net/ceph/auth_x.h | 1 | ||||
| -rw-r--r-- | net/ceph/buffer.c | 4 | ||||
| -rw-r--r-- | net/ceph/ceph_common.c | 21 | ||||
| -rw-r--r-- | net/ceph/messenger.c | 34 | ||||
| -rw-r--r-- | net/ceph/osd_client.c | 118 |
6 files changed, 203 insertions, 51 deletions
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 7e38b729696a..15845814a0f2 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include <linux/ceph/decode.h> | 9 | #include <linux/ceph/decode.h> |
| 10 | #include <linux/ceph/auth.h> | 10 | #include <linux/ceph/auth.h> |
| 11 | #include <linux/ceph/messenger.h> | ||
| 11 | 12 | ||
| 12 | #include "crypto.h" | 13 | #include "crypto.h" |
| 13 | #include "auth_x.h" | 14 | #include "auth_x.h" |
| @@ -293,6 +294,11 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac, | |||
| 293 | dout("build_authorizer for %s %p\n", | 294 | dout("build_authorizer for %s %p\n", |
| 294 | ceph_entity_type_name(th->service), au); | 295 | ceph_entity_type_name(th->service), au); |
| 295 | 296 | ||
| 297 | ceph_crypto_key_destroy(&au->session_key); | ||
| 298 | ret = ceph_crypto_key_clone(&au->session_key, &th->session_key); | ||
| 299 | if (ret) | ||
| 300 | return ret; | ||
| 301 | |||
| 296 | maxlen = sizeof(*msg_a) + sizeof(msg_b) + | 302 | maxlen = sizeof(*msg_a) + sizeof(msg_b) + |
| 297 | ceph_x_encrypt_buflen(ticket_blob_len); | 303 | ceph_x_encrypt_buflen(ticket_blob_len); |
| 298 | dout(" need len %d\n", maxlen); | 304 | dout(" need len %d\n", maxlen); |
| @@ -302,8 +308,10 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac, | |||
| 302 | } | 308 | } |
| 303 | if (!au->buf) { | 309 | if (!au->buf) { |
| 304 | au->buf = ceph_buffer_new(maxlen, GFP_NOFS); | 310 | au->buf = ceph_buffer_new(maxlen, GFP_NOFS); |
| 305 | if (!au->buf) | 311 | if (!au->buf) { |
| 312 | ceph_crypto_key_destroy(&au->session_key); | ||
| 306 | return -ENOMEM; | 313 | return -ENOMEM; |
| 314 | } | ||
| 307 | } | 315 | } |
| 308 | au->service = th->service; | 316 | au->service = th->service; |
| 309 | au->secret_id = th->secret_id; | 317 | au->secret_id = th->secret_id; |
| @@ -329,7 +337,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac, | |||
| 329 | get_random_bytes(&au->nonce, sizeof(au->nonce)); | 337 | get_random_bytes(&au->nonce, sizeof(au->nonce)); |
| 330 | msg_b.struct_v = 1; | 338 | msg_b.struct_v = 1; |
| 331 | msg_b.nonce = cpu_to_le64(au->nonce); | 339 | msg_b.nonce = cpu_to_le64(au->nonce); |
| 332 | ret = ceph_x_encrypt(&th->session_key, &msg_b, sizeof(msg_b), | 340 | ret = ceph_x_encrypt(&au->session_key, &msg_b, sizeof(msg_b), |
| 333 | p, end - p); | 341 | p, end - p); |
| 334 | if (ret < 0) | 342 | if (ret < 0) |
| 335 | goto out_buf; | 343 | goto out_buf; |
| @@ -560,6 +568,8 @@ static int ceph_x_create_authorizer( | |||
| 560 | auth->authorizer_buf_len = au->buf->vec.iov_len; | 568 | auth->authorizer_buf_len = au->buf->vec.iov_len; |
| 561 | auth->authorizer_reply_buf = au->reply_buf; | 569 | auth->authorizer_reply_buf = au->reply_buf; |
| 562 | auth->authorizer_reply_buf_len = sizeof (au->reply_buf); | 570 | auth->authorizer_reply_buf_len = sizeof (au->reply_buf); |
| 571 | auth->sign_message = ac->ops->sign_message; | ||
| 572 | auth->check_message_signature = ac->ops->check_message_signature; | ||
| 563 | 573 | ||
| 564 | return 0; | 574 | return 0; |
| 565 | } | 575 | } |
| @@ -588,17 +598,13 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac, | |||
| 588 | struct ceph_authorizer *a, size_t len) | 598 | struct ceph_authorizer *a, size_t len) |
| 589 | { | 599 | { |
| 590 | struct ceph_x_authorizer *au = (void *)a; | 600 | struct ceph_x_authorizer *au = (void *)a; |
| 591 | struct ceph_x_ticket_handler *th; | ||
| 592 | int ret = 0; | 601 | int ret = 0; |
| 593 | struct ceph_x_authorize_reply reply; | 602 | struct ceph_x_authorize_reply reply; |
| 594 | void *preply = &reply; | 603 | void *preply = &reply; |
| 595 | void *p = au->reply_buf; | 604 | void *p = au->reply_buf; |
| 596 | void *end = p + sizeof(au->reply_buf); | 605 | void *end = p + sizeof(au->reply_buf); |
| 597 | 606 | ||
| 598 | th = get_ticket_handler(ac, au->service); | 607 | ret = ceph_x_decrypt(&au->session_key, &p, end, &preply, sizeof(reply)); |
| 599 | if (IS_ERR(th)) | ||
| 600 | return PTR_ERR(th); | ||
| 601 | ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply)); | ||
| 602 | if (ret < 0) | 608 | if (ret < 0) |
| 603 | return ret; | 609 | return ret; |
| 604 | if (ret != sizeof(reply)) | 610 | if (ret != sizeof(reply)) |
| @@ -618,6 +624,7 @@ static void ceph_x_destroy_authorizer(struct ceph_auth_client *ac, | |||
| 618 | { | 624 | { |
| 619 | struct ceph_x_authorizer *au = (void *)a; | 625 | struct ceph_x_authorizer *au = (void *)a; |
| 620 | 626 | ||
| 627 | ceph_crypto_key_destroy(&au->session_key); | ||
| 621 | ceph_buffer_put(au->buf); | 628 | ceph_buffer_put(au->buf); |
| 622 | kfree(au); | 629 | kfree(au); |
| 623 | } | 630 | } |
| @@ -663,6 +670,59 @@ static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac, | |||
| 663 | memset(&th->validity, 0, sizeof(th->validity)); | 670 | memset(&th->validity, 0, sizeof(th->validity)); |
| 664 | } | 671 | } |
| 665 | 672 | ||
| 673 | static int calcu_signature(struct ceph_x_authorizer *au, | ||
| 674 | struct ceph_msg *msg, __le64 *sig) | ||
| 675 | { | ||
| 676 | int ret; | ||
| 677 | char tmp_enc[40]; | ||
| 678 | __le32 tmp[5] = { | ||
| 679 | 16u, msg->hdr.crc, msg->footer.front_crc, | ||
| 680 | msg->footer.middle_crc, msg->footer.data_crc, | ||
| 681 | }; | ||
| 682 | ret = ceph_x_encrypt(&au->session_key, &tmp, sizeof(tmp), | ||
| 683 | tmp_enc, sizeof(tmp_enc)); | ||
| 684 | if (ret < 0) | ||
| 685 | return ret; | ||
| 686 | *sig = *(__le64*)(tmp_enc + 4); | ||
| 687 | return 0; | ||
| 688 | } | ||
| 689 | |||
| 690 | static int ceph_x_sign_message(struct ceph_auth_handshake *auth, | ||
| 691 | struct ceph_msg *msg) | ||
| 692 | { | ||
| 693 | int ret; | ||
| 694 | if (!auth->authorizer) | ||
| 695 | return 0; | ||
| 696 | ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer, | ||
| 697 | msg, &msg->footer.sig); | ||
| 698 | if (ret < 0) | ||
| 699 | return ret; | ||
| 700 | msg->footer.flags |= CEPH_MSG_FOOTER_SIGNED; | ||
| 701 | return 0; | ||
| 702 | } | ||
| 703 | |||
| 704 | static int ceph_x_check_message_signature(struct ceph_auth_handshake *auth, | ||
| 705 | struct ceph_msg *msg) | ||
| 706 | { | ||
| 707 | __le64 sig_check; | ||
| 708 | int ret; | ||
| 709 | |||
| 710 | if (!auth->authorizer) | ||
| 711 | return 0; | ||
| 712 | ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer, | ||
| 713 | msg, &sig_check); | ||
| 714 | if (ret < 0) | ||
| 715 | return ret; | ||
| 716 | if (sig_check == msg->footer.sig) | ||
| 717 | return 0; | ||
| 718 | if (msg->footer.flags & CEPH_MSG_FOOTER_SIGNED) | ||
| 719 | dout("ceph_x_check_message_signature %p has signature %llx " | ||
| 720 | "expect %llx\n", msg, msg->footer.sig, sig_check); | ||
| 721 | else | ||
| 722 | dout("ceph_x_check_message_signature %p sender did not set " | ||
| 723 | "CEPH_MSG_FOOTER_SIGNED\n", msg); | ||
| 724 | return -EBADMSG; | ||
| 725 | } | ||
| 666 | 726 | ||
| 667 | static const struct ceph_auth_client_ops ceph_x_ops = { | 727 | static const struct ceph_auth_client_ops ceph_x_ops = { |
| 668 | .name = "x", | 728 | .name = "x", |
| @@ -677,6 +737,8 @@ static const struct ceph_auth_client_ops ceph_x_ops = { | |||
| 677 | .invalidate_authorizer = ceph_x_invalidate_authorizer, | 737 | .invalidate_authorizer = ceph_x_invalidate_authorizer, |
| 678 | .reset = ceph_x_reset, | 738 | .reset = ceph_x_reset, |
| 679 | .destroy = ceph_x_destroy, | 739 | .destroy = ceph_x_destroy, |
| 740 | .sign_message = ceph_x_sign_message, | ||
| 741 | .check_message_signature = ceph_x_check_message_signature, | ||
| 680 | }; | 742 | }; |
| 681 | 743 | ||
| 682 | 744 | ||
diff --git a/net/ceph/auth_x.h b/net/ceph/auth_x.h index 65ee72082d99..e8b7c6917d47 100644 --- a/net/ceph/auth_x.h +++ b/net/ceph/auth_x.h | |||
| @@ -26,6 +26,7 @@ struct ceph_x_ticket_handler { | |||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | struct ceph_x_authorizer { | 28 | struct ceph_x_authorizer { |
| 29 | struct ceph_crypto_key session_key; | ||
| 29 | struct ceph_buffer *buf; | 30 | struct ceph_buffer *buf; |
| 30 | unsigned int service; | 31 | unsigned int service; |
| 31 | u64 nonce; | 32 | u64 nonce; |
diff --git a/net/ceph/buffer.c b/net/ceph/buffer.c index 621b5f65407f..add5f921a0ff 100644 --- a/net/ceph/buffer.c +++ b/net/ceph/buffer.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <linux/ceph/buffer.h> | 7 | #include <linux/ceph/buffer.h> |
| 8 | #include <linux/ceph/decode.h> | 8 | #include <linux/ceph/decode.h> |
| 9 | #include <linux/ceph/libceph.h> /* for ceph_kv{malloc,free} */ | 9 | #include <linux/ceph/libceph.h> /* for ceph_kvmalloc */ |
| 10 | 10 | ||
| 11 | struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp) | 11 | struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp) |
| 12 | { | 12 | { |
| @@ -35,7 +35,7 @@ void ceph_buffer_release(struct kref *kref) | |||
| 35 | struct ceph_buffer *b = container_of(kref, struct ceph_buffer, kref); | 35 | struct ceph_buffer *b = container_of(kref, struct ceph_buffer, kref); |
| 36 | 36 | ||
| 37 | dout("buffer_release %p\n", b); | 37 | dout("buffer_release %p\n", b); |
| 38 | ceph_kvfree(b->vec.iov_base); | 38 | kvfree(b->vec.iov_base); |
| 39 | kfree(b); | 39 | kfree(b); |
| 40 | } | 40 | } |
| 41 | EXPORT_SYMBOL(ceph_buffer_release); | 41 | EXPORT_SYMBOL(ceph_buffer_release); |
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 58fbfe134f93..5d5ab67f516d 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
| @@ -184,14 +184,6 @@ void *ceph_kvmalloc(size_t size, gfp_t flags) | |||
| 184 | return __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL); | 184 | return __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL); |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | void ceph_kvfree(const void *ptr) | ||
| 188 | { | ||
| 189 | if (is_vmalloc_addr(ptr)) | ||
| 190 | vfree(ptr); | ||
| 191 | else | ||
| 192 | kfree(ptr); | ||
| 193 | } | ||
| 194 | |||
| 195 | 187 | ||
| 196 | static int parse_fsid(const char *str, struct ceph_fsid *fsid) | 188 | static int parse_fsid(const char *str, struct ceph_fsid *fsid) |
| 197 | { | 189 | { |
| @@ -245,6 +237,8 @@ enum { | |||
| 245 | Opt_noshare, | 237 | Opt_noshare, |
| 246 | Opt_crc, | 238 | Opt_crc, |
| 247 | Opt_nocrc, | 239 | Opt_nocrc, |
| 240 | Opt_cephx_require_signatures, | ||
| 241 | Opt_nocephx_require_signatures, | ||
| 248 | }; | 242 | }; |
| 249 | 243 | ||
| 250 | static match_table_t opt_tokens = { | 244 | static match_table_t opt_tokens = { |
| @@ -263,6 +257,8 @@ static match_table_t opt_tokens = { | |||
| 263 | {Opt_noshare, "noshare"}, | 257 | {Opt_noshare, "noshare"}, |
| 264 | {Opt_crc, "crc"}, | 258 | {Opt_crc, "crc"}, |
| 265 | {Opt_nocrc, "nocrc"}, | 259 | {Opt_nocrc, "nocrc"}, |
| 260 | {Opt_cephx_require_signatures, "cephx_require_signatures"}, | ||
| 261 | {Opt_nocephx_require_signatures, "nocephx_require_signatures"}, | ||
| 266 | {-1, NULL} | 262 | {-1, NULL} |
| 267 | }; | 263 | }; |
| 268 | 264 | ||
| @@ -461,6 +457,12 @@ ceph_parse_options(char *options, const char *dev_name, | |||
| 461 | case Opt_nocrc: | 457 | case Opt_nocrc: |
| 462 | opt->flags |= CEPH_OPT_NOCRC; | 458 | opt->flags |= CEPH_OPT_NOCRC; |
| 463 | break; | 459 | break; |
| 460 | case Opt_cephx_require_signatures: | ||
| 461 | opt->flags &= ~CEPH_OPT_NOMSGAUTH; | ||
| 462 | break; | ||
| 463 | case Opt_nocephx_require_signatures: | ||
| 464 | opt->flags |= CEPH_OPT_NOMSGAUTH; | ||
| 465 | break; | ||
| 464 | 466 | ||
| 465 | default: | 467 | default: |
| 466 | BUG_ON(token); | 468 | BUG_ON(token); |
| @@ -504,6 +506,9 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, | |||
| 504 | init_waitqueue_head(&client->auth_wq); | 506 | init_waitqueue_head(&client->auth_wq); |
| 505 | client->auth_err = 0; | 507 | client->auth_err = 0; |
| 506 | 508 | ||
| 509 | if (!ceph_test_opt(client, NOMSGAUTH)) | ||
| 510 | required_features |= CEPH_FEATURE_MSG_AUTH; | ||
| 511 | |||
| 507 | client->extra_mon_dispatch = NULL; | 512 | client->extra_mon_dispatch = NULL; |
| 508 | client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT | | 513 | client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT | |
| 509 | supported_features; | 514 | supported_features; |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 8d1653caffdb..33a2f201e460 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
| @@ -1196,8 +1196,18 @@ static void prepare_write_message_footer(struct ceph_connection *con) | |||
| 1196 | dout("prepare_write_message_footer %p\n", con); | 1196 | dout("prepare_write_message_footer %p\n", con); |
| 1197 | con->out_kvec_is_msg = true; | 1197 | con->out_kvec_is_msg = true; |
| 1198 | con->out_kvec[v].iov_base = &m->footer; | 1198 | con->out_kvec[v].iov_base = &m->footer; |
| 1199 | con->out_kvec[v].iov_len = sizeof(m->footer); | 1199 | if (con->peer_features & CEPH_FEATURE_MSG_AUTH) { |
| 1200 | con->out_kvec_bytes += sizeof(m->footer); | 1200 | if (con->ops->sign_message) |
| 1201 | con->ops->sign_message(con, m); | ||
| 1202 | else | ||
| 1203 | m->footer.sig = 0; | ||
| 1204 | con->out_kvec[v].iov_len = sizeof(m->footer); | ||
| 1205 | con->out_kvec_bytes += sizeof(m->footer); | ||
| 1206 | } else { | ||
| 1207 | m->old_footer.flags = m->footer.flags; | ||
| 1208 | con->out_kvec[v].iov_len = sizeof(m->old_footer); | ||
| 1209 | con->out_kvec_bytes += sizeof(m->old_footer); | ||
| 1210 | } | ||
| 1201 | con->out_kvec_left++; | 1211 | con->out_kvec_left++; |
| 1202 | con->out_more = m->more_to_follow; | 1212 | con->out_more = m->more_to_follow; |
| 1203 | con->out_msg_done = true; | 1213 | con->out_msg_done = true; |
| @@ -2249,6 +2259,7 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 2249 | int ret; | 2259 | int ret; |
| 2250 | unsigned int front_len, middle_len, data_len; | 2260 | unsigned int front_len, middle_len, data_len; |
| 2251 | bool do_datacrc = !con->msgr->nocrc; | 2261 | bool do_datacrc = !con->msgr->nocrc; |
| 2262 | bool need_sign = (con->peer_features & CEPH_FEATURE_MSG_AUTH); | ||
| 2252 | u64 seq; | 2263 | u64 seq; |
| 2253 | u32 crc; | 2264 | u32 crc; |
| 2254 | 2265 | ||
| @@ -2361,12 +2372,21 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 2361 | } | 2372 | } |
| 2362 | 2373 | ||
| 2363 | /* footer */ | 2374 | /* footer */ |
| 2364 | size = sizeof (m->footer); | 2375 | if (need_sign) |
| 2376 | size = sizeof(m->footer); | ||
| 2377 | else | ||
| 2378 | size = sizeof(m->old_footer); | ||
| 2379 | |||
| 2365 | end += size; | 2380 | end += size; |
| 2366 | ret = read_partial(con, end, size, &m->footer); | 2381 | ret = read_partial(con, end, size, &m->footer); |
| 2367 | if (ret <= 0) | 2382 | if (ret <= 0) |
| 2368 | return ret; | 2383 | return ret; |
| 2369 | 2384 | ||
| 2385 | if (!need_sign) { | ||
| 2386 | m->footer.flags = m->old_footer.flags; | ||
| 2387 | m->footer.sig = 0; | ||
| 2388 | } | ||
| 2389 | |||
| 2370 | dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n", | 2390 | dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n", |
| 2371 | m, front_len, m->footer.front_crc, middle_len, | 2391 | m, front_len, m->footer.front_crc, middle_len, |
| 2372 | m->footer.middle_crc, data_len, m->footer.data_crc); | 2392 | m->footer.middle_crc, data_len, m->footer.data_crc); |
| @@ -2390,6 +2410,12 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 2390 | return -EBADMSG; | 2410 | return -EBADMSG; |
| 2391 | } | 2411 | } |
| 2392 | 2412 | ||
| 2413 | if (need_sign && con->ops->check_message_signature && | ||
| 2414 | con->ops->check_message_signature(con, m)) { | ||
| 2415 | pr_err("read_partial_message %p signature check failed\n", m); | ||
| 2416 | return -EBADMSG; | ||
| 2417 | } | ||
| 2418 | |||
| 2393 | return 1; /* done! */ | 2419 | return 1; /* done! */ |
| 2394 | } | 2420 | } |
| 2395 | 2421 | ||
| @@ -3288,7 +3314,7 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) | |||
| 3288 | static void ceph_msg_free(struct ceph_msg *m) | 3314 | static void ceph_msg_free(struct ceph_msg *m) |
| 3289 | { | 3315 | { |
| 3290 | dout("%s %p\n", __func__, m); | 3316 | dout("%s %p\n", __func__, m); |
| 3291 | ceph_kvfree(m->front.iov_base); | 3317 | kvfree(m->front.iov_base); |
| 3292 | kmem_cache_free(ceph_msg_cache, m); | 3318 | kmem_cache_free(ceph_msg_cache, m); |
| 3293 | } | 3319 | } |
| 3294 | 3320 | ||
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 6f164289bde8..53299c7b0ca4 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
| @@ -292,6 +292,10 @@ static void osd_req_op_data_release(struct ceph_osd_request *osd_req, | |||
| 292 | ceph_osd_data_release(&op->cls.request_data); | 292 | ceph_osd_data_release(&op->cls.request_data); |
| 293 | ceph_osd_data_release(&op->cls.response_data); | 293 | ceph_osd_data_release(&op->cls.response_data); |
| 294 | break; | 294 | break; |
| 295 | case CEPH_OSD_OP_SETXATTR: | ||
| 296 | case CEPH_OSD_OP_CMPXATTR: | ||
| 297 | ceph_osd_data_release(&op->xattr.osd_data); | ||
| 298 | break; | ||
| 295 | default: | 299 | default: |
| 296 | break; | 300 | break; |
| 297 | } | 301 | } |
| @@ -476,8 +480,7 @@ void osd_req_op_extent_init(struct ceph_osd_request *osd_req, | |||
| 476 | size_t payload_len = 0; | 480 | size_t payload_len = 0; |
| 477 | 481 | ||
| 478 | BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE && | 482 | BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE && |
| 479 | opcode != CEPH_OSD_OP_DELETE && opcode != CEPH_OSD_OP_ZERO && | 483 | opcode != CEPH_OSD_OP_ZERO && opcode != CEPH_OSD_OP_TRUNCATE); |
| 480 | opcode != CEPH_OSD_OP_TRUNCATE); | ||
| 481 | 484 | ||
| 482 | op->extent.offset = offset; | 485 | op->extent.offset = offset; |
| 483 | op->extent.length = length; | 486 | op->extent.length = length; |
| @@ -545,6 +548,39 @@ void osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which, | |||
| 545 | } | 548 | } |
| 546 | EXPORT_SYMBOL(osd_req_op_cls_init); | 549 | EXPORT_SYMBOL(osd_req_op_cls_init); |
| 547 | 550 | ||
| 551 | int osd_req_op_xattr_init(struct ceph_osd_request *osd_req, unsigned int which, | ||
| 552 | u16 opcode, const char *name, const void *value, | ||
| 553 | size_t size, u8 cmp_op, u8 cmp_mode) | ||
| 554 | { | ||
| 555 | struct ceph_osd_req_op *op = _osd_req_op_init(osd_req, which, opcode); | ||
| 556 | struct ceph_pagelist *pagelist; | ||
| 557 | size_t payload_len; | ||
| 558 | |||
| 559 | BUG_ON(opcode != CEPH_OSD_OP_SETXATTR && opcode != CEPH_OSD_OP_CMPXATTR); | ||
| 560 | |||
| 561 | pagelist = kmalloc(sizeof(*pagelist), GFP_NOFS); | ||
| 562 | if (!pagelist) | ||
| 563 | return -ENOMEM; | ||
| 564 | |||
| 565 | ceph_pagelist_init(pagelist); | ||
| 566 | |||
| 567 | payload_len = strlen(name); | ||
| 568 | op->xattr.name_len = payload_len; | ||
| 569 | ceph_pagelist_append(pagelist, name, payload_len); | ||
| 570 | |||
| 571 | op->xattr.value_len = size; | ||
| 572 | ceph_pagelist_append(pagelist, value, size); | ||
| 573 | payload_len += size; | ||
| 574 | |||
| 575 | op->xattr.cmp_op = cmp_op; | ||
| 576 | op->xattr.cmp_mode = cmp_mode; | ||
| 577 | |||
| 578 | ceph_osd_data_pagelist_init(&op->xattr.osd_data, pagelist); | ||
| 579 | op->payload_len = payload_len; | ||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | EXPORT_SYMBOL(osd_req_op_xattr_init); | ||
| 583 | |||
| 548 | void osd_req_op_watch_init(struct ceph_osd_request *osd_req, | 584 | void osd_req_op_watch_init(struct ceph_osd_request *osd_req, |
| 549 | unsigned int which, u16 opcode, | 585 | unsigned int which, u16 opcode, |
| 550 | u64 cookie, u64 version, int flag) | 586 | u64 cookie, u64 version, int flag) |
| @@ -626,7 +662,6 @@ static u64 osd_req_encode_op(struct ceph_osd_request *req, | |||
| 626 | case CEPH_OSD_OP_READ: | 662 | case CEPH_OSD_OP_READ: |
| 627 | case CEPH_OSD_OP_WRITE: | 663 | case CEPH_OSD_OP_WRITE: |
| 628 | case CEPH_OSD_OP_ZERO: | 664 | case CEPH_OSD_OP_ZERO: |
| 629 | case CEPH_OSD_OP_DELETE: | ||
| 630 | case CEPH_OSD_OP_TRUNCATE: | 665 | case CEPH_OSD_OP_TRUNCATE: |
| 631 | if (src->op == CEPH_OSD_OP_WRITE) | 666 | if (src->op == CEPH_OSD_OP_WRITE) |
| 632 | request_data_len = src->extent.length; | 667 | request_data_len = src->extent.length; |
| @@ -676,6 +711,19 @@ static u64 osd_req_encode_op(struct ceph_osd_request *req, | |||
| 676 | dst->alloc_hint.expected_write_size = | 711 | dst->alloc_hint.expected_write_size = |
| 677 | cpu_to_le64(src->alloc_hint.expected_write_size); | 712 | cpu_to_le64(src->alloc_hint.expected_write_size); |
| 678 | break; | 713 | break; |
| 714 | case CEPH_OSD_OP_SETXATTR: | ||
| 715 | case CEPH_OSD_OP_CMPXATTR: | ||
| 716 | dst->xattr.name_len = cpu_to_le32(src->xattr.name_len); | ||
| 717 | dst->xattr.value_len = cpu_to_le32(src->xattr.value_len); | ||
| 718 | dst->xattr.cmp_op = src->xattr.cmp_op; | ||
| 719 | dst->xattr.cmp_mode = src->xattr.cmp_mode; | ||
| 720 | osd_data = &src->xattr.osd_data; | ||
| 721 | ceph_osdc_msg_data_add(req->r_request, osd_data); | ||
| 722 | request_data_len = osd_data->pagelist->length; | ||
| 723 | break; | ||
| 724 | case CEPH_OSD_OP_CREATE: | ||
| 725 | case CEPH_OSD_OP_DELETE: | ||
| 726 | break; | ||
| 679 | default: | 727 | default: |
| 680 | pr_err("unsupported osd opcode %s\n", | 728 | pr_err("unsupported osd opcode %s\n", |
| 681 | ceph_osd_op_name(src->op)); | 729 | ceph_osd_op_name(src->op)); |
| @@ -705,7 +753,8 @@ static u64 osd_req_encode_op(struct ceph_osd_request *req, | |||
| 705 | struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, | 753 | struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, |
| 706 | struct ceph_file_layout *layout, | 754 | struct ceph_file_layout *layout, |
| 707 | struct ceph_vino vino, | 755 | struct ceph_vino vino, |
| 708 | u64 off, u64 *plen, int num_ops, | 756 | u64 off, u64 *plen, |
| 757 | unsigned int which, int num_ops, | ||
| 709 | int opcode, int flags, | 758 | int opcode, int flags, |
| 710 | struct ceph_snap_context *snapc, | 759 | struct ceph_snap_context *snapc, |
| 711 | u32 truncate_seq, | 760 | u32 truncate_seq, |
| @@ -716,13 +765,11 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, | |||
| 716 | u64 objnum = 0; | 765 | u64 objnum = 0; |
| 717 | u64 objoff = 0; | 766 | u64 objoff = 0; |
| 718 | u64 objlen = 0; | 767 | u64 objlen = 0; |
| 719 | u32 object_size; | ||
| 720 | u64 object_base; | ||
| 721 | int r; | 768 | int r; |
| 722 | 769 | ||
| 723 | BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE && | 770 | BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE && |
| 724 | opcode != CEPH_OSD_OP_DELETE && opcode != CEPH_OSD_OP_ZERO && | 771 | opcode != CEPH_OSD_OP_ZERO && opcode != CEPH_OSD_OP_TRUNCATE && |
| 725 | opcode != CEPH_OSD_OP_TRUNCATE); | 772 | opcode != CEPH_OSD_OP_CREATE && opcode != CEPH_OSD_OP_DELETE); |
| 726 | 773 | ||
| 727 | req = ceph_osdc_alloc_request(osdc, snapc, num_ops, use_mempool, | 774 | req = ceph_osdc_alloc_request(osdc, snapc, num_ops, use_mempool, |
| 728 | GFP_NOFS); | 775 | GFP_NOFS); |
| @@ -738,29 +785,24 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, | |||
| 738 | return ERR_PTR(r); | 785 | return ERR_PTR(r); |
| 739 | } | 786 | } |
| 740 | 787 | ||
| 741 | object_size = le32_to_cpu(layout->fl_object_size); | 788 | if (opcode == CEPH_OSD_OP_CREATE || opcode == CEPH_OSD_OP_DELETE) { |
| 742 | object_base = off - objoff; | 789 | osd_req_op_init(req, which, opcode); |
| 743 | if (!(truncate_seq == 1 && truncate_size == -1ULL)) { | 790 | } else { |
| 744 | if (truncate_size <= object_base) { | 791 | u32 object_size = le32_to_cpu(layout->fl_object_size); |
| 745 | truncate_size = 0; | 792 | u32 object_base = off - objoff; |
| 746 | } else { | 793 | if (!(truncate_seq == 1 && truncate_size == -1ULL)) { |
| 747 | truncate_size -= object_base; | 794 | if (truncate_size <= object_base) { |
| 748 | if (truncate_size > object_size) | 795 | truncate_size = 0; |
| 749 | truncate_size = object_size; | 796 | } else { |
| 797 | truncate_size -= object_base; | ||
| 798 | if (truncate_size > object_size) | ||
| 799 | truncate_size = object_size; | ||
| 800 | } | ||
| 750 | } | 801 | } |
| 802 | osd_req_op_extent_init(req, which, opcode, objoff, objlen, | ||
| 803 | truncate_size, truncate_seq); | ||
| 751 | } | 804 | } |
| 752 | 805 | ||
| 753 | osd_req_op_extent_init(req, 0, opcode, objoff, objlen, | ||
| 754 | truncate_size, truncate_seq); | ||
| 755 | |||
| 756 | /* | ||
| 757 | * A second op in the ops array means the caller wants to | ||
| 758 | * also issue a include a 'startsync' command so that the | ||
| 759 | * osd will flush data quickly. | ||
| 760 | */ | ||
| 761 | if (num_ops > 1) | ||
| 762 | osd_req_op_init(req, 1, CEPH_OSD_OP_STARTSYNC); | ||
| 763 | |||
| 764 | req->r_base_oloc.pool = ceph_file_layout_pg_pool(*layout); | 806 | req->r_base_oloc.pool = ceph_file_layout_pg_pool(*layout); |
| 765 | 807 | ||
| 766 | snprintf(req->r_base_oid.name, sizeof(req->r_base_oid.name), | 808 | snprintf(req->r_base_oid.name, sizeof(req->r_base_oid.name), |
| @@ -2626,7 +2668,7 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc, | |||
| 2626 | 2668 | ||
| 2627 | dout("readpages on ino %llx.%llx on %llu~%llu\n", vino.ino, | 2669 | dout("readpages on ino %llx.%llx on %llu~%llu\n", vino.ino, |
| 2628 | vino.snap, off, *plen); | 2670 | vino.snap, off, *plen); |
| 2629 | req = ceph_osdc_new_request(osdc, layout, vino, off, plen, 1, | 2671 | req = ceph_osdc_new_request(osdc, layout, vino, off, plen, 0, 1, |
| 2630 | CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, | 2672 | CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, |
| 2631 | NULL, truncate_seq, truncate_size, | 2673 | NULL, truncate_seq, truncate_size, |
| 2632 | false); | 2674 | false); |
| @@ -2669,7 +2711,7 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino, | |||
| 2669 | int page_align = off & ~PAGE_MASK; | 2711 | int page_align = off & ~PAGE_MASK; |
| 2670 | 2712 | ||
| 2671 | BUG_ON(vino.snap != CEPH_NOSNAP); /* snapshots aren't writeable */ | 2713 | BUG_ON(vino.snap != CEPH_NOSNAP); /* snapshots aren't writeable */ |
| 2672 | req = ceph_osdc_new_request(osdc, layout, vino, off, &len, 1, | 2714 | req = ceph_osdc_new_request(osdc, layout, vino, off, &len, 0, 1, |
| 2673 | CEPH_OSD_OP_WRITE, | 2715 | CEPH_OSD_OP_WRITE, |
| 2674 | CEPH_OSD_FLAG_ONDISK | CEPH_OSD_FLAG_WRITE, | 2716 | CEPH_OSD_FLAG_ONDISK | CEPH_OSD_FLAG_WRITE, |
| 2675 | snapc, truncate_seq, truncate_size, | 2717 | snapc, truncate_seq, truncate_size, |
| @@ -2920,6 +2962,20 @@ static int invalidate_authorizer(struct ceph_connection *con) | |||
| 2920 | return ceph_monc_validate_auth(&osdc->client->monc); | 2962 | return ceph_monc_validate_auth(&osdc->client->monc); |
| 2921 | } | 2963 | } |
| 2922 | 2964 | ||
| 2965 | static int sign_message(struct ceph_connection *con, struct ceph_msg *msg) | ||
| 2966 | { | ||
| 2967 | struct ceph_osd *o = con->private; | ||
| 2968 | struct ceph_auth_handshake *auth = &o->o_auth; | ||
| 2969 | return ceph_auth_sign_message(auth, msg); | ||
| 2970 | } | ||
| 2971 | |||
| 2972 | static int check_message_signature(struct ceph_connection *con, struct ceph_msg *msg) | ||
| 2973 | { | ||
| 2974 | struct ceph_osd *o = con->private; | ||
| 2975 | struct ceph_auth_handshake *auth = &o->o_auth; | ||
| 2976 | return ceph_auth_check_message_signature(auth, msg); | ||
| 2977 | } | ||
| 2978 | |||
| 2923 | static const struct ceph_connection_operations osd_con_ops = { | 2979 | static const struct ceph_connection_operations osd_con_ops = { |
| 2924 | .get = get_osd_con, | 2980 | .get = get_osd_con, |
| 2925 | .put = put_osd_con, | 2981 | .put = put_osd_con, |
| @@ -2928,5 +2984,7 @@ static const struct ceph_connection_operations osd_con_ops = { | |||
| 2928 | .verify_authorizer_reply = verify_authorizer_reply, | 2984 | .verify_authorizer_reply = verify_authorizer_reply, |
| 2929 | .invalidate_authorizer = invalidate_authorizer, | 2985 | .invalidate_authorizer = invalidate_authorizer, |
| 2930 | .alloc_msg = alloc_msg, | 2986 | .alloc_msg = alloc_msg, |
| 2987 | .sign_message = sign_message, | ||
| 2988 | .check_message_signature = check_message_signature, | ||
| 2931 | .fault = osd_reset, | 2989 | .fault = osd_reset, |
| 2932 | }; | 2990 | }; |
