+
+ oscc_internal_create(oscc);
+ RETURN(1);
+}
+
+static int handle_async_create(struct ptlrpc_request *req, int rc)
+{
+ struct osc_create_async_args *args = ptlrpc_req_async_args(req);
+ struct osc_creator *oscc = args->rq_oscc;
+ struct lov_stripe_md *lsm = args->rq_lsm;
+ struct obd_info *oinfo = args->rq_oinfo;
+ struct obdo *oa = oinfo->oi_oa;
+
+ LASSERT_SPIN_LOCKED(&oscc->oscc_lock);
+
+ if(rc)
+ GOTO(out_wake, rc);
+
+ if ((oscc->oscc_flags & OSCC_FLAG_EXITING))
+ GOTO(out_wake, rc = -EIO);
+
+ if (oscc_has_objects_nolock(oscc, 1)) {
+ memcpy(oa, &oscc->oscc_oa, sizeof(*oa));
+ oa->o_id = oscc->oscc_next_id;
+ lsm->lsm_object_id = oscc->oscc_next_id;
+ oscc->oscc_next_id++;
+
+ CDEBUG(D_RPCTRACE, " set oscc_next_id = "LPU64"\n",
+ oscc->oscc_next_id);
+ GOTO(out_wake, rc = 0);
+ }
+
+ /* should be try wait until recovery finished */
+ if(oscc->oscc_flags & OSCC_FLAG_RECOVERING)
+ RETURN(-EAGAIN);
+
+ if (oscc->oscc_flags & OSCC_FLAG_NOSPC)
+ GOTO(out_wake, rc = -ENOSPC);
+
+ /* we not have objects now - continue wait */
+ RETURN(-EAGAIN);
+
+out_wake:
+
+ rc = oinfo->oi_cb_up(oinfo, rc);
+ ptlrpc_fakereq_finished(req);
+
+ RETURN(rc);
+}
+
+static int async_create_interpret(const struct lu_env *env,
+ struct ptlrpc_request *req, void *data, int rc)
+{
+ struct osc_create_async_args *args = ptlrpc_req_async_args(req);
+ struct osc_creator *oscc = args->rq_oscc;
+ int ret;
+
+ spin_lock(&oscc->oscc_lock);
+ ret = handle_async_create(req, rc);
+ spin_unlock(&oscc->oscc_lock);
+
+ return ret;
+}
+
+int osc_create_async(struct obd_export *exp, struct obd_info *oinfo,
+ struct lov_stripe_md **ea, struct obd_trans_info *oti)
+{
+ int rc;
+ struct ptlrpc_request *fake_req;
+ struct osc_create_async_args *args;
+ struct osc_creator *oscc = &exp->exp_obd->u.cli.cl_oscc;
+ struct obdo *oa = oinfo->oi_oa;
+ ENTRY;
+
+ if ((oa->o_valid & OBD_MD_FLGROUP) && (oa->o_gr != 0)){
+ rc = osc_real_create(exp, oinfo->oi_oa, ea, oti);
+ rc = oinfo->oi_cb_up(oinfo, rc);
+ RETURN(rc);
+ }
+
+ if ((oa->o_valid & OBD_MD_FLFLAGS) &&
+ oa->o_flags == OBD_FL_RECREATE_OBJS) {
+ rc = osc_real_create(exp, oinfo->oi_oa, ea, oti);
+ rc = oinfo->oi_cb_up(oinfo, rc);
+ RETURN(rc);
+ }
+
+ LASSERT((*ea) != NULL);
+
+ fake_req = ptlrpc_prep_fakereq(oscc->oscc_obd->u.cli.cl_import,
+ osc_create_timeout,
+ async_create_interpret);
+ if (fake_req == NULL) {
+ rc = oinfo->oi_cb_up(oinfo, -ENOMEM);
+ RETURN(-ENOMEM);
+ }
+
+ args = ptlrpc_req_async_args(fake_req);
+ CLASSERT(sizeof(*args) <= sizeof(fake_req->rq_async_args));
+
+ args->rq_oscc = oscc;
+ args->rq_lsm = *ea;
+ args->rq_oinfo = oinfo;
+
+ spin_lock(&oscc->oscc_lock);
+ /* try fast path */
+ rc = handle_async_create(fake_req, 0);
+ if (rc == -EAGAIN) {
+ int is_add;
+ /* we not have objects - try wait */
+ is_add = ptlrpcd_add_req(fake_req, PSCOPE_OTHER);
+ if (!is_add)
+ list_add(&fake_req->rq_list,
+ &oscc->oscc_wait_create_list);
+ else
+ rc = is_add;
+ }
+ spin_unlock(&oscc->oscc_lock);
+
+ if (rc != -EAGAIN)
+ /* need free request if was error hit or
+ * objects already allocated */
+ ptlrpc_req_finished(fake_req);
+ else
+ /* EAGAIN mean - request is delayed */
+ rc = 0;
+
+ RETURN(rc);