+int osc_brw_write(struct obd_conn *conn, obd_count num_oa, struct obdo **oa,
+ obd_count *oa_bufs, struct page **buf, obd_size *count,
+ obd_off *offset, obd_flag *flags)
+{
+ struct ptlrpc_client *cl;
+ struct ptlrpc_connection *connection;
+ struct ptlrpc_request *request;
+ struct obd_ioobj ioo;
+ struct ost_body *body;
+ struct niobuf *src;
+ int pages, rc, i, j, size[3] = {sizeof(*body)};
+ void *ptr1, *ptr2;
+ ENTRY;
+
+ size[1] = num_oa * sizeof(ioo);
+ pages = 0;
+ for (i = 0; i < num_oa; i++)
+ pages += oa_bufs[i];
+ size[2] = pages * sizeof(*src);
+
+ OBD_ALLOC(src, size[2]);
+ if (!src)
+ RETURN(-ENOMEM);
+
+ osc_con2cl(conn, &cl, &connection);
+ request = ptlrpc_prep_req(cl, connection, OST_BRW, 3, size, NULL);
+ if (!request)
+ RETURN(-ENOMEM);
+ body = lustre_msg_buf(request->rq_reqmsg, 0);
+ body->data = OBD_BRW_WRITE;
+
+ ptr1 = lustre_msg_buf(request->rq_reqmsg, 1);
+ ptr2 = lustre_msg_buf(request->rq_reqmsg, 2);
+ for (pages = 0, i = 0; i < num_oa; i++) {
+ ost_pack_ioo(&ptr1, oa[i], oa_bufs[i]);
+ for (j = 0; j < oa_bufs[i]; j++, pages++) {
+ ost_pack_niobuf(&ptr2, kmap(buf[pages]), offset[pages],
+ count[pages], flags[pages], 0);
+ }
+ }
+ memcpy(src, lustre_msg_buf(request->rq_reqmsg, 2), size[2]);
+
+ size[1] = pages * sizeof(struct niobuf);
+ request->rq_replen = lustre_msg_size(2, size);
+
+ rc = ptlrpc_queue_wait(request);
+ if (rc)
+ GOTO(out, rc);
+
+ ptr2 = lustre_msg_buf(request->rq_repmsg, 1);
+ if (ptr2 == NULL)
+ GOTO(out, rc = -EINVAL);
+
+ if (request->rq_repmsg->buflens[1] != pages * sizeof(struct niobuf)) {
+ CERROR("buffer length wrong (%d vs. %d)\n",
+ request->rq_repmsg->buflens[1],
+ pages * sizeof(struct niobuf));
+ GOTO(out, rc = -EINVAL);
+ }
+
+ for (pages = 0, i = 0; i < num_oa; i++) {
+ for (j = 0; j < oa_bufs[i]; j++, pages++) {
+ struct niobuf *dst;
+ ost_unpack_niobuf(&ptr2, &dst);
+ osc_sendpage(conn, request, dst, &src[pages]);
+ }
+ }
+ OBD_FREE(src, size[2]);
+ out:
+ for (pages = 0, i = 0; i < num_oa; i++)
+ for (j = 0; j < oa_bufs[i]; j++, pages++)
+ kunmap(buf[pages]);
+
+ ptlrpc_free_req(request);
+ return 0;
+}