Skip to content

Commit 41f76d8

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull ceph fixes from Sage Weil: "There is an RBD fix for a crash due to the immutable bio changes, an error path fix, and a locking fix in the recent redirect support" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: libceph: do not dereference a NULL bio pointer libceph: take map_sem for read in handle_reply() libceph: factor out logic from ceph_osdc_start_request() libceph: fix error handling in ceph_osdc_init()
2 parents 42be3f3 + 0ec1d15 commit 41f76d8

File tree

2 files changed

+60
-32
lines changed

2 files changed

+60
-32
lines changed

net/ceph/messenger.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -840,9 +840,13 @@ static bool ceph_msg_data_bio_advance(struct ceph_msg_data_cursor *cursor,
840840

841841
if (!cursor->bvec_iter.bi_size) {
842842
bio = bio->bi_next;
843-
cursor->bvec_iter = bio->bi_iter;
843+
cursor->bio = bio;
844+
if (bio)
845+
cursor->bvec_iter = bio->bi_iter;
846+
else
847+
memset(&cursor->bvec_iter, 0,
848+
sizeof(cursor->bvec_iter));
844849
}
845-
cursor->bio = bio;
846850

847851
if (!cursor->last_piece) {
848852
BUG_ON(!cursor->resid);

net/ceph/osd_client.c

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,40 @@ static void __send_queued(struct ceph_osd_client *osdc)
14261426
__send_request(osdc, req);
14271427
}
14281428

1429+
/*
1430+
* Caller should hold map_sem for read and request_mutex.
1431+
*/
1432+
static int __ceph_osdc_start_request(struct ceph_osd_client *osdc,
1433+
struct ceph_osd_request *req,
1434+
bool nofail)
1435+
{
1436+
int rc;
1437+
1438+
__register_request(osdc, req);
1439+
req->r_sent = 0;
1440+
req->r_got_reply = 0;
1441+
rc = __map_request(osdc, req, 0);
1442+
if (rc < 0) {
1443+
if (nofail) {
1444+
dout("osdc_start_request failed map, "
1445+
" will retry %lld\n", req->r_tid);
1446+
rc = 0;
1447+
} else {
1448+
__unregister_request(osdc, req);
1449+
}
1450+
return rc;
1451+
}
1452+
1453+
if (req->r_osd == NULL) {
1454+
dout("send_request %p no up osds in pg\n", req);
1455+
ceph_monc_request_next_osdmap(&osdc->client->monc);
1456+
} else {
1457+
__send_queued(osdc);
1458+
}
1459+
1460+
return 0;
1461+
}
1462+
14291463
/*
14301464
* Timeout callback, called every N seconds when 1 or more osd
14311465
* requests has been active for more than N seconds. When this
@@ -1653,6 +1687,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
16531687
osdmap_epoch = ceph_decode_32(&p);
16541688

16551689
/* lookup */
1690+
down_read(&osdc->map_sem);
16561691
mutex_lock(&osdc->request_mutex);
16571692
req = __lookup_request(osdc, tid);
16581693
if (req == NULL) {
@@ -1709,7 +1744,6 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
17091744
dout("redirect pool %lld\n", redir.oloc.pool);
17101745

17111746
__unregister_request(osdc, req);
1712-
mutex_unlock(&osdc->request_mutex);
17131747

17141748
req->r_target_oloc = redir.oloc; /* struct */
17151749

@@ -1721,10 +1755,10 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
17211755
* successfully. In the future we might want to follow
17221756
* original request's nofail setting here.
17231757
*/
1724-
err = ceph_osdc_start_request(osdc, req, true);
1758+
err = __ceph_osdc_start_request(osdc, req, true);
17251759
BUG_ON(err);
17261760

1727-
goto done;
1761+
goto out_unlock;
17281762
}
17291763

17301764
already_completed = req->r_got_reply;
@@ -1742,8 +1776,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
17421776
req->r_got_reply = 1;
17431777
} else if ((flags & CEPH_OSD_FLAG_ONDISK) == 0) {
17441778
dout("handle_reply tid %llu dup ack\n", tid);
1745-
mutex_unlock(&osdc->request_mutex);
1746-
goto done;
1779+
goto out_unlock;
17471780
}
17481781

17491782
dout("handle_reply tid %llu flags %d\n", tid, flags);
@@ -1758,6 +1791,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
17581791
__unregister_request(osdc, req);
17591792

17601793
mutex_unlock(&osdc->request_mutex);
1794+
up_read(&osdc->map_sem);
17611795

17621796
if (!already_completed) {
17631797
if (req->r_unsafe_callback &&
@@ -1775,10 +1809,14 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
17751809
complete_request(req);
17761810
}
17771811

1778-
done:
1812+
out:
17791813
dout("req=%p req->r_linger=%d\n", req, req->r_linger);
17801814
ceph_osdc_put_request(req);
17811815
return;
1816+
out_unlock:
1817+
mutex_unlock(&osdc->request_mutex);
1818+
up_read(&osdc->map_sem);
1819+
goto out;
17821820

17831821
bad_put:
17841822
req->r_result = -EIO;
@@ -1791,6 +1829,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
17911829
ceph_osdc_put_request(req);
17921830
bad_mutex:
17931831
mutex_unlock(&osdc->request_mutex);
1832+
up_read(&osdc->map_sem);
17941833
bad:
17951834
pr_err("corrupt osd_op_reply got %d %d\n",
17961835
(int)msg->front.iov_len, le32_to_cpu(msg->hdr.front_len));
@@ -2351,34 +2390,16 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
23512390
struct ceph_osd_request *req,
23522391
bool nofail)
23532392
{
2354-
int rc = 0;
2393+
int rc;
23552394

23562395
down_read(&osdc->map_sem);
23572396
mutex_lock(&osdc->request_mutex);
2358-
__register_request(osdc, req);
2359-
req->r_sent = 0;
2360-
req->r_got_reply = 0;
2361-
rc = __map_request(osdc, req, 0);
2362-
if (rc < 0) {
2363-
if (nofail) {
2364-
dout("osdc_start_request failed map, "
2365-
" will retry %lld\n", req->r_tid);
2366-
rc = 0;
2367-
} else {
2368-
__unregister_request(osdc, req);
2369-
}
2370-
goto out_unlock;
2371-
}
2372-
if (req->r_osd == NULL) {
2373-
dout("send_request %p no up osds in pg\n", req);
2374-
ceph_monc_request_next_osdmap(&osdc->client->monc);
2375-
} else {
2376-
__send_queued(osdc);
2377-
}
2378-
rc = 0;
2379-
out_unlock:
2397+
2398+
rc = __ceph_osdc_start_request(osdc, req, nofail);
2399+
23802400
mutex_unlock(&osdc->request_mutex);
23812401
up_read(&osdc->map_sem);
2402+
23822403
return rc;
23832404
}
23842405
EXPORT_SYMBOL(ceph_osdc_start_request);
@@ -2504,9 +2525,12 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client)
25042525
err = -ENOMEM;
25052526
osdc->notify_wq = create_singlethread_workqueue("ceph-watch-notify");
25062527
if (!osdc->notify_wq)
2507-
goto out_msgpool;
2528+
goto out_msgpool_reply;
2529+
25082530
return 0;
25092531

2532+
out_msgpool_reply:
2533+
ceph_msgpool_destroy(&osdc->msgpool_op_reply);
25102534
out_msgpool:
25112535
ceph_msgpool_destroy(&osdc->msgpool_op);
25122536
out_mempool:

0 commit comments

Comments
 (0)