diff options
author | Ilya Dryomov <ilya.dryomov@inktank.com> | 2014-01-09 19:08:21 +0100 |
---|---|---|
committer | Ilya Dryomov <ilya.dryomov@inktank.com> | 2014-01-14 10:27:47 +0100 |
commit | f2be82b0058e90b5d9ac2cb896b4914276fb50ef (patch) | |
tree | 0754bf0d97cb300fc611a2ce4527649f29cc41c6 /net/ceph/messenger.c | |
parent | libceph: rename front to front_len in get_reply() (diff) | |
download | linux-f2be82b0058e90b5d9ac2cb896b4914276fb50ef.tar.xz linux-f2be82b0058e90b5d9ac2cb896b4914276fb50ef.zip |
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>
Diffstat (limited to 'net/ceph/messenger.c')
-rw-r--r-- | net/ceph/messenger.c | 3 |
1 files changed, 1 insertions, 2 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f4d411c017e7..252ad4e01cf8 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -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; |