-int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req)
-{
- struct lustre_msg *early_buf;
- int early_bufsz, early_size;
- int rc;
- ENTRY;
-
- LASSERT(req->rq_repbuf);
- LASSERT(req->rq_repdata == NULL);
- LASSERT(req->rq_repmsg == NULL);
-
- early_size = req->rq_nob_received;
- if (early_size < sizeof(struct lustre_msg)) {
- CERROR("early reply length %d too small\n", early_size);
- RETURN(-EPROTO);
- }
-
- early_bufsz = size_roundup_power2(early_size);
- OBD_ALLOC(early_buf, early_bufsz);
- if (early_buf == NULL)
- RETURN(-ENOMEM);
-
- /* copy data out, do it inside spinlock */
- spin_lock(&req->rq_lock);
-
- if (req->rq_replied) {
- spin_unlock(&req->rq_lock);
- GOTO(err_free, rc = -EALREADY);
- }
-
- if (req->rq_reply_off != 0) {
- CERROR("early reply with offset %u\n", req->rq_reply_off);
- GOTO(err_free, rc = -EPROTO);
- }
-
- if (req->rq_nob_received != early_size) {
- /* even another early arrived the size should be the same */
- CWARN("data size has changed from %u to %u\n",
- early_size, req->rq_nob_received);
- spin_unlock(&req->rq_lock);
- GOTO(err_free, rc = -EINVAL);
- }
-
- if (req->rq_nob_received < sizeof(struct lustre_msg)) {
- CERROR("early reply length %d too small\n",
- req->rq_nob_received);
- spin_unlock(&req->rq_lock);
- GOTO(err_free, rc = -EALREADY);
- }
-
- memcpy(early_buf, req->rq_repbuf, early_size);
- spin_unlock(&req->rq_lock);
-
- req->rq_repdata = early_buf;
- req->rq_repdata_len = early_size;
-
- rc = do_cli_unwrap_reply(req);
-
- /* treate resend as an error case. in fact server should never ask
- * resend via early reply. */
- if (req->rq_resend) {
- req->rq_resend = 0;
- rc = -EPROTO;
- }
-
+int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req,
+ struct ptlrpc_request **req_ret)
+{
+ struct ptlrpc_request *early_req;
+ char *early_buf;
+ int early_bufsz, early_size;
+ int rc;
+ ENTRY;
+
+ early_req = ptlrpc_request_cache_alloc(GFP_NOFS);
+ if (early_req == NULL)
+ RETURN(-ENOMEM);
+
+ ptlrpc_cli_req_init(early_req);
+
+ early_size = req->rq_nob_received;
+ early_bufsz = size_roundup_power2(early_size);
+ OBD_ALLOC_LARGE(early_buf, early_bufsz);
+ if (early_buf == NULL)
+ GOTO(err_req, rc = -ENOMEM);
+
+ /* sanity checkings and copy data out, do it inside spinlock */
+ spin_lock(&req->rq_lock);
+
+ if (req->rq_replied) {
+ spin_unlock(&req->rq_lock);
+ GOTO(err_buf, rc = -EALREADY);
+ }
+
+ LASSERT(req->rq_repbuf);
+ LASSERT(req->rq_repdata == NULL);
+ LASSERT(req->rq_repmsg == NULL);
+
+ if (req->rq_reply_off != 0) {
+ CERROR("early reply with offset %u\n", req->rq_reply_off);
+ spin_unlock(&req->rq_lock);
+ GOTO(err_buf, rc = -EPROTO);
+ }
+
+ if (req->rq_nob_received != early_size) {
+ /* even another early arrived the size should be the same */
+ CERROR("data size has changed from %u to %u\n",
+ early_size, req->rq_nob_received);
+ spin_unlock(&req->rq_lock);
+ GOTO(err_buf, rc = -EINVAL);
+ }
+
+ if (req->rq_nob_received < sizeof(struct lustre_msg)) {
+ CERROR("early reply length %d too small\n",
+ req->rq_nob_received);
+ spin_unlock(&req->rq_lock);
+ GOTO(err_buf, rc = -EALREADY);
+ }
+
+ memcpy(early_buf, req->rq_repbuf, early_size);
+ spin_unlock(&req->rq_lock);
+
+ early_req->rq_cli_ctx = sptlrpc_cli_ctx_get(req->rq_cli_ctx);
+ early_req->rq_flvr = req->rq_flvr;
+ early_req->rq_repbuf = early_buf;
+ early_req->rq_repbuf_len = early_bufsz;
+ early_req->rq_repdata = (struct lustre_msg *) early_buf;
+ early_req->rq_repdata_len = early_size;
+ early_req->rq_early = 1;
+ early_req->rq_reqmsg = req->rq_reqmsg;
+
+ rc = do_cli_unwrap_reply(early_req);