diff options
Diffstat (limited to 'net/ceph/mon_client.c')
| -rw-r--r-- | net/ceph/mon_client.c | 158 | 
1 files changed, 149 insertions, 9 deletions
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 1fe25cd29d0..067d3af2eaf 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -152,7 +152,7 @@ static int __open_session(struct ceph_mon_client *monc)  		/* initiatiate authentication handshake */  		ret = ceph_auth_build_hello(monc->auth,  					    monc->m_auth->front.iov_base, -					    monc->m_auth->front_max); +					    monc->m_auth->front_alloc_len);  		__send_prepared_auth_request(monc, ret);  	} else {  		dout("open_session mon%d already open\n", monc->cur_mon); @@ -196,7 +196,7 @@ static void __send_subscribe(struct ceph_mon_client *monc)  		int num;  		p = msg->front.iov_base; -		end = p + msg->front_max; +		end = p + msg->front_alloc_len;  		num = 1 + !!monc->want_next_osdmap + !!monc->want_mdsmap;  		ceph_encode_32(&p, num); @@ -296,6 +296,33 @@ void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc)  		__send_subscribe(monc);  	mutex_unlock(&monc->mutex);  } +EXPORT_SYMBOL(ceph_monc_request_next_osdmap); + +int ceph_monc_wait_osdmap(struct ceph_mon_client *monc, u32 epoch, +			  unsigned long timeout) +{ +	unsigned long started = jiffies; +	int ret; + +	mutex_lock(&monc->mutex); +	while (monc->have_osdmap < epoch) { +		mutex_unlock(&monc->mutex); + +		if (timeout != 0 && time_after_eq(jiffies, started + timeout)) +			return -ETIMEDOUT; + +		ret = wait_event_interruptible_timeout(monc->client->auth_wq, +					 monc->have_osdmap >= epoch, timeout); +		if (ret < 0) +			return ret; + +		mutex_lock(&monc->mutex); +	} + +	mutex_unlock(&monc->mutex); +	return 0; +} +EXPORT_SYMBOL(ceph_monc_wait_osdmap);  /*   * @@ -477,14 +504,13 @@ static struct ceph_msg *get_generic_reply(struct ceph_connection *con,  	return m;  } -static int do_generic_request(struct ceph_mon_client *monc, -			      struct ceph_mon_generic_request *req) +static int __do_generic_request(struct ceph_mon_client *monc, u64 tid, +				struct ceph_mon_generic_request *req)  {  	int err;  	/* register request */ -	mutex_lock(&monc->mutex); -	req->tid = ++monc->last_tid; +	req->tid = tid != 0 ? tid : ++monc->last_tid;  	req->request->hdr.tid = cpu_to_le64(req->tid);  	__insert_generic_request(monc, req);  	monc->num_generic_requests++; @@ -496,13 +522,24 @@ static int do_generic_request(struct ceph_mon_client *monc,  	mutex_lock(&monc->mutex);  	rb_erase(&req->node, &monc->generic_request_tree);  	monc->num_generic_requests--; -	mutex_unlock(&monc->mutex);  	if (!err)  		err = req->result;  	return err;  } +static int do_generic_request(struct ceph_mon_client *monc, +			      struct ceph_mon_generic_request *req) +{ +	int err; + +	mutex_lock(&monc->mutex); +	err = __do_generic_request(monc, 0, req); +	mutex_unlock(&monc->mutex); + +	return err; +} +  /*   * statfs   */ @@ -579,6 +616,96 @@ out:  }  EXPORT_SYMBOL(ceph_monc_do_statfs); +static void handle_get_version_reply(struct ceph_mon_client *monc, +				     struct ceph_msg *msg) +{ +	struct ceph_mon_generic_request *req; +	u64 tid = le64_to_cpu(msg->hdr.tid); +	void *p = msg->front.iov_base; +	void *end = p + msg->front_alloc_len; +	u64 handle; + +	dout("%s %p tid %llu\n", __func__, msg, tid); + +	ceph_decode_need(&p, end, 2*sizeof(u64), bad); +	handle = ceph_decode_64(&p); +	if (tid != 0 && tid != handle) +		goto bad; + +	mutex_lock(&monc->mutex); +	req = __lookup_generic_req(monc, handle); +	if (req) { +		*(u64 *)req->buf = ceph_decode_64(&p); +		req->result = 0; +		get_generic_request(req); +	} +	mutex_unlock(&monc->mutex); +	if (req) { +		complete_all(&req->completion); +		put_generic_request(req); +	} + +	return; +bad: +	pr_err("corrupt mon_get_version reply\n"); +	ceph_msg_dump(msg); +} + +/* + * Send MMonGetVersion and wait for the reply. + * + * @what: one of "mdsmap", "osdmap" or "monmap" + */ +int ceph_monc_do_get_version(struct ceph_mon_client *monc, const char *what, +			     u64 *newest) +{ +	struct ceph_mon_generic_request *req; +	void *p, *end; +	u64 tid; +	int err; + +	req = kzalloc(sizeof(*req), GFP_NOFS); +	if (!req) +		return -ENOMEM; + +	kref_init(&req->kref); +	req->buf = newest; +	req->buf_len = sizeof(*newest); +	init_completion(&req->completion); + +	req->request = ceph_msg_new(CEPH_MSG_MON_GET_VERSION, +				    sizeof(u64) + sizeof(u32) + strlen(what), +				    GFP_NOFS, true); +	if (!req->request) { +		err = -ENOMEM; +		goto out; +	} + +	req->reply = ceph_msg_new(CEPH_MSG_MON_GET_VERSION_REPLY, 1024, +				  GFP_NOFS, true); +	if (!req->reply) { +		err = -ENOMEM; +		goto out; +	} + +	p = req->request->front.iov_base; +	end = p + req->request->front_alloc_len; + +	/* fill out request */ +	mutex_lock(&monc->mutex); +	tid = ++monc->last_tid; +	ceph_encode_64(&p, tid); /* handle */ +	ceph_encode_string(&p, end, what, strlen(what)); + +	err = __do_generic_request(monc, tid, req); + +	mutex_unlock(&monc->mutex); +out: +	kref_put(&req->kref, release_generic_request); +	return err; +} +EXPORT_SYMBOL(ceph_monc_do_get_version); +  /*   * pool ops   */ @@ -897,7 +1024,7 @@ static void handle_auth_reply(struct ceph_mon_client *monc,  	ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,  				     msg->front.iov_len,  				     monc->m_auth->front.iov_base, -				     monc->m_auth->front_max); +				     monc->m_auth->front_alloc_len);  	if (ret < 0) {  		monc->client->auth_err = ret;  		wake_up_all(&monc->client->auth_wq); @@ -939,7 +1066,7 @@ static int __validate_auth(struct ceph_mon_client *monc)  		return 0;  	ret = ceph_build_auth(monc->auth, monc->m_auth->front.iov_base, -			      monc->m_auth->front_max); +			      monc->m_auth->front_alloc_len);  	if (ret <= 0)  		return ret; /* either an error, or no need to authenticate */  	__send_prepared_auth_request(monc, ret); @@ -981,6 +1108,10 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)  		handle_statfs_reply(monc, msg);  		break; +	case CEPH_MSG_MON_GET_VERSION_REPLY: +		handle_get_version_reply(monc, msg); +		break; +  	case CEPH_MSG_POOLOP_REPLY:  		handle_poolop_reply(monc, msg);  		break; @@ -1029,6 +1160,15 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con,  	case CEPH_MSG_AUTH_REPLY:  		m = ceph_msg_get(monc->m_auth_reply);  		break; +	case CEPH_MSG_MON_GET_VERSION_REPLY: +		if (le64_to_cpu(hdr->tid) != 0) +			return get_generic_reply(con, hdr, skip); + +		/* +		 * Older OSDs don't set reply tid even if the orignal +		 * request had a non-zero tid.  Workaround this weirdness +		 * by falling through to the allocate case. +		 */  	case CEPH_MSG_MON_MAP:  	case CEPH_MSG_MDS_MAP:  	case CEPH_MSG_OSD_MAP:  | 
