diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-02 20:32:49 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-02 20:32:49 -0500 |
| commit | 58890c06691462ca29900d1116b28c7a3e131252 (patch) | |
| tree | 2fe512c5a664176de8078f06264da850b1460fb5 | |
| parent | 42288fe366c4f1ce7522bc9f27d0bc2a81c55264 (diff) | |
| parent | 0fa6ebc600bc8e830551aee47a0e929e818a1868 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull Ceph fixes from Sage Weil:
"Two of Alex's patches deal with a race when reseting server
connections for open RBD images, one demotes some non-fatal BUGs to
WARNs, and my patch fixes a protocol feature bit failure path."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
libceph: fix protocol feature mismatch failure path
libceph: WARN, don't BUG on unexpected connection states
libceph: always reset osds when kicking
libceph: move linger requests sooner in kick_requests()
| -rw-r--r-- | net/ceph/messenger.c | 23 | ||||
| -rw-r--r-- | net/ceph/osd_client.c | 34 |
2 files changed, 29 insertions, 28 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 4d111fd2b49..5ccf87ed8d6 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
| @@ -506,6 +506,7 @@ static void reset_connection(struct ceph_connection *con) | |||
| 506 | { | 506 | { |
| 507 | /* reset connection, out_queue, msg_ and connect_seq */ | 507 | /* reset connection, out_queue, msg_ and connect_seq */ |
| 508 | /* discard existing out_queue and msg_seq */ | 508 | /* discard existing out_queue and msg_seq */ |
| 509 | dout("reset_connection %p\n", con); | ||
| 509 | ceph_msg_remove_list(&con->out_queue); | 510 | ceph_msg_remove_list(&con->out_queue); |
| 510 | ceph_msg_remove_list(&con->out_sent); | 511 | ceph_msg_remove_list(&con->out_sent); |
| 511 | 512 | ||
| @@ -561,7 +562,7 @@ void ceph_con_open(struct ceph_connection *con, | |||
| 561 | mutex_lock(&con->mutex); | 562 | mutex_lock(&con->mutex); |
| 562 | dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); | 563 | dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); |
| 563 | 564 | ||
| 564 | BUG_ON(con->state != CON_STATE_CLOSED); | 565 | WARN_ON(con->state != CON_STATE_CLOSED); |
| 565 | con->state = CON_STATE_PREOPEN; | 566 | con->state = CON_STATE_PREOPEN; |
| 566 | 567 | ||
| 567 | con->peer_name.type = (__u8) entity_type; | 568 | con->peer_name.type = (__u8) entity_type; |
| @@ -1506,13 +1507,6 @@ static int process_banner(struct ceph_connection *con) | |||
| 1506 | return 0; | 1507 | return 0; |
| 1507 | } | 1508 | } |
| 1508 | 1509 | ||
| 1509 | static void fail_protocol(struct ceph_connection *con) | ||
| 1510 | { | ||
| 1511 | reset_connection(con); | ||
| 1512 | BUG_ON(con->state != CON_STATE_NEGOTIATING); | ||
| 1513 | con->state = CON_STATE_CLOSED; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | static int process_connect(struct ceph_connection *con) | 1510 | static int process_connect(struct ceph_connection *con) |
| 1517 | { | 1511 | { |
| 1518 | u64 sup_feat = con->msgr->supported_features; | 1512 | u64 sup_feat = con->msgr->supported_features; |
| @@ -1530,7 +1524,7 @@ static int process_connect(struct ceph_connection *con) | |||
| 1530 | ceph_pr_addr(&con->peer_addr.in_addr), | 1524 | ceph_pr_addr(&con->peer_addr.in_addr), |
| 1531 | sup_feat, server_feat, server_feat & ~sup_feat); | 1525 | sup_feat, server_feat, server_feat & ~sup_feat); |
| 1532 | con->error_msg = "missing required protocol features"; | 1526 | con->error_msg = "missing required protocol features"; |
| 1533 | fail_protocol(con); | 1527 | reset_connection(con); |
| 1534 | return -1; | 1528 | return -1; |
| 1535 | 1529 | ||
| 1536 | case CEPH_MSGR_TAG_BADPROTOVER: | 1530 | case CEPH_MSGR_TAG_BADPROTOVER: |
| @@ -1541,7 +1535,7 @@ static int process_connect(struct ceph_connection *con) | |||
| 1541 | le32_to_cpu(con->out_connect.protocol_version), | 1535 | le32_to_cpu(con->out_connect.protocol_version), |
| 1542 | le32_to_cpu(con->in_reply.protocol_version)); | 1536 | le32_to_cpu(con->in_reply.protocol_version)); |
| 1543 | con->error_msg = "protocol version mismatch"; | 1537 | con->error_msg = "protocol version mismatch"; |
| 1544 | fail_protocol(con); | 1538 | reset_connection(con); |
| 1545 | return -1; | 1539 | return -1; |
| 1546 | 1540 | ||
| 1547 | case CEPH_MSGR_TAG_BADAUTHORIZER: | 1541 | case CEPH_MSGR_TAG_BADAUTHORIZER: |
| @@ -1631,11 +1625,11 @@ static int process_connect(struct ceph_connection *con) | |||
| 1631 | ceph_pr_addr(&con->peer_addr.in_addr), | 1625 | ceph_pr_addr(&con->peer_addr.in_addr), |
| 1632 | req_feat, server_feat, req_feat & ~server_feat); | 1626 | req_feat, server_feat, req_feat & ~server_feat); |
| 1633 | con->error_msg = "missing required protocol features"; | 1627 | con->error_msg = "missing required protocol features"; |
| 1634 | fail_protocol(con); | 1628 | reset_connection(con); |
| 1635 | return -1; | 1629 | return -1; |
| 1636 | } | 1630 | } |
| 1637 | 1631 | ||
| 1638 | BUG_ON(con->state != CON_STATE_NEGOTIATING); | 1632 | WARN_ON(con->state != CON_STATE_NEGOTIATING); |
| 1639 | con->state = CON_STATE_OPEN; | 1633 | con->state = CON_STATE_OPEN; |
| 1640 | 1634 | ||
| 1641 | con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); | 1635 | con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); |
| @@ -2132,7 +2126,6 @@ more: | |||
| 2132 | if (ret < 0) | 2126 | if (ret < 0) |
| 2133 | goto out; | 2127 | goto out; |
| 2134 | 2128 | ||
| 2135 | BUG_ON(con->state != CON_STATE_CONNECTING); | ||
| 2136 | con->state = CON_STATE_NEGOTIATING; | 2129 | con->state = CON_STATE_NEGOTIATING; |
| 2137 | 2130 | ||
| 2138 | /* | 2131 | /* |
| @@ -2160,7 +2153,7 @@ more: | |||
| 2160 | goto more; | 2153 | goto more; |
| 2161 | } | 2154 | } |
| 2162 | 2155 | ||
| 2163 | BUG_ON(con->state != CON_STATE_OPEN); | 2156 | WARN_ON(con->state != CON_STATE_OPEN); |
| 2164 | 2157 | ||
| 2165 | if (con->in_base_pos < 0) { | 2158 | if (con->in_base_pos < 0) { |
| 2166 | /* | 2159 | /* |
| @@ -2382,7 +2375,7 @@ static void ceph_fault(struct ceph_connection *con) | |||
| 2382 | dout("fault %p state %lu to peer %s\n", | 2375 | dout("fault %p state %lu to peer %s\n", |
| 2383 | con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); | 2376 | con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); |
| 2384 | 2377 | ||
| 2385 | BUG_ON(con->state != CON_STATE_CONNECTING && | 2378 | WARN_ON(con->state != CON_STATE_CONNECTING && |
| 2386 | con->state != CON_STATE_NEGOTIATING && | 2379 | con->state != CON_STATE_NEGOTIATING && |
| 2387 | con->state != CON_STATE_OPEN); | 2380 | con->state != CON_STATE_OPEN); |
| 2388 | 2381 | ||
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 780caf6b049..eb9a4447876 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
| @@ -1270,7 +1270,7 @@ static void reset_changed_osds(struct ceph_osd_client *osdc) | |||
| 1270 | * Requeue requests whose mapping to an OSD has changed. If requests map to | 1270 | * Requeue requests whose mapping to an OSD has changed. If requests map to |
| 1271 | * no osd, request a new map. | 1271 | * no osd, request a new map. |
| 1272 | * | 1272 | * |
| 1273 | * Caller should hold map_sem for read and request_mutex. | 1273 | * Caller should hold map_sem for read. |
| 1274 | */ | 1274 | */ |
| 1275 | static void kick_requests(struct ceph_osd_client *osdc, int force_resend) | 1275 | static void kick_requests(struct ceph_osd_client *osdc, int force_resend) |
| 1276 | { | 1276 | { |
| @@ -1284,6 +1284,24 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) | |||
| 1284 | for (p = rb_first(&osdc->requests); p; ) { | 1284 | for (p = rb_first(&osdc->requests); p; ) { |
| 1285 | req = rb_entry(p, struct ceph_osd_request, r_node); | 1285 | req = rb_entry(p, struct ceph_osd_request, r_node); |
| 1286 | p = rb_next(p); | 1286 | p = rb_next(p); |
| 1287 | |||
| 1288 | /* | ||
| 1289 | * For linger requests that have not yet been | ||
| 1290 | * registered, move them to the linger list; they'll | ||
| 1291 | * be sent to the osd in the loop below. Unregister | ||
| 1292 | * the request before re-registering it as a linger | ||
| 1293 | * request to ensure the __map_request() below | ||
| 1294 | * will decide it needs to be sent. | ||
| 1295 | */ | ||
| 1296 | if (req->r_linger && list_empty(&req->r_linger_item)) { | ||
| 1297 | dout("%p tid %llu restart on osd%d\n", | ||
| 1298 | req, req->r_tid, | ||
| 1299 | req->r_osd ? req->r_osd->o_osd : -1); | ||
| 1300 | __unregister_request(osdc, req); | ||
| 1301 | __register_linger_request(osdc, req); | ||
| 1302 | continue; | ||
| 1303 | } | ||
| 1304 | |||
| 1287 | err = __map_request(osdc, req, force_resend); | 1305 | err = __map_request(osdc, req, force_resend); |
| 1288 | if (err < 0) | 1306 | if (err < 0) |
| 1289 | continue; /* error */ | 1307 | continue; /* error */ |
| @@ -1298,17 +1316,6 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) | |||
| 1298 | req->r_flags |= CEPH_OSD_FLAG_RETRY; | 1316 | req->r_flags |= CEPH_OSD_FLAG_RETRY; |
| 1299 | } | 1317 | } |
| 1300 | } | 1318 | } |
| 1301 | if (req->r_linger && list_empty(&req->r_linger_item)) { | ||
| 1302 | /* | ||
| 1303 | * register as a linger so that we will | ||
| 1304 | * re-submit below and get a new tid | ||
| 1305 | */ | ||
| 1306 | dout("%p tid %llu restart on osd%d\n", | ||
| 1307 | req, req->r_tid, | ||
| 1308 | req->r_osd ? req->r_osd->o_osd : -1); | ||
| 1309 | __register_linger_request(osdc, req); | ||
| 1310 | __unregister_request(osdc, req); | ||
| 1311 | } | ||
| 1312 | } | 1319 | } |
| 1313 | 1320 | ||
| 1314 | list_for_each_entry_safe(req, nreq, &osdc->req_linger, | 1321 | list_for_each_entry_safe(req, nreq, &osdc->req_linger, |
| @@ -1316,6 +1323,7 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) | |||
| 1316 | dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); | 1323 | dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); |
| 1317 | 1324 | ||
| 1318 | err = __map_request(osdc, req, force_resend); | 1325 | err = __map_request(osdc, req, force_resend); |
| 1326 | dout("__map_request returned %d\n", err); | ||
| 1319 | if (err == 0) | 1327 | if (err == 0) |
| 1320 | continue; /* no change and no osd was specified */ | 1328 | continue; /* no change and no osd was specified */ |
| 1321 | if (err < 0) | 1329 | if (err < 0) |
| @@ -1337,6 +1345,7 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) | |||
| 1337 | dout("%d requests for down osds, need new map\n", needmap); | 1345 | dout("%d requests for down osds, need new map\n", needmap); |
| 1338 | ceph_monc_request_next_osdmap(&osdc->client->monc); | 1346 | ceph_monc_request_next_osdmap(&osdc->client->monc); |
| 1339 | } | 1347 | } |
| 1348 | reset_changed_osds(osdc); | ||
| 1340 | } | 1349 | } |
| 1341 | 1350 | ||
| 1342 | 1351 | ||
| @@ -1393,7 +1402,6 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
| 1393 | osdc->osdmap = newmap; | 1402 | osdc->osdmap = newmap; |
| 1394 | } | 1403 | } |
| 1395 | kick_requests(osdc, 0); | 1404 | kick_requests(osdc, 0); |
| 1396 | reset_changed_osds(osdc); | ||
| 1397 | } else { | 1405 | } else { |
| 1398 | dout("ignoring incremental map %u len %d\n", | 1406 | dout("ignoring incremental map %u len %d\n", |
| 1399 | epoch, maplen); | 1407 | epoch, maplen); |
