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 lov_read_and_clear_async_rc(struct cl_object *clob) { struct lu_object *luobj; int rc = 0; luobj = lu_object_locate(&cl_object_header(clob)->coh_lu, &lov_device_type); if (luobj != NULL) { struct lov_object *lov = lu2lov(luobj); lov_conf_freeze(lov); switch (lov->lo_type) { case LLT_RAID0: { struct lov_stripe_md *lsm; int i; lsm = lov->lo_lsm; LASSERT(lsm != NULL); for (i = 0; i < lsm->lsm_stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; if (loi->loi_ar.ar_rc && !rc) rc = loi->loi_ar.ar_rc; loi->loi_ar.ar_rc = 0; } } case LLT_RELEASED: case LLT_EMPTY: break; default: LBUG(); } lov_conf_thaw(lov); } return rc; }
static int lov_layout_change(const struct lu_env *unused, struct lov_object *lov, const struct cl_object_conf *conf) { int result; enum lov_layout_type llt = LLT_EMPTY; union lov_layout_state *state = &lov->u; const struct lov_layout_operations *old_ops; const struct lov_layout_operations *new_ops; struct cl_object_header *hdr = cl_object_header(&lov->lo_cl); void *cookie; struct lu_env *env; int refcheck; ENTRY; LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch)); if (conf->u.coc_md != NULL) llt = lov_type(conf->u.coc_md->lsm); LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch)); cookie = cl_env_reenter(); env = cl_env_get(&refcheck); if (IS_ERR(env)) { cl_env_reexit(cookie); RETURN(PTR_ERR(env)); } old_ops = &lov_dispatch[lov->lo_type]; new_ops = &lov_dispatch[llt]; result = old_ops->llo_delete(env, lov, &lov->u); if (result == 0) { old_ops->llo_fini(env, lov, &lov->u); LASSERT(cfs_atomic_read(&lov->lo_active_ios) == 0); LASSERT(hdr->coh_tree.rnode == NULL); LASSERT(hdr->coh_pages == 0); lov->lo_type = LLT_EMPTY; result = new_ops->llo_init(env, lu2lov_dev(lov->lo_cl.co_lu.lo_dev), lov, conf, state); if (result == 0) { new_ops->llo_install(env, lov, state); lov->lo_type = llt; } else { new_ops->llo_delete(env, lov, state); new_ops->llo_fini(env, lov, state); /* this file becomes an EMPTY file. */ } } cl_env_put(env, &refcheck); cl_env_reexit(cookie); RETURN(result); }
struct lov_stripe_md *lov_lsm_get(struct cl_object *clobj) { struct lu_object *luobj; struct lov_stripe_md *lsm = NULL; if (clobj == NULL) return NULL; luobj = lu_object_locate(&cl_object_header(clobj)->coh_lu, &lov_device_type); if (luobj != NULL) lsm = lov_lsm_addref(lu2lov(luobj)); return lsm; }
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 int lov_init_raid0(const struct lu_env *env, struct lov_device *dev, struct lov_object *lov, const struct cl_object_conf *conf, union lov_layout_state *state) { int result; int i; struct cl_object *stripe; struct lov_thread_info *lti = lov_env_info(env); struct cl_object_conf *subconf = <i->lti_stripe_conf; struct lov_stripe_md *lsm = conf->u.coc_md->lsm; struct lu_fid *ofid = <i->lti_fid; struct lov_layout_raid0 *r0 = &state->raid0; if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) { dump_lsm(D_ERROR, lsm); LASSERTF(0, "magic mismatch, expected %d/%d, actual %d.\n", LOV_MAGIC_V1, LOV_MAGIC_V3, lsm->lsm_magic); } LASSERT(!lov->lo_lsm); lov->lo_lsm = lsm_addref(lsm); r0->lo_nr = lsm->lsm_stripe_count; LASSERT(r0->lo_nr <= lov_targets_nr(dev)); r0->lo_sub = libcfs_kvzalloc(r0->lo_nr * sizeof(r0->lo_sub[0]), GFP_NOFS); if (r0->lo_sub) { int psz = 0; result = 0; subconf->coc_inode = conf->coc_inode; spin_lock_init(&r0->lo_sub_lock); /* * Create stripe cl_objects. */ for (i = 0; i < r0->lo_nr && result == 0; ++i) { struct cl_device *subdev; struct lov_oinfo *oinfo = lsm->lsm_oinfo[i]; int ost_idx = oinfo->loi_ost_idx; if (lov_oinfo_is_dummy(oinfo)) continue; result = ostid_to_fid(ofid, &oinfo->loi_oi, oinfo->loi_ost_idx); if (result != 0) goto out; subdev = lovsub2cl_dev(dev->ld_target[ost_idx]); subconf->u.coc_oinfo = oinfo; LASSERTF(subdev, "not init ost %d\n", ost_idx); /* In the function below, .hs_keycmp resolves to * lu_obj_hop_keycmp() */ /* coverity[overrun-buffer-val] */ stripe = lov_sub_find(env, subdev, ofid, subconf); if (!IS_ERR(stripe)) { result = lov_init_sub(env, lov, stripe, r0, i); if (result == -EAGAIN) { /* try again */ --i; result = 0; continue; } } else { result = PTR_ERR(stripe); } if (result == 0) { int sz = lov_page_slice_fixup(lov, stripe); LASSERT(ergo(psz > 0, psz == sz)); psz = sz; } } if (result == 0) cl_object_header(&lov->lo_cl)->coh_page_bufsize += psz; } else { result = -ENOMEM; } out: return result; }
/** * Implementation of struct cl_req_operations::cro_attr_set() for osc * layer. osc is responsible for struct obdo::o_id and struct obdo::o_seq * fields. */ static void osc_req_attr_set(const struct lu_env *env, const struct cl_req_slice *slice, const struct cl_object *obj, struct cl_req_attr *attr, u64 flags) { struct lov_oinfo *oinfo; struct cl_req *clerq; struct cl_page *apage; /* _some_ page in @clerq */ struct cl_lock *lock; /* _some_ lock protecting @apage */ struct osc_lock *olck; struct osc_page *opg; struct obdo *oa; struct ost_lvb *lvb; oinfo = cl2osc(obj)->oo_oinfo; lvb = &oinfo->loi_lvb; oa = attr->cra_oa; if ((flags & OBD_MD_FLMTIME) != 0) { oa->o_mtime = lvb->lvb_mtime; oa->o_valid |= OBD_MD_FLMTIME; } if ((flags & OBD_MD_FLATIME) != 0) { oa->o_atime = lvb->lvb_atime; oa->o_valid |= OBD_MD_FLATIME; } if ((flags & OBD_MD_FLCTIME) != 0) { oa->o_ctime = lvb->lvb_ctime; oa->o_valid |= OBD_MD_FLCTIME; } if (flags & OBD_MD_FLGROUP) { ostid_set_seq(&oa->o_oi, ostid_seq(&oinfo->loi_oi)); oa->o_valid |= OBD_MD_FLGROUP; } if (flags & OBD_MD_FLID) { ostid_set_id(&oa->o_oi, ostid_id(&oinfo->loi_oi)); oa->o_valid |= OBD_MD_FLID; } if (flags & OBD_MD_FLHANDLE) { clerq = slice->crs_req; LASSERT(!list_empty(&clerq->crq_pages)); apage = container_of(clerq->crq_pages.next, struct cl_page, cp_flight); opg = osc_cl_page_osc(apage); apage = opg->ops_cl.cpl_page; /* now apage is a sub-page */ lock = cl_lock_at_page(env, apage->cp_obj, apage, NULL, 1, 1); if (lock == NULL) { struct cl_object_header *head; struct cl_lock *scan; head = cl_object_header(apage->cp_obj); list_for_each_entry(scan, &head->coh_locks, cll_linkage) CL_LOCK_DEBUG(D_ERROR, env, scan, "no cover page!\n"); CL_PAGE_DEBUG(D_ERROR, env, apage, "dump uncover page!\n"); dump_stack(); LBUG(); } olck = osc_lock_at(lock); LASSERT(olck != NULL); LASSERT(ergo(opg->ops_srvlock, olck->ols_lock == NULL)); /* check for lockless io. */ if (olck->ols_lock != NULL) { oa->o_handle = olck->ols_lock->l_remote_handle; oa->o_valid |= OBD_MD_FLHANDLE; } cl_lock_put(env, lock); }
static int lov_layout_change(const struct lu_env *unused, struct lov_object *lov, struct lov_stripe_md *lsm, const struct cl_object_conf *conf) { enum lov_layout_type llt = lov_type(lsm); union lov_layout_state *state = &lov->u; const struct lov_layout_operations *old_ops; const struct lov_layout_operations *new_ops; void *cookie; struct lu_env *env; __u16 refcheck; int rc; ENTRY; LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch)); cookie = cl_env_reenter(); env = cl_env_get(&refcheck); if (IS_ERR(env)) { cl_env_reexit(cookie); RETURN(PTR_ERR(env)); } LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch)); CDEBUG(D_INODE, DFID" from %s to %s\n", PFID(lu_object_fid(lov2lu(lov))), llt2str(lov->lo_type), llt2str(llt)); old_ops = &lov_dispatch[lov->lo_type]; new_ops = &lov_dispatch[llt]; rc = cl_object_prune(env, &lov->lo_cl); if (rc != 0) GOTO(out, rc); rc = old_ops->llo_delete(env, lov, &lov->u); if (rc != 0) GOTO(out, rc); old_ops->llo_fini(env, lov, &lov->u); LASSERT(atomic_read(&lov->lo_active_ios) == 0); lov->lo_type = LLT_EMPTY; /* page bufsize fixup */ cl_object_header(&lov->lo_cl)->coh_page_bufsize -= lov_page_slice_fixup(lov, NULL); rc = new_ops->llo_init(env, lov_object_dev(lov), lov, lsm, conf, state); if (rc != 0) { new_ops->llo_delete(env, lov, state); new_ops->llo_fini(env, lov, state); /* this file becomes an EMPTY file. */ GOTO(out, rc); } new_ops->llo_install(env, lov, state); lov->lo_type = llt; out: cl_env_put(env, &refcheck); cl_env_reexit(cookie); RETURN(rc); }
static int lov_layout_change(const struct lu_env *unused, struct lov_object *lov, const struct cl_object_conf *conf) { int result; enum lov_layout_type llt = LLT_EMPTY; union lov_layout_state *state = &lov->u; const struct lov_layout_operations *old_ops; const struct lov_layout_operations *new_ops; void *cookie; struct lu_env *env; int refcheck; LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch)); if (conf->u.coc_md) llt = lov_type(conf->u.coc_md->lsm); LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch)); cookie = cl_env_reenter(); env = cl_env_get(&refcheck); if (IS_ERR(env)) { cl_env_reexit(cookie); return PTR_ERR(env); } CDEBUG(D_INODE, DFID" from %s to %s\n", PFID(lu_object_fid(lov2lu(lov))), llt2str(lov->lo_type), llt2str(llt)); old_ops = &lov_dispatch[lov->lo_type]; new_ops = &lov_dispatch[llt]; result = cl_object_prune(env, &lov->lo_cl); if (result != 0) goto out; result = old_ops->llo_delete(env, lov, &lov->u); if (result == 0) { old_ops->llo_fini(env, lov, &lov->u); LASSERT(atomic_read(&lov->lo_active_ios) == 0); lov->lo_type = LLT_EMPTY; /* page bufsize fixup */ cl_object_header(&lov->lo_cl)->coh_page_bufsize -= lov_page_slice_fixup(lov, NULL); result = new_ops->llo_init(env, lu2lov_dev(lov->lo_cl.co_lu.lo_dev), lov, conf, state); if (result == 0) { new_ops->llo_install(env, lov, state); lov->lo_type = llt; } else { new_ops->llo_delete(env, lov, state); new_ops->llo_fini(env, lov, state); /* this file becomes an EMPTY file. */ } } out: cl_env_put(env, &refcheck); cl_env_reexit(cookie); return result; }