/* copied from lov/lov_ea.c, just for debugging, will be removed later */ void mdt_dump_lmm(int level, const struct lov_mds_md *lmm, __u64 valid) { const struct lov_ost_data_v1 *lod; int i; __u16 count; if (likely(!cfs_cdebug_show(level, DEBUG_SUBSYSTEM))) return; count = le16_to_cpu(((struct lov_user_md *)lmm)->lmm_stripe_count); CDEBUG(level, "objid "DOSTID", magic 0x%08X, pattern %#X\n", POSTID(&lmm->lmm_oi), le32_to_cpu(lmm->lmm_magic), le32_to_cpu(lmm->lmm_pattern)); CDEBUG(level, "stripe_size=0x%x, stripe_count=0x%x\n", le32_to_cpu(lmm->lmm_stripe_size), count); /* If it's a directory or a released file, then there are * no actual objects to print, so bail out. */ if (valid & OBD_MD_FLDIREA || le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED) return; LASSERT(count <= LOV_MAX_STRIPE_COUNT); for (i = 0, lod = lmm->lmm_objects; i < count; i++, lod++) { struct ost_id oi; ostid_le_to_cpu(&lod->l_ost_oi, &oi); CDEBUG(level, "stripe %u idx %u subobj "DOSTID"\n", i, le32_to_cpu(lod->l_ost_idx), POSTID(&oi)); } }
/* returns negative on error; 0 if success; 1 if success & log destroyed */ int llog_cancel_rec(const struct lu_env *env, struct llog_handle *loghandle, int index) { struct llog_log_hdr *llh = loghandle->lgh_hdr; int rc = 0; ENTRY; CDEBUG(D_RPCTRACE, "Canceling %d in log "DOSTID"\n", index, POSTID(&loghandle->lgh_id.lgl_oi)); if (index == 0) { CERROR("Can't cancel index 0 which is header\n"); RETURN(-EINVAL); } spin_lock(&loghandle->lgh_hdr_lock); if (!ext2_clear_bit(index, llh->llh_bitmap)) { spin_unlock(&loghandle->lgh_hdr_lock); CDEBUG(D_RPCTRACE, "Catalog index %u already clear?\n", index); RETURN(-ENOENT); } llh->llh_count--; if ((llh->llh_flags & LLOG_F_ZAP_WHEN_EMPTY) && (llh->llh_count == 1) && (loghandle->lgh_last_idx == (LLOG_BITMAP_BYTES * 8) - 1)) { spin_unlock(&loghandle->lgh_hdr_lock); rc = llog_destroy(env, loghandle); if (rc < 0) { CERROR("%s: can't destroy empty llog #"DOSTID "#%08x: rc = %d\n", loghandle->lgh_ctxt->loc_obd->obd_name, POSTID(&loghandle->lgh_id.lgl_oi), loghandle->lgh_id.lgl_ogen, rc); GOTO(out_err, rc); } RETURN(1); } spin_unlock(&loghandle->lgh_hdr_lock); rc = llog_write(env, loghandle, &llh->llh_hdr, NULL, 0, NULL, 0); if (rc < 0) { CERROR("%s: fail to write header for llog #"DOSTID "#%08x: rc = %d\n", loghandle->lgh_ctxt->loc_obd->obd_name, POSTID(&loghandle->lgh_id.lgl_oi), loghandle->lgh_id.lgl_ogen, rc); GOTO(out_err, rc); } RETURN(0); out_err: spin_lock(&loghandle->lgh_hdr_lock); ext2_set_bit(index, llh->llh_bitmap); llh->llh_count++; spin_unlock(&loghandle->lgh_hdr_lock); return rc; }
static int llog_remove_log(const struct lu_env *env, struct llog_handle *cat, struct llog_logid *logid) { struct llog_handle *log; int rc; ENTRY; rc = llog_cat_id2handle(env, cat, &log, logid); if (rc) { CDEBUG(D_IOCTL, "cannot find log #"DOSTID"#%08x\n", POSTID(&logid->lgl_oi), logid->lgl_ogen); RETURN(-ENOENT); } rc = llog_destroy(env, log); if (rc) { CDEBUG(D_IOCTL, "cannot destroy log\n"); GOTO(out, rc); } llog_cat_cleanup(env, cat, log, log->u.phd.phd_cookie.lgc_index); out: llog_handle_put(log); RETURN(rc); }
void dump_lsm(unsigned int level, const struct lov_stripe_md *lsm) { CDEBUG(level, "lsm %p, objid " DOSTID ", maxbytes %#llx, magic 0x%08X, stripe_size %u, stripe_count %u, refc: %d, layout_gen %u, pool [" LOV_POOLNAMEF "]\n", lsm, POSTID(&lsm->lsm_oi), lsm->lsm_maxbytes, lsm->lsm_magic, lsm->lsm_stripe_size, lsm->lsm_stripe_count, atomic_read(&lsm->lsm_refc), lsm->lsm_layout_gen, lsm->lsm_pool_name); }
void obdo_cpy_md(struct obdo *dst, struct obdo *src, obd_flag valid) { CDEBUG(D_INODE, "src obdo "DOSTID" valid "LPX64", dst obdo "DOSTID"\n", POSTID(&src->o_oi), src->o_valid, POSTID(&dst->o_oi)); if (valid & OBD_MD_FLATIME) dst->o_atime = src->o_atime; if (valid & OBD_MD_FLMTIME) dst->o_mtime = src->o_mtime; if (valid & OBD_MD_FLCTIME) dst->o_ctime = src->o_ctime; if (valid & OBD_MD_FLSIZE) dst->o_size = src->o_size; if (valid & OBD_MD_FLBLOCKS) /* allocation of space */ dst->o_blocks = src->o_blocks; if (valid & OBD_MD_FLBLKSZ) dst->o_blksize = src->o_blksize; if (valid & OBD_MD_FLTYPE) dst->o_mode = (dst->o_mode & ~S_IFMT) | (src->o_mode & S_IFMT); if (valid & OBD_MD_FLMODE) dst->o_mode = (dst->o_mode & S_IFMT) | (src->o_mode & ~S_IFMT); if (valid & OBD_MD_FLUID) dst->o_uid = src->o_uid; if (valid & OBD_MD_FLGID) dst->o_gid = src->o_gid; if (valid & OBD_MD_FLFLAGS) dst->o_flags = src->o_flags; if (valid & OBD_MD_FLFID) { dst->o_parent_seq = src->o_parent_seq; dst->o_parent_ver = src->o_parent_ver; } if (valid & OBD_MD_FLGENER) dst->o_parent_oid = src->o_parent_oid; if (valid & OBD_MD_FLHANDLE) dst->o_handle = src->o_handle; if (valid & OBD_MD_FLCOOKIE) dst->o_lcookie = src->o_lcookie; dst->o_valid |= valid; }
static void print_llogd_body(struct llogd_body *d) { CDEBUG(D_OTHER, "llogd body: %p\n", d); CDEBUG(D_OTHER, "\tlgd_logid.lgl_oi: "DOSTID"\n", POSTID(&d->lgd_logid.lgl_oi)); CDEBUG(D_OTHER, "\tlgd_logid.lgl_ogen: %#x\n", d->lgd_logid.lgl_ogen); CDEBUG(D_OTHER, "\tlgd_ctxt_idx: %#x\n", d->lgd_ctxt_idx); CDEBUG(D_OTHER, "\tlgd_llh_flags: %#x\n", d->lgd_llh_flags); CDEBUG(D_OTHER, "\tlgd_index: %#x\n", d->lgd_index); CDEBUG(D_OTHER, "\tlgd_saved_index: %#x\n", d->lgd_saved_index); CDEBUG(D_OTHER, "\tlgd_len: %#x\n", d->lgd_len); CDEBUG(D_OTHER, "\tlgd_cur_offset: %#llx\n", d->lgd_cur_offset); }
/* the replicators commit callback */ static int lov_llog_repl_cancel(const struct lu_env *env, struct llog_ctxt *ctxt, struct lov_stripe_md *lsm, int count, struct llog_cookie *cookies, int flags) { struct lov_obd *lov; struct obd_device *obd = ctxt->loc_obd; int rc = 0, i; ENTRY; LASSERT(lsm != NULL); LASSERT(count == lsm->lsm_stripe_count); lov = &obd->u.lov; obd_getref(obd); for (i = 0; i < count; i++, cookies++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; struct obd_device *child = lov->lov_tgts[loi->loi_ost_idx]->ltd_exp->exp_obd; struct llog_ctxt *cctxt = llog_get_context(child, ctxt->loc_idx); int err; err = llog_cancel(env, cctxt, NULL, 1, cookies, flags); llog_ctxt_put(cctxt); if (err && lov->lov_tgts[loi->loi_ost_idx]->ltd_active) { CERROR("%s: objid "DOSTID" subobj "DOSTID " on OST idx %d: rc = %d\n", obd->obd_name, POSTID(&lsm->lsm_oi), POSTID(&loi->loi_oi), loi->loi_ost_idx, err); if (!rc) rc = err; } } obd_putref(obd); RETURN(rc); }
static int osc_object_print(const struct lu_env *env, void *cookie, lu_printer_t p, const struct lu_object *obj) { struct osc_object *osc = lu2osc(obj); struct lov_oinfo *oinfo = osc->oo_oinfo; struct osc_async_rc *ar = &oinfo->loi_ar; (*p)(env, cookie, "id: " DOSTID " idx: %d gen: %d kms_valid: %u kms %llu rc: %d force_sync: %d min_xid: %llu ", POSTID(&oinfo->loi_oi), oinfo->loi_ost_idx, oinfo->loi_ost_gen, oinfo->loi_kms_valid, oinfo->loi_kms, ar->ar_rc, ar->ar_force_sync, ar->ar_min_xid); osc_lvb_print(env, cookie, p, &oinfo->loi_lvb); return 0; }
void lov_dump_lmm_common(int level, void *lmmp) { struct lov_mds_md *lmm = lmmp; struct ost_id oi; lmm_oi_le_to_cpu(&oi, &lmm->lmm_oi); CDEBUG(level, "objid "DOSTID", magic 0x%08x, pattern %#x\n", POSTID(&oi), le32_to_cpu(lmm->lmm_magic), le32_to_cpu(lmm->lmm_pattern)); CDEBUG(level, "stripe_size %u, stripe_count %u, layout_gen %u\n", le32_to_cpu(lmm->lmm_stripe_size), le16_to_cpu(lmm->lmm_stripe_count), le16_to_cpu(lmm->lmm_layout_gen)); }
/* copied from lov/lov_ea.c, just for debugging, will be removed later */ void mdt_dump_lmm(int level, const struct lov_mds_md *lmm) { const struct lov_ost_data_v1 *lod; int i; __u16 count; count = le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count); CDEBUG(level, "objid "DOSTID", magic 0x%08X, pattern %#X\n", POSTID(&lmm->lmm_oi), le32_to_cpu(lmm->lmm_magic), le32_to_cpu(lmm->lmm_pattern)); CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n", le32_to_cpu(lmm->lmm_stripe_size), count); if (count == LOV_ALL_STRIPES) return; LASSERT(count <= LOV_MAX_STRIPE_COUNT); for (i = 0, lod = lmm->lmm_objects; i < count; i++, lod++) { struct ost_id oi; ostid_le_to_cpu((struct ost_id *)&lod->l_ost_oi, &oi); CDEBUG(level, "stripe %u idx %u subobj "DOSTID"\n", i, le32_to_cpu(lod->l_ost_idx), POSTID(&oi)); } }
int llog_catalog_list(const struct lu_env *env, struct dt_device *d, int count, struct obd_ioctl_data *data, const struct lu_fid *fid) { int size, i; struct llog_catid *idarray; struct llog_logid *id; char *out; int l, remains, rc = 0; ENTRY; if (count == 0) { /* get total number of logs */ rc = llog_osd_get_cat_list(env, d, 0, 0, NULL, fid); if (rc < 0) RETURN(rc); count = rc; } size = sizeof(*idarray) * count; OBD_ALLOC_LARGE(idarray, size); if (!idarray) RETURN(-ENOMEM); rc = llog_osd_get_cat_list(env, d, 0, count, idarray, fid); if (rc) GOTO(out, rc); out = data->ioc_bulk; remains = data->ioc_inllen1; for (i = 0; i < count; i++) { id = &idarray[i].lci_logid; l = snprintf(out, remains, "catalog log: #"DOSTID"#%08x\n", POSTID(&id->lgl_oi), id->lgl_ogen); out += l; remains -= l; if (remains <= 0) break; } out: OBD_FREE_LARGE(idarray, size); RETURN(rc); }
static int changelog_init_cb(const struct lu_env *env, struct llog_handle *llh, struct llog_rec_hdr *hdr, void *data) { struct mdd_device *mdd = (struct mdd_device *)data; struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr; LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN); LASSERT(rec->cr_hdr.lrh_type == CHANGELOG_REC); CDEBUG(D_INFO, "seeing record at index %d/%d/"LPU64" t=%x %.*s in log" DOSTID"\n", hdr->lrh_index, rec->cr_hdr.lrh_index, rec->cr.cr_index, rec->cr.cr_type, rec->cr.cr_namelen, changelog_rec_name(&rec->cr), POSTID(&llh->lgh_id.lgl_oi)); mdd->mdd_cl.mc_index = rec->cr.cr_index; return LLOG_PROC_BREAK; }
/** Merge the lock value block(&lvb) attributes from each of the stripes in a * file into a single lvb. It is expected that the caller initializes the * current atime, mtime, ctime to avoid regressing a more uptodate time on * the local client. * * If \a kms_only is set then we do not consider the recently seen size (rss) * when updating the known minimum size (kms). Even when merging RSS, we will * take the KMS value if it's larger. This prevents getattr from stomping on * dirty cached pages which extend the file size. */ int lov_merge_lvb(struct obd_export *exp, struct lov_stripe_md *lsm, struct ost_lvb *lvb, int kms_only) { int rc; __u64 kms; ENTRY; lov_stripe_lock(lsm); rc = lov_merge_lvb_kms(lsm, lvb, &kms); lov_stripe_unlock(lsm); if (kms_only) lvb->lvb_size = kms; CDEBUG(D_INODE, "merged for ID "DOSTID" s="LPU64" m="LPU64" a="LPU64 " c="LPU64" b="LPU64"\n", POSTID(&lsm->lsm_oi), lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks); RETURN(rc); }
int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp, struct lov_user_md *lump) { int i; int rc; struct obd_export *oexp; struct lov_obd *lov = &exp->exp_obd->u.lov; obd_id last_id = 0; struct lov_user_ost_data_v1 *lmm_objects; ENTRY; if (lump->lmm_magic == LOV_USER_MAGIC_V3) lmm_objects = ((struct lov_user_md_v3 *)lump)->lmm_objects; else lmm_objects = lump->lmm_objects; for (i = 0; i < lump->lmm_stripe_count; i++) { __u32 len = sizeof(last_id); oexp = lov->lov_tgts[lmm_objects[i].l_ost_idx]->ltd_exp; rc = obd_get_info(NULL, oexp, sizeof(KEY_LAST_ID), KEY_LAST_ID, &len, &last_id, NULL); if (rc) RETURN(rc); if (ostid_id(&lmm_objects[i].l_ost_oi) > last_id) { CERROR("Setting EA for object > than last id on" " ost idx %d "DOSTID" > "LPD64" \n", lmm_objects[i].l_ost_idx, POSTID(&lmm_objects[i].l_ost_oi), last_id); RETURN(-EINVAL); } } rc = lov_setstripe(exp, 0, lsmp, lump); if (rc) RETURN(rc); for (i = 0; i < lump->lmm_stripe_count; i++) { (*lsmp)->lsm_oinfo[i]->loi_ost_idx = lmm_objects[i].l_ost_idx; (*lsmp)->lsm_oinfo[i]->loi_oi = lmm_objects[i].l_ost_oi; } RETURN(0); }
static void lov_dump_lmm_objects(int level, struct lov_ost_data *lod, int stripe_count) { int i; if (stripe_count > LOV_V1_INSANE_STRIPE_COUNT) { CDEBUG(level, "bad stripe_count %u > max_stripe_count %u\n", stripe_count, LOV_V1_INSANE_STRIPE_COUNT); return; } for (i = 0; i < stripe_count; ++i, ++lod) { struct ost_id oi; ostid_le_to_cpu(&lod->l_ost_oi, &oi); CDEBUG(level, "stripe %u idx %u subobj "DOSTID"\n", i, le32_to_cpu(lod->l_ost_idx), POSTID(&oi)); } }
static int llog_lvfs_close(const struct lu_env *env, struct llog_handle *handle) { int rc; if (handle->lgh_file == NULL) return 0; rc = filp_close(handle->lgh_file, 0); if (rc) CERROR("%s: error closing llog #"DOSTID"#%08x: " "rc = %d\n", handle->lgh_ctxt->loc_obd->obd_name, POSTID(&handle->lgh_id.lgl_oi), handle->lgh_id.lgl_ogen, rc); handle->lgh_file = NULL; if (handle->lgh_name) { OBD_FREE(handle->lgh_name, strlen(handle->lgh_name) + 1); handle->lgh_name = NULL; } return rc; }
void obdo_to_inode(struct inode *dst, struct obdo *src, obd_flag valid) { valid &= src->o_valid; LASSERTF(!(valid & (OBD_MD_FLTYPE | OBD_MD_FLGENER | OBD_MD_FLFID | OBD_MD_FLID | OBD_MD_FLGROUP)), "object "DOSTID", valid %x\n", POSTID(&src->o_oi), valid); if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME)) CDEBUG(D_INODE, "valid %#llx, cur time %lu/%lu, new %llu/%llu\n", src->o_valid, LTIME_S(dst->i_mtime), LTIME_S(dst->i_ctime), src->o_mtime, src->o_ctime); if (valid & OBD_MD_FLATIME) LTIME_S(dst->i_atime) = src->o_atime; if (valid & OBD_MD_FLMTIME) LTIME_S(dst->i_mtime) = src->o_mtime; if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(dst->i_ctime)) LTIME_S(dst->i_ctime) = src->o_ctime; if (valid & OBD_MD_FLSIZE) i_size_write(dst, src->o_size); if (valid & OBD_MD_FLBLOCKS) { /* allocation of space */ dst->i_blocks = src->o_blocks; if (dst->i_blocks < src->o_blocks) /* overflow */ dst->i_blocks = -1; } if (valid & OBD_MD_FLBLKSZ) dst->i_blkbits = ffs(src->o_blksize)-1; if (valid & OBD_MD_FLMODE) dst->i_mode = (dst->i_mode & S_IFMT) | (src->o_mode & ~S_IFMT); if (valid & OBD_MD_FLUID) dst->i_uid = make_kuid(&init_user_ns, src->o_uid); if (valid & OBD_MD_FLGID) dst->i_gid = make_kgid(&init_user_ns, src->o_gid); if (valid & OBD_MD_FLFLAGS) dst->i_flags = src->o_flags; }
static int changelog_user_init_cb(const struct lu_env *env, struct llog_handle *llh, struct llog_rec_hdr *hdr, void *data) { struct mdd_device *mdd = (struct mdd_device *)data; struct llog_changelog_user_rec *rec = (struct llog_changelog_user_rec *)hdr; LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN); LASSERT(rec->cur_hdr.lrh_type == CHANGELOG_USER_REC); CDEBUG(D_INFO, "seeing user at index %d/%d id=%d endrec="LPU64 " in log "DOSTID"\n", hdr->lrh_index, rec->cur_hdr.lrh_index, rec->cur_id, rec->cur_endrec, POSTID(&llh->lgh_id.lgl_oi)); spin_lock(&mdd->mdd_cl.mc_user_lock); mdd->mdd_cl.mc_lastuser = rec->cur_id; if (rec->cur_endrec > mdd->mdd_cl.mc_index) mdd->mdd_cl.mc_index = rec->cur_endrec; spin_unlock(&mdd->mdd_cl.mc_user_lock); return LLOG_PROC_BREAK; }
static int llog_changelog_cancel(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_cookie *cookies, int flags) { struct llog_handle *cathandle = ctxt->loc_handle; int rc; ENTRY; /* This should only be called with the catalog handle */ LASSERT(cathandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT); rc = llog_cat_process(env, cathandle, llog_changelog_cancel_cb, (void *)cookies, 0, 0); if (rc >= 0) /* 0 or 1 means we're done */ rc = 0; else CERROR("%s: cancel idx %u of catalog "DOSTID" rc=%d\n", ctxt->loc_obd->obd_name, cathandle->lgh_last_idx, POSTID(&cathandle->lgh_id.lgl_oi), rc); RETURN(rc); }
/** * Implementation of the llog_operations::lop_prev_block * * This function finds the llog block to return which contains * record with required index but in reverse order - from end of llog * to the beginning. * It is main part of reverse llog processing. * * \param[in] env execution environment * \param[in] loghandle llog handle of the current llog * \param[in] prev_idx target index to find * \param[in] buf pointer to data buffer to fill * \param[in] len required len to read, it is LLOG_CHUNK_SIZE usually. * * \retval 0 on successful buffer read * \retval negative value on error */ static int llog_osd_prev_block(const struct lu_env *env, struct llog_handle *loghandle, int prev_idx, void *buf, int len) { struct llog_thread_info *lgi = llog_info(env); struct dt_object *o; struct dt_device *dt; loff_t cur_offset; int rc; ENTRY; if (len == 0 || len & (LLOG_CHUNK_SIZE - 1)) RETURN(-EINVAL); CDEBUG(D_OTHER, "looking for log index %u\n", prev_idx); LASSERT(loghandle); LASSERT(loghandle->lgh_ctxt); o = loghandle->lgh_obj; LASSERT(o); LASSERT(dt_object_exists(o)); dt = lu2dt_dev(o->do_lu.lo_dev); LASSERT(dt); cur_offset = LLOG_CHUNK_SIZE; llog_skip_over(&cur_offset, 0, prev_idx); rc = dt_attr_get(env, o, &lgi->lgi_attr, BYPASS_CAPA); if (rc) GOTO(out, rc); while (cur_offset < lgi->lgi_attr.la_size) { struct llog_rec_hdr *rec, *last_rec; struct llog_rec_tail *tail; lgi->lgi_buf.lb_len = len; lgi->lgi_buf.lb_buf = buf; rc = dt_read(env, o, &lgi->lgi_buf, &cur_offset); if (rc < 0) { CERROR("%s: can't read llog block from log "DFID " offset "LPU64": rc = %d\n", o->do_lu.lo_dev->ld_obd->obd_name, PFID(lu_object_fid(&o->do_lu)), cur_offset, rc); GOTO(out, rc); } if (rc == 0) /* end of file, nothing to do */ GOTO(out, rc); if (rc < sizeof(*tail)) { CERROR("%s: invalid llog block at log id "DOSTID"/%u " "offset "LPU64"\n", o->do_lu.lo_dev->ld_obd->obd_name, POSTID(&loghandle->lgh_id.lgl_oi), loghandle->lgh_id.lgl_ogen, cur_offset); GOTO(out, rc = -EINVAL); } rec = buf; if (LLOG_REC_HDR_NEEDS_SWABBING(rec)) lustre_swab_llog_rec(rec); tail = (struct llog_rec_tail *)((char *)buf + rc - sizeof(struct llog_rec_tail)); /* get the last record in block */ last_rec = (struct llog_rec_hdr *)((char *)buf + rc - le32_to_cpu(tail->lrt_len)); if (LLOG_REC_HDR_NEEDS_SWABBING(last_rec)) lustre_swab_llog_rec(last_rec); LASSERT(last_rec->lrh_index == tail->lrt_index); /* this shouldn't happen */ if (tail->lrt_index == 0) { CERROR("%s: invalid llog tail at log id "DOSTID"/%u " "offset "LPU64"\n", o->do_lu.lo_dev->ld_obd->obd_name, POSTID(&loghandle->lgh_id.lgl_oi), loghandle->lgh_id.lgl_ogen, cur_offset); GOTO(out, rc = -EINVAL); } if (tail->lrt_index < prev_idx) continue; /* sanity check that the start of the new buffer is no farther * than the record that we wanted. This shouldn't happen. */ if (rec->lrh_index > prev_idx) { CERROR("%s: missed desired record? %u > %u\n", o->do_lu.lo_dev->ld_obd->obd_name, rec->lrh_index, prev_idx); GOTO(out, rc = -ENOENT); } GOTO(out, rc = 0); } GOTO(out, rc = -EIO); out: return rc; }
/** * Implementation of the llog_operations::lop_write * * This function writes the new record in the llog or modify the existed one. * * \param[in] env execution environment * \param[in] loghandle llog handle of the current llog * \param[in] rec llog record header. This is a real header of * the full llog record to write. This is * the beginning of buffer to write, the length * of buffer is stored in \a rec::lrh_len * \param[out] reccookie pointer to the cookie to return back if needed. * It is used for further cancel of this llog * record. * \param[in] idx index of the llog record. If \a idx == -1 then * this is append case, otherwise \a idx is * the index of record to modify * \param[in] th current transaction handle * * \retval 0 on successful write && \a reccookie == NULL * 1 on successful write && \a reccookie != NULL * \retval negative error if write failed */ static int llog_osd_write_rec(const struct lu_env *env, struct llog_handle *loghandle, struct llog_rec_hdr *rec, struct llog_cookie *reccookie, int idx, struct thandle *th) { struct llog_thread_info *lgi = llog_info(env); struct llog_log_hdr *llh; int reclen = rec->lrh_len; int index, rc; struct llog_rec_tail *lrt; struct dt_object *o; size_t left; bool header_is_updated = false; ENTRY; LASSERT(env); llh = loghandle->lgh_hdr; LASSERT(llh); o = loghandle->lgh_obj; LASSERT(o); LASSERT(th); CDEBUG(D_OTHER, "new record %x to "DFID"\n", rec->lrh_type, PFID(lu_object_fid(&o->do_lu))); /* record length should not bigger than LLOG_CHUNK_SIZE */ if (reclen > LLOG_CHUNK_SIZE) RETURN(-E2BIG); rc = dt_attr_get(env, o, &lgi->lgi_attr, NULL); if (rc) RETURN(rc); /** * The modification case. * If idx set then the record with that index must be modified. * There are three cases possible: * 1) the common case is the llog header update (idx == 0) * 2) the llog record modification during llog process. * This is indicated by the \a loghandle::lgh_cur_idx > 0. * In that case the \a loghandle::lgh_cur_offset * 3) otherwise this is assumed that llog consist of records of * fixed size, i.e. catalog. The llog header must has llh_size * field equal to record size. The record offset is calculated * just by /a idx value * * During modification we don't need extra header update because * the bitmap and record count are not changed. The record header * and tail remains the same too. */ if (idx != LLOG_NEXT_IDX) { /* llog can be empty only when first record is being written */ LASSERT(ergo(idx > 0, lgi->lgi_attr.la_size > 0)); if (!ext2_test_bit(idx, llh->llh_bitmap)) { CERROR("%s: modify unset record %u\n", o->do_lu.lo_dev->ld_obd->obd_name, idx); RETURN(-ENOENT); } if (idx != rec->lrh_index) { CERROR("%s: modify index mismatch %d %u\n", o->do_lu.lo_dev->ld_obd->obd_name, idx, rec->lrh_index); RETURN(-EFAULT); } if (idx == LLOG_HEADER_IDX) { /* llog header update */ LASSERT(reclen == sizeof(struct llog_log_hdr)); LASSERT(rec == &llh->llh_hdr); lgi->lgi_off = 0; lgi->lgi_buf.lb_len = reclen; lgi->lgi_buf.lb_buf = rec; rc = dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th); RETURN(rc); } else if (loghandle->lgh_cur_idx > 0) { /** * The lgh_cur_offset can be used only if index is * the same. */ if (idx != loghandle->lgh_cur_idx) { CERROR("%s: modify index mismatch %d %d\n", o->do_lu.lo_dev->ld_obd->obd_name, idx, loghandle->lgh_cur_idx); RETURN(-EFAULT); } lgi->lgi_off = loghandle->lgh_cur_offset; CDEBUG(D_OTHER, "modify record "DOSTID": idx:%d, " "len:%u offset %llu\n", POSTID(&loghandle->lgh_id.lgl_oi), idx, rec->lrh_len, (long long)lgi->lgi_off); } else if (llh->llh_size > 0) { if (llh->llh_size != rec->lrh_len) { CERROR("%s: wrong record size, llh_size is %u" " but record size is %u\n", o->do_lu.lo_dev->ld_obd->obd_name, llh->llh_size, rec->lrh_len); RETURN(-EINVAL); } lgi->lgi_off = sizeof(*llh) + (idx - 1) * reclen; } else { /* This can be result of lgh_cur_idx is not set during * llog processing or llh_size is not set to proper * record size for fixed records llog. Therefore it is * impossible to get record offset. */ CERROR("%s: can't get record offset, idx:%d, " "len:%u.\n", o->do_lu.lo_dev->ld_obd->obd_name, idx, rec->lrh_len); RETURN(-EFAULT); } /* update only data, header and tail remain the same */ lgi->lgi_off += sizeof(struct llog_rec_hdr); lgi->lgi_buf.lb_len = REC_DATA_LEN(rec); lgi->lgi_buf.lb_buf = REC_DATA(rec); rc = dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th); if (rc == 0 && reccookie) { reccookie->lgc_lgl = loghandle->lgh_id; reccookie->lgc_index = idx; rc = 1; } RETURN(rc); } /** * The append case. * The most common case of using llog. The new index is assigned to * the new record, new bit is set in llog bitmap and llog count is * incremented. * * Make sure that records don't cross a chunk boundary, so we can * process them page-at-a-time if needed. If it will cross a chunk * boundary, write in a fake (but referenced) entry to pad the chunk. */ LASSERT(lgi->lgi_attr.la_valid & LA_SIZE); lgi->lgi_off = lgi->lgi_attr.la_size; left = LLOG_CHUNK_SIZE - (lgi->lgi_off & (LLOG_CHUNK_SIZE - 1)); /* NOTE: padding is a record, but no bit is set */ if (left != 0 && left != reclen && left < (reclen + LLOG_MIN_REC_SIZE)) { index = loghandle->lgh_last_idx + 1; rc = llog_osd_pad(env, o, &lgi->lgi_off, left, index, th); if (rc) RETURN(rc); loghandle->lgh_last_idx++; /* for pad rec */ } /* if it's the last idx in log file, then return -ENOSPC */ if (loghandle->lgh_last_idx >= LLOG_BITMAP_SIZE(llh) - 1) RETURN(-ENOSPC); /* increment the last_idx along with llh_tail index, they should * be equal for a llog lifetime */ loghandle->lgh_last_idx++; index = loghandle->lgh_last_idx; llh->llh_tail.lrt_index = index; /** * NB: the caller should make sure only 1 process access * the lgh_last_idx, e.g. append should be exclusive. * Otherwise it might hit the assert. */ LASSERT(index < LLOG_BITMAP_SIZE(llh)); rec->lrh_index = index; lrt = rec_tail(rec); lrt->lrt_len = rec->lrh_len; lrt->lrt_index = rec->lrh_index; /* the lgh_hdr_lock protects llog header data from concurrent * update/cancel, the llh_count and llh_bitmap are protected */ spin_lock(&loghandle->lgh_hdr_lock); if (ext2_set_bit(index, llh->llh_bitmap)) { CERROR("%s: index %u already set in log bitmap\n", o->do_lu.lo_dev->ld_obd->obd_name, index); spin_unlock(&loghandle->lgh_hdr_lock); LBUG(); /* should never happen */ } llh->llh_count++; spin_unlock(&loghandle->lgh_hdr_lock); lgi->lgi_off = 0; lgi->lgi_buf.lb_len = llh->llh_hdr.lrh_len; lgi->lgi_buf.lb_buf = &llh->llh_hdr; rc = dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th); if (rc) GOTO(out, rc); header_is_updated = true; rc = dt_attr_get(env, o, &lgi->lgi_attr, NULL); if (rc) GOTO(out, rc); LASSERT(lgi->lgi_attr.la_valid & LA_SIZE); lgi->lgi_off = lgi->lgi_attr.la_size; lgi->lgi_buf.lb_len = reclen; lgi->lgi_buf.lb_buf = rec; rc = dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th); if (rc < 0) GOTO(out, rc); CDEBUG(D_OTHER, "added record "DOSTID": idx: %u, %u\n", POSTID(&loghandle->lgh_id.lgl_oi), index, rec->lrh_len); if (reccookie != NULL) { reccookie->lgc_lgl = loghandle->lgh_id; reccookie->lgc_index = index; if ((rec->lrh_type == MDS_UNLINK_REC) || (rec->lrh_type == MDS_SETATTR64_REC)) reccookie->lgc_subsys = LLOG_MDS_OST_ORIG_CTXT; else if (rec->lrh_type == OST_SZ_REC) reccookie->lgc_subsys = LLOG_SIZE_ORIG_CTXT; else reccookie->lgc_subsys = -1; rc = 1; } RETURN(rc); out: /* cleanup llog for error case */ spin_lock(&loghandle->lgh_hdr_lock); ext2_clear_bit(index, llh->llh_bitmap); llh->llh_count--; spin_unlock(&loghandle->lgh_hdr_lock); /* restore llog last_idx */ loghandle->lgh_last_idx--; llh->llh_tail.lrt_index = loghandle->lgh_last_idx; /* restore the header on disk if it was written */ if (header_is_updated) { lgi->lgi_off = 0; lgi->lgi_buf.lb_len = llh->llh_hdr.lrh_len; lgi->lgi_buf.lb_buf = &llh->llh_hdr; dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th); } 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; }
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; }
/* Pack LOV object metadata for disk storage. It is packed in LE byte * order and is opaque to the networking layer. * * XXX In the future, this will be enhanced to get the EA size from the * underlying OSC device(s) to get their EA sizes so we can stack * LOVs properly. For now lov_mds_md_size() just assumes one obd_id * per stripe. */ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, struct lov_stripe_md *lsm) { struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; struct lov_mds_md_v1 *lmmv1; struct lov_mds_md_v3 *lmmv3; __u16 stripe_count; struct lov_ost_data_v1 *lmm_objects; int lmm_size, lmm_magic; int i; int cplen = 0; if (lsm) { lmm_magic = lsm->lsm_magic; } else { if (lmmp && *lmmp) lmm_magic = le32_to_cpu((*lmmp)->lmm_magic); else /* lsm == NULL and lmmp == NULL */ lmm_magic = LOV_MAGIC; } if ((lmm_magic != LOV_MAGIC_V1) && (lmm_magic != LOV_MAGIC_V3)) { CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", lmm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); return -EINVAL; } if (lsm) { /* If we are just sizing the EA, limit the stripe count * to the actual number of OSTs in this filesystem. */ if (!lmmp) { stripe_count = lov_get_stripecnt(lov, lmm_magic, lsm->lsm_stripe_count); lsm->lsm_stripe_count = stripe_count; } else if (!lsm_is_released(lsm)) { stripe_count = lsm->lsm_stripe_count; } else { stripe_count = 0; } } else { /* No need to allocate more than maximum supported stripes. * Anyway, this is pretty inaccurate since ld_tgt_count now * represents max index and we should rely on the actual number * of OSTs instead */ stripe_count = lov_mds_md_max_stripe_count( lov->lov_ocd.ocd_max_easize, lmm_magic); if (stripe_count > lov->desc.ld_tgt_count) stripe_count = lov->desc.ld_tgt_count; } /* XXX LOV STACKING call into osc for sizes */ lmm_size = lov_mds_md_size(stripe_count, lmm_magic); if (!lmmp) return lmm_size; if (*lmmp && !lsm) { stripe_count = le16_to_cpu((*lmmp)->lmm_stripe_count); lmm_size = lov_mds_md_size(stripe_count, lmm_magic); OBD_FREE_LARGE(*lmmp, lmm_size); *lmmp = NULL; return 0; } if (!*lmmp) { OBD_ALLOC_LARGE(*lmmp, lmm_size); if (!*lmmp) return -ENOMEM; } CDEBUG(D_INFO, "lov_packmd: LOV_MAGIC 0x%08X, lmm_size = %d \n", lmm_magic, lmm_size); lmmv1 = *lmmp; lmmv3 = (struct lov_mds_md_v3 *)*lmmp; if (lmm_magic == LOV_MAGIC_V3) lmmv3->lmm_magic = cpu_to_le32(LOV_MAGIC_V3); else lmmv1->lmm_magic = cpu_to_le32(LOV_MAGIC_V1); if (!lsm) return lmm_size; /* lmmv1 and lmmv3 point to the same struct and have the * same first fields */ lmm_oi_cpu_to_le(&lmmv1->lmm_oi, &lsm->lsm_oi); lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size); lmmv1->lmm_stripe_count = cpu_to_le16(stripe_count); lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern); lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen); if (lsm->lsm_magic == LOV_MAGIC_V3) { cplen = strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name, sizeof(lmmv3->lmm_pool_name)); if (cplen >= sizeof(lmmv3->lmm_pool_name)) return -E2BIG; lmm_objects = lmmv3->lmm_objects; } else { lmm_objects = lmmv1->lmm_objects; } for (i = 0; i < stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; /* XXX LOV STACKING call down to osc_packmd() to do packing */ LASSERTF(ostid_id(&loi->loi_oi) != 0, "lmm_oi "DOSTID " stripe %u/%u idx %u\n", POSTID(&lmmv1->lmm_oi), i, stripe_count, loi->loi_ost_idx); ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi); lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); } return lmm_size; }
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; }
/** Merge the lock value block(&lvb) attributes and KMS from each of the * stripes in a file into a single lvb. It is expected that the caller * initializes the current atime, mtime, ctime to avoid regressing a more * uptodate time on the local client. */ int lov_merge_lvb_kms(struct lov_stripe_md *lsm, struct ost_lvb *lvb, __u64 *kms_place) { __u64 size = 0; __u64 kms = 0; __u64 blocks = 0; s64 current_mtime = lvb->lvb_mtime; s64 current_atime = lvb->lvb_atime; s64 current_ctime = lvb->lvb_ctime; int i; int rc = 0; assert_spin_locked(&lsm->lsm_lock); LASSERT(lsm->lsm_lock_owner == current_pid()); CDEBUG(D_INODE, "MDT ID "DOSTID" initial value: s=%llu m=%llu a=%llu c=%llu b=%llu\n", POSTID(&lsm->lsm_oi), lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks); for (i = 0; i < lsm->lsm_stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; u64 lov_size, tmpsize; if (OST_LVB_IS_ERR(loi->loi_lvb.lvb_blocks)) { rc = OST_LVB_GET_ERR(loi->loi_lvb.lvb_blocks); continue; } tmpsize = loi->loi_kms; lov_size = lov_stripe_size(lsm, tmpsize, i); if (lov_size > kms) kms = lov_size; if (loi->loi_lvb.lvb_size > tmpsize) tmpsize = loi->loi_lvb.lvb_size; lov_size = lov_stripe_size(lsm, tmpsize, i); if (lov_size > size) size = lov_size; /* merge blocks, mtime, atime */ blocks += loi->loi_lvb.lvb_blocks; if (loi->loi_lvb.lvb_mtime > current_mtime) current_mtime = loi->loi_lvb.lvb_mtime; if (loi->loi_lvb.lvb_atime > current_atime) current_atime = loi->loi_lvb.lvb_atime; if (loi->loi_lvb.lvb_ctime > current_ctime) current_ctime = loi->loi_lvb.lvb_ctime; CDEBUG(D_INODE, "MDT ID "DOSTID" on OST[%u]: s=%llu m=%llu a=%llu c=%llu b=%llu\n", POSTID(&lsm->lsm_oi), loi->loi_ost_idx, loi->loi_lvb.lvb_size, loi->loi_lvb.lvb_mtime, loi->loi_lvb.lvb_atime, loi->loi_lvb.lvb_ctime, loi->loi_lvb.lvb_blocks); } *kms_place = kms; lvb->lvb_size = size; lvb->lvb_blocks = blocks; lvb->lvb_mtime = current_mtime; lvb->lvb_atime = current_atime; lvb->lvb_ctime = current_ctime; return rc; }
/** * Prepare bulk IO requests for processing. * * This function does initial checks of IO and calls corresponding * functions for read/write processing. * * \param[in] env execution environment * \param[in] cmd IO type (read/write) * \param[in] exp OBD export of client * \param[in] oa OBDO structure from request * \param[in] objcount always 1 * \param[in] obj object data * \param[in] rnb remote buffers * \param[in] nr_local number of local buffers * \param[in] lnb local buffers * * \retval 0 on successful prepare * \retval negative value on error */ int ofd_preprw(const struct lu_env *env, int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *rnb, int *nr_local, struct niobuf_local *lnb) { struct tgt_session_info *tsi = tgt_ses_info(env); struct ofd_device *ofd = ofd_exp(exp); struct ofd_thread_info *info; char *jobid; const struct lu_fid *fid = &oa->o_oi.oi_fid; int rc = 0; if (*nr_local > PTLRPC_MAX_BRW_PAGES) { CERROR("%s: bulk has too many pages %d, which exceeds the" "maximum pages per RPC of %d\n", exp->exp_obd->obd_name, *nr_local, PTLRPC_MAX_BRW_PAGES); RETURN(-EPROTO); } if (tgt_ses_req(tsi) == NULL) { /* echo client case */ info = ofd_info_init(env, exp); jobid = NULL; } else { info = tsi2ofd_info(tsi); jobid = tsi->tsi_jobid; } LASSERT(oa != NULL); if (OBD_FAIL_CHECK(OBD_FAIL_SRV_ENOENT)) { struct ofd_seq *oseq; oseq = ofd_seq_load(env, ofd, ostid_seq(&oa->o_oi)); if (IS_ERR(oseq)) { CERROR("%s: Can not find seq for "DOSTID ": rc = %ld\n", ofd_name(ofd), POSTID(&oa->o_oi), PTR_ERR(oseq)); RETURN(-EINVAL); } if (oseq->os_destroys_in_progress == 0) { /* don't fail lookups for orphan recovery, it causes * later LBUGs when objects still exist during * precreate */ ofd_seq_put(env, oseq); RETURN(-ENOENT); } ofd_seq_put(env, oseq); } LASSERT(objcount == 1); LASSERT(obj->ioo_bufcnt > 0); if (cmd == OBD_BRW_WRITE) { la_from_obdo(&info->fti_attr, oa, OBD_MD_FLGETATTR); rc = ofd_preprw_write(env, exp, ofd, fid, &info->fti_attr, oa, objcount, obj, rnb, nr_local, lnb, jobid); } else if (cmd == OBD_BRW_READ) { ofd_grant_prepare_read(env, exp, oa); rc = ofd_preprw_read(env, exp, ofd, fid, &info->fti_attr, oa, obj->ioo_bufcnt, rnb, nr_local, lnb, jobid); obdo_from_la(oa, &info->fti_attr, LA_ATIME); } else { CERROR("%s: wrong cmd %d received!\n", exp->exp_obd->obd_name, cmd); rc = -EPROTO; } RETURN(rc); }
/** * Prepare buffers for write request processing. * * This function converts remote buffers from client to local buffers * and prepares the latter. If there is recovery in progress and required * object is missing then it can be re-created before write. * * \param[in] env execution environment * \param[in] exp OBD export of client * \param[in] ofd OFD device * \param[in] fid FID of object * \param[in] la object attributes * \param[in] oa OBDO structure from client * \param[in] objcount always 1 * \param[in] obj object data * \param[in] rnb remote buffers * \param[in] nr_local number of local buffers * \param[in] lnb local buffers * \param[in] jobid job ID name * * \retval 0 on successful prepare * \retval negative value on error */ static int ofd_preprw_write(const struct lu_env *env, struct obd_export *exp, struct ofd_device *ofd, const struct lu_fid *fid, struct lu_attr *la, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *rnb, int *nr_local, struct niobuf_local *lnb, char *jobid) { struct ofd_object *fo; int i, j, k, rc = 0, tot_bytes = 0; ENTRY; LASSERT(env != NULL); LASSERT(objcount == 1); if (unlikely(exp->exp_obd->obd_recovering)) { u64 seq = fid_seq(fid); u64 oid = fid_oid(fid); struct ofd_seq *oseq; oseq = ofd_seq_load(env, ofd, seq); if (IS_ERR(oseq)) { CERROR("%s: Can't find FID Sequence "LPX64": rc = %d\n", ofd_name(ofd), seq, (int)PTR_ERR(oseq)); GOTO(out, rc = -EINVAL); } if (oid > ofd_seq_last_oid(oseq)) { int sync = 0; int diff; mutex_lock(&oseq->os_create_lock); diff = oid - ofd_seq_last_oid(oseq); /* Do sync create if the seq is about to used up */ if (fid_seq_is_idif(seq) || fid_seq_is_mdt0(seq)) { if (unlikely(oid >= IDIF_MAX_OID - 1)) sync = 1; } else if (fid_seq_is_norm(seq)) { if (unlikely(oid >= LUSTRE_DATA_SEQ_MAX_WIDTH - 1)) sync = 1; } else { CERROR("%s : invalid o_seq "DOSTID"\n", ofd_name(ofd), POSTID(&oa->o_oi)); mutex_unlock(&oseq->os_create_lock); ofd_seq_put(env, oseq); GOTO(out, rc = -EINVAL); } while (diff > 0) { u64 next_id = ofd_seq_last_oid(oseq) + 1; int count = ofd_precreate_batch(ofd, diff); rc = ofd_precreate_objects(env, ofd, next_id, oseq, count, sync); if (rc < 0) { mutex_unlock(&oseq->os_create_lock); ofd_seq_put(env, oseq); GOTO(out, rc); } diff -= rc; } mutex_unlock(&oseq->os_create_lock); } ofd_seq_put(env, oseq); } fo = ofd_object_find(env, ofd, fid); if (IS_ERR(fo)) GOTO(out, rc = PTR_ERR(fo)); LASSERT(fo != NULL); ofd_read_lock(env, fo); if (!ofd_object_exists(fo)) { CERROR("%s: BRW to missing obj "DOSTID"\n", exp->exp_obd->obd_name, POSTID(&obj->ioo_oid)); ofd_read_unlock(env, fo); ofd_object_put(env, fo); GOTO(out, rc = -ENOENT); } if (ofd->ofd_lfsck_verify_pfid && oa->o_valid & OBD_MD_FLFID) { rc = ofd_verify_ff(env, fo, oa); if (rc != 0) { ofd_read_unlock(env, fo); ofd_object_put(env, fo); GOTO(out, rc); } } /* Process incoming grant info, set OBD_BRW_GRANTED flag and grant some * space back if possible */ ofd_grant_prepare_write(env, exp, oa, rnb, obj->ioo_bufcnt); /* parse remote buffers to local buffers and prepare the latter */ *nr_local = 0; for (i = 0, j = 0; i < obj->ioo_bufcnt; i++) { rc = dt_bufs_get(env, ofd_object_child(fo), rnb + i, lnb + j, 1); if (unlikely(rc < 0)) GOTO(err, rc); LASSERT(rc <= PTLRPC_MAX_BRW_PAGES); /* correct index for local buffers to continue with */ for (k = 0; k < rc; k++) { lnb[j+k].lnb_flags = rnb[i].rnb_flags; if (!(rnb[i].rnb_flags & OBD_BRW_GRANTED)) lnb[j+k].lnb_rc = -ENOSPC; } j += rc; *nr_local += rc; LASSERT(j <= PTLRPC_MAX_BRW_PAGES); tot_bytes += rnb[i].rnb_len; } LASSERT(*nr_local > 0 && *nr_local <= PTLRPC_MAX_BRW_PAGES); rc = dt_write_prep(env, ofd_object_child(fo), lnb, *nr_local); if (unlikely(rc != 0)) GOTO(err, rc); ofd_counter_incr(exp, LPROC_OFD_STATS_WRITE, jobid, tot_bytes); RETURN(0); err: dt_bufs_put(env, ofd_object_child(fo), lnb, *nr_local); ofd_read_unlock(env, fo); ofd_object_put(env, fo); /* ofd_grant_prepare_write() was called, so we must commit */ ofd_grant_commit(exp, oa->o_grant_used, rc); out: /* let's still process incoming grant information packed in the oa, * but without enforcing grant since we won't proceed with the write. * Just like a read request actually. */ ofd_grant_prepare_read(env, exp, oa); return rc; }
static int lov_init_sub(const struct lu_env *env, struct lov_object *lov, struct cl_object *stripe, struct lov_layout_raid0 *r0, int idx) { struct cl_object_header *hdr; struct cl_object_header *subhdr; struct cl_object_header *parent; struct lov_oinfo *oinfo; int result; if (OBD_FAIL_CHECK(OBD_FAIL_LOV_INIT)) { /* For sanity:test_206. * Do not leave the object in cache to avoid accessing * freed memory. This is because osc_object is referring to * lov_oinfo of lsm_stripe_data which will be freed due to * this failure. */ cl_object_kill(env, stripe); cl_object_put(env, stripe); return -EIO; } hdr = cl_object_header(lov2cl(lov)); subhdr = cl_object_header(stripe); oinfo = lov->lo_lsm->lsm_oinfo[idx]; CDEBUG(D_INODE, DFID"@%p[%d] -> "DFID"@%p: ostid: "DOSTID " idx: %d gen: %d\n", PFID(&subhdr->coh_lu.loh_fid), subhdr, idx, PFID(&hdr->coh_lu.loh_fid), hdr, POSTID(&oinfo->loi_oi), oinfo->loi_ost_idx, oinfo->loi_ost_gen); /* reuse ->coh_attr_guard to protect coh_parent change */ spin_lock(&subhdr->coh_attr_guard); parent = subhdr->coh_parent; if (parent == NULL) { subhdr->coh_parent = hdr; spin_unlock(&subhdr->coh_attr_guard); subhdr->coh_nesting = hdr->coh_nesting + 1; lu_object_ref_add(&stripe->co_lu, "lov-parent", lov); r0->lo_sub[idx] = cl2lovsub(stripe); r0->lo_sub[idx]->lso_super = lov; r0->lo_sub[idx]->lso_index = idx; result = 0; } else { struct lu_object *old_obj; struct lov_object *old_lov; unsigned int mask = D_INODE; spin_unlock(&subhdr->coh_attr_guard); old_obj = lu_object_locate(&parent->coh_lu, &lov_device_type); LASSERT(old_obj != NULL); old_lov = cl2lov(lu2cl(old_obj)); if (old_lov->lo_layout_invalid) { /* the object's layout has already changed but isn't * refreshed */ lu_object_unhash(env, &stripe->co_lu); result = -EAGAIN; } else { mask = D_ERROR; result = -EIO; } LU_OBJECT_DEBUG(mask, env, &stripe->co_lu, "stripe %d is already owned.\n", idx); LU_OBJECT_DEBUG(mask, env, old_obj, "owned.\n"); LU_OBJECT_HEADER(mask, env, lov2lu(lov), "try to own.\n"); cl_object_put(env, stripe); } return result; }
static void print_logid(struct llog_logid_rec *lid) { printf("ogen=%X name="DOSTID"\n", lid->lid_id.lgl_ogen, POSTID(&lid->lid_id.lgl_oi)); }