aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Dryomov <ilya.dryomov@inktank.com>2014-05-13 03:19:26 -0400
committerYan, Zheng <zheng.z.yan@intel.com>2014-06-05 21:29:57 -0400
commit513a8243d67f8e8d27f2883bd2f18bc87c7ca376 (patch)
treefd782278a338b2e8b695f47950628dc82d246c5d
parent002b36ba5ef7a0e2ad0392130a71029765136cf0 (diff)
libceph: mon_get_version request infrastructure
Add support for mon_get_version requests to libceph. This reuses much of the ceph_mon_generic_request infrastructure, with one exception. Older OSDs don't set mon_get_version reply hdr->tid even if the original request had a non-zero tid, which makes it impossible to lookup ceph_mon_generic_request contexts by tid in get_generic_reply() for such replies. As a workaround, we allocate a reply message on the reply path. This can probably interfere with revoke, but I don't see a better way. Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com> Reviewed-by: Sage Weil <sage@inktank.com>
-rw-r--r--include/linux/ceph/mon_client.h9
-rw-r--r--net/ceph/ceph_common.c2
-rw-r--r--net/ceph/debugfs.c2
-rw-r--r--net/ceph/mon_client.c123
4 files changed, 128 insertions, 8 deletions
diff --git a/include/linux/ceph/mon_client.h b/include/linux/ceph/mon_client.h
index a486f390dfbe..585ef9450e9d 100644
--- a/include/linux/ceph/mon_client.h
+++ b/include/linux/ceph/mon_client.h
@@ -40,9 +40,9 @@ struct ceph_mon_request {
40}; 40};
41 41
42/* 42/*
43 * ceph_mon_generic_request is being used for the statfs and poolop requests 43 * ceph_mon_generic_request is being used for the statfs, poolop and
44 * which are bening done a bit differently because we need to get data back 44 * mon_get_version requests which are being done a bit differently
45 * to the caller 45 * because we need to get data back to the caller
46 */ 46 */
47struct ceph_mon_generic_request { 47struct ceph_mon_generic_request {
48 struct kref kref; 48 struct kref kref;
@@ -108,6 +108,9 @@ extern void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc);
108extern int ceph_monc_do_statfs(struct ceph_mon_client *monc, 108extern int ceph_monc_do_statfs(struct ceph_mon_client *monc,
109 struct ceph_statfs *buf); 109 struct ceph_statfs *buf);
110 110
111extern int ceph_monc_do_get_version(struct ceph_mon_client *monc,
112 const char *what, u64 *newest);
113
111extern int ceph_monc_open_session(struct ceph_mon_client *monc); 114extern int ceph_monc_open_session(struct ceph_mon_client *monc);
112 115
113extern int ceph_monc_validate_auth(struct ceph_mon_client *monc); 116extern int ceph_monc_validate_auth(struct ceph_mon_client *monc);
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
index 67d7721d237e..1675021d8c12 100644
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -72,6 +72,8 @@ const char *ceph_msg_type_name(int type)
72 case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack"; 72 case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack";
73 case CEPH_MSG_STATFS: return "statfs"; 73 case CEPH_MSG_STATFS: return "statfs";
74 case CEPH_MSG_STATFS_REPLY: return "statfs_reply"; 74 case CEPH_MSG_STATFS_REPLY: return "statfs_reply";
75 case CEPH_MSG_MON_GET_VERSION: return "mon_get_version";
76 case CEPH_MSG_MON_GET_VERSION_REPLY: return "mon_get_version_reply";
75 case CEPH_MSG_MDS_MAP: return "mds_map"; 77 case CEPH_MSG_MDS_MAP: return "mds_map";
76 case CEPH_MSG_CLIENT_SESSION: return "client_session"; 78 case CEPH_MSG_CLIENT_SESSION: return "client_session";
77 case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect"; 79 case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect";
diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c
index 8903dcee8d8e..d1a62c69a9f4 100644
--- a/net/ceph/debugfs.c
+++ b/net/ceph/debugfs.c
@@ -129,6 +129,8 @@ static int monc_show(struct seq_file *s, void *p)
129 seq_printf(s, "%llu statfs\n", req->tid); 129 seq_printf(s, "%llu statfs\n", req->tid);
130 else if (op == CEPH_MSG_POOLOP) 130 else if (op == CEPH_MSG_POOLOP)
131 seq_printf(s, "%llu poolop\n", req->tid); 131 seq_printf(s, "%llu poolop\n", req->tid);
132 else if (op == CEPH_MSG_MON_GET_VERSION)
133 seq_printf(s, "%llu mon_get_version", req->tid);
132 else 134 else
133 seq_printf(s, "%llu unknown\n", req->tid); 135 seq_printf(s, "%llu unknown\n", req->tid);
134 } 136 }
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
index 2ac9ef35110b..11d8d2f2708a 100644
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -477,14 +477,13 @@ static struct ceph_msg *get_generic_reply(struct ceph_connection *con,
477 return m; 477 return m;
478} 478}
479 479
480static int do_generic_request(struct ceph_mon_client *monc, 480static int __do_generic_request(struct ceph_mon_client *monc, u64 tid,
481 struct ceph_mon_generic_request *req) 481 struct ceph_mon_generic_request *req)
482{ 482{
483 int err; 483 int err;
484 484
485 /* register request */ 485 /* register request */
486 mutex_lock(&monc->mutex); 486 req->tid = tid != 0 ? tid : ++monc->last_tid;
487 req->tid = ++monc->last_tid;
488 req->request->hdr.tid = cpu_to_le64(req->tid); 487 req->request->hdr.tid = cpu_to_le64(req->tid);
489 __insert_generic_request(monc, req); 488 __insert_generic_request(monc, req);
490 monc->num_generic_requests++; 489 monc->num_generic_requests++;
@@ -496,13 +495,24 @@ static int do_generic_request(struct ceph_mon_client *monc,
496 mutex_lock(&monc->mutex); 495 mutex_lock(&monc->mutex);
497 rb_erase(&req->node, &monc->generic_request_tree); 496 rb_erase(&req->node, &monc->generic_request_tree);
498 monc->num_generic_requests--; 497 monc->num_generic_requests--;
499 mutex_unlock(&monc->mutex);
500 498
501 if (!err) 499 if (!err)
502 err = req->result; 500 err = req->result;
503 return err; 501 return err;
504} 502}
505 503
504static int do_generic_request(struct ceph_mon_client *monc,
505 struct ceph_mon_generic_request *req)
506{
507 int err;
508
509 mutex_lock(&monc->mutex);
510 err = __do_generic_request(monc, 0, req);
511 mutex_unlock(&monc->mutex);
512
513 return err;
514}
515
506/* 516/*
507 * statfs 517 * statfs
508 */ 518 */
@@ -579,6 +589,96 @@ out:
579} 589}
580EXPORT_SYMBOL(ceph_monc_do_statfs); 590EXPORT_SYMBOL(ceph_monc_do_statfs);
581 591
592static void handle_get_version_reply(struct ceph_mon_client *monc,
593 struct ceph_msg *msg)
594{
595 struct ceph_mon_generic_request *req;
596 u64 tid = le64_to_cpu(msg->hdr.tid);
597 void *p = msg->front.iov_base;
598 void *end = p + msg->front_alloc_len;
599 u64 handle;
600
601 dout("%s %p tid %llu\n", __func__, msg, tid);
602
603 ceph_decode_need(&p, end, 2*sizeof(u64), bad);
604 handle = ceph_decode_64(&p);
605 if (tid != 0 && tid != handle)
606 goto bad;
607
608 mutex_lock(&monc->mutex);
609 req = __lookup_generic_req(monc, handle);
610 if (req) {
611 *(u64 *)req->buf = ceph_decode_64(&p);
612 req->result = 0;
613 get_generic_request(req);
614 }
615 mutex_unlock(&monc->mutex);
616 if (req) {
617 complete_all(&req->completion);
618 put_generic_request(req);
619 }
620
621 return;
622bad:
623 pr_err("corrupt mon_get_version reply\n");
624 ceph_msg_dump(msg);
625}
626
627/*
628 * Send MMonGetVersion and wait for the reply.
629 *
630 * @what: one of "mdsmap", "osdmap" or "monmap"
631 */
632int ceph_monc_do_get_version(struct ceph_mon_client *monc, const char *what,
633 u64 *newest)
634{
635 struct ceph_mon_generic_request *req;
636 void *p, *end;
637 u64 tid;
638 int err;
639
640 req = kzalloc(sizeof(*req), GFP_NOFS);
641 if (!req)
642 return -ENOMEM;
643
644 kref_init(&req->kref);
645 req->buf = newest;
646 req->buf_len = sizeof(*newest);
647 init_completion(&req->completion);
648
649 req->request = ceph_msg_new(CEPH_MSG_MON_GET_VERSION,
650 sizeof(u64) + sizeof(u32) + strlen(what),
651 GFP_NOFS, true);
652 if (!req->request) {
653 err = -ENOMEM;
654 goto out;
655 }
656
657 req->reply = ceph_msg_new(CEPH_MSG_MON_GET_VERSION_REPLY, 1024,
658 GFP_NOFS, true);
659 if (!req->reply) {
660 err = -ENOMEM;
661 goto out;
662 }
663
664 p = req->request->front.iov_base;
665 end = p + req->request->front_alloc_len;
666
667 /* fill out request */
668 mutex_lock(&monc->mutex);
669 tid = ++monc->last_tid;
670 ceph_encode_64(&p, tid); /* handle */
671 ceph_encode_string(&p, end, what, strlen(what));
672
673 err = __do_generic_request(monc, tid, req);
674
675 mutex_unlock(&monc->mutex);
676out:
677 kref_put(&req->kref, release_generic_request);
678 return err;
679}
680EXPORT_SYMBOL(ceph_monc_do_get_version);
681
582/* 682/*
583 * pool ops 683 * pool ops
584 */ 684 */
@@ -981,6 +1081,10 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
981 handle_statfs_reply(monc, msg); 1081 handle_statfs_reply(monc, msg);
982 break; 1082 break;
983 1083
1084 case CEPH_MSG_MON_GET_VERSION_REPLY:
1085 handle_get_version_reply(monc, msg);
1086 break;
1087
984 case CEPH_MSG_POOLOP_REPLY: 1088 case CEPH_MSG_POOLOP_REPLY:
985 handle_poolop_reply(monc, msg); 1089 handle_poolop_reply(monc, msg);
986 break; 1090 break;
@@ -1029,6 +1133,15 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con,
1029 case CEPH_MSG_AUTH_REPLY: 1133 case CEPH_MSG_AUTH_REPLY:
1030 m = ceph_msg_get(monc->m_auth_reply); 1134 m = ceph_msg_get(monc->m_auth_reply);
1031 break; 1135 break;
1136 case CEPH_MSG_MON_GET_VERSION_REPLY:
1137 if (le64_to_cpu(hdr->tid) != 0)
1138 return get_generic_reply(con, hdr, skip);
1139
1140 /*
1141 * Older OSDs don't set reply tid even if the orignal
1142 * request had a non-zero tid. Workaround this weirdness
1143 * by falling through to the allocate case.
1144 */
1032 case CEPH_MSG_MON_MAP: 1145 case CEPH_MSG_MON_MAP:
1033 case CEPH_MSG_MDS_MAP: 1146 case CEPH_MSG_MDS_MAP:
1034 case CEPH_MSG_OSD_MAP: 1147 case CEPH_MSG_OSD_MAP: