libceph: fix preallocation check in get_reply()
authorIlya Dryomov <ilya.dryomov@inktank.com>
Thu, 9 Jan 2014 18:08:21 +0000 (20:08 +0200)
committerIlya Dryomov <ilya.dryomov@inktank.com>
Tue, 14 Jan 2014 09:27:47 +0000 (11:27 +0200)
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>
net/ceph/messenger.c
net/ceph/osd_client.c

index f4d411c017e7e4f69482719101cfcc63bfe3e08f..252ad4e01cf8784f04b4ec28f8fe0bef2eddea12 100644 (file)
@@ -3130,7 +3130,6 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags,
        INIT_LIST_HEAD(&m->data);
 
        /* front */
-       m->front_alloc_len = front_len;
        if (front_len) {
                if (front_len > PAGE_CACHE_SIZE) {
                        m->front.iov_base = __vmalloc(front_len, flags,
@@ -3147,7 +3146,7 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags,
        } else {
                m->front.iov_base = NULL;
        }
-       m->front.iov_len = front_len;
+       m->front_alloc_len = m->front.iov_len = front_len;
 
        dout("ceph_msg_new %p front %d\n", m, front_len);
        return m;
index 7619c37bfed4342f43b937cd29b88ce114d5d6d5..7331951704907e47337f8ac7fb4c0491beededee 100644 (file)
@@ -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,
This page took 0.032067 seconds and 5 git commands to generate.