--- /dev/null
+From a00861eb3377fc51a555d0bc367cc2473d7b7efc Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Wed, 16 May 2012 15:16:39 -0500
+Subject: ceph: ensure auth ops are defined before use
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit a255651d4cad89f1a606edd36135af892ada4f20)
+
+In the create_authorizer method for both the mds and osd clients,
+the auth_client->ops pointer is blindly dereferenced. There is no
+obvious guarantee that this pointer has been assigned. And
+furthermore, even if the ops pointer is non-null there is definitely
+no guarantee that the create_authorizer or destroy_authorizer
+methods are defined.
+
+Add checks in both routines to make sure they are defined (non-null)
+before use. Add similar checks in a few other spots in these files
+while we're at it.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/mds_client.c | 14 ++++++--------
+ net/ceph/osd_client.c | 15 ++++++++++-----
+ 2 files changed, 16 insertions(+), 13 deletions(-)
+
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -3406,16 +3406,14 @@ static int get_authorizer(struct ceph_co
+ int ret = 0;
+
+ if (force_new && auth->authorizer) {
+- ac->ops->destroy_authorizer(ac, auth->authorizer);
++ if (ac->ops && ac->ops->destroy_authorizer)
++ ac->ops->destroy_authorizer(ac, auth->authorizer);
+ auth->authorizer = NULL;
+ }
+- if (auth->authorizer == NULL) {
+- if (ac->ops->create_authorizer) {
+- ret = ac->ops->create_authorizer(ac,
+- CEPH_ENTITY_TYPE_MDS, auth);
+- if (ret)
+- return ret;
+- }
++ if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
++ ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, auth);
++ if (ret)
++ return ret;
+ }
+
+ *proto = ac->protocol;
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -664,10 +664,10 @@ static void put_osd(struct ceph_osd *osd
+ {
+ dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
+ atomic_read(&osd->o_ref) - 1);
+- if (atomic_dec_and_test(&osd->o_ref)) {
++ if (atomic_dec_and_test(&osd->o_ref) && osd->o_auth.authorizer) {
+ struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth;
+
+- if (osd->o_auth.authorizer)
++ if (ac->ops && ac->ops->destroy_authorizer)
+ ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer);
+ kfree(osd);
+ }
+@@ -2119,10 +2119,11 @@ static int get_authorizer(struct ceph_co
+ int ret = 0;
+
+ if (force_new && auth->authorizer) {
+- ac->ops->destroy_authorizer(ac, auth->authorizer);
++ if (ac->ops && ac->ops->destroy_authorizer)
++ ac->ops->destroy_authorizer(ac, auth->authorizer);
+ auth->authorizer = NULL;
+ }
+- if (auth->authorizer == NULL) {
++ if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
+ ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, auth);
+ if (ret)
+ return ret;
+@@ -2144,6 +2145,10 @@ static int verify_authorizer_reply(struc
+ struct ceph_osd_client *osdc = o->o_osdc;
+ struct ceph_auth_client *ac = osdc->client->monc.auth;
+
++ /*
++ * XXX If ac->ops or ac->ops->verify_authorizer_reply is null,
++ * XXX which do we do: succeed or fail?
++ */
+ return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len);
+ }
+
+@@ -2153,7 +2158,7 @@ static int invalidate_authorizer(struct
+ struct ceph_osd_client *osdc = o->o_osdc;
+ struct ceph_auth_client *ac = osdc->client->monc.auth;
+
+- if (ac->ops->invalidate_authorizer)
++ if (ac->ops && ac->ops->invalidate_authorizer)
+ ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD);
+
+ return ceph_monc_validate_auth(&osdc->client->monc);
--- /dev/null
+From b306a7107e65cde5350584e00ea2b04fe84faa6f Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Wed, 16 May 2012 15:16:39 -0500
+Subject: ceph: have get_authorizer methods return pointers
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit a3530df33eb91d787d08c7383a0a9982690e42d0)
+
+Have the get_authorizer auth_client method return a ceph_auth
+pointer rather than an integer, pointer-encoding any returned
+error value. This is to pave the way for making use of the
+returned value in an upcoming patch.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/mds_client.c | 20 +++++++++++++-------
+ include/linux/ceph/messenger.h | 8 +++++---
+ net/ceph/messenger.c | 8 ++++----
+ net/ceph/osd_client.c | 19 ++++++++++++-------
+ 4 files changed, 34 insertions(+), 21 deletions(-)
+
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -3395,15 +3395,20 @@ out:
+ /*
+ * authentication
+ */
+-static int get_authorizer(struct ceph_connection *con,
+- void **buf, int *len, int *proto,
+- void **reply_buf, int *reply_len, int force_new)
++
++/*
++ * Note: returned pointer is the address of a structure that's
++ * managed separately. Caller must *not* attempt to free it.
++ */
++static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
++ void **buf, int *len, int *proto,
++ void **reply_buf, int *reply_len,
++ int force_new)
+ {
+ struct ceph_mds_session *s = con->private;
+ struct ceph_mds_client *mdsc = s->s_mdsc;
+ struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
+ struct ceph_auth_handshake *auth = &s->s_auth;
+- int ret = 0;
+
+ if (force_new && auth->authorizer) {
+ if (ac->ops && ac->ops->destroy_authorizer)
+@@ -3411,9 +3416,10 @@ static int get_authorizer(struct ceph_co
+ auth->authorizer = NULL;
+ }
+ if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
+- ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, auth);
++ int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS,
++ auth);
+ if (ret)
+- return ret;
++ return ERR_PTR(ret);
+ }
+
+ *proto = ac->protocol;
+@@ -3422,7 +3428,7 @@ static int get_authorizer(struct ceph_co
+ *reply_buf = auth->authorizer_reply_buf;
+ *reply_len = auth->authorizer_reply_buf_len;
+
+- return 0;
++ return auth;
+ }
+
+
+--- a/include/linux/ceph/messenger.h
++++ b/include/linux/ceph/messenger.h
+@@ -25,9 +25,11 @@ struct ceph_connection_operations {
+ void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m);
+
+ /* authorize an outgoing connection */
+- int (*get_authorizer) (struct ceph_connection *con,
+- void **buf, int *len, int *proto,
+- void **reply_buf, int *reply_len, int force_new);
++ struct ceph_auth_handshake *(*get_authorizer) (
++ struct ceph_connection *con,
++ void **buf, int *len, int *proto,
++ void **reply_buf, int *reply_len,
++ int force_new);
+ int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
+ int (*invalidate_authorizer)(struct ceph_connection *con);
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -658,7 +658,7 @@ static int prepare_connect_authorizer(st
+ void *auth_buf;
+ int auth_len;
+ int auth_protocol;
+- int ret;
++ struct ceph_auth_handshake *auth;
+
+ if (!con->ops->get_authorizer) {
+ con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN;
+@@ -674,13 +674,13 @@ static int prepare_connect_authorizer(st
+ auth_buf = NULL;
+ auth_len = 0;
+ auth_protocol = CEPH_AUTH_UNKNOWN;
+- ret = con->ops->get_authorizer(con, &auth_buf, &auth_len,
++ auth = con->ops->get_authorizer(con, &auth_buf, &auth_len,
+ &auth_protocol, &con->auth_reply_buf,
+ &con->auth_reply_buf_len, con->auth_retry);
+ mutex_lock(&con->mutex);
+
+- if (ret)
+- return ret;
++ if (IS_ERR(auth))
++ return PTR_ERR(auth);
+
+ if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
+ return -EAGAIN;
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -2108,15 +2108,19 @@ static void put_osd_con(struct ceph_conn
+ /*
+ * authentication
+ */
+-static int get_authorizer(struct ceph_connection *con,
+- void **buf, int *len, int *proto,
+- void **reply_buf, int *reply_len, int force_new)
++/*
++ * Note: returned pointer is the address of a structure that's
++ * managed separately. Caller must *not* attempt to free it.
++ */
++static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
++ void **buf, int *len, int *proto,
++ void **reply_buf, int *reply_len,
++ int force_new)
+ {
+ struct ceph_osd *o = con->private;
+ struct ceph_osd_client *osdc = o->o_osdc;
+ struct ceph_auth_client *ac = osdc->client->monc.auth;
+ struct ceph_auth_handshake *auth = &o->o_auth;
+- int ret = 0;
+
+ if (force_new && auth->authorizer) {
+ if (ac->ops && ac->ops->destroy_authorizer)
+@@ -2124,9 +2128,10 @@ static int get_authorizer(struct ceph_co
+ auth->authorizer = NULL;
+ }
+ if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
+- ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, auth);
++ int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD,
++ auth);
+ if (ret)
+- return ret;
++ return ERR_PTR(ret);
+ }
+
+ *proto = ac->protocol;
+@@ -2135,7 +2140,7 @@ static int get_authorizer(struct ceph_co
+ *reply_buf = auth->authorizer_reply_buf;
+ *reply_len = auth->authorizer_reply_buf_len;
+
+- return 0;
++ return auth;
+ }
+
+
--- /dev/null
+From 8f78f1676fed681923b213924d75474e4da08228 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Wed, 16 May 2012 15:16:39 -0500
+Subject: ceph: use info returned by get_authorizer
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 8f43fb53894079bf0caab6e348ceaffe7adc651a)
+
+Rather than passing a bunch of arguments to be filled in with the
+content of the ceph_auth_handshake buffer now returned by the
+get_authorizer method, just use the returned information in the
+caller, and drop the unnecessary arguments.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/mds_client.c | 9 +--------
+ include/linux/ceph/messenger.h | 4 +---
+ net/ceph/messenger.c | 13 +++++++------
+ net/ceph/osd_client.c | 9 +--------
+ 4 files changed, 10 insertions(+), 25 deletions(-)
+
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -3401,9 +3401,7 @@ out:
+ * managed separately. Caller must *not* attempt to free it.
+ */
+ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
+- void **buf, int *len, int *proto,
+- void **reply_buf, int *reply_len,
+- int force_new)
++ int *proto, int force_new)
+ {
+ struct ceph_mds_session *s = con->private;
+ struct ceph_mds_client *mdsc = s->s_mdsc;
+@@ -3421,12 +3419,7 @@ static struct ceph_auth_handshake *get_a
+ if (ret)
+ return ERR_PTR(ret);
+ }
+-
+ *proto = ac->protocol;
+- *buf = auth->authorizer_buf;
+- *len = auth->authorizer_buf_len;
+- *reply_buf = auth->authorizer_reply_buf;
+- *reply_len = auth->authorizer_reply_buf_len;
+
+ return auth;
+ }
+--- a/include/linux/ceph/messenger.h
++++ b/include/linux/ceph/messenger.h
+@@ -27,9 +27,7 @@ struct ceph_connection_operations {
+ /* authorize an outgoing connection */
+ struct ceph_auth_handshake *(*get_authorizer) (
+ struct ceph_connection *con,
+- void **buf, int *len, int *proto,
+- void **reply_buf, int *reply_len,
+- int force_new);
++ int *proto, int force_new);
+ int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
+ int (*invalidate_authorizer)(struct ceph_connection *con);
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -671,20 +671,21 @@ static int prepare_connect_authorizer(st
+
+ mutex_unlock(&con->mutex);
+
+- auth_buf = NULL;
+- auth_len = 0;
+ auth_protocol = CEPH_AUTH_UNKNOWN;
+- auth = con->ops->get_authorizer(con, &auth_buf, &auth_len,
+- &auth_protocol, &con->auth_reply_buf,
+- &con->auth_reply_buf_len, con->auth_retry);
++ auth = con->ops->get_authorizer(con, &auth_protocol, con->auth_retry);
++
+ mutex_lock(&con->mutex);
+
+ if (IS_ERR(auth))
+ return PTR_ERR(auth);
+-
+ if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
+ return -EAGAIN;
+
++ auth_buf = auth->authorizer_buf;
++ auth_len = auth->authorizer_buf_len;
++ con->auth_reply_buf = auth->authorizer_reply_buf;
++ con->auth_reply_buf_len = auth->authorizer_reply_buf_len;
++
+ con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol);
+ con->out_connect.authorizer_len = cpu_to_le32(auth_len);
+
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -2113,9 +2113,7 @@ static void put_osd_con(struct ceph_conn
+ * managed separately. Caller must *not* attempt to free it.
+ */
+ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
+- void **buf, int *len, int *proto,
+- void **reply_buf, int *reply_len,
+- int force_new)
++ int *proto, int force_new)
+ {
+ struct ceph_osd *o = con->private;
+ struct ceph_osd_client *osdc = o->o_osdc;
+@@ -2133,12 +2131,7 @@ static struct ceph_auth_handshake *get_a
+ if (ret)
+ return ERR_PTR(ret);
+ }
+-
+ *proto = ac->protocol;
+- *buf = auth->authorizer_buf;
+- *len = auth->authorizer_buf_len;
+- *reply_buf = auth->authorizer_reply_buf;
+- *reply_len = auth->authorizer_reply_buf_len;
+
+ return auth;
+ }
--- /dev/null
+From 38466376a17ef15fb40c879c76598a5c1ffdc042 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Wed, 16 May 2012 15:16:39 -0500
+Subject: ceph: return pointer from prepare_connect_authorizer()
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 729796be9190f57ca40ccca315e8ad34a1eb8fef)
+
+Change prepare_connect_authorizer() so it returns a pointer (or
+pointer-coded error).
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/messenger.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -653,7 +653,7 @@ static void prepare_write_keepalive(stru
+ * Connection negotiation.
+ */
+
+-static int prepare_connect_authorizer(struct ceph_connection *con)
++static struct ceph_auth_handshake *prepare_connect_authorizer(struct ceph_connection *con)
+ {
+ void *auth_buf;
+ int auth_len;
+@@ -664,7 +664,7 @@ static int prepare_connect_authorizer(st
+ con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN;
+ con->out_connect.authorizer_len = 0;
+
+- return 0;
++ return NULL;
+ }
+
+ /* Can't hold the mutex while getting authorizer */
+@@ -677,9 +677,9 @@ static int prepare_connect_authorizer(st
+ mutex_lock(&con->mutex);
+
+ if (IS_ERR(auth))
+- return PTR_ERR(auth);
++ return auth;
+ if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
+- return -EAGAIN;
++ return ERR_PTR(-EAGAIN);
+
+ auth_buf = auth->authorizer_buf;
+ auth_len = auth->authorizer_buf_len;
+@@ -692,7 +692,7 @@ static int prepare_connect_authorizer(st
+ if (auth_len)
+ ceph_con_out_kvec_add(con, auth_len, auth_buf);
+
+- return 0;
++ return auth;
+ }
+
+ /*
+@@ -712,7 +712,7 @@ static int prepare_write_connect(struct
+ {
+ unsigned global_seq = get_global_seq(con->msgr, 0);
+ int proto;
+- int ret;
++ struct ceph_auth_handshake *auth;
+
+ switch (con->peer_name.type) {
+ case CEPH_ENTITY_TYPE_MON:
+@@ -739,9 +739,9 @@ static int prepare_write_connect(struct
+ con->out_connect.flags = 0;
+
+ ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
+- ret = prepare_connect_authorizer(con);
+- if (ret)
+- return ret;
++ auth = prepare_connect_authorizer(con);
++ if (IS_ERR(auth))
++ return PTR_ERR(auth);
+
+ con->out_more = 0;
+ set_bit(WRITE_PENDING, &con->state);
--- /dev/null
+From 6309b70e547cb121bdba4933d794237ab397bd54 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Wed, 16 May 2012 15:16:39 -0500
+Subject: ceph: rename prepare_connect_authorizer()
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit dac1e716c60161867a47745bca592987ca3a9cb2)
+
+Change the name of prepare_connect_authorizer(). The next
+patch is going to make this function no longer add anything to the
+connection's out_kvec, so it will no longer fit the pattern of
+the rest of the prepare_connect_*() functions.
+
+In addition, pass the address of a variable that will hold the
+authorization protocol to use. Move the assignment of that to the
+connection's out_connect structure into prepare_write_connect().
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/messenger.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -653,11 +653,11 @@ static void prepare_write_keepalive(stru
+ * Connection negotiation.
+ */
+
+-static struct ceph_auth_handshake *prepare_connect_authorizer(struct ceph_connection *con)
++static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection *con,
++ int *auth_proto)
+ {
+ void *auth_buf;
+ int auth_len;
+- int auth_protocol;
+ struct ceph_auth_handshake *auth;
+
+ if (!con->ops->get_authorizer) {
+@@ -671,8 +671,7 @@ static struct ceph_auth_handshake *prepa
+
+ mutex_unlock(&con->mutex);
+
+- auth_protocol = CEPH_AUTH_UNKNOWN;
+- auth = con->ops->get_authorizer(con, &auth_protocol, con->auth_retry);
++ auth = con->ops->get_authorizer(con, auth_proto, con->auth_retry);
+
+ mutex_lock(&con->mutex);
+
+@@ -686,7 +685,6 @@ static struct ceph_auth_handshake *prepa
+ con->auth_reply_buf = auth->authorizer_reply_buf;
+ con->auth_reply_buf_len = auth->authorizer_reply_buf_len;
+
+- con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol);
+ con->out_connect.authorizer_len = cpu_to_le32(auth_len);
+
+ if (auth_len)
+@@ -712,6 +710,7 @@ static int prepare_write_connect(struct
+ {
+ unsigned global_seq = get_global_seq(con->msgr, 0);
+ int proto;
++ int auth_proto;
+ struct ceph_auth_handshake *auth;
+
+ switch (con->peer_name.type) {
+@@ -739,9 +738,11 @@ static int prepare_write_connect(struct
+ con->out_connect.flags = 0;
+
+ ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
+- auth = prepare_connect_authorizer(con);
++ auth_proto = CEPH_AUTH_UNKNOWN;
++ auth = get_connect_authorizer(con, &auth_proto);
+ if (IS_ERR(auth))
+ return PTR_ERR(auth);
++ con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto);
+
+ con->out_more = 0;
+ set_bit(WRITE_PENDING, &con->state);
--- /dev/null
+From 2c53b5a488ac87f848f0ce09742500108a4bfa23 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Wed, 16 May 2012 15:16:39 -0500
+Subject: ceph: add auth buf in prepare_write_connect()
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 3da54776e2c0385c32d143fd497a7f40a88e29dd)
+
+Move the addition of the authorizer buffer to a connection's
+out_kvec out of get_connect_authorizer() and into its caller. This
+way, the caller--prepare_write_connect()--can avoid adding the
+connect header to out_kvec before it has been fully initialized.
+
+Prior to this patch, it was possible for a connect header to be
+sent over the wire before the authorizer protocol or buffer length
+fields were initialized. An authorizer buffer associated with that
+header could also be queued to send only after the connection header
+that describes it was on the wire.
+
+Fixes http://tracker.newdream.net/issues/2424
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/messenger.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -656,8 +656,6 @@ static void prepare_write_keepalive(stru
+ static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection *con,
+ int *auth_proto)
+ {
+- void *auth_buf;
+- int auth_len;
+ struct ceph_auth_handshake *auth;
+
+ if (!con->ops->get_authorizer) {
+@@ -680,15 +678,9 @@ static struct ceph_auth_handshake *get_c
+ if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
+ return ERR_PTR(-EAGAIN);
+
+- auth_buf = auth->authorizer_buf;
+- auth_len = auth->authorizer_buf_len;
+ con->auth_reply_buf = auth->authorizer_reply_buf;
+ con->auth_reply_buf_len = auth->authorizer_reply_buf_len;
+
+- con->out_connect.authorizer_len = cpu_to_le32(auth_len);
+-
+- if (auth_len)
+- ceph_con_out_kvec_add(con, auth_len, auth_buf);
+
+ return auth;
+ }
+@@ -737,12 +729,20 @@ static int prepare_write_connect(struct
+ con->out_connect.protocol_version = cpu_to_le32(proto);
+ con->out_connect.flags = 0;
+
+- ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
+ auth_proto = CEPH_AUTH_UNKNOWN;
+ auth = get_connect_authorizer(con, &auth_proto);
+ if (IS_ERR(auth))
+ return PTR_ERR(auth);
++
+ con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto);
++ con->out_connect.authorizer_len = auth ?
++ cpu_to_le32(auth->authorizer_buf_len) : 0;
++
++ ceph_con_out_kvec_add(con, sizeof (con->out_connect),
++ &con->out_connect);
++ if (auth && auth->authorizer_buf_len)
++ ceph_con_out_kvec_add(con, auth->authorizer_buf_len,
++ auth->authorizer_buf);
+
+ con->out_more = 0;
+ set_bit(WRITE_PENDING, &con->state);
--- /dev/null
+From 30b2118228f619ff7ec30651e914fe4d61ad7d3b Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Wed, 16 May 2012 15:16:38 -0500
+Subject: libceph: avoid unregistering osd request when not registered
+
+From: Sage Weil <sage@inktank.com>
+
+(cherry picked from commit 35f9f8a09e1e88e31bd34a1e645ca0e5f070dd5c)
+
+There is a race between two __unregister_request() callers: the
+reply path and the ceph_osdc_wait_request(). If we get a reply
+*and* the timeout expires at roughly the same time, both callers
+will try to unregister the request, and the second one will do bad
+things.
+
+Simply check if the request is still already unregistered; if so,
+return immediately and do nothing.
+
+Fixes http://tracker.newdream.net/issues/2420
+
+Signed-off-by: Sage Weil <sage@inktank.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/osd_client.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -841,6 +841,12 @@ static void register_request(struct ceph
+ static void __unregister_request(struct ceph_osd_client *osdc,
+ struct ceph_osd_request *req)
+ {
++ if (RB_EMPTY_NODE(&req->r_node)) {
++ dout("__unregister_request %p tid %lld not registered\n",
++ req, req->r_tid);
++ return;
++ }
++
+ dout("__unregister_request %p tid %lld\n", req, req->r_tid);
+ rb_erase(&req->r_node, &osdc->requests);
+ osdc->num_requests--;
--- /dev/null
+From 0e27f7ac12ed7a3e6f57bfccec2150a028f2c92f Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Mon, 21 May 2012 09:45:23 -0700
+Subject: libceph: fix pg_temp updates
+
+From: Sage Weil <sage@inktank.com>
+
+(cherry picked from commit 6bd9adbdf9ca6a052b0b7455ac67b925eb38cfad)
+
+Usually, we are adding pg_temp entries or removing them. Occasionally they
+update. In that case, osdmap_apply_incremental() was failing because the
+rbtree entry already exists.
+
+Fix by removing the existing entry before inserting a new one.
+
+Fixes http://tracker.newdream.net/issues/2446
+
+Signed-off-by: Sage Weil <sage@inktank.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/osdmap.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/net/ceph/osdmap.c
++++ b/net/ceph/osdmap.c
+@@ -890,8 +890,12 @@ struct ceph_osdmap *osdmap_apply_increme
+ pglen = ceph_decode_32(p);
+
+ if (pglen) {
+- /* insert */
+ ceph_decode_need(p, end, pglen*sizeof(u32), bad);
++
++ /* removing existing (if any) */
++ (void) __remove_pg_mapping(&map->pg_temp, pgid);
++
++ /* insert */
+ pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS);
+ if (!pg) {
+ err = -ENOMEM;
--- /dev/null
+From b7a73c1b29db3186c5a612ff146e466a3286ce60 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Mon, 4 Jun 2012 14:43:32 -0500
+Subject: libceph: osd_client: don't drop reply reference too early
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit ab8cb34a4b2f60281a4b18b1f1ad23bc2313d91b)
+
+In ceph_osdc_release_request(), a reference to the r_reply message
+is dropped. But just after that, that same message is revoked if it
+was in use to receive an incoming reply. Reorder these so we are
+sure we hold a reference until we're actually done with the message.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 680584fab05efff732b5ae16ad601ba994d7b505)
+---
+ net/ceph/osd_client.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -139,8 +139,6 @@ void ceph_osdc_release_request(struct kr
+
+ if (req->r_request)
+ ceph_msg_put(req->r_request);
+- if (req->r_reply)
+- ceph_msg_put(req->r_reply);
+ if (req->r_con_filling_msg) {
+ dout("release_request revoking pages %p from con %p\n",
+ req->r_pages, req->r_con_filling_msg);
+@@ -148,6 +146,8 @@ void ceph_osdc_release_request(struct kr
+ req->r_reply);
+ ceph_con_put(req->r_con_filling_msg);
+ }
++ if (req->r_reply)
++ ceph_msg_put(req->r_reply);
+ if (req->r_own_pages)
+ ceph_release_page_vector(req->r_pages,
+ req->r_num_pages);
--- /dev/null
+From 2e8494b7f222e9a1d5eae5ed4af59c9e6e4d4864 Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Thu, 31 May 2012 20:22:18 -0700
+Subject: libceph: use con get/put ops from osd_client
+
+From: Sage Weil <sage@inktank.com>
+
+(cherry picked from commit 0d47766f14211a73eaf54cab234db134ece79f49)
+
+There were a few direct calls to ceph_con_{get,put}() instead of the con
+ops from osd_client.c. This is a bug since those ops aren't defined to
+be ceph_con_get/put.
+
+This breaks refcounting on the ceph_osd structs that contain the
+ceph_connections, and could lead to all manner of strangeness.
+
+The purpose of the ->get and ->put methods in a ceph connection are
+to allow the connection to indicate it has a reference to something
+external to the messaging system, *not* to indicate something
+external has a reference to the connection.
+
+[elder@inktank.com: added that last sentence]
+
+Signed-off-by: Sage Weil <sage@newdream.net>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 88ed6ea0b295f8e2383d599a04027ec596cdf97b)
+---
+ net/ceph/osd_client.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -144,7 +144,7 @@ void ceph_osdc_release_request(struct kr
+ req->r_pages, req->r_con_filling_msg);
+ ceph_con_revoke_message(req->r_con_filling_msg,
+ req->r_reply);
+- ceph_con_put(req->r_con_filling_msg);
++ req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
+ }
+ if (req->r_reply)
+ ceph_msg_put(req->r_reply);
+@@ -1216,7 +1216,7 @@ static void handle_reply(struct ceph_osd
+ if (req->r_con_filling_msg == con && req->r_reply == msg) {
+ dout(" dropping con_filling_msg ref %p\n", con);
+ req->r_con_filling_msg = NULL;
+- ceph_con_put(con);
++ con->ops->put(con);
+ }
+
+ if (!req->r_got_reply) {
+@@ -2028,7 +2028,7 @@ static struct ceph_msg *get_reply(struct
+ dout("get_reply revoking msg %p from old con %p\n",
+ req->r_reply, req->r_con_filling_msg);
+ ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply);
+- ceph_con_put(req->r_con_filling_msg);
++ req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
+ req->r_con_filling_msg = NULL;
+ }
+
+@@ -2063,7 +2063,7 @@ static struct ceph_msg *get_reply(struct
+ #endif
+ }
+ *skip = 0;
+- req->r_con_filling_msg = ceph_con_get(con);
++ req->r_con_filling_msg = con->ops->get(con);
+ dout("get_reply tid %lld %p\n", tid, m);
+
+ out:
--- /dev/null
+From da0ac672eb4e4d4dad4c1ef2d924b4ece702f947 Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+Date: Wed, 6 Jun 2012 19:35:55 -0500
+Subject: rbd: Clear ceph_msg->bio_iter for retransmitted message
+
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+
+(cherry picked from commit 43643528cce60ca184fe8197efa8e8da7c89a037)
+(cherry picked from commit b132cf4c733f91bb4dd2277ea049243cf16e8b66)
+
+The bug can cause NULL pointer dereference in write_partial_msg_pages
+
+Signed-off-by: Zheng Yan <zheng.z.yan@intel.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/messenger.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -563,6 +563,10 @@ static void prepare_write_message(struct
+ m->hdr.seq = cpu_to_le64(++con->out_seq);
+ m->needs_out_seq = false;
+ }
++#ifdef CONFIG_BLOCK
++ else
++ m->bio_iter = NULL;
++#endif
+
+ dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n",
+ m, con->out_seq, le16_to_cpu(m->hdr.type),
--- /dev/null
+From b3351398dab239cb1f34be383f1126011514b126 Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Sun, 10 Jun 2012 20:43:56 -0700
+Subject: libceph: flush msgr queue during mon_client shutdown
+
+From: Sage Weil <sage@inktank.com>
+
+(cherry picked from commit f3dea7edd3d449fe7a6d402c1ce56a294b985261)
+(cherry picked from commit 642c0dbde32f34baa7886e988a067089992adc8f)
+
+We need to flush the msgr workqueue during mon_client shutdown to
+ensure that any work affecting our embedded ceph_connection is
+finished so that we can be safely destroyed.
+
+Previously, we were flushing the work queue after osd_client
+shutdown and before mon_client shutdown to ensure that any osd
+connection refs to authorizers are flushed. Remove the redundant
+flush, and document in the comment that the mon_client flush is
+needed to cover that case as well.
+
+Signed-off-by: Sage Weil <sage@inktank.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/ceph_common.c | 7 -------
+ net/ceph/mon_client.c | 8 ++++++++
+ 2 files changed, 8 insertions(+), 7 deletions(-)
+
+--- a/net/ceph/ceph_common.c
++++ b/net/ceph/ceph_common.c
+@@ -504,13 +504,6 @@ void ceph_destroy_client(struct ceph_cli
+ /* unmount */
+ ceph_osdc_stop(&client->osdc);
+
+- /*
+- * make sure osd connections close out before destroying the
+- * auth module, which is needed to free those connections'
+- * ceph_authorizers.
+- */
+- ceph_msgr_flush();
+-
+ ceph_monc_stop(&client->monc);
+
+ ceph_debugfs_client_cleanup(client);
+--- a/net/ceph/mon_client.c
++++ b/net/ceph/mon_client.c
+@@ -847,6 +847,14 @@ void ceph_monc_stop(struct ceph_mon_clie
+
+ mutex_unlock(&monc->mutex);
+
++ /*
++ * flush msgr queue before we destroy ourselves to ensure that:
++ * - any work that references our embedded con is finished.
++ * - any osd_client or other work that may reference an authorizer
++ * finishes before we shut down the auth subsystem.
++ */
++ ceph_msgr_flush();
++
+ ceph_auth_destroy(monc->auth);
+
+ ceph_msg_put(monc->m_auth);
--- /dev/null
+From 97e7f3ee21ecef94c8cf6914b6c549d683e83739 Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Tue, 10 Jul 2012 11:53:34 -0700
+Subject: libceph: fix messenger retry
+
+From: Sage Weil <sage@inktank.com>
+
+(cherry picked from commit 5bdca4e0768d3e0f4efa43d9a2cc8210aeb91ab9)
+
+In ancient times, the messenger could both initiate and accept connections.
+An artifact if that was data structures to store/process an incoming
+ceph_msg_connect request and send an outgoing ceph_msg_connect_reply.
+Sadly, the negotiation code was referencing those structures and ignoring
+important information (like the peer's connect_seq) from the correct ones.
+
+Among other things, this fixes tight reconnect loops where the server sends
+RETRY_SESSION and we (the client) retries with the same connect_seq as last
+time. This bug pretty easily triggered by injecting socket failures on the
+MDS and running some fs workload like workunits/direct_io/test_sync_io.
+
+Signed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/ceph/messenger.h | 12 ++----------
+ net/ceph/messenger.c | 12 ++++++------
+ 2 files changed, 8 insertions(+), 16 deletions(-)
+
+--- a/include/linux/ceph/messenger.h
++++ b/include/linux/ceph/messenger.h
+@@ -163,16 +163,8 @@ struct ceph_connection {
+
+ /* connection negotiation temps */
+ char in_banner[CEPH_BANNER_MAX_LEN];
+- union {
+- struct { /* outgoing connection */
+- struct ceph_msg_connect out_connect;
+- struct ceph_msg_connect_reply in_reply;
+- };
+- struct { /* incoming */
+- struct ceph_msg_connect in_connect;
+- struct ceph_msg_connect_reply out_reply;
+- };
+- };
++ struct ceph_msg_connect out_connect;
++ struct ceph_msg_connect_reply in_reply;
+ struct ceph_entity_addr actual_peer_addr;
+
+ /* message out temps */
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -1423,7 +1423,7 @@ static int process_connect(struct ceph_c
+ * dropped messages.
+ */
+ dout("process_connect got RESET peer seq %u\n",
+- le32_to_cpu(con->in_connect.connect_seq));
++ le32_to_cpu(con->in_reply.connect_seq));
+ pr_err("%s%lld %s connection reset\n",
+ ENTITY_NAME(con->peer_name),
+ ceph_pr_addr(&con->peer_addr.in_addr));
+@@ -1450,10 +1450,10 @@ static int process_connect(struct ceph_c
+ * If we sent a smaller connect_seq than the peer has, try
+ * again with a larger value.
+ */
+- dout("process_connect got RETRY my seq = %u, peer_seq = %u\n",
++ dout("process_connect got RETRY_SESSION my seq %u, peer %u\n",
+ le32_to_cpu(con->out_connect.connect_seq),
+- le32_to_cpu(con->in_connect.connect_seq));
+- con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
++ le32_to_cpu(con->in_reply.connect_seq));
++ con->connect_seq = le32_to_cpu(con->in_reply.connect_seq);
+ ceph_con_out_kvec_reset(con);
+ ret = prepare_write_connect(con);
+ if (ret < 0)
+@@ -1468,9 +1468,9 @@ static int process_connect(struct ceph_c
+ */
+ dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n",
+ con->peer_global_seq,
+- le32_to_cpu(con->in_connect.global_seq));
++ le32_to_cpu(con->in_reply.global_seq));
+ get_global_seq(con->msgr,
+- le32_to_cpu(con->in_connect.global_seq));
++ le32_to_cpu(con->in_reply.global_seq));
+ ceph_con_out_kvec_reset(con);
+ ret = prepare_write_connect(con);
+ if (ret < 0)
--- /dev/null
+From 6d7e495a8347311ddf5f1785c94ce71627b3efe0 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@dreamhost.com>
+Date: Wed, 4 Apr 2012 13:35:44 -0500
+Subject: rbd: don't hold spinlock during messenger flush
+
+From: Alex Elder <elder@dreamhost.com>
+
+(cherry picked from commit cd9d9f5df6098c50726200d4185e9e8da32785b3)
+
+A recent change made changes to the rbd_client_list be protected by
+a spinlock. Unfortunately in rbd_put_client(), the lock is taken
+before possibly dropping the last reference to an rbd_client, and on
+the last reference that eventually calls flush_workqueue() which can
+sleep.
+
+The problem was flagged by a debug spinlock warning:
+ BUG: spinlock wrong CPU on CPU#3, rbd/27814
+
+The solution is to move the spinlock acquisition and release inside
+rbd_client_release(), which is the spot where it's really needed for
+protecting the removal of the rbd_client from the client list.
+
+Signed-off-by: Alex Elder <elder@dreamhost.com>
+Reviewed-by: Sage Weil <sage@newdream.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -450,7 +450,9 @@ static void rbd_client_release(struct kr
+ struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);
+
+ dout("rbd_release_client %p\n", rbdc);
++ spin_lock(&rbd_client_list_lock);
+ list_del(&rbdc->node);
++ spin_unlock(&rbd_client_list_lock);
+
+ ceph_destroy_client(rbdc->client);
+ kfree(rbdc->rbd_opts);
+@@ -463,9 +465,7 @@ static void rbd_client_release(struct kr
+ */
+ static void rbd_put_client(struct rbd_device *rbd_dev)
+ {
+- spin_lock(&rbd_client_list_lock);
+ kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
+- spin_unlock(&rbd_client_list_lock);
+ rbd_dev->rbd_client = NULL;
+ }
+
--- /dev/null
+From ef2cfb917fb296102bf9c2f9cfbf83cfcb370000 Mon Sep 17 00:00:00 2001
+From: Josh Durgin <josh.durgin@dreamhost.com>
+Date: Mon, 5 Dec 2011 10:47:13 -0800
+Subject: rbd: protect read of snapshot sequence number
+
+From: Josh Durgin <josh.durgin@dreamhost.com>
+
+(cherry picked from commit 403f24d3d51760a8b9368d595fa5f48c309f1a0f)
+
+This is updated whenever a snapshot is added or deleted, and the
+snapc pointer is changed with every refresh of the header.
+
+Signed-off-by: Josh Durgin <josh.durgin@dreamhost.com>
+Reviewed-by: Alex Elder <elder@dreamhost.com>
+Reviewed-by: Yehuda Sadeh <yehuda@hq.newdream.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -1683,7 +1683,9 @@ static int rbd_header_add_snap(struct rb
+ if (ret < 0)
+ return ret;
+
+- dev->header.snapc->seq = new_snapid;
++ down_write(&dev->header_rwsem);
++ dev->header.snapc->seq = new_snapid;
++ up_write(&dev->header_rwsem);
+
+ return 0;
+ bad:
--- /dev/null
+From 526a884fb3062978673b4ec3ae2d1498add6e532 Mon Sep 17 00:00:00 2001
+From: Josh Durgin <josh.durgin@dreamhost.com>
+Date: Mon, 21 Nov 2011 13:04:42 -0800
+Subject: rbd: store snapshot id instead of index
+
+From: Josh Durgin <josh.durgin@dreamhost.com>
+
+(cherry picked from commit 77dfe99fe3cb0b2b0545e19e2d57b7a9134ee3c0)
+
+When a device was open at a snapshot, and snapshots were deleted or
+added, data from the wrong snapshot could be read. Instead of
+assuming the snap context is constant, store the actual snap id when
+the device is initialized, and rely on the OSDs to signal an error
+if we try reading from a snapshot that was deleted.
+
+Signed-off-by: Josh Durgin <josh.durgin@dreamhost.com>
+Reviewed-by: Alex Elder <elder@dreamhost.com>
+Reviewed-by: Yehuda Sadeh <yehuda@hq.newdream.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c | 27 +++++----------------------
+ 1 file changed, 5 insertions(+), 22 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -175,8 +175,7 @@ struct rbd_device {
+ /* protects updating the header */
+ struct rw_semaphore header_rwsem;
+ char snap_name[RBD_MAX_SNAP_NAME_LEN];
+- u32 cur_snap; /* index+1 of current snapshot within snap context
+- 0 - for the head */
++ u64 snap_id; /* current snapshot id */
+ int read_only;
+
+ struct list_head node;
+@@ -552,21 +551,6 @@ err_snapc:
+ return -ENOMEM;
+ }
+
+-static int snap_index(struct rbd_image_header *header, int snap_num)
+-{
+- return header->total_snaps - snap_num;
+-}
+-
+-static u64 cur_snap_id(struct rbd_device *rbd_dev)
+-{
+- struct rbd_image_header *header = &rbd_dev->header;
+-
+- if (!rbd_dev->cur_snap)
+- return 0;
+-
+- return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)];
+-}
+-
+ static int snap_by_name(struct rbd_image_header *header, const char *snap_name,
+ u64 *seq, u64 *size)
+ {
+@@ -605,7 +589,7 @@ static int rbd_header_set_snap(struct rb
+ snapc->seq = header->snap_seq;
+ else
+ snapc->seq = 0;
+- dev->cur_snap = 0;
++ dev->snap_id = CEPH_NOSNAP;
+ dev->read_only = 0;
+ if (size)
+ *size = header->image_size;
+@@ -613,8 +597,7 @@ static int rbd_header_set_snap(struct rb
+ ret = snap_by_name(header, dev->snap_name, &snapc->seq, size);
+ if (ret < 0)
+ goto done;
+-
+- dev->cur_snap = header->total_snaps - ret;
++ dev->snap_id = snapc->seq;
+ dev->read_only = 1;
+ }
+
+@@ -1521,7 +1504,7 @@ static void rbd_rq_fn(struct request_que
+ coll, cur_seg);
+ else
+ rbd_req_read(rq, rbd_dev,
+- cur_snap_id(rbd_dev),
++ rbd_dev->snap_id,
+ ofs,
+ op_size, bio,
+ coll, cur_seg);
+@@ -1656,7 +1639,7 @@ static int rbd_header_add_snap(struct rb
+ struct ceph_mon_client *monc;
+
+ /* we should create a snapshot only if we're pointing at the head */
+- if (dev->cur_snap)
++ if (dev->snap_id != CEPH_NOSNAP)
+ return -EINVAL;
+
+ monc = &dev->rbd_client->client->monc;
--- /dev/null
+From 46fc0381517148e9e24eec09413aa3311e7adaf6 Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+Date: Wed, 6 Jun 2012 09:15:33 -0500
+Subject: rbd: Fix ceph_snap_context size calculation
+
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+
+(cherry picked from commit f9f9a1904467816452fc70740165030e84c2c659)
+
+ceph_snap_context->snaps is an u64 array
+
+Signed-off-by: Zheng Yan <zheng.z.yan@intel.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -497,7 +497,7 @@ static int rbd_header_from_disk(struct r
+
+ snap_count = le32_to_cpu(ondisk->snap_count);
+ header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
+- snap_count * sizeof (*ondisk),
++ snap_count * sizeof(u64),
+ gfp_flags);
+ if (!header->snapc)
+ return -ENOMEM;
--- /dev/null
+From f0be86dddb0ce060e6ea0b747206b807d446b51f Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+Date: Mon, 28 May 2012 14:44:30 +0800
+Subject: ceph: check PG_Private flag before accessing page->private
+
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+
+(cherry picked from commit 28c0254ede13ab575d2df5c6585ed3d4817c3e6b)
+
+I got lots of NULL pointer dereference Oops when compiling kernel on ceph.
+The bug is because the kernel page migration routine replaces some pages
+in the page cache with new pages, these new pages' private can be non-zero.
+
+Signed-off-by: Zheng Yan <zheng.z.yan@intel.com>
+Signed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/addr.c | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+--- a/fs/ceph/addr.c
++++ b/fs/ceph/addr.c
+@@ -54,7 +54,12 @@
+ (CONGESTION_ON_THRESH(congestion_kb) - \
+ (CONGESTION_ON_THRESH(congestion_kb) >> 2))
+
+-
++static inline struct ceph_snap_context *page_snap_context(struct page *page)
++{
++ if (PagePrivate(page))
++ return (void *)page->private;
++ return NULL;
++}
+
+ /*
+ * Dirty a page. Optimistically adjust accounting, on the assumption
+@@ -142,10 +147,9 @@ static void ceph_invalidatepage(struct p
+ {
+ struct inode *inode;
+ struct ceph_inode_info *ci;
+- struct ceph_snap_context *snapc = (void *)page->private;
++ struct ceph_snap_context *snapc = page_snap_context(page);
+
+ BUG_ON(!PageLocked(page));
+- BUG_ON(!page->private);
+ BUG_ON(!PagePrivate(page));
+ BUG_ON(!page->mapping);
+
+@@ -182,7 +186,6 @@ static int ceph_releasepage(struct page
+ struct inode *inode = page->mapping ? page->mapping->host : NULL;
+ dout("%p releasepage %p idx %lu\n", inode, page, page->index);
+ WARN_ON(PageDirty(page));
+- WARN_ON(page->private);
+ WARN_ON(PagePrivate(page));
+ return 0;
+ }
+@@ -443,7 +446,7 @@ static int writepage_nounlock(struct pag
+ osdc = &fsc->client->osdc;
+
+ /* verify this is a writeable snap context */
+- snapc = (void *)page->private;
++ snapc = page_snap_context(page);
+ if (snapc == NULL) {
+ dout("writepage %p page %p not dirty?\n", inode, page);
+ goto out;
+@@ -451,7 +454,7 @@ static int writepage_nounlock(struct pag
+ oldest = get_oldest_context(inode, &snap_size);
+ if (snapc->seq > oldest->seq) {
+ dout("writepage %p page %p snapc %p not writeable - noop\n",
+- inode, page, (void *)page->private);
++ inode, page, snapc);
+ /* we should only noop if called by kswapd */
+ WARN_ON((current->flags & PF_MEMALLOC) == 0);
+ ceph_put_snap_context(oldest);
+@@ -591,7 +594,7 @@ static void writepages_finish(struct cep
+ clear_bdi_congested(&fsc->backing_dev_info,
+ BLK_RW_ASYNC);
+
+- ceph_put_snap_context((void *)page->private);
++ ceph_put_snap_context(page_snap_context(page));
+ page->private = 0;
+ ClearPagePrivate(page);
+ dout("unlocking %d %p\n", i, page);
+@@ -795,7 +798,7 @@ get_more_pages:
+ }
+
+ /* only if matching snap context */
+- pgsnapc = (void *)page->private;
++ pgsnapc = page_snap_context(page);
+ if (pgsnapc->seq > snapc->seq) {
+ dout("page snapc %p %lld > oldest %p %lld\n",
+ pgsnapc, pgsnapc->seq, snapc, snapc->seq);
+@@ -984,7 +987,7 @@ retry_locked:
+ BUG_ON(!ci->i_snap_realm);
+ down_read(&mdsc->snap_rwsem);
+ BUG_ON(!ci->i_snap_realm->cached_context);
+- snapc = (void *)page->private;
++ snapc = page_snap_context(page);
+ if (snapc && snapc != ci->i_head_snapc) {
+ /*
+ * this page is already dirty in another (older) snap
--- /dev/null
+From b9adfb9e021bad7c0c49620b0f10f9395aa69c90 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Tue, 22 May 2012 11:41:43 -0500
+Subject: libceph: eliminate connection state "DEAD"
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit e5e372da9a469dfe3ece40277090a7056c566838)
+
+The ceph connection state "DEAD" is never set and is therefore not
+needed. Eliminate it.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Yehuda Sadeh <yehuda@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/ceph/messenger.h | 1 -
+ net/ceph/messenger.c | 6 ------
+ 2 files changed, 7 deletions(-)
+
+--- a/include/linux/ceph/messenger.h
++++ b/include/linux/ceph/messenger.h
+@@ -119,7 +119,6 @@ struct ceph_msg_pos {
+ #define CLOSED 10 /* we've closed the connection */
+ #define SOCK_CLOSED 11 /* socket state changed to closed */
+ #define OPENING 13 /* open connection w/ (possibly new) peer */
+-#define DEAD 14 /* dead, about to kfree */
+ #define BACKOFF 15
+
+ /*
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -2091,12 +2091,6 @@ bad_tag:
+ */
+ static void queue_con(struct ceph_connection *con)
+ {
+- if (test_bit(DEAD, &con->state)) {
+- dout("queue_con %p ignoring: DEAD\n",
+- con);
+- return;
+- }
+-
+ if (!con->ops->get(con)) {
+ dout("queue_con %p ref count 0\n", con);
+ return;
--- /dev/null
+From cf2b6bf7d77fb4a85e864ba147f5964e7e6f86f5 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Tue, 29 May 2012 21:47:38 -0500
+Subject: libceph: kill bad_proto ceph connection op
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 6384bb8b8e88a9c6bf2ae0d9517c2c0199177c34)
+
+No code sets a bad_proto method in its ceph connection operations
+vector, so just get rid of it.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Yehuda Sadeh <yehuda@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/ceph/messenger.h | 3 ---
+ net/ceph/messenger.c | 5 -----
+ 2 files changed, 8 deletions(-)
+
+--- a/include/linux/ceph/messenger.h
++++ b/include/linux/ceph/messenger.h
+@@ -31,9 +31,6 @@ struct ceph_connection_operations {
+ int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
+ int (*invalidate_authorizer)(struct ceph_connection *con);
+
+- /* protocol version mismatch */
+- void (*bad_proto) (struct ceph_connection *con);
+-
+ /* there was some error on the socket (disconnect, whatever) */
+ void (*fault) (struct ceph_connection *con);
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -1360,11 +1360,6 @@ static void fail_protocol(struct ceph_co
+ {
+ reset_connection(con);
+ set_bit(CLOSED, &con->state); /* in case there's queued work */
+-
+- mutex_unlock(&con->mutex);
+- if (con->ops->bad_proto)
+- con->ops->bad_proto(con);
+- mutex_lock(&con->mutex);
+ }
+
+ static int process_connect(struct ceph_connection *con)
0017-ceph-messenger-check-return-from-get_authorizer.patch
0018-ceph-define-ceph_auth_handshake-type.patch
0019-ceph-messenger-reduce-args-to-create_authorizer.patch
+0020-ceph-ensure-auth-ops-are-defined-before-use.patch
+0021-ceph-have-get_authorizer-methods-return-pointers.patch
+0022-ceph-use-info-returned-by-get_authorizer.patch
+0023-ceph-return-pointer-from-prepare_connect_authorizer.patch
+0024-ceph-rename-prepare_connect_authorizer.patch
+0025-ceph-add-auth-buf-in-prepare_write_connect.patch
+0026-libceph-avoid-unregistering-osd-request-when-not-reg.patch
+0027-libceph-fix-pg_temp-updates.patch
+0028-libceph-osd_client-don-t-drop-reply-reference-too-ea.patch
+0029-libceph-use-con-get-put-ops-from-osd_client.patch
+0030-rbd-Clear-ceph_msg-bio_iter-for-retransmitted-messag.patch
+0031-libceph-flush-msgr-queue-during-mon_client-shutdown.patch
+0032-libceph-fix-messenger-retry.patch
+0033-rbd-don-t-hold-spinlock-during-messenger-flush.patch
+0034-rbd-protect-read-of-snapshot-sequence-number.patch
+0035-rbd-store-snapshot-id-instead-of-index.patch
+0036-rbd-Fix-ceph_snap_context-size-calculation.patch
+0037-ceph-check-PG_Private-flag-before-accessing-page-pri.patch
+0038-libceph-eliminate-connection-state-DEAD.patch
+0039-libceph-kill-bad_proto-ceph-connection-op.patch