From: Greg Kroah-Hartman Date: Tue, 15 Jan 2013 14:00:18 +0000 (-0800) Subject: 3.7-stable patches X-Git-Tag: v3.7.3~19 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6436397345df6896efd72ec6e74c8e3810356fe6;p=thirdparty%2Fkernel%2Fstable-queue.git 3.7-stable patches added patches: 0002-libceph-report-connection-fault-with-warning.patch 0003-libceph-init-osd-o_node-in-create_osd.patch 0004-libceph-init-event-node-in-ceph_osdc_create_event.patch 0005-libceph-don-t-use-rb_init_node-in-ceph_osdc_alloc_re.patch 0006-libceph-register-request-before-unregister-linger.patch 0007-libceph-move-linger-requests-sooner-in-kick_requests.patch 0008-libceph-always-reset-osds-when-kicking.patch 0009-libceph-WARN-don-t-BUG-on-unexpected-connection-stat.patch --- diff --git a/queue-3.7/0002-libceph-report-connection-fault-with-warning.patch b/queue-3.7/0002-libceph-report-connection-fault-with-warning.patch new file mode 100644 index 00000000000..08eadee20af --- /dev/null +++ b/queue-3.7/0002-libceph-report-connection-fault-with-warning.patch @@ -0,0 +1,39 @@ +From 5f64737fb44ee280362a1be280f26adb38c689e4 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 14 Dec 2012 16:47:41 -0600 +Subject: libceph: report connection fault with warning + +From: Alex Elder + +(cherry picked from commit 28362986f8743124b3a0fda20a8ed3e80309cce1) + +When a connection's socket disconnects, or if there's a protocol +error of some kind on the connection, a fault is signaled and +the connection is reset (closed and reopened, basically). We +currently get an error message on the log whenever this occurs. + +A ceph connection will attempt to reestablish a socket connection +repeatedly if a fault occurs. This means that these error messages +will get repeatedly added to the log, which is undesirable. + +Change the error message to be a warning, so they don't get +logged by default. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -2369,7 +2369,7 @@ fault: + static void ceph_fault(struct ceph_connection *con) + __releases(con->mutex) + { +- pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), ++ pr_warning("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), + ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); + dout("fault %p state %lu to peer %s\n", + con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); diff --git a/queue-3.7/0003-libceph-init-osd-o_node-in-create_osd.patch b/queue-3.7/0003-libceph-init-osd-o_node-in-create_osd.patch new file mode 100644 index 00000000000..f6d266a8588 --- /dev/null +++ b/queue-3.7/0003-libceph-init-osd-o_node-in-create_osd.patch @@ -0,0 +1,32 @@ +From d49d943a24d4addbb5c6d1e4feb45bb98b2885fa Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 6 Dec 2012 07:22:04 -0600 +Subject: libceph: init osd->o_node in create_osd() + +From: Alex Elder + +(cherry picked from commit f407731d12214e7686819018f3a1e9d7b6f83a02) + +The red-black node node in the ceph osd structure is not initialized +in create_osd(). Because this node can be the subject of a +RB_EMPTY_NODE() call later on, we should ensure the node is +initialized properly for that. Add a call to RB_CLEAR_NODE() +initialize it. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -647,6 +647,7 @@ static struct ceph_osd *create_osd(struc + atomic_set(&osd->o_ref, 1); + osd->o_osdc = osdc; + osd->o_osd = onum; ++ RB_CLEAR_NODE(&osd->o_node); + INIT_LIST_HEAD(&osd->o_requests); + INIT_LIST_HEAD(&osd->o_linger_requests); + INIT_LIST_HEAD(&osd->o_osd_lru); diff --git a/queue-3.7/0004-libceph-init-event-node-in-ceph_osdc_create_event.patch b/queue-3.7/0004-libceph-init-event-node-in-ceph_osdc_create_event.patch new file mode 100644 index 00000000000..2db37fc8d60 --- /dev/null +++ b/queue-3.7/0004-libceph-init-event-node-in-ceph_osdc_create_event.patch @@ -0,0 +1,31 @@ +From b4c0c6243efad1ae18a8aa17694952fd6c13bbaa Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Mon, 17 Dec 2012 12:23:48 -0600 +Subject: libceph: init event->node in ceph_osdc_create_event() + +From: Alex Elder + +(cherry picked from commit 3ee5234df68d253c415ba4f2db72ad250d9c21a9) + +The red-black node node in the ceph osd event structure is not +initialized in create_osdc_create_event(). Because this node can +be the subject of a RB_EMPTY_NODE() call later on, we should ensure +the node is initialized properly for that. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1600,6 +1600,7 @@ int ceph_osdc_create_event(struct ceph_o + event->data = data; + event->osdc = osdc; + INIT_LIST_HEAD(&event->osd_node); ++ RB_CLEAR_NODE(&event->node); + kref_init(&event->kref); /* one ref for us */ + kref_get(&event->kref); /* one ref for the caller */ + init_completion(&event->completion); diff --git a/queue-3.7/0005-libceph-don-t-use-rb_init_node-in-ceph_osdc_alloc_re.patch b/queue-3.7/0005-libceph-don-t-use-rb_init_node-in-ceph_osdc_alloc_re.patch new file mode 100644 index 00000000000..adee32ec779 --- /dev/null +++ b/queue-3.7/0005-libceph-don-t-use-rb_init_node-in-ceph_osdc_alloc_re.patch @@ -0,0 +1,36 @@ +From f660813d76b3634c39c2b3ed8715af7e9db14f9c Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Mon, 17 Dec 2012 12:23:48 -0600 +Subject: libceph: don't use rb_init_node() in ceph_osdc_alloc_request() + +From: Alex Elder + +(cherry picked from commit a978fa20fb657548561dddbfb605fe43654f0825) + +The red-black node in the ceph osd request structure is initialized +in ceph_osdc_alloc_request() using rbd_init_node(). We do need to +initialize this, because in __unregister_request() we call +RB_EMPTY_NODE(), which expects the node it's checking to have +been initialized. But rb_init_node() is apparently overkill, and +may in fact be on its way out. So use RB_CLEAR_NODE() instead. + +For a little more background, see this commit: + 4c199a93 rbtree: empty nodes have no color" + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -221,6 +221,7 @@ struct ceph_osd_request *ceph_osdc_alloc + kref_init(&req->r_kref); + init_completion(&req->r_completion); + init_completion(&req->r_safe_completion); ++ RB_CLEAR_NODE(&req->r_node); + INIT_LIST_HEAD(&req->r_unsafe_item); + INIT_LIST_HEAD(&req->r_linger_item); + INIT_LIST_HEAD(&req->r_linger_osd); diff --git a/queue-3.7/0006-libceph-register-request-before-unregister-linger.patch b/queue-3.7/0006-libceph-register-request-before-unregister-linger.patch new file mode 100644 index 00000000000..6d95b9bcc36 --- /dev/null +++ b/queue-3.7/0006-libceph-register-request-before-unregister-linger.patch @@ -0,0 +1,32 @@ +From c9ddd2cac5e5e9bf278a9c08976592972a2d15c1 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 6 Dec 2012 07:22:04 -0600 +Subject: libceph: register request before unregister linger + +From: Alex Elder + +(cherry picked from commit c89ce05e0c5a01a256100ac6a6019f276bdd1ca6) + +In kick_requests(), we need to register the request before we +unregister the linger request. Otherwise the unregister will +reset the request's osd pointer to NULL. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1366,8 +1366,8 @@ static void kick_requests(struct ceph_os + + dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); +- __unregister_linger_request(osdc, req); + __register_request(osdc, req); ++ __unregister_linger_request(osdc, req); + } + mutex_unlock(&osdc->request_mutex); + diff --git a/queue-3.7/0007-libceph-move-linger-requests-sooner-in-kick_requests.patch b/queue-3.7/0007-libceph-move-linger-requests-sooner-in-kick_requests.patch new file mode 100644 index 00000000000..34ca1d153d7 --- /dev/null +++ b/queue-3.7/0007-libceph-move-linger-requests-sooner-in-kick_requests.patch @@ -0,0 +1,112 @@ +From d92a42b79c755e911495bd36316d2573804293ea Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 19 Dec 2012 15:52:36 -0600 +Subject: libceph: move linger requests sooner in kick_requests() + +From: Alex Elder + +(cherry picked from commit ab60b16d3c31b9bd9fd5b39f97dc42c52a50b67d) + +The kick_requests() function is called by ceph_osdc_handle_map() +when an osd map change has been indicated. Its purpose is to +re-queue any request whose target osd is different from what it +was when it was originally sent. + +It is structured as two loops, one for incomplete but registered +requests, and a second for handling completed linger requests. +As a special case, in the first loop if a request marked to linger +has not yet completed, it is moved from the request list to the +linger list. This is as a quick and dirty way to have the second +loop handle sending the request along with all the other linger +requests. + +Because of the way it's done now, however, this quick and dirty +solution can result in these incomplete linger requests never +getting re-sent as desired. The problem lies in the fact that +the second loop only arranges for a linger request to be sent +if it appears its target osd has changed. This is the proper +handling for *completed* linger requests (it avoids issuing +the same linger request twice to the same osd). + +But although the linger requests added to the list in the first loop +may have been sent, they have not yet completed, so they need to be +re-sent regardless of whether their target osd has changed. + +The first required fix is we need to avoid calling __map_request() +on any incomplete linger request. Otherwise the subsequent +__map_request() call in the second loop will find the target osd +has not changed and will therefore not re-send the request. + +Second, we need to be sure that a sent but incomplete linger request +gets re-sent. If the target osd is the same with the new osd map as +it was when the request was originally sent, this won't happen. +This can be fixed through careful handling when we move these +requests from the request list to the linger list, by unregistering +the request *before* it is registered as a linger request. This +works because a side-effect of unregistering the request is to make +the request's r_osd pointer be NULL, and *that* will ensure the +second loop actually re-sends the linger request. + +Processing of such a request is done at that point, so continue with +the next one once it's been moved. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 30 +++++++++++++++++++----------- + 1 file changed, 19 insertions(+), 11 deletions(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1322,6 +1322,24 @@ static void kick_requests(struct ceph_os + for (p = rb_first(&osdc->requests); p; ) { + req = rb_entry(p, struct ceph_osd_request, r_node); + p = rb_next(p); ++ ++ /* ++ * For linger requests that have not yet been ++ * registered, move them to the linger list; they'll ++ * be sent to the osd in the loop below. Unregister ++ * the request before re-registering it as a linger ++ * request to ensure the __map_request() below ++ * will decide it needs to be sent. ++ */ ++ if (req->r_linger && list_empty(&req->r_linger_item)) { ++ dout("%p tid %llu restart on osd%d\n", ++ req, req->r_tid, ++ req->r_osd ? req->r_osd->o_osd : -1); ++ __unregister_request(osdc, req); ++ __register_linger_request(osdc, req); ++ continue; ++ } ++ + err = __map_request(osdc, req, force_resend); + if (err < 0) + continue; /* error */ +@@ -1336,17 +1354,6 @@ static void kick_requests(struct ceph_os + req->r_flags |= CEPH_OSD_FLAG_RETRY; + } + } +- if (req->r_linger && list_empty(&req->r_linger_item)) { +- /* +- * register as a linger so that we will +- * re-submit below and get a new tid +- */ +- dout("%p tid %llu restart on osd%d\n", +- req, req->r_tid, +- req->r_osd ? req->r_osd->o_osd : -1); +- __register_linger_request(osdc, req); +- __unregister_request(osdc, req); +- } + } + + list_for_each_entry_safe(req, nreq, &osdc->req_linger, +@@ -1354,6 +1361,7 @@ static void kick_requests(struct ceph_os + dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); + + err = __map_request(osdc, req, force_resend); ++ dout("__map_request returned %d\n", err); + if (err == 0) + continue; /* no change and no osd was specified */ + if (err < 0) diff --git a/queue-3.7/0008-libceph-always-reset-osds-when-kicking.patch b/queue-3.7/0008-libceph-always-reset-osds-when-kicking.patch new file mode 100644 index 00000000000..0522cb6b119 --- /dev/null +++ b/queue-3.7/0008-libceph-always-reset-osds-when-kicking.patch @@ -0,0 +1,60 @@ +From 8cc1491a5d9e720f0b6f69244fc1548597bb868b Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 26 Dec 2012 14:31:40 -0600 +Subject: libceph: always reset osds when kicking + +From: Alex Elder + +(cherry picked from commit e6d50f67a6b1a6252a616e6e629473b5c4277218) + +When ceph_osdc_handle_map() is called to process a new osd map, +kick_requests() is called to ensure all affected requests are +updated if necessary to reflect changes in the osd map. This +happens in two cases: whenever an incremental map update is +processed; and when a full map update (or the last one if there is +more than one) gets processed. + +In the former case, the kick_requests() call is followed immediately +by a call to reset_changed_osds() to ensure any connections to osds +affected by the map change are reset. But for full map updates +this isn't done. + +Both cases should be doing this osd reset. + +Rather than duplicating the reset_changed_osds() call, move it into +the end of kick_requests(). + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -1308,7 +1308,7 @@ static void reset_changed_osds(struct ce + * Requeue requests whose mapping to an OSD has changed. If requests map to + * no osd, request a new map. + * +- * Caller should hold map_sem for read and request_mutex. ++ * Caller should hold map_sem for read. + */ + static void kick_requests(struct ceph_osd_client *osdc, int force_resend) + { +@@ -1383,6 +1383,7 @@ static void kick_requests(struct ceph_os + dout("%d requests for down osds, need new map\n", needmap); + ceph_monc_request_next_osdmap(&osdc->client->monc); + } ++ reset_changed_osds(osdc); + } + + +@@ -1439,7 +1440,6 @@ void ceph_osdc_handle_map(struct ceph_os + osdc->osdmap = newmap; + } + kick_requests(osdc, 0); +- reset_changed_osds(osdc); + } else { + dout("ignoring incremental map %u len %d\n", + epoch, maplen); diff --git a/queue-3.7/0009-libceph-WARN-don-t-BUG-on-unexpected-connection-stat.patch b/queue-3.7/0009-libceph-WARN-don-t-BUG-on-unexpected-connection-stat.patch new file mode 100644 index 00000000000..3ec395c5d1f --- /dev/null +++ b/queue-3.7/0009-libceph-WARN-don-t-BUG-on-unexpected-connection-stat.patch @@ -0,0 +1,85 @@ +From b95ad0140dc8d2375bff4b0f30f6832cbb29e17c Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 26 Dec 2012 10:43:57 -0600 +Subject: libceph: WARN, don't BUG on unexpected connection states + +From: Alex Elder + +(cherry picked from commit 122070a2ffc91f87fe8e8493eb0ac61986c5557c) + +A number of assertions in the ceph messenger are implemented with +BUG_ON(), killing the system if connection's state doesn't match +what's expected. At this point our state model is (evidently) not +well understood enough for these assertions to trigger a BUG(). +Convert all BUG_ON(con->state...) calls to be WARN_ON(con->state...) +so we learn about these issues without killing the machine. + +We now recognize that a connection fault can occur due to a socket +closure at any time, regardless of the state of the connection. So +there is really nothing we can assert about the state of the +connection at that point so eliminate that assertion. + +Reported-by: Ugis +Tested-by: Ugis +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -561,7 +561,7 @@ void ceph_con_open(struct ceph_connectio + mutex_lock(&con->mutex); + dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); + +- BUG_ON(con->state != CON_STATE_CLOSED); ++ WARN_ON(con->state != CON_STATE_CLOSED); + con->state = CON_STATE_PREOPEN; + + con->peer_name.type = (__u8) entity_type; +@@ -1509,7 +1509,7 @@ static int process_banner(struct ceph_co + static void fail_protocol(struct ceph_connection *con) + { + reset_connection(con); +- BUG_ON(con->state != CON_STATE_NEGOTIATING); ++ WARN_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_CLOSED; + } + +@@ -1635,7 +1635,7 @@ static int process_connect(struct ceph_c + return -1; + } + +- BUG_ON(con->state != CON_STATE_NEGOTIATING); ++ WARN_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_OPEN; + + con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); +@@ -2132,7 +2132,6 @@ more: + if (ret < 0) + goto out; + +- BUG_ON(con->state != CON_STATE_CONNECTING); + con->state = CON_STATE_NEGOTIATING; + + /* +@@ -2160,7 +2159,7 @@ more: + goto more; + } + +- BUG_ON(con->state != CON_STATE_OPEN); ++ WARN_ON(con->state != CON_STATE_OPEN); + + if (con->in_base_pos < 0) { + /* +@@ -2374,7 +2373,7 @@ static void ceph_fault(struct ceph_conne + dout("fault %p state %lu to peer %s\n", + con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); + +- BUG_ON(con->state != CON_STATE_CONNECTING && ++ WARN_ON(con->state != CON_STATE_CONNECTING && + con->state != CON_STATE_NEGOTIATING && + con->state != CON_STATE_OPEN); + diff --git a/queue-3.7/series b/queue-3.7/series index f75893714ef..b750f8f06fc 100644 --- a/queue-3.7/series +++ b/queue-3.7/series @@ -188,3 +188,11 @@ edac-fix-kernel-panic-on-module-unloading.patch drm-i915-disable-cpt-phase-pointer-fdi-rx-workaround.patch kvm-ppc-44x-fix-dcr-read-write.patch 0001-libceph-socket-can-close-in-any-connection-state.patch +0002-libceph-report-connection-fault-with-warning.patch +0003-libceph-init-osd-o_node-in-create_osd.patch +0004-libceph-init-event-node-in-ceph_osdc_create_event.patch +0005-libceph-don-t-use-rb_init_node-in-ceph_osdc_alloc_re.patch +0006-libceph-register-request-before-unregister-linger.patch +0007-libceph-move-linger-requests-sooner-in-kick_requests.patch +0008-libceph-always-reset-osds-when-kicking.patch +0009-libceph-WARN-don-t-BUG-on-unexpected-connection-stat.patch