/** * Object updates between Targets. Because all the updates has been * dis-assemblied into object updates at sender side, so OUT will * call OSD API directly to execute these updates. * * In DNE phase I all of the updates in the request need to be executed * in one transaction, and the transaction has to be synchronously. * * Please refer to lustre/include/lustre/lustre_idl.h for req/reply * format. */ int out_handle(struct tgt_session_info *tsi) { const struct lu_env *env = tsi->tsi_env; struct tgt_thread_info *tti = tgt_th_info(env); struct thandle_exec_args *ta = &tti->tti_tea; struct req_capsule *pill = tsi->tsi_pill; struct dt_device *dt = tsi->tsi_tgt->lut_bottom; struct update_buf *ubuf; struct update *update; struct update_reply *update_reply; int bufsize; int count; int old_batchid = -1; unsigned off; int i; int rc = 0; int rc1 = 0; ENTRY; req_capsule_set(pill, &RQF_UPDATE_OBJ); bufsize = req_capsule_get_size(pill, &RMF_UPDATE, RCL_CLIENT); if (bufsize != UPDATE_BUFFER_SIZE) { CERROR("%s: invalid bufsize %d: rc = %d\n", tgt_name(tsi->tsi_tgt), bufsize, -EPROTO); RETURN(err_serious(-EPROTO)); } ubuf = req_capsule_client_get(pill, &RMF_UPDATE); if (ubuf == NULL) { CERROR("%s: No buf!: rc = %d\n", tgt_name(tsi->tsi_tgt), -EPROTO); RETURN(err_serious(-EPROTO)); } if (le32_to_cpu(ubuf->ub_magic) != UPDATE_BUFFER_MAGIC) { CERROR("%s: invalid magic %x expect %x: rc = %d\n", tgt_name(tsi->tsi_tgt), le32_to_cpu(ubuf->ub_magic), UPDATE_BUFFER_MAGIC, -EPROTO); RETURN(err_serious(-EPROTO)); } count = le32_to_cpu(ubuf->ub_count); if (count <= 0) { CERROR("%s: No update!: rc = %d\n", tgt_name(tsi->tsi_tgt), -EPROTO); RETURN(err_serious(-EPROTO)); } req_capsule_set_size(pill, &RMF_UPDATE_REPLY, RCL_SERVER, UPDATE_BUFFER_SIZE); rc = req_capsule_server_pack(pill); if (rc != 0) { CERROR("%s: Can't pack response: rc = %d\n", tgt_name(tsi->tsi_tgt), rc); RETURN(rc); } /* Prepare the update reply buffer */ update_reply = req_capsule_server_get(pill, &RMF_UPDATE_REPLY); if (update_reply == NULL) RETURN(err_serious(-EPROTO)); update_init_reply_buf(update_reply, count); tti->tti_u.update.tti_update_reply = update_reply; rc = out_tx_start(env, dt, ta); if (rc != 0) RETURN(rc); tti->tti_mult_trans = !req_is_replay(tgt_ses_req(tsi)); /* Walk through updates in the request to execute them synchronously */ off = cfs_size_round(offsetof(struct update_buf, ub_bufs[0])); for (i = 0; i < count; i++) { struct tgt_handler *h; struct dt_object *dt_obj; update = (struct update *)((char *)ubuf + off); if (old_batchid == -1) { old_batchid = update->u_batchid; } else if (old_batchid != update->u_batchid) { /* Stop the current update transaction, * create a new one */ rc = out_tx_end(env, ta); if (rc != 0) RETURN(rc); rc = out_tx_start(env, dt, ta); if (rc != 0) RETURN(rc); old_batchid = update->u_batchid; } fid_le_to_cpu(&update->u_fid, &update->u_fid); if (!fid_is_sane(&update->u_fid)) { CERROR("%s: invalid FID "DFID": rc = %d\n", tgt_name(tsi->tsi_tgt), PFID(&update->u_fid), -EPROTO); GOTO(out, rc = err_serious(-EPROTO)); } dt_obj = dt_locate(env, dt, &update->u_fid); if (IS_ERR(dt_obj)) GOTO(out, rc = PTR_ERR(dt_obj)); tti->tti_u.update.tti_dt_object = dt_obj; tti->tti_u.update.tti_update = update; tti->tti_u.update.tti_update_reply_index = i; h = out_handler_find(update->u_type); if (likely(h != NULL)) { /* For real modification RPC, check if the update * has been executed */ if (h->th_flags & MUTABOR) { struct ptlrpc_request *req = tgt_ses_req(tsi); if (out_check_resent(env, dt, dt_obj, req, out_reconstruct, update_reply, i)) GOTO(next, rc); } rc = h->th_act(tsi); } else { CERROR("%s: The unsupported opc: 0x%x\n", tgt_name(tsi->tsi_tgt), update->u_type); lu_object_put(env, &dt_obj->do_lu); GOTO(out, rc = -ENOTSUPP); } next: lu_object_put(env, &dt_obj->do_lu); if (rc < 0) GOTO(out, rc); off += cfs_size_round(update_size(update)); } out: rc1 = out_tx_end(env, ta); if (rc == 0) rc = rc1; RETURN(rc); }
/** * Object updates between Targets. Because all the updates has been * dis-assemblied into object updates in master MDD layer, so out * will skip MDD layer, and call OSD API directly to execute these * updates. * * In phase I, all of the updates in the request need to be executed * in one transaction, and the transaction has to be synchronously. * * Please refer to lustre/include/lustre/lustre_idl.h for req/reply * format. */ int out_handle(struct mdt_thread_info *info) { struct req_capsule *pill = info->mti_pill; struct update_buf *ubuf; struct update *update; struct thandle_exec_args *th = &info->mti_handle; int bufsize; int count; unsigned off; int i; int rc = 0; int rc1 = 0; ENTRY; req_capsule_set(pill, &RQF_UPDATE_OBJ); bufsize = req_capsule_get_size(pill, &RMF_UPDATE, RCL_CLIENT); if (bufsize != UPDATE_BUFFER_SIZE) { CERROR("%s: invalid bufsize %d: rc = %d\n", mdt_obd_name(info->mti_mdt), bufsize, -EPROTO); RETURN(err_serious(-EPROTO)); } ubuf = req_capsule_client_get(pill, &RMF_UPDATE); if (ubuf == NULL) { CERROR("%s: No buf!: rc = %d\n", mdt_obd_name(info->mti_mdt), -EPROTO); RETURN(err_serious(-EPROTO)); } if (le32_to_cpu(ubuf->ub_magic) != UPDATE_BUFFER_MAGIC) { CERROR("%s: invalid magic %x expect %x: rc = %d\n", mdt_obd_name(info->mti_mdt), le32_to_cpu(ubuf->ub_magic), UPDATE_BUFFER_MAGIC, -EPROTO); RETURN(err_serious(-EPROTO)); } count = le32_to_cpu(ubuf->ub_count); if (count <= 0) { CERROR("%s: No update!: rc = %d\n", mdt_obd_name(info->mti_mdt), -EPROTO); RETURN(err_serious(-EPROTO)); } req_capsule_set_size(pill, &RMF_UPDATE_REPLY, RCL_SERVER, UPDATE_BUFFER_SIZE); rc = req_capsule_server_pack(pill); if (rc != 0) { CERROR("%s: Can't pack response: rc = %d\n", mdt_obd_name(info->mti_mdt), rc); RETURN(rc); } /* Prepare the update reply buffer */ info->mti_u.update.mti_update_reply = req_capsule_server_get(pill, &RMF_UPDATE_REPLY); update_init_reply_buf(info->mti_u.update.mti_update_reply, count); rc = out_tx_start(info->mti_env, info->mti_mdt, th); if (rc != 0) RETURN(rc); /* Walk through updates in the request to execute them synchronously */ off = cfs_size_round(offsetof(struct update_buf, ub_bufs[0])); for (i = 0; i < count; i++) { struct out_handler *h; struct dt_object *dt_obj; update = (struct update *)((char *)ubuf + off); fid_le_to_cpu(&update->u_fid, &update->u_fid); if (!fid_is_sane(&update->u_fid)) { CERROR("%s: invalid FID "DFID": rc = %d\n", mdt_obd_name(info->mti_mdt), PFID(&update->u_fid), -EPROTO); GOTO(out, rc = err_serious(-EPROTO)); } dt_obj = out_object_find(info, &update->u_fid); if (IS_ERR(dt_obj)) GOTO(out, rc = PTR_ERR(dt_obj)); info->mti_u.update.mti_dt_object = dt_obj; info->mti_u.update.mti_update = update; info->mti_u.update.mti_update_reply_index = i; h = mdt_handler_find(update->u_type, out_handlers); if (likely(h != NULL)) { rc = h->mh_act(info); } else { CERROR("%s: The unsupported opc: 0x%x\n", mdt_obd_name(info->mti_mdt), update->u_type); lu_object_put(info->mti_env, &dt_obj->do_lu); GOTO(out, rc = -ENOTSUPP); } lu_object_put(info->mti_env, &dt_obj->do_lu); if (rc < 0) GOTO(out, rc); off += cfs_size_round(update_size(update)); } out: rc1 = out_tx_end(info, th); rc = rc == 0 ? rc1 : rc; info->mti_fail_id = OBD_FAIL_UPDATE_OBJ_NET; RETURN(rc); }