static inline size_t libcfs_ioctl_packlen(struct libcfs_ioctl_data *data) { size_t len = sizeof(*data); len += cfs_size_round(data->ioc_inllen1); len += cfs_size_round(data->ioc_inllen2); return len; }
static int llog_print_cb(struct llog_handle *handle, struct llog_rec_hdr *rec, void *data) { struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data; static int l, remains, from, to; static char *out; char *endp; int cur_index; ENTRY; if (ioc_data->ioc_inllen1) { l = 0; remains = ioc_data->ioc_inllen4 + cfs_size_round(ioc_data->ioc_inllen1) + cfs_size_round(ioc_data->ioc_inllen2) + cfs_size_round(ioc_data->ioc_inllen3); from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0); if (*endp != '\0') RETURN(-EINVAL); to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0); if (*endp != '\0') RETURN(-EINVAL); out = ioc_data->ioc_bulk; ioc_data->ioc_inllen1 = 0; } cur_index = rec->lrh_index; if (cur_index < from) RETURN(0); if (to > 0 && cur_index > to) RETURN(-LLOG_EEMPTY); if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) { struct llog_logid_rec *lir = (struct llog_logid_rec *)rec; if (rec->lrh_type != LLOG_LOGID_MAGIC) { CERROR("invalid record in catalog\n"); RETURN(-EINVAL); } l = snprintf(out, remains, "[index]: %05d [logid]: #"LPX64"#"LPX64"#%08x\n", cur_index, lir->lid_id.lgl_oid, lir->lid_id.lgl_oseq, lir->lid_id.lgl_ogen); } else { l = snprintf(out, remains, "[index]: %05d [type]: %02x [len]: %04d\n", cur_index, rec->lrh_type, rec->lrh_len); } out += l; remains -= l; if (remains <= 0) { CERROR("not enough space for print log records\n"); RETURN(-LLOG_EEMPTY); } RETURN(0); }
int llog_write_rec(const struct lu_env *env, struct llog_handle *handle, struct llog_rec_hdr *rec, struct llog_cookie *logcookies, int numcookies, void *buf, int idx, struct thandle *th) { struct llog_operations *lop; int raised, rc, buflen; rc = llog_handle2ops(handle, &lop); if (rc) return rc; LASSERT(lop); if (lop->lop_write_rec == NULL) return -EOPNOTSUPP; if (buf) buflen = rec->lrh_len + sizeof(struct llog_rec_hdr) + sizeof(struct llog_rec_tail); else buflen = rec->lrh_len; LASSERT(cfs_size_round(buflen) == buflen); raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE); if (!raised) cfs_cap_raise(CFS_CAP_SYS_RESOURCE); rc = lop->lop_write_rec(env, handle, rec, logcookies, numcookies, buf, idx, th); if (!raised) cfs_cap_lower(CFS_CAP_SYS_RESOURCE); return rc; }
int llog_write_rec(const struct lu_env *env, struct llog_handle *handle, struct llog_rec_hdr *rec, struct llog_cookie *logcookies, int idx, struct thandle *th) { struct llog_operations *lop; int raised, rc, buflen; ENTRY; rc = llog_handle2ops(handle, &lop); if (rc) RETURN(rc); LASSERT(lop); if (lop->lop_write_rec == NULL) RETURN(-EOPNOTSUPP); buflen = rec->lrh_len; LASSERT(cfs_size_round(buflen) == buflen); raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE); if (!raised) cfs_cap_raise(CFS_CAP_SYS_RESOURCE); rc = lop->lop_write_rec(env, handle, rec, logcookies, idx, th); if (!raised) cfs_cap_lower(CFS_CAP_SYS_RESOURCE); RETURN(rc); }
struct lu_object *vvp_object_alloc(const struct lu_env *env, const struct lu_object_header *unused, struct lu_device *dev) { struct vvp_object *vob; struct lu_object *obj; OBD_SLAB_ALLOC_PTR_GFP(vob, vvp_object_kmem, GFP_NOFS); if (vob != NULL) { struct cl_object_header *hdr; obj = &vob->vob_cl.co_lu; hdr = &vob->vob_header; cl_object_header_init(hdr); hdr->coh_page_bufsize = cfs_size_round(sizeof(struct cl_page)); lu_object_init(obj, &hdr->coh_lu, dev); lu_object_add_top(&hdr->coh_lu, obj); vob->vob_cl.co_ops = &vvp_ops; obj->lo_ops = &vvp_lu_obj_ops; } else obj = NULL; return obj; }
/* temporary for testing */ static int mdc_wr_kuc(struct file *file, const char *buffer, unsigned long count, void *data) { struct obd_device *obd = data; struct kuc_hdr *lh; struct hsm_action_list *hal; struct hsm_action_item *hai; int len; int fd, rc; ENTRY; rc = lprocfs_write_helper(buffer, count, &fd); if (rc) RETURN(rc); if (fd < 0) RETURN(-ERANGE); CWARN("message to fd %d\n", fd); len = sizeof(*lh) + sizeof(*hal) + MTI_NAME_MAXLEN + /* for mockup below */ 2 * cfs_size_round(sizeof(*hai)); OBD_ALLOC(lh, len); lh->kuc_magic = KUC_MAGIC; lh->kuc_transport = KUC_TRANSPORT_HSM; lh->kuc_msgtype = HMT_ACTION_LIST; lh->kuc_msglen = len; hal = (struct hsm_action_list *)(lh + 1); hal->hal_version = HAL_VERSION; hal->hal_archive_id = 1; hal->hal_flags = 0; obd_uuid2fsname(hal->hal_fsname, obd->obd_name, MTI_NAME_MAXLEN); /* mock up an action list */ hal->hal_count = 2; hai = hai_zero(hal); hai->hai_action = HSMA_ARCHIVE; hai->hai_fid.f_oid = 5; hai->hai_len = sizeof(*hai); hai = hai_next(hai); hai->hai_action = HSMA_RESTORE; hai->hai_fid.f_oid = 10; hai->hai_len = sizeof(*hai); /* This works for either broadcast or unicast to a single fd */ if (fd == 0) { rc = libcfs_kkuc_group_put(KUC_GRP_HSM, lh); } else { cfs_file_t *fp = cfs_get_fd(fd); rc = libcfs_kkuc_msg_put(fp, lh); cfs_put_file(fp); } OBD_FREE(lh, len); if (rc < 0) RETURN(rc); RETURN(count); }
static inline bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data) { if (data->ioc_hdr.ioc_len > BIT(30)) { CERROR("LIBCFS ioctl: ioc_len larger than 1<<30\n"); return true; } if (data->ioc_inllen1 > BIT(30)) { CERROR("LIBCFS ioctl: ioc_inllen1 larger than 1<<30\n"); return true; } if (data->ioc_inllen2 > BIT(30)) { CERROR("LIBCFS ioctl: ioc_inllen2 larger than 1<<30\n"); return true; } if (data->ioc_inlbuf1 && !data->ioc_inllen1) { CERROR("LIBCFS ioctl: inlbuf1 pointer but 0 length\n"); return true; } if (data->ioc_inlbuf2 && !data->ioc_inllen2) { CERROR("LIBCFS ioctl: inlbuf2 pointer but 0 length\n"); return true; } if (data->ioc_pbuf1 && !data->ioc_plen1) { CERROR("LIBCFS ioctl: pbuf1 pointer but 0 length\n"); return true; } if (data->ioc_pbuf2 && !data->ioc_plen2) { CERROR("LIBCFS ioctl: pbuf2 pointer but 0 length\n"); return true; } if (data->ioc_plen1 && !data->ioc_pbuf1) { CERROR("LIBCFS ioctl: plen1 nonzero but no pbuf1 pointer\n"); return true; } if (data->ioc_plen2 && !data->ioc_pbuf2) { CERROR("LIBCFS ioctl: plen2 nonzero but no pbuf2 pointer\n"); return true; } if ((__u32)libcfs_ioctl_packlen(data) != data->ioc_hdr.ioc_len) { CERROR("LIBCFS ioctl: packlen != ioc_len\n"); return true; } if (data->ioc_inllen1 && data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { CERROR("LIBCFS ioctl: inlbuf1 not 0 terminated\n"); return true; } if (data->ioc_inllen2 && data->ioc_bulk[cfs_size_round(data->ioc_inllen1) + data->ioc_inllen2 - 1] != '\0') { CERROR("LIBCFS ioctl: inlbuf2 not 0 terminated\n"); return true; } return false; }
static int lov_page_slice_fixup(struct lov_object *lov, struct cl_object *stripe) { struct cl_object_header *hdr = cl_object_header(&lov->lo_cl); struct cl_object *o; if (stripe == NULL) return hdr->coh_page_bufsize - lov->lo_cl.co_slice_off - cfs_size_round(sizeof(struct lov_page)); cl_object_for_each(o, stripe) o->co_slice_off += hdr->coh_page_bufsize; return cl_object_header(stripe)->coh_page_bufsize; }
int libcfs_ioctl_getdata(char *buf, char *end, void *arg) { struct libcfs_ioctl_hdr *hdr; struct libcfs_ioctl_data *data; int err; ENTRY; hdr = (struct libcfs_ioctl_hdr *)buf; data = (struct libcfs_ioctl_data *)buf; err = copy_from_user(buf, (void *)arg, sizeof(*hdr)); if (err) RETURN(err); if (hdr->ioc_version != LIBCFS_IOCTL_VERSION) { CERROR("PORTALS: version mismatch kernel vs application\n"); RETURN(-EINVAL); } if (hdr->ioc_len + buf >= end) { CERROR("PORTALS: user buffer exceeds kernel buffer\n"); RETURN(-EINVAL); } if (hdr->ioc_len < sizeof(struct libcfs_ioctl_data)) { CERROR("PORTALS: user buffer too small for ioctl\n"); RETURN(-EINVAL); } err = copy_from_user(buf, (void *)arg, hdr->ioc_len); if (err) RETURN(err); if (libcfs_ioctl_is_invalid(data)) { CERROR("PORTALS: ioctl not correctly formatted\n"); RETURN(-EINVAL); } if (data->ioc_inllen1) data->ioc_inlbuf1 = &data->ioc_bulk[0]; if (data->ioc_inllen2) data->ioc_inlbuf2 = &data->ioc_bulk[0] + cfs_size_round(data->ioc_inllen1); RETURN(0); }
int libcfs_ioctl_getdata(char *buf, char *end, void *arg) { struct libcfs_ioctl_hdr *hdr; struct libcfs_ioctl_data *data; int orig_len; hdr = (struct libcfs_ioctl_hdr *)buf; data = (struct libcfs_ioctl_data *)buf; if (copy_from_user(buf, (void *)arg, sizeof(*hdr))) return -EFAULT; if (hdr->ioc_version != LIBCFS_IOCTL_VERSION) { CERROR("PORTALS: version mismatch kernel vs application\n"); return -EINVAL; } if (hdr->ioc_len + buf >= end) { CERROR("PORTALS: user buffer exceeds kernel buffer\n"); return -EINVAL; } if (hdr->ioc_len < sizeof(struct libcfs_ioctl_data)) { CERROR("PORTALS: user buffer too small for ioctl\n"); return -EINVAL; } orig_len = hdr->ioc_len; if (copy_from_user(buf, (void *)arg, hdr->ioc_len)) return -EFAULT; if (orig_len != data->ioc_len) return -EINVAL; if (libcfs_ioctl_is_invalid(data)) { CERROR("PORTALS: ioctl not correctly formatted\n"); return -EINVAL; } if (data->ioc_inllen1) data->ioc_inlbuf1 = &data->ioc_bulk[0]; if (data->ioc_inllen2) data->ioc_inlbuf2 = &data->ioc_bulk[0] + cfs_size_round(data->ioc_inllen1); return 0; }
int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data) { if (libcfs_ioctl_is_invalid(data)) { CERROR("libcfs ioctl: parameter not correctly formatted\n"); return -EINVAL; } if (data->ioc_inllen1) data->ioc_inlbuf1 = &data->ioc_bulk[0]; if (data->ioc_inllen2) data->ioc_inlbuf2 = &data->ioc_bulk[0] + cfs_size_round(data->ioc_inllen1); return 0; }
int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data) { ENTRY; if (libcfs_ioctl_is_invalid(data)) { CERROR("libcfs ioctl: parameter not correctly formatted\n"); RETURN(-EINVAL); } if (data->ioc_inllen1 != 0) data->ioc_inlbuf1 = &data->ioc_bulk[0]; if (data->ioc_inllen2 != 0) data->ioc_inlbuf2 = &data->ioc_bulk[0] + cfs_size_round(data->ioc_inllen1); RETURN(0); }
/** * 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); }
static int llog_print_cb(const struct lu_env *env, struct llog_handle *handle, struct llog_rec_hdr *rec, void *data) { struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data; static int l, remains, from, to; static char *out; char *endp; int cur_index; if (ioc_data != NULL && ioc_data->ioc_inllen1 > 0) { l = 0; remains = ioc_data->ioc_inllen4 + cfs_size_round(ioc_data->ioc_inllen1) + cfs_size_round(ioc_data->ioc_inllen2) + cfs_size_round(ioc_data->ioc_inllen3); from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0); if (*endp != '\0') return -EINVAL; to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0); if (*endp != '\0') return -EINVAL; out = ioc_data->ioc_bulk; ioc_data->ioc_inllen1 = 0; } cur_index = rec->lrh_index; if (cur_index < from) return 0; if (to > 0 && cur_index > to) return -LLOG_EEMPTY; if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) { struct llog_logid_rec *lir = (struct llog_logid_rec *)rec; if (rec->lrh_type != LLOG_LOGID_MAGIC) { CERROR("invalid record in catalog\n"); return -EINVAL; } l = snprintf(out, remains, "[index]: %05d [logid]: #"DOSTID"#%08x\n", cur_index, POSTID(&lir->lid_id.lgl_oi), lir->lid_id.lgl_ogen); } else if (rec->lrh_type == OBD_CFG_REC) { int rc; rc = class_config_parse_rec(rec, out, remains); if (rc < 0) return rc; l = rc; } else { l = snprintf(out, remains, "[index]: %05d [type]: %02x [len]: %04d\n", cur_index, rec->lrh_type, rec->lrh_len); } out += l; remains -= l; if (remains <= 0) { CERROR("not enough space for print log records\n"); return -LLOG_EEMPTY; } return 0; }
/** * Process the HSM actions described in a struct hsm_user_request. * * The action described in hur will be send to coordinator to be saved and * processed later or either handled directly if hur.hur_action is HUA_RELEASE. * * This is MDS_HSM_REQUEST RPC handler. */ int mdt_hsm_request(struct tgt_session_info *tsi) { struct mdt_thread_info *info; struct req_capsule *pill = tsi->tsi_pill; struct hsm_request *hr; struct hsm_user_item *hui; struct hsm_action_list *hal; struct hsm_action_item *hai; const void *data; int hui_list_size; int data_size; enum hsm_copytool_action action = HSMA_NONE; __u64 compound_id; int hal_size, i, rc; ENTRY; hr = req_capsule_client_get(pill, &RMF_MDS_HSM_REQUEST); hui = req_capsule_client_get(pill, &RMF_MDS_HSM_USER_ITEM); data = req_capsule_client_get(pill, &RMF_GENERIC_DATA); if (tsi->tsi_mdt_body == NULL || hr == NULL || hui == NULL || data == NULL) RETURN(-EPROTO); /* Sanity check. Nothing to do with an empty list */ if (hr->hr_itemcount == 0) RETURN(0); hui_list_size = req_capsule_get_size(pill, &RMF_MDS_HSM_USER_ITEM, RCL_CLIENT); if (hui_list_size < hr->hr_itemcount * sizeof(*hui)) RETURN(-EPROTO); data_size = req_capsule_get_size(pill, &RMF_GENERIC_DATA, RCL_CLIENT); if (data_size != hr->hr_data_len) RETURN(-EPROTO); info = tsi2mdt_info(tsi); /* Only valid if client is remote */ rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body); if (rc) GOTO(out, rc); switch (hr->hr_action) { /* code to be removed in hsm1_merge and final patch */ case HUA_RELEASE: CERROR("Release action is not working in hsm1_coord\n"); GOTO(out_ucred, rc = -EINVAL); break; /* end of code to be removed */ case HUA_ARCHIVE: action = HSMA_ARCHIVE; break; case HUA_RESTORE: action = HSMA_RESTORE; break; case HUA_REMOVE: action = HSMA_REMOVE; break; case HUA_CANCEL: action = HSMA_CANCEL; break; default: CERROR("Unknown hsm action: %d\n", hr->hr_action); GOTO(out_ucred, rc = -EINVAL); } hal_size = sizeof(*hal) + cfs_size_round(MTI_NAME_MAXLEN) /* fsname */ + (sizeof(*hai) + cfs_size_round(hr->hr_data_len)) * hr->hr_itemcount; MDT_HSM_ALLOC(hal, hal_size); if (hal == NULL) GOTO(out_ucred, rc = -ENOMEM); hal->hal_version = HAL_VERSION; hal->hal_archive_id = hr->hr_archive_id; hal->hal_flags = hr->hr_flags; obd_uuid2fsname(hal->hal_fsname, mdt_obd_name(info->mti_mdt), MTI_NAME_MAXLEN); hal->hal_count = 0; hai = hai_first(hal); for (i = 0; i < hr->hr_itemcount; i++, hai = hai_next(hai)) { /* Get rid of duplicate entries. Otherwise we get * duplicated work in the llog. */ if (is_fid_in_hal(hal, &hui[i].hui_fid)) continue; hai->hai_action = action; hai->hai_cookie = 0; hai->hai_gid = 0; hai->hai_fid = hui[i].hui_fid; hai->hai_extent = hui[i].hui_extent; memcpy(hai->hai_data, data, hr->hr_data_len); hai->hai_len = sizeof(*hai) + hr->hr_data_len; hal->hal_count++; } rc = mdt_hsm_add_actions(info, hal, &compound_id); MDT_HSM_FREE(hal, hal_size); GOTO(out_ucred, rc); out_ucred: mdt_exit_ucred(info); out: mdt_thread_info_fini(info); return rc; }
/** * Retrieve undergoing HSM requests for the fid provided in RPC body. * Current requests are read from coordinator states. * * This is MDS_HSM_ACTION RPC handler. */ int mdt_hsm_action(struct tgt_session_info *tsi) { struct mdt_thread_info *info; struct hsm_current_action *hca; struct hsm_action_list *hal = NULL; struct hsm_action_item *hai; int hal_size; int rc; ENTRY; hca = req_capsule_server_get(tsi->tsi_pill, &RMF_MDS_HSM_CURRENT_ACTION); if (hca == NULL) RETURN(err_serious(-EPROTO)); if (tsi->tsi_mdt_body == NULL) RETURN(-EPROTO); info = tsi2mdt_info(tsi); /* Only valid if client is remote */ rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body); if (rc) GOTO(out, rc = err_serious(rc)); /* Coordinator information */ hal_size = sizeof(*hal) + cfs_size_round(MTI_NAME_MAXLEN) /* fsname */ + cfs_size_round(sizeof(*hai)); MDT_HSM_ALLOC(hal, hal_size); if (hal == NULL) GOTO(out_ucred, rc = -ENOMEM); hal->hal_version = HAL_VERSION; hal->hal_archive_id = 0; hal->hal_flags = 0; obd_uuid2fsname(hal->hal_fsname, mdt_obd_name(info->mti_mdt), MTI_NAME_MAXLEN); hal->hal_count = 1; hai = hai_first(hal); hai->hai_action = HSMA_NONE; hai->hai_cookie = 0; hai->hai_gid = 0; hai->hai_fid = info->mti_body->mbo_fid1; hai->hai_len = sizeof(*hai); rc = mdt_hsm_get_actions(info, hal); if (rc) GOTO(out_free, rc); /* cookie is used to give back request status */ if (hai->hai_cookie == 0) hca->hca_state = HPS_WAITING; else hca->hca_state = HPS_RUNNING; switch (hai->hai_action) { case HSMA_NONE: hca->hca_action = HUA_NONE; break; case HSMA_ARCHIVE: hca->hca_action = HUA_ARCHIVE; break; case HSMA_RESTORE: hca->hca_action = HUA_RESTORE; break; case HSMA_REMOVE: hca->hca_action = HUA_REMOVE; break; case HSMA_CANCEL: hca->hca_action = HUA_CANCEL; break; default: hca->hca_action = HUA_NONE; CERROR("%s: Unknown hsm action: %d on "DFID"\n", mdt_obd_name(info->mti_mdt), hai->hai_action, PFID(&hai->hai_fid)); break; } hca->hca_location = hai->hai_extent; EXIT; out_free: MDT_HSM_FREE(hal, hal_size); out_ucred: mdt_exit_ucred(info); out: mdt_thread_info_fini(info); return rc; }
static int out_read(struct tgt_session_info *tsi) { const struct lu_env *env = tsi->tsi_env; struct tgt_thread_info *tti = tgt_th_info(env); struct object_update *update = tti->tti_u.update.tti_update; struct dt_object *obj = tti->tti_u.update.tti_dt_object; struct object_update_reply *reply = tti->tti_u.update.tti_update_reply; int index = tti->tti_u.update.tti_update_reply_index; struct lu_rdbuf *rdbuf; struct object_update_result *update_result; struct out_read_reply *orr; void *tmp; size_t size; size_t total_size = 0; __u64 pos; unsigned int i; unsigned int nbufs; int rc = 0; ENTRY; update_result = object_update_result_get(reply, index, NULL); LASSERT(update_result != NULL); update_result->our_datalen = sizeof(*orr); if (!lu_object_exists(&obj->do_lu)) GOTO(out, rc = -ENOENT); tmp = object_update_param_get(update, 0, NULL); if (IS_ERR(tmp)) { CERROR("%s: empty size for read: rc = %ld\n", tgt_name(tsi->tsi_tgt), PTR_ERR(tmp)); GOTO(out, rc = PTR_ERR(tmp)); } size = le64_to_cpu(*(size_t *)(tmp)); tmp = object_update_param_get(update, 1, NULL); if (IS_ERR(tmp)) { CERROR("%s: empty pos for read: rc = %ld\n", tgt_name(tsi->tsi_tgt), PTR_ERR(tmp)); GOTO(out, rc = PTR_ERR(tmp)); } pos = le64_to_cpu(*(__u64 *)(tmp)); /* Put the offset into the begining of the buffer in reply */ orr = (struct out_read_reply *)update_result->our_data; nbufs = (size + OUT_BULK_BUFFER_SIZE - 1) / OUT_BULK_BUFFER_SIZE; OBD_ALLOC(rdbuf, sizeof(struct lu_rdbuf) + nbufs * sizeof(rdbuf->rb_bufs[0])); if (rdbuf == NULL) GOTO(out, rc = -ENOMEM); rdbuf->rb_nbufs = 0; total_size = 0; for (i = 0; i < nbufs; i++) { __u32 read_size; read_size = size > OUT_BULK_BUFFER_SIZE ? OUT_BULK_BUFFER_SIZE : size; OBD_ALLOC(rdbuf->rb_bufs[i].lb_buf, read_size); if (rdbuf->rb_bufs[i].lb_buf == NULL) GOTO(out_free, rc = -ENOMEM); rdbuf->rb_bufs[i].lb_len = read_size; dt_read_lock(env, obj, MOR_TGT_CHILD); rc = dt_read(env, obj, &rdbuf->rb_bufs[i], &pos); dt_read_unlock(env, obj); total_size += rc < 0 ? 0 : rc; if (rc <= 0) break; rdbuf->rb_nbufs++; size -= read_size; } /* send pages to client */ rc = tgt_send_buffer(tsi, rdbuf); if (rc < 0) GOTO(out_free, rc); orr->orr_size = total_size; orr->orr_offset = pos; orr_cpu_to_le(orr, orr); update_result->our_datalen += orr->orr_size; out_free: for (i = 0; i < nbufs; i++) { if (rdbuf->rb_bufs[i].lb_buf != NULL) { OBD_FREE(rdbuf->rb_bufs[i].lb_buf, rdbuf->rb_bufs[i].lb_len); } } OBD_FREE(rdbuf, sizeof(struct lu_rdbuf) + nbufs * sizeof(rdbuf->rb_bufs[0])); out: /* Insert read buffer */ update_result->our_rc = ptlrpc_status_hton(rc); reply->ourp_lens[index] = cfs_size_round(update_result->our_datalen + sizeof(*update_result)); RETURN(rc); }
static int llog_check_cb(struct llog_handle *handle, struct llog_rec_hdr *rec, void *data) { struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data; static int l, remains, from, to; static char *out; char *endp; int cur_index, rc = 0; ENTRY; cur_index = rec->lrh_index; if (ioc_data && (ioc_data->ioc_inllen1)) { l = 0; remains = ioc_data->ioc_inllen4 + cfs_size_round(ioc_data->ioc_inllen1) + cfs_size_round(ioc_data->ioc_inllen2) + cfs_size_round(ioc_data->ioc_inllen3); from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0); if (*endp != '\0') RETURN(-EINVAL); to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0); if (*endp != '\0') RETURN(-EINVAL); ioc_data->ioc_inllen1 = 0; out = ioc_data->ioc_bulk; if (cur_index < from) RETURN(0); if (to > 0 && cur_index > to) RETURN(-LLOG_EEMPTY); } if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) { struct llog_logid_rec *lir = (struct llog_logid_rec *)rec; struct llog_handle *log_handle; if (rec->lrh_type != LLOG_LOGID_MAGIC) { l = snprintf(out, remains, "[index]: %05d [type]: " "%02x [len]: %04d failed\n", cur_index, rec->lrh_type, rec->lrh_len); } if (handle->lgh_ctxt == NULL) RETURN(-EOPNOTSUPP); rc = llog_cat_id2handle(handle, &log_handle, &lir->lid_id); if (rc) { CDEBUG(D_IOCTL, "cannot find log #"LPX64"#"LPX64"#%08x\n", lir->lid_id.lgl_oid, lir->lid_id.lgl_oseq, lir->lid_id.lgl_ogen); RETURN(rc); } rc = llog_process(log_handle, llog_check_cb, NULL, NULL); llog_close(log_handle); } else { switch (rec->lrh_type) { case OST_SZ_REC: case OST_RAID1_REC: case MDS_UNLINK_REC: case MDS_SETATTR_REC: case MDS_SETATTR64_REC: case OBD_CFG_REC: case LLOG_HDR_MAGIC: { l = snprintf(out, remains, "[index]: %05d [type]: " "%02x [len]: %04d ok\n", cur_index, rec->lrh_type, rec->lrh_len); out += l; remains -= l; if (remains <= 0) { CERROR("no space to print log records\n"); RETURN(-LLOG_EEMPTY); } RETURN(0); } default: { l = snprintf(out, remains, "[index]: %05d [type]: " "%02x [len]: %04d failed\n", cur_index, rec->lrh_type, rec->lrh_len); out += l; remains -= l; if (remains <= 0) { CERROR("no space to print log records\n"); RETURN(-LLOG_EEMPTY); } RETURN(0); } } } RETURN(rc); }
int llog_ioctl(struct llog_ctxt *ctxt, int cmd, struct obd_ioctl_data *data) { struct llog_logid logid; int err = 0; struct llog_handle *handle = NULL; ENTRY; if (*data->ioc_inlbuf1 == '#') { err = str2logid(&logid, data->ioc_inlbuf1, data->ioc_inllen1); if (err) GOTO(out, err); err = llog_create(ctxt, &handle, &logid, NULL); if (err) GOTO(out, err); } else if (*data->ioc_inlbuf1 == '$') { char *name = data->ioc_inlbuf1 + 1; err = llog_create(ctxt, &handle, NULL, name); if (err) GOTO(out, err); } else { GOTO(out, err = -EINVAL); } err = llog_init_handle(handle, 0, NULL); if (err) GOTO(out_close, err = -ENOENT); switch (cmd) { case OBD_IOC_LLOG_INFO: { int l; int remains = data->ioc_inllen2 + cfs_size_round(data->ioc_inllen1); char *out = data->ioc_bulk; l = snprintf(out, remains, "logid: #"LPX64"#"LPX64"#%08x\n" "flags: %x (%s)\n" "records count: %d\n" "last index: %d\n", handle->lgh_id.lgl_oid, handle->lgh_id.lgl_oseq, handle->lgh_id.lgl_ogen, handle->lgh_hdr->llh_flags, handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT ? "cat" : "plain", handle->lgh_hdr->llh_count, handle->lgh_last_idx); out += l; remains -= l; if (remains <= 0) CERROR("not enough space for log header info\n"); GOTO(out_close, err); } case OBD_IOC_LLOG_CHECK: { LASSERT(data->ioc_inllen1); err = llog_process(handle, llog_check_cb, data, NULL); if (err == -LLOG_EEMPTY) err = 0; GOTO(out_close, err); } case OBD_IOC_LLOG_PRINT: { LASSERT(data->ioc_inllen1); err = llog_process(handle, class_config_dump_handler,data,NULL); if (err == -LLOG_EEMPTY) err = 0; else err = llog_process(handle, llog_print_cb, data, NULL); GOTO(out_close, err); } case OBD_IOC_LLOG_CANCEL: { struct llog_cookie cookie; struct llog_logid plain; char *endp; cookie.lgc_index = simple_strtoul(data->ioc_inlbuf3, &endp, 0); if (*endp != '\0') GOTO(out_close, err = -EINVAL); if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) { cfs_down_write(&handle->lgh_lock); err = llog_cancel_rec(handle, cookie.lgc_index); cfs_up_write(&handle->lgh_lock); GOTO(out_close, err); } err = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2); if (err) GOTO(out_close, err); cookie.lgc_lgl = plain; if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) GOTO(out_close, err = -EINVAL); err = llog_cat_cancel_records(handle, 1, &cookie); GOTO(out_close, err); } case OBD_IOC_LLOG_REMOVE: { struct llog_logid plain; if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) { err = llog_destroy(handle); if (!err) llog_free_handle(handle); GOTO(out, err); } if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) GOTO(out_close, err = -EINVAL); if (data->ioc_inlbuf2) { /*remove indicate log from the catalog*/ err = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2); if (err) GOTO(out_close, err); err = llog_remove_log(handle, &plain); } else { /*remove all the log of the catalog*/ llog_process(handle, llog_delete_cb, NULL, NULL); } GOTO(out_close, err); } } out_close: if (handle->lgh_hdr && handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) llog_cat_put(handle); else llog_close(handle); out: RETURN(err); }
int llog_ioctl(const struct lu_env *env, struct llog_ctxt *ctxt, int cmd, struct obd_ioctl_data *data) { struct llog_logid logid; int rc = 0; struct llog_handle *handle = NULL; if (*data->ioc_inlbuf1 == '#') { rc = str2logid(&logid, data->ioc_inlbuf1, data->ioc_inllen1); if (rc) return rc; rc = llog_open(env, ctxt, &handle, &logid, NULL, LLOG_OPEN_EXISTS); if (rc) return rc; } else if (*data->ioc_inlbuf1 == '$') { char *name = data->ioc_inlbuf1 + 1; rc = llog_open(env, ctxt, &handle, NULL, name, LLOG_OPEN_EXISTS); if (rc) return rc; } else { return -EINVAL; } rc = llog_init_handle(env, handle, 0, NULL); if (rc) GOTO(out_close, rc = -ENOENT); switch (cmd) { case OBD_IOC_LLOG_INFO: { int l; int remains = data->ioc_inllen2 + cfs_size_round(data->ioc_inllen1); char *out = data->ioc_bulk; l = snprintf(out, remains, "logid: #"DOSTID"#%08x\n" "flags: %x (%s)\n" "records count: %d\n" "last index: %d\n", POSTID(&handle->lgh_id.lgl_oi), handle->lgh_id.lgl_ogen, handle->lgh_hdr->llh_flags, handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT ? "cat" : "plain", handle->lgh_hdr->llh_count, handle->lgh_last_idx); out += l; remains -= l; if (remains <= 0) { CERROR("%s: not enough space for log header info\n", ctxt->loc_obd->obd_name); rc = -ENOSPC; } break; } case OBD_IOC_LLOG_CHECK: LASSERT(data->ioc_inllen1 > 0); rc = llog_process(env, handle, llog_check_cb, data, NULL); if (rc == -LLOG_EEMPTY) rc = 0; else if (rc) GOTO(out_close, rc); break; case OBD_IOC_LLOG_PRINT: LASSERT(data->ioc_inllen1 > 0); rc = llog_process(env, handle, llog_print_cb, data, NULL); if (rc == -LLOG_EEMPTY) rc = 0; else if (rc) GOTO(out_close, rc); break; case OBD_IOC_LLOG_CANCEL: { struct llog_cookie cookie; struct llog_logid plain; char *endp; cookie.lgc_index = simple_strtoul(data->ioc_inlbuf3, &endp, 0); if (*endp != '\0') GOTO(out_close, rc = -EINVAL); if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) { rc = llog_cancel_rec(NULL, handle, cookie.lgc_index); GOTO(out_close, rc); } else if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) { GOTO(out_close, rc = -EINVAL); } if (data->ioc_inlbuf2 == NULL) /* catalog but no logid */ GOTO(out_close, rc = -ENOTTY); rc = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2); if (rc) GOTO(out_close, rc); cookie.lgc_lgl = plain; rc = llog_cat_cancel_records(env, handle, 1, &cookie); if (rc) GOTO(out_close, rc); break; } case OBD_IOC_LLOG_REMOVE: { struct llog_logid plain; if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) { rc = llog_destroy(env, handle); GOTO(out_close, rc); } else if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) { GOTO(out_close, rc = -EINVAL); } if (data->ioc_inlbuf2 > 0) { /* remove indicate log from the catalog */ rc = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2); if (rc) GOTO(out_close, rc); rc = llog_remove_log(env, handle, &plain); } else { /* remove all the log of the catalog */ rc = llog_process(env, handle, llog_delete_cb, NULL, NULL); if (rc) GOTO(out_close, rc); } break; } default: CERROR("%s: Unknown ioctl cmd %#x\n", ctxt->loc_obd->obd_name, cmd); GOTO(out_close, rc = -ENOTTY); } out_close: if (handle->lgh_hdr && handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) llog_cat_close(env, handle); else llog_close(env, handle); return rc; }
/* temporary for testing */ static ssize_t mdc_kuc_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct kuc_hdr *lh; struct hsm_action_list *hal; struct hsm_action_item *hai; int len; int fd, rc; rc = lprocfs_write_helper(buffer, count, &fd); if (rc) return rc; if (fd < 0) return -ERANGE; CWARN("message to fd %d\n", fd); len = sizeof(*lh) + sizeof(*hal) + MTI_NAME_MAXLEN + /* for mockup below */ 2 * cfs_size_round(sizeof(*hai)); OBD_ALLOC(lh, len); if (!lh) return -ENOMEM; lh->kuc_magic = KUC_MAGIC; lh->kuc_transport = KUC_TRANSPORT_HSM; lh->kuc_msgtype = HMT_ACTION_LIST; lh->kuc_msglen = len; hal = (struct hsm_action_list *)(lh + 1); hal->hal_version = HAL_VERSION; hal->hal_archive_id = 1; hal->hal_flags = 0; obd_uuid2fsname(hal->hal_fsname, obd->obd_name, MTI_NAME_MAXLEN); /* mock up an action list */ hal->hal_count = 2; hai = hai_zero(hal); hai->hai_action = HSMA_ARCHIVE; hai->hai_fid.f_oid = 5; hai->hai_len = sizeof(*hai); hai = hai_next(hai); hai->hai_action = HSMA_RESTORE; hai->hai_fid.f_oid = 10; hai->hai_len = sizeof(*hai); /* This works for either broadcast or unicast to a single fd */ if (fd == 0) { rc = libcfs_kkuc_group_put(KUC_GRP_HSM, lh); } else { struct file *fp = fget(fd); rc = libcfs_kkuc_msg_put(fp, lh); fput(fp); } OBD_FREE(lh, len); if (rc < 0) return rc; return count; }
static int out_xattr_get(struct tgt_session_info *tsi) { const struct lu_env *env = tsi->tsi_env; struct tgt_thread_info *tti = tgt_th_info(env); struct object_update *update = tti->tti_u.update.tti_update; struct lu_buf *lbuf = &tti->tti_buf; struct object_update_reply *reply = tti->tti_u.update.tti_update_reply; struct dt_object *obj = tti->tti_u.update.tti_dt_object; char *name; struct object_update_result *update_result; int idx = tti->tti_u.update.tti_update_reply_index; int rc; ENTRY; if (!lu_object_exists(&obj->do_lu)) { set_bit(LU_OBJECT_HEARD_BANSHEE, &obj->do_lu.lo_header->loh_flags); RETURN(-ENOENT); } name = object_update_param_get(update, 0, NULL); if (name == NULL) { CERROR("%s: empty name for xattr get: rc = %d\n", tgt_name(tsi->tsi_tgt), -EPROTO); RETURN(err_serious(-EPROTO)); } update_result = object_update_result_get(reply, 0, NULL); if (update_result == NULL) { CERROR("%s: empty name for xattr get: rc = %d\n", tgt_name(tsi->tsi_tgt), -EPROTO); RETURN(err_serious(-EPROTO)); } lbuf->lb_buf = update_result->our_data; lbuf->lb_len = OUT_UPDATE_REPLY_SIZE - cfs_size_round((unsigned long)update_result->our_data - (unsigned long)update_result); dt_read_lock(env, obj, MOR_TGT_CHILD); rc = dt_xattr_get(env, obj, lbuf, name, NULL); dt_read_unlock(env, obj); if (rc < 0) { lbuf->lb_len = 0; GOTO(out, rc); } if (rc == 0) { lbuf->lb_len = 0; GOTO(out, rc = -ENOENT); } lbuf->lb_len = rc; rc = 0; CDEBUG(D_INFO, "%s: "DFID" get xattr %s len %d\n", tgt_name(tsi->tsi_tgt), PFID(lu_object_fid(&obj->do_lu)), name, (int)lbuf->lb_len); GOTO(out, rc); out: object_update_result_insert(reply, lbuf->lb_buf, lbuf->lb_len, idx, rc); 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); }
static int llog_check_cb(const struct lu_env *env, struct llog_handle *handle, struct llog_rec_hdr *rec, void *data) { struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data; static int l, remains, from, to; static char *out; char *endp; int cur_index, rc = 0; if (ioc_data && ioc_data->ioc_inllen1 > 0) { l = 0; remains = ioc_data->ioc_inllen4 + cfs_size_round(ioc_data->ioc_inllen1) + cfs_size_round(ioc_data->ioc_inllen2) + cfs_size_round(ioc_data->ioc_inllen3); from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0); if (*endp != '\0') return -EINVAL; to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0); if (*endp != '\0') return -EINVAL; ioc_data->ioc_inllen1 = 0; out = ioc_data->ioc_bulk; } cur_index = rec->lrh_index; if (cur_index < from) return 0; if (to > 0 && cur_index > to) return -LLOG_EEMPTY; if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) { struct llog_logid_rec *lir = (struct llog_logid_rec *)rec; struct llog_handle *loghandle; if (rec->lrh_type != LLOG_LOGID_MAGIC) { l = snprintf(out, remains, "[index]: %05d [type]: " "%02x [len]: %04d failed\n", cur_index, rec->lrh_type, rec->lrh_len); } if (handle->lgh_ctxt == NULL) return -EOPNOTSUPP; rc = llog_cat_id2handle(env, handle, &loghandle, &lir->lid_id); if (rc) { CDEBUG(D_IOCTL, "cannot find log #"DOSTID"#%08x\n", POSTID(&lir->lid_id.lgl_oi), lir->lid_id.lgl_ogen); return rc; } rc = llog_process(env, loghandle, llog_check_cb, NULL, NULL); llog_handle_put(loghandle); } else { bool ok; switch (rec->lrh_type) { case OST_SZ_REC: case MDS_UNLINK_REC: case MDS_UNLINK64_REC: case MDS_SETATTR64_REC: case OBD_CFG_REC: case LLOG_GEN_REC: case LLOG_HDR_MAGIC: ok = true; break; default: ok = false; } l = snprintf(out, remains, "[index]: %05d [type]: " "%02x [len]: %04d %s\n", cur_index, rec->lrh_type, rec->lrh_len, ok ? "ok" : "failed"); out += l; remains -= l; if (remains <= 0) { CERROR("%s: no space to print log records\n", handle->lgh_ctxt->loc_obd->obd_name); return -LLOG_EEMPTY; } } return rc; }