return 1;
 }
 
-static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
-                               struct ceph_msg_header *hdr,
-                               int *skip);
+static bool ceph_con_in_msg_alloc(struct ceph_connection *con,
+                               struct ceph_msg_header *hdr);
 
 
 static int read_partial_message_pages(struct ceph_connection *con,
        int ret;
        unsigned front_len, middle_len, data_len;
        bool do_datacrc = !con->msgr->nocrc;
-       int skip;
        u64 seq;
        u32 crc;
 
        if (!con->in_msg) {
                dout("got hdr type %d front %d data %d\n", con->in_hdr.type,
                     con->in_hdr.front_len, con->in_hdr.data_len);
-               skip = 0;
-               con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip);
-               if (skip) {
+               if (ceph_con_in_msg_alloc(con, &con->in_hdr)) {
                        /* skip this message */
                        dout("alloc_msg said skip message\n");
                        BUG_ON(con->in_msg);
 }
 
 /*
- * Generic message allocator, for incoming messages.
+ * Allocate a message for receiving an incoming message on a
+ * connection, and save the result in con->in_msg.  Uses the
+ * connection's private alloc_msg op if available.
+ *
+ * Returns true if the message should be skipped, false otherwise.
+ * If true is returned (skip message), con->in_msg will be NULL.
+ * If false is returned, con->in_msg will contain a pointer to the
+ * newly-allocated message, or NULL in case of memory exhaustion.
  */
-static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
-                               struct ceph_msg_header *hdr,
-                               int *skip)
+static bool ceph_con_in_msg_alloc(struct ceph_connection *con,
+                               struct ceph_msg_header *hdr)
 {
        int type = le16_to_cpu(hdr->type);
        int front_len = le32_to_cpu(hdr->front_len);
        int middle_len = le32_to_cpu(hdr->middle_len);
-       struct ceph_msg *msg = NULL;
        int ret;
 
+       BUG_ON(con->in_msg != NULL);
+
        if (con->ops->alloc_msg) {
+               int skip = 0;
+
                mutex_unlock(&con->mutex);
-               msg = con->ops->alloc_msg(con, hdr, skip);
+               con->in_msg = con->ops->alloc_msg(con, hdr, &skip);
                mutex_lock(&con->mutex);
-               if (!msg || *skip)
-                       return NULL;
+               if (skip)
+                       con->in_msg = NULL;
+
+               if (!con->in_msg)
+                       return skip != 0;
        }
-       if (!msg) {
-               *skip = 0;
-               msg = ceph_msg_new(type, front_len, GFP_NOFS, false);
-               if (!msg) {
+       if (!con->in_msg) {
+               con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false);
+               if (!con->in_msg) {
                        pr_err("unable to allocate msg type %d len %d\n",
                               type, front_len);
-                       return NULL;
+                       return false;
                }
-               msg->page_alignment = le16_to_cpu(hdr->data_off);
+               con->in_msg->page_alignment = le16_to_cpu(hdr->data_off);
        }
-       memcpy(&msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
+       memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
 
-       if (middle_len && !msg->middle) {
-               ret = ceph_alloc_middle(con, msg);
+       if (middle_len && !con->in_msg->middle) {
+               ret = ceph_alloc_middle(con, con->in_msg);
                if (ret < 0) {
-                       ceph_msg_put(msg);
-                       return NULL;
+                       ceph_msg_put(con->in_msg);
+                       con->in_msg = NULL;
                }
        }
 
-       return msg;
+       return false;
 }