/* * Concurrency: no concurrent access is possible that early in object * life-cycle. */ static int osd_object_init(const struct lu_env *env, struct lu_object *l, const struct lu_object_conf *conf) { struct osd_object *obj = osd_obj(l); struct osd_device *osd = osd_obj2dev(obj); uint64_t oid; int rc; ENTRY; LASSERT(osd_invariant(obj)); if (fid_is_otable_it(&l->lo_header->loh_fid)) { obj->oo_dt.do_ops = &osd_obj_otable_it_ops; l->lo_header->loh_attr |= LOHA_EXISTS; RETURN(0); } rc = osd_fid_lookup(env, osd, lu_object_fid(l), &oid); if (rc == 0) { LASSERT(obj->oo_db == NULL); rc = __osd_obj2dbuf(env, osd->od_objset.os, oid, &obj->oo_db, osd_obj_tag); if (rc == 0) { LASSERT(obj->oo_db); rc = osd_object_init0(env, obj); } else { CERROR("%s: lookup "DFID"/"LPX64" failed: rc = %d\n", osd->od_svname, PFID(lu_object_fid(l)), oid, rc); } } else if (rc == -ENOENT) { rc = 0; } LASSERT(osd_invariant(obj)); RETURN(rc); }
/* * Concurrency: no concurrent access is possible that early in object * life-cycle. */ static int osd_object_init(const struct lu_env *env, struct lu_object *l, const struct lu_object_conf *conf) { struct osd_object *obj = osd_obj(l); struct osd_device *osd = osd_obj2dev(obj); uint64_t oid; int rc; ENTRY; LASSERT(osd_invariant(obj)); if (fid_is_otable_it(&l->lo_header->loh_fid)) { obj->oo_dt.do_ops = &osd_obj_otable_it_ops; l->lo_header->loh_attr |= LOHA_EXISTS; RETURN(0); } if (conf != NULL && conf->loc_flags & LOC_F_NEW) GOTO(out, rc = 0); rc = osd_fid_lookup(env, osd, lu_object_fid(l), &oid); if (rc == 0) { LASSERT(obj->oo_db == NULL); rc = __osd_obj2dbuf(env, osd->od_os, oid, &obj->oo_db); /* EEXIST will be returned if object is being deleted in ZFS */ if (rc == -EEXIST) { rc = 0; GOTO(out, rc); } if (rc != 0) { CERROR("%s: lookup "DFID"/%#llx failed: rc = %d\n", osd->od_svname, PFID(lu_object_fid(l)), oid, rc); GOTO(out, rc); } LASSERT(obj->oo_db); rc = osd_object_init0(env, obj); if (rc != 0) GOTO(out, rc); rc = osd_check_lma(env, obj); if (rc != 0) GOTO(out, rc); } else if (rc == -ENOENT) { rc = 0; } LASSERT(osd_invariant(obj)); out: RETURN(rc); }
static int osd_scrub_check_update(const struct lu_env *env, struct osd_device *dev, const struct lu_fid *fid, uint64_t oid, int val) { struct lustre_scrub *scrub = &dev->od_scrub; struct scrub_file *sf = &scrub->os_file; struct osd_inconsistent_item *oii = NULL; nvlist_t *nvbuf = NULL; dnode_t *dn = NULL; uint64_t oid2; int ops = DTO_INDEX_UPDATE; int rc; ENTRY; down_write(&scrub->os_rwsem); scrub->os_new_checked++; if (val < 0) GOTO(out, rc = val); if (scrub->os_in_prior) oii = list_entry(scrub->os_inconsistent_items.next, struct osd_inconsistent_item, oii_list); if (oid < sf->sf_pos_latest_start && !oii) GOTO(out, rc = 0); if (oii && oii->oii_insert) { ops = DTO_INDEX_INSERT; goto zget; } rc = osd_fid_lookup(env, dev, fid, &oid2); if (rc) { if (rc != -ENOENT) GOTO(out, rc); ops = DTO_INDEX_INSERT; zget: rc = __osd_obj2dnode(dev->od_os, oid, &dn); if (rc) { /* Someone removed the object by race. */ if (rc == -ENOENT || rc == -EEXIST) rc = 0; GOTO(out, rc); } scrub->os_full_speed = 1; sf->sf_flags |= SF_INCONSISTENT; } else if (oid == oid2) { GOTO(out, rc = 0); } else { struct lustre_mdt_attrs *lma = NULL; int size; rc = __osd_xattr_load_by_oid(dev, oid2, &nvbuf); if (rc == -ENOENT || rc == -EEXIST || rc == -ENODATA) goto update; if (rc) GOTO(out, rc); rc = -nvlist_lookup_byte_array(nvbuf, XATTR_NAME_LMA, (uchar_t **)&lma, &size); if (rc == -ENOENT || rc == -EEXIST || rc == -ENODATA) goto update; if (rc) GOTO(out, rc); lustre_lma_swab(lma); if (unlikely(lu_fid_eq(&lma->lma_self_fid, fid))) { CDEBUG(D_LFSCK, "%s: the FID "DFID" is used by " "two objects: %llu and %llu (in OI)\n", osd_name(dev), PFID(fid), oid, oid2); GOTO(out, rc = -EEXIST); } update: scrub->os_full_speed = 1; sf->sf_flags |= SF_INCONSISTENT; } rc = osd_scrub_refresh_mapping(env, dev, fid, oid, ops, false, NULL); if (!rc) { if (scrub->os_in_prior) sf->sf_items_updated_prior++; else sf->sf_items_updated++; } GOTO(out, rc); out: if (nvbuf) nvlist_free(nvbuf); if (rc < 0) { sf->sf_items_failed++; if (sf->sf_pos_first_inconsistent == 0 || sf->sf_pos_first_inconsistent > oid) sf->sf_pos_first_inconsistent = oid; } else { rc = 0; } /* There may be conflict unlink during the OI scrub, * if happend, then remove the new added OI mapping. */ if (ops == DTO_INDEX_INSERT && dn && dn->dn_free_txg) osd_scrub_refresh_mapping(env, dev, fid, oid, DTO_INDEX_DELETE, false, NULL); up_write(&scrub->os_rwsem); if (dn) osd_dnode_rele(dn); if (oii) { spin_lock(&scrub->os_lock); if (likely(!list_empty(&oii->oii_list))) list_del(&oii->oii_list); spin_unlock(&scrub->os_lock); OBD_FREE_PTR(oii); } RETURN(sf->sf_param & SP_FAILOUT ? rc : 0); }