static ssize_t ldiskfs_osd_index_in_idif_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct lu_env env; struct seq_file *m = file->private_data; struct dt_device *dt = m->private; struct osd_device *dev = osd_dt_dev(dt); struct lu_target *tgt; __s64 val; int rc; LASSERT(dev != NULL); if (unlikely(dev->od_mnt == NULL)) return -EINPROGRESS; rc = lprocfs_str_to_s64(buffer, count, &val); if (rc != 0) return rc; if (dev->od_index_in_idif) { if (val != 0) return count; LCONSOLE_WARN("%s: OST-index in IDIF has been enabled, " "it cannot be reverted back.\n", osd_name(dev)); return -EPERM; } if (val == 0) return count; rc = lu_env_init(&env, LCT_DT_THREAD); if (rc != 0) return rc; tgt = dev->od_dt_dev.dd_lu_dev.ld_site->ls_tgt; tgt->lut_lsd.lsd_feature_rocompat |= OBD_ROCOMPAT_IDX_IN_IDIF; rc = tgt_server_data_update(&env, tgt, 1); lu_env_fini(&env); if (rc < 0) return rc; LCONSOLE_INFO("%s: enable OST-index in IDIF successfully, " "it cannot be reverted back.\n", osd_name(dev)); dev->od_index_in_idif = 1; return count; }
int fid_is_on_ost(struct osd_thread_info *info, struct osd_device *osd, const struct lu_fid *fid, enum oi_check_flags flags) { struct lu_seq_range *range = &info->oti_seq_range; int rc; ENTRY; if (flags & OI_KNOWN_ON_OST) RETURN(1); if (unlikely(fid_is_local_file(fid) || fid_is_igif(fid) || fid_is_llog(fid)) || fid_is_name_llog(fid) || fid_is_quota(fid)) RETURN(0); if (fid_is_idif(fid) || fid_is_last_id(fid)) RETURN(1); if (!(flags & OI_CHECK_FLD)) RETURN(0); rc = osd_fld_lookup(info->oti_env, osd, fid_seq(fid), range); if (rc != 0) { if (rc != -ENOENT) CERROR("%s: lookup FLD "DFID": rc = %d\n", osd_name(osd), PFID(fid), rc); RETURN(0); } if (fld_range_is_ost(range)) RETURN(1); RETURN(0); }
static int osd_seq_exists(const struct lu_env *env, struct osd_device *osd, obd_seq seq) { struct lu_seq_range *range = &osd_oti_get(env)->oti_seq_range; struct seq_server_site *ss = osd_seq_site(osd); int rc; ENTRY; if (ss == NULL) RETURN(1); rc = osd_fld_lookup(env, osd, seq, range); if (rc != 0) { CERROR("%s: Can not lookup fld for "LPX64"\n", osd_name(osd), seq); RETURN(0); } RETURN(ss->ss_node_id == range->lsr_index); }
/** * update/insert/delete the specified OI mapping (@fid @id) according to the ops * * \retval 1, changed nothing * \retval 0, changed successfully * \retval -ve, on error */ static int osd_scrub_refresh_mapping(const struct lu_env *env, struct osd_device *dev, const struct lu_fid *fid, uint64_t oid, int ops, bool force, const char *name) { struct osd_thread_info *info = osd_oti_get(env); struct zpl_direntry *zde = &info->oti_zde.lzd_reg; char *buf = info->oti_str; dmu_tx_t *tx = NULL; dnode_t *dn = NULL; uint64_t zapid; int rc; ENTRY; if (dev->od_scrub.os_file.sf_param & SP_DRYRUN && !force) GOTO(log, rc = 0); tx = dmu_tx_create(dev->od_os); if (!tx) GOTO(log, rc = -ENOMEM); zapid = osd_get_name_n_idx(env, dev, fid, buf, sizeof(info->oti_str), &dn); osd_tx_hold_zap(tx, zapid, dn, ops == DTO_INDEX_INSERT ? TRUE : FALSE, NULL); rc = -dmu_tx_assign(tx, TXG_WAIT); if (rc) { dmu_tx_abort(tx); GOTO(log, rc); } switch (ops) { case DTO_INDEX_UPDATE: zde->zde_pad = 0; zde->zde_dnode = oid; zde->zde_type = 0; /* The type in OI mapping is useless. */ rc = -zap_update(dev->od_os, zapid, buf, 8, sizeof(*zde) / 8, zde, tx); if (unlikely(rc == -ENOENT)) { /* Some unlink thread may removed the OI mapping. */ rc = 1; } break; case DTO_INDEX_INSERT: zde->zde_pad = 0; zde->zde_dnode = oid; zde->zde_type = 0; /* The type in OI mapping is useless. */ rc = osd_zap_add(dev, zapid, dn, buf, 8, sizeof(*zde) / 8, zde, tx); if (unlikely(rc == -EEXIST)) rc = 1; break; case DTO_INDEX_DELETE: rc = osd_zap_remove(dev, zapid, dn, buf, tx); if (rc == -ENOENT) { /* It is normal that the unlink thread has removed the * OI mapping already. */ rc = 1; } break; default: LASSERTF(0, "Unexpected ops %d\n", ops); rc = -EINVAL; break; } dmu_tx_commit(tx); GOTO(log, rc); log: CDEBUG(D_LFSCK, "%s: refresh OI map for scrub, op %d, force %s, " DFID" => %llu (%s): rc = %d\n", osd_name(dev), ops, force ? "yes" : "no", PFID(fid), oid, name ? name : "null", rc); 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); }