]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 20:01:59 +0000 (12:01 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 20:01:59 +0000 (12:01 -0800)
added patches:
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

21 files changed:
queue-3.4/0020-ceph-ensure-auth-ops-are-defined-before-use.patch [new file with mode: 0644]
queue-3.4/0021-ceph-have-get_authorizer-methods-return-pointers.patch [new file with mode: 0644]
queue-3.4/0022-ceph-use-info-returned-by-get_authorizer.patch [new file with mode: 0644]
queue-3.4/0023-ceph-return-pointer-from-prepare_connect_authorizer.patch [new file with mode: 0644]
queue-3.4/0024-ceph-rename-prepare_connect_authorizer.patch [new file with mode: 0644]
queue-3.4/0025-ceph-add-auth-buf-in-prepare_write_connect.patch [new file with mode: 0644]
queue-3.4/0026-libceph-avoid-unregistering-osd-request-when-not-reg.patch [new file with mode: 0644]
queue-3.4/0027-libceph-fix-pg_temp-updates.patch [new file with mode: 0644]
queue-3.4/0028-libceph-osd_client-don-t-drop-reply-reference-too-ea.patch [new file with mode: 0644]
queue-3.4/0029-libceph-use-con-get-put-ops-from-osd_client.patch [new file with mode: 0644]
queue-3.4/0030-rbd-Clear-ceph_msg-bio_iter-for-retransmitted-messag.patch [new file with mode: 0644]
queue-3.4/0031-libceph-flush-msgr-queue-during-mon_client-shutdown.patch [new file with mode: 0644]
queue-3.4/0032-libceph-fix-messenger-retry.patch [new file with mode: 0644]
queue-3.4/0033-rbd-don-t-hold-spinlock-during-messenger-flush.patch [new file with mode: 0644]
queue-3.4/0034-rbd-protect-read-of-snapshot-sequence-number.patch [new file with mode: 0644]
queue-3.4/0035-rbd-store-snapshot-id-instead-of-index.patch [new file with mode: 0644]
queue-3.4/0036-rbd-Fix-ceph_snap_context-size-calculation.patch [new file with mode: 0644]
queue-3.4/0037-ceph-check-PG_Private-flag-before-accessing-page-pri.patch [new file with mode: 0644]
queue-3.4/0038-libceph-eliminate-connection-state-DEAD.patch [new file with mode: 0644]
queue-3.4/0039-libceph-kill-bad_proto-ceph-connection-op.patch [new file with mode: 0644]
queue-3.4/series

diff --git a/queue-3.4/0020-ceph-ensure-auth-ops-are-defined-before-use.patch b/queue-3.4/0020-ceph-ensure-auth-ops-are-defined-before-use.patch
new file mode 100644 (file)
index 0000000..bd7bebd
--- /dev/null
@@ -0,0 +1,102 @@
+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);
diff --git a/queue-3.4/0021-ceph-have-get_authorizer-methods-return-pointers.patch b/queue-3.4/0021-ceph-have-get_authorizer-methods-return-pointers.patch
new file mode 100644 (file)
index 0000000..6a4fa05
--- /dev/null
@@ -0,0 +1,166 @@
+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;
+ }
diff --git a/queue-3.4/0022-ceph-use-info-returned-by-get_authorizer.patch b/queue-3.4/0022-ceph-use-info-returned-by-get_authorizer.patch
new file mode 100644 (file)
index 0000000..f14bdc2
--- /dev/null
@@ -0,0 +1,119 @@
+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;
+ }
diff --git a/queue-3.4/0023-ceph-return-pointer-from-prepare_connect_authorizer.patch b/queue-3.4/0023-ceph-return-pointer-from-prepare_connect_authorizer.patch
new file mode 100644 (file)
index 0000000..daff2a1
--- /dev/null
@@ -0,0 +1,82 @@
+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);
diff --git a/queue-3.4/0024-ceph-rename-prepare_connect_authorizer.patch b/queue-3.4/0024-ceph-rename-prepare_connect_authorizer.patch
new file mode 100644 (file)
index 0000000..ef5279d
--- /dev/null
@@ -0,0 +1,80 @@
+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);
diff --git a/queue-3.4/0025-ceph-add-auth-buf-in-prepare_write_connect.patch b/queue-3.4/0025-ceph-add-auth-buf-in-prepare_write_connect.patch
new file mode 100644 (file)
index 0000000..c09a412
--- /dev/null
@@ -0,0 +1,78 @@
+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);
diff --git a/queue-3.4/0026-libceph-avoid-unregistering-osd-request-when-not-reg.patch b/queue-3.4/0026-libceph-avoid-unregistering-osd-request-when-not-reg.patch
new file mode 100644 (file)
index 0000000..e9118a9
--- /dev/null
@@ -0,0 +1,42 @@
+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--;
diff --git a/queue-3.4/0027-libceph-fix-pg_temp-updates.patch b/queue-3.4/0027-libceph-fix-pg_temp-updates.patch
new file mode 100644 (file)
index 0000000..fe955c1
--- /dev/null
@@ -0,0 +1,40 @@
+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;
diff --git a/queue-3.4/0028-libceph-osd_client-don-t-drop-reply-reference-too-ea.patch b/queue-3.4/0028-libceph-osd_client-don-t-drop-reply-reference-too-ea.patch
new file mode 100644 (file)
index 0000000..08cfea5
--- /dev/null
@@ -0,0 +1,42 @@
+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);
diff --git a/queue-3.4/0029-libceph-use-con-get-put-ops-from-osd_client.patch b/queue-3.4/0029-libceph-use-con-get-put-ops-from-osd_client.patch
new file mode 100644 (file)
index 0000000..fa6a5a8
--- /dev/null
@@ -0,0 +1,69 @@
+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:
diff --git a/queue-3.4/0030-rbd-Clear-ceph_msg-bio_iter-for-retransmitted-messag.patch b/queue-3.4/0030-rbd-Clear-ceph_msg-bio_iter-for-retransmitted-messag.patch
new file mode 100644 (file)
index 0000000..400a9c4
--- /dev/null
@@ -0,0 +1,32 @@
+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),
diff --git a/queue-3.4/0031-libceph-flush-msgr-queue-during-mon_client-shutdown.patch b/queue-3.4/0031-libceph-flush-msgr-queue-during-mon_client-shutdown.patch
new file mode 100644 (file)
index 0000000..32cdbba
--- /dev/null
@@ -0,0 +1,61 @@
+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);
diff --git a/queue-3.4/0032-libceph-fix-messenger-retry.patch b/queue-3.4/0032-libceph-fix-messenger-retry.patch
new file mode 100644 (file)
index 0000000..abfae73
--- /dev/null
@@ -0,0 +1,85 @@
+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)
diff --git a/queue-3.4/0033-rbd-don-t-hold-spinlock-during-messenger-flush.patch b/queue-3.4/0033-rbd-don-t-hold-spinlock-during-messenger-flush.patch
new file mode 100644 (file)
index 0000000..b6324e0
--- /dev/null
@@ -0,0 +1,51 @@
+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;
+ }
diff --git a/queue-3.4/0034-rbd-protect-read-of-snapshot-sequence-number.patch b/queue-3.4/0034-rbd-protect-read-of-snapshot-sequence-number.patch
new file mode 100644 (file)
index 0000000..df60f4f
--- /dev/null
@@ -0,0 +1,33 @@
+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:
diff --git a/queue-3.4/0035-rbd-store-snapshot-id-instead-of-index.patch b/queue-3.4/0035-rbd-store-snapshot-id-instead-of-index.patch
new file mode 100644 (file)
index 0000000..3fa19ba
--- /dev/null
@@ -0,0 +1,94 @@
+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;
diff --git a/queue-3.4/0036-rbd-Fix-ceph_snap_context-size-calculation.patch b/queue-3.4/0036-rbd-Fix-ceph_snap_context-size-calculation.patch
new file mode 100644 (file)
index 0000000..03d8fdc
--- /dev/null
@@ -0,0 +1,29 @@
+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;
diff --git a/queue-3.4/0037-ceph-check-PG_Private-flag-before-accessing-page-pri.patch b/queue-3.4/0037-ceph-check-PG_Private-flag-before-accessing-page-pri.patch
new file mode 100644 (file)
index 0000000..c470a72
--- /dev/null
@@ -0,0 +1,101 @@
+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
diff --git a/queue-3.4/0038-libceph-eliminate-connection-state-DEAD.patch b/queue-3.4/0038-libceph-eliminate-connection-state-DEAD.patch
new file mode 100644 (file)
index 0000000..ccc2283
--- /dev/null
@@ -0,0 +1,45 @@
+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;
diff --git a/queue-3.4/0039-libceph-kill-bad_proto-ceph-connection-op.patch b/queue-3.4/0039-libceph-kill-bad_proto-ceph-connection-op.patch
new file mode 100644 (file)
index 0000000..e020b73
--- /dev/null
@@ -0,0 +1,46 @@
+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)
index 101ba5cf4649c698aaf85b89a3e07d67919914c7..a01044356213b32ecff1258515e1a049ef64e4d6 100644 (file)
@@ -72,3 +72,23 @@ selinux-fix-sel_netnode_insert-suspicious-rcu-dereference.patch
 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