return 0;
}
-static int ceph_alloc_data_section(struct ceph_connection *con, struct ceph_msg *msg)
-{
- int ret;
- int want;
- int data_len = le32_to_cpu(msg->hdr.data_len);
- unsigned data_off = le16_to_cpu(msg->hdr.data_off);
-
- want = calc_pages_for(data_off & ~PAGE_MASK, data_len);
- ret = -1;
- mutex_unlock(&con->mutex);
- if (con->ops->prepare_pages)
- ret = con->ops->prepare_pages(con, msg, want);
- mutex_lock(&con->mutex);
-
- BUG_ON(msg->nr_pages < want);
-
- return ret;
-}
-
/*
* Generic message allocator, for incoming messages.
*/
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);
- int data_len = le32_to_cpu(hdr->data_len);
struct ceph_msg *msg = NULL;
int ret;
if (con->ops->alloc_msg) {
+ mutex_unlock(&con->mutex);
msg = con->ops->alloc_msg(con, hdr, skip);
+ mutex_lock(&con->mutex);
if (IS_ERR(msg))
return msg;
}
}
- if (data_len) {
- ret = ceph_alloc_data_section(con, msg);
-
- if (ret < 0) {
- *skip = 1;
- ceph_msg_put(msg);
- return NULL;
- }
- }
-
-
return msg;
}
* find those pages.
* 0 = success, -1 failure.
*/
-static int prepare_pages(struct ceph_connection *con, struct ceph_msg *m,
- int want)
+static int prepare_pages(struct ceph_connection *con,
+ struct ceph_msg_header *hdr,
+ struct ceph_osd_request *req,
+ u64 tid,
+ struct ceph_msg *m)
{
struct ceph_osd *osd = con->private;
struct ceph_osd_client *osdc;
- struct ceph_osd_request *req;
- u64 tid;
int ret = -1;
- int type = le16_to_cpu(m->hdr.type);
+ int data_len = le32_to_cpu(hdr->data_len);
+ unsigned data_off = le16_to_cpu(hdr->data_off);
+
+ int want = calc_pages_for(data_off & ~PAGE_MASK, data_len);
if (!osd)
return -1;
+
osdc = osd->o_osdc;
dout("prepare_pages on msg %p want %d\n", m, want);
- if (unlikely(type != CEPH_MSG_OSD_OPREPLY))
- return -1; /* hmm! */
-
- tid = le64_to_cpu(m->hdr.tid);
- mutex_lock(&osdc->request_mutex);
- req = __lookup_request(osdc, tid);
- if (!req) {
- dout("prepare_pages unknown tid %llu\n", tid);
- goto out;
- }
dout("prepare_pages tid %llu has %d pages, want %d\n",
tid, req->r_num_pages, want);
if (unlikely(req->r_num_pages < want))
m->nr_pages = req->r_num_pages;
ret = 0; /* success */
out:
- mutex_unlock(&osdc->request_mutex);
+ BUG_ON(ret < 0 || m->nr_pages < want);
+
return ret;
}
struct ceph_osd_client *osdc = osd->o_osdc;
int type = le16_to_cpu(hdr->type);
int front = le32_to_cpu(hdr->front_len);
+ int data_len = le32_to_cpu(hdr->data_len);
struct ceph_msg *m;
+ struct ceph_osd_request *req;
+ u64 tid;
+ int err;
*skip = 0;
- switch (type) {
- case CEPH_MSG_OSD_OPREPLY:
- m = ceph_msgpool_get(&osdc->msgpool_op_reply, front);
- break;
- default:
+ if (type != CEPH_MSG_OSD_OPREPLY)
return NULL;
- }
- if (!m)
+ tid = le64_to_cpu(hdr->tid);
+ mutex_lock(&osdc->request_mutex);
+ req = __lookup_request(osdc, tid);
+ if (!req) {
+ *skip = 1;
+ m = NULL;
+ dout("prepare_pages unknown tid %llu\n", tid);
+ goto out;
+ }
+ m = ceph_msgpool_get(&osdc->msgpool_op_reply, front);
+ if (!m) {
*skip = 1;
+ goto out;
+ }
+
+ if (data_len > 0) {
+ err = prepare_pages(con, hdr, req, tid, m);
+ if (err < 0) {
+ *skip = 1;
+ ceph_msg_put(m);
+ m = ERR_PTR(err);
+ }
+ }
+
+out:
+ mutex_unlock(&osdc->request_mutex);
return m;
}
.verify_authorizer_reply = verify_authorizer_reply,
.alloc_msg = alloc_msg,
.fault = osd_reset,
- .prepare_pages = prepare_pages,
};