libceph: fix preallocation check in get_reply()
The check that makes sure that we have enough memory allocated to read in the entire header of the message in question is currently busted. It compares front_len of the incoming message with iov_len field of ceph_msg::front structure, which is used primarily to indicate the amount of data already read in, and not the size of the allocated buffer. Under certain conditions (e.g. a short read from a socket followed by that socket's shutdown and owning ceph_connection reset) this results in a warning similar to [85688.975866] libceph: get_reply front 198 > preallocated 122 (4#0) and, through another bug, leads to forever hung tasks and forced reboots. Fix this by comparing front_len with front_alloc_len field of struct ceph_msg, which stores the actual size of the buffer. Fixes: http://tracker.ceph.com/issues/5425 Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com> Reviewed-by: Sage Weil <sage@inktank.com>
This commit is contained in:
@@ -2522,9 +2522,9 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
|
||||
req->r_reply, req->r_reply->con);
|
||||
ceph_msg_revoke_incoming(req->r_reply);
|
||||
|
||||
if (front_len > req->r_reply->front.iov_len) {
|
||||
if (front_len > req->r_reply->front_alloc_len) {
|
||||
pr_warning("get_reply front %d > preallocated %d (%u#%llu)\n",
|
||||
front_len, (int)req->r_reply->front.iov_len,
|
||||
front_len, req->r_reply->front_alloc_len,
|
||||
(unsigned int)con->peer_name.type,
|
||||
le64_to_cpu(con->peer_name.num));
|
||||
m = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, front_len, GFP_NOFS,
|
||||
|
||||
Reference in New Issue
Block a user