diff options
author | Ilya Dryomov <ilya.dryomov@inktank.com> | 2014-05-13 03:19:26 -0400 |
---|---|---|
committer | Yan, Zheng <zheng.z.yan@intel.com> | 2014-06-05 21:29:57 -0400 |
commit | 513a8243d67f8e8d27f2883bd2f18bc87c7ca376 (patch) | |
tree | fd782278a338b2e8b695f47950628dc82d246c5d | |
parent | 002b36ba5ef7a0e2ad0392130a71029765136cf0 (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.h | 9 | ||||
-rw-r--r-- | net/ceph/ceph_common.c | 2 | ||||
-rw-r--r-- | net/ceph/debugfs.c | 2 | ||||
-rw-r--r-- | net/ceph/mon_client.c | 123 |
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 | */ |
47 | struct ceph_mon_generic_request { | 47 | struct 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); | |||
108 | extern int ceph_monc_do_statfs(struct ceph_mon_client *monc, | 108 | extern int ceph_monc_do_statfs(struct ceph_mon_client *monc, |
109 | struct ceph_statfs *buf); | 109 | struct ceph_statfs *buf); |
110 | 110 | ||
111 | extern int ceph_monc_do_get_version(struct ceph_mon_client *monc, | ||
112 | const char *what, u64 *newest); | ||
113 | |||
111 | extern int ceph_monc_open_session(struct ceph_mon_client *monc); | 114 | extern int ceph_monc_open_session(struct ceph_mon_client *monc); |
112 | 115 | ||
113 | extern int ceph_monc_validate_auth(struct ceph_mon_client *monc); | 116 | extern 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 | ||
480 | static int do_generic_request(struct ceph_mon_client *monc, | 480 | static 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 | ||
504 | static 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 | } |
580 | EXPORT_SYMBOL(ceph_monc_do_statfs); | 590 | EXPORT_SYMBOL(ceph_monc_do_statfs); |
581 | 591 | ||
592 | static 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; | ||
622 | bad: | ||
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 | */ | ||
632 | int 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); | ||
676 | out: | ||
677 | kref_put(&req->kref, release_generic_request); | ||
678 | return err; | ||
679 | } | ||
680 | EXPORT_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: |