aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-17 19:03:12 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-17 19:03:12 -0500
commit57666509b70030a9483d13222bfec8eec5db07df (patch)
tree1e0021c2aabc2ce8832e8c816e2aa94b0b77a323 /net
parent87c31b39abcb6fb6bd7d111200c9627a594bf6a9 (diff)
parent0aeff37abada9f8c08d2b10481a43d3ae406c823 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull ceph updates from Sage Weil: "The big item here is support for inline data for CephFS and for message signatures from Zheng. There are also several bug fixes, including interrupted flock request handling, 0-length xattrs, mksnap, cached readdir results, and a message version compat field. Finally there are several cleanups from Ilya, Dan, and Markus. Note that there is another series coming soon that fixes some bugs in the RBD 'lingering' requests, but it isn't quite ready yet" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: (27 commits) ceph: fix setting empty extended attribute ceph: fix mksnap crash ceph: do_sync is never initialized libceph: fixup includes in pagelist.h ceph: support inline data feature ceph: flush inline version ceph: convert inline data to normal data before data write ceph: sync read inline data ceph: fetch inline data when getting Fcr cap refs ceph: use getattr request to fetch inline data ceph: add inline data to pagecache ceph: parse inline data in MClientReply and MClientCaps libceph: specify position of extent operation libceph: add CREATE osd operation support libceph: add SETXATTR/CMPXATTR osd operations support rbd: don't treat CEPH_OSD_OP_DELETE as extent op ceph: remove unused stringification macros libceph: require cephx message signature by default ceph: introduce global empty snap context ceph: message versioning fixes ...
Diffstat (limited to 'net')
-rw-r--r--net/ceph/auth_x.c76
-rw-r--r--net/ceph/auth_x.h1
-rw-r--r--net/ceph/buffer.c4
-rw-r--r--net/ceph/ceph_common.c21
-rw-r--r--net/ceph/messenger.c34
-rw-r--r--net/ceph/osd_client.c118
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
673static 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
690static 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
704static 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
667static const struct ceph_auth_client_ops ceph_x_ops = { 727static 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
28struct ceph_x_authorizer { 28struct 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
11struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp) 11struct 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}
41EXPORT_SYMBOL(ceph_buffer_release); 41EXPORT_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
187void ceph_kvfree(const void *ptr)
188{
189 if (is_vmalloc_addr(ptr))
190 vfree(ptr);
191 else
192 kfree(ptr);
193}
194
195 187
196static int parse_fsid(const char *str, struct ceph_fsid *fsid) 188static 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
250static match_table_t opt_tokens = { 244static 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)
3288static void ceph_msg_free(struct ceph_msg *m) 3314static 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}
546EXPORT_SYMBOL(osd_req_op_cls_init); 549EXPORT_SYMBOL(osd_req_op_cls_init);
547 550
551int 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}
582EXPORT_SYMBOL(osd_req_op_xattr_init);
583
548void osd_req_op_watch_init(struct ceph_osd_request *osd_req, 584void 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,
705struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, 753struct 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
2965static 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
2972static 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
2923static const struct ceph_connection_operations osd_con_ops = { 2979static 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};