|
@@ -1733,9 +1733,7 @@ static int read_partial_message_section(struct ceph_connection *con,
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
-static bool ceph_con_in_msg_alloc(struct ceph_connection *con,
|
|
|
|
- struct ceph_msg_header *hdr);
|
|
|
|
-
|
|
|
|
|
|
+static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip);
|
|
|
|
|
|
static int read_partial_message_pages(struct ceph_connection *con,
|
|
static int read_partial_message_pages(struct ceph_connection *con,
|
|
struct page **pages,
|
|
struct page **pages,
|
|
@@ -1864,9 +1862,14 @@ static int read_partial_message(struct ceph_connection *con)
|
|
|
|
|
|
/* allocate message? */
|
|
/* allocate message? */
|
|
if (!con->in_msg) {
|
|
if (!con->in_msg) {
|
|
|
|
+ int skip = 0;
|
|
|
|
+
|
|
dout("got hdr type %d front %d data %d\n", con->in_hdr.type,
|
|
dout("got hdr type %d front %d data %d\n", con->in_hdr.type,
|
|
con->in_hdr.front_len, con->in_hdr.data_len);
|
|
con->in_hdr.front_len, con->in_hdr.data_len);
|
|
- if (ceph_con_in_msg_alloc(con, &con->in_hdr)) {
|
|
|
|
|
|
+ ret = ceph_con_in_msg_alloc(con, &skip);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+ if (skip) {
|
|
/* skip this message */
|
|
/* skip this message */
|
|
dout("alloc_msg said skip message\n");
|
|
dout("alloc_msg said skip message\n");
|
|
BUG_ON(con->in_msg);
|
|
BUG_ON(con->in_msg);
|
|
@@ -1876,12 +1879,8 @@ static int read_partial_message(struct ceph_connection *con)
|
|
con->in_seq++;
|
|
con->in_seq++;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
- if (!con->in_msg) {
|
|
|
|
- con->error_msg =
|
|
|
|
- "error allocating memory for incoming message";
|
|
|
|
- return -ENOMEM;
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
+ BUG_ON(!con->in_msg);
|
|
BUG_ON(con->in_msg->con != con);
|
|
BUG_ON(con->in_msg->con != con);
|
|
m = con->in_msg;
|
|
m = con->in_msg;
|
|
m->front.iov_len = 0; /* haven't read it yet */
|
|
m->front.iov_len = 0; /* haven't read it yet */
|
|
@@ -2715,43 +2714,50 @@ static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg)
|
|
* connection, and save the result in con->in_msg. Uses the
|
|
* connection, and save the result in con->in_msg. Uses the
|
|
* connection's private alloc_msg op if available.
|
|
* 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.
|
|
|
|
|
|
+ * Returns 0 on success, or a negative error code.
|
|
|
|
+ *
|
|
|
|
+ * On success, if we set *skip = 1:
|
|
|
|
+ * - the next message should be skipped and ignored.
|
|
|
|
+ * - con->in_msg == NULL
|
|
|
|
+ * or if we set *skip = 0:
|
|
|
|
+ * - con->in_msg is non-null.
|
|
|
|
+ * On error (ENOMEM, EAGAIN, ...),
|
|
|
|
+ * - con->in_msg == NULL
|
|
*/
|
|
*/
|
|
-static bool ceph_con_in_msg_alloc(struct ceph_connection *con,
|
|
|
|
- struct ceph_msg_header *hdr)
|
|
|
|
|
|
+static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)
|
|
{
|
|
{
|
|
|
|
+ struct ceph_msg_header *hdr = &con->in_hdr;
|
|
int type = le16_to_cpu(hdr->type);
|
|
int type = le16_to_cpu(hdr->type);
|
|
int front_len = le32_to_cpu(hdr->front_len);
|
|
int front_len = le32_to_cpu(hdr->front_len);
|
|
int middle_len = le32_to_cpu(hdr->middle_len);
|
|
int middle_len = le32_to_cpu(hdr->middle_len);
|
|
- int ret;
|
|
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
BUG_ON(con->in_msg != NULL);
|
|
BUG_ON(con->in_msg != NULL);
|
|
|
|
|
|
if (con->ops->alloc_msg) {
|
|
if (con->ops->alloc_msg) {
|
|
- int skip = 0;
|
|
|
|
-
|
|
|
|
mutex_unlock(&con->mutex);
|
|
mutex_unlock(&con->mutex);
|
|
- con->in_msg = con->ops->alloc_msg(con, hdr, &skip);
|
|
|
|
|
|
+ con->in_msg = con->ops->alloc_msg(con, hdr, skip);
|
|
mutex_lock(&con->mutex);
|
|
mutex_lock(&con->mutex);
|
|
if (con->in_msg) {
|
|
if (con->in_msg) {
|
|
con->in_msg->con = con->ops->get(con);
|
|
con->in_msg->con = con->ops->get(con);
|
|
BUG_ON(con->in_msg->con == NULL);
|
|
BUG_ON(con->in_msg->con == NULL);
|
|
}
|
|
}
|
|
- if (skip)
|
|
|
|
|
|
+ if (*skip) {
|
|
con->in_msg = NULL;
|
|
con->in_msg = NULL;
|
|
-
|
|
|
|
- if (!con->in_msg)
|
|
|
|
- return skip != 0;
|
|
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ if (!con->in_msg) {
|
|
|
|
+ con->error_msg =
|
|
|
|
+ "error allocating memory for incoming message";
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
if (!con->in_msg) {
|
|
if (!con->in_msg) {
|
|
con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false);
|
|
con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false);
|
|
if (!con->in_msg) {
|
|
if (!con->in_msg) {
|
|
pr_err("unable to allocate msg type %d len %d\n",
|
|
pr_err("unable to allocate msg type %d len %d\n",
|
|
type, front_len);
|
|
type, front_len);
|
|
- return false;
|
|
|
|
|
|
+ return -ENOMEM;
|
|
}
|
|
}
|
|
con->in_msg->con = con->ops->get(con);
|
|
con->in_msg->con = con->ops->get(con);
|
|
BUG_ON(con->in_msg->con == NULL);
|
|
BUG_ON(con->in_msg->con == NULL);
|
|
@@ -2767,7 +2773,7 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- return false;
|
|
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|