ceph: fix message revocation
authorSage Weil <sage@newdream.net>
Mon, 5 Jul 2010 19:15:14 +0000 (12:15 -0700)
committerSage Weil <sage@newdream.net>
Mon, 5 Jul 2010 19:16:23 +0000 (12:16 -0700)
A message can be on a queue (pending or sent), or out_msg (sending), or
both.  We were assuming that if it's not on a queue it couldn't be out_msg,
but that was false in the case of lossy connections like the OSD.  Fix
ceph_con_revoke() to treat these cases independently.  Also, fix the
out_kvec_is_message check to only trigger if we are currently sending
_this_ message.

This fixes a GPF in tcp_sendpage, triggered by OSD restarts.

Signed-off-by: Sage Weil <sage@newdream.net>
fs/ceph/messenger.c

index 9ad43a3..9692d08 100644 (file)
@@ -2015,20 +2015,20 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg)
 {
        mutex_lock(&con->mutex);
        if (!list_empty(&msg->list_head)) {
-               dout("con_revoke %p msg %p\n", con, msg);
+               dout("con_revoke %p msg %p - was on queue\n", con, msg);
                list_del_init(&msg->list_head);
                ceph_msg_put(msg);
                msg->hdr.seq = 0;
-               if (con->out_msg == msg) {
-                       ceph_msg_put(con->out_msg);
-                       con->out_msg = NULL;
-               }
+       }
+       if (con->out_msg == msg) {
+               dout("con_revoke %p msg %p - was sending\n", con, msg);
+               con->out_msg = NULL;
                if (con->out_kvec_is_msg) {
                        con->out_skip = con->out_kvec_bytes;
                        con->out_kvec_is_msg = false;
                }
-       } else {
-               dout("con_revoke %p msg %p - not queued (sent?)\n", con, msg);
+               ceph_msg_put(msg);
+               msg->hdr.seq = 0;
        }
        mutex_unlock(&con->mutex);
 }