diff options
author | Sage Weil <sage@newdream.net> | 2010-04-22 18:47:01 +0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-05-03 21:49:24 +0400 |
commit | ae18756b9fa7bb93132cff06cd8575e3d46633f9 (patch) | |
tree | e09f5c89b4611e2c53bb50118d8fa8133b58c73b /fs | |
parent | 684be25c52a1e43638ced160be0b0b46596e7f2b (diff) |
ceph: discard incoming messages with bad seq #
We can get old message seq #'s after a tcp reconnect for stateful sessions
(i.e., the MDS). If we get a higher seq #, that is an error, and we
shouldn't see any bad seq #'s for stateless (mon, osd) connections.
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/messenger.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c index e7b91e093f54..509f57d9ccb3 100644 --- a/fs/ceph/messenger.c +++ b/fs/ceph/messenger.c @@ -1334,6 +1334,7 @@ static int read_partial_message(struct ceph_connection *con) unsigned front_len, middle_len, data_len, data_off; int datacrc = con->msgr->nocrc; int skip; + u64 seq; dout("read_partial_message con %p msg %p\n", con, m); @@ -1368,6 +1369,25 @@ static int read_partial_message(struct ceph_connection *con) return -EIO; data_off = le16_to_cpu(con->in_hdr.data_off); + /* verify seq# */ + seq = le64_to_cpu(con->in_hdr.seq); + if ((s64)seq - (s64)con->in_seq < 1) { + pr_info("skipping %s%lld %s seq %lld, expected %lld\n", + ENTITY_NAME(con->peer_name), + pr_addr(&con->peer_addr.in_addr), + seq, con->in_seq + 1); + con->in_base_pos = -front_len - middle_len - data_len - + sizeof(m->footer); + con->in_tag = CEPH_MSGR_TAG_READY; + con->in_seq++; + return 0; + } else if ((s64)seq - (s64)con->in_seq > 1) { + pr_err("read_partial_message bad seq %lld expected %lld\n", + seq, con->in_seq + 1); + con->error_msg = "bad message sequence # for incoming message"; + return -EBADMSG; + } + /* allocate message? */ if (!con->in_msg) { dout("got hdr type %d front %d data %d\n", con->in_hdr.type, |