int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, mdsno_t *mds) { int rc; /* FIXME: Currently ZFS still use local seq for ROOT unfortunately, and * this fid_is_local check should be removed once LU-2240 is fixed */ LASSERTF((fid_seq_in_fldb(fid_seq(fid)) || fid_seq_is_local_file(fid_seq(fid))) && fid_is_sane(fid), DFID" is insane!\n", PFID(fid)); rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds, LU_SEQ_RANGE_MDT, NULL); if (rc) { CERROR("Error while looking for mds number. Seq %#llx, err = %d\n", fid_seq(fid), rc); return rc; } CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n", *mds, PFID(fid)); if (*mds >= lmv->desc.ld_tgt_count) { CERROR("FLD lookup got invalid mds #%x (max: %x) " "for fid="DFID"\n", *mds, lmv->desc.ld_tgt_count, PFID(fid)); rc = -EINVAL; } return rc; }
int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds) { struct obd_device *obd = lmv2obd_dev(lmv); int rc; /* * FIXME: Currently ZFS still use local seq for ROOT unfortunately, and * this fid_is_local check should be removed once LU-2240 is fixed */ if (!fid_is_sane(fid) || !(fid_seq_in_fldb(fid_seq(fid)) || fid_seq_is_local_file(fid_seq(fid)))) { CERROR("%s: invalid FID " DFID "\n", obd->obd_name, PFID(fid)); return -EINVAL; } rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds, LU_SEQ_RANGE_MDT, NULL); if (rc) { CERROR("Error while looking for mds number. Seq %#llx, err = %d\n", fid_seq(fid), rc); return rc; } CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n", *mds, PFID(fid)); if (*mds >= lmv->desc.ld_tgt_count) { CERROR("FLD lookup got invalid mds #%x (max: %x) for fid=" DFID "\n", *mds, lmv->desc.ld_tgt_count, PFID(fid)); rc = -EINVAL; } return rc; }
static int osd_remote_fid(const struct lu_env *env, struct osd_device *osd, struct lu_fid *fid) { ENTRY; /* FID seqs not in FLDB, must be local seq */ if (unlikely(!fid_seq_in_fldb(fid_seq(fid)))) RETURN(0); if (osd_seq_exists(env, osd, fid_seq(fid))) RETURN(0); RETURN(1); }
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); }
int osd_oi_update(struct osd_thread_info *info, struct osd_device *osd, const struct lu_fid *fid, const struct osd_inode_id *id, handle_t *th, enum oi_check_flags flags) { struct lu_fid *oi_fid = &info->oti_fid2; struct osd_inode_id *oi_id = &info->oti_id2; int rc = 0; if (unlikely(fid_is_last_id(fid))) return osd_obj_spec_update(info, osd, fid, id, th); if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid)) return osd_obj_map_update(info, osd, fid, id, th); fid_cpu_to_be(oi_fid, fid); osd_id_pack(oi_id, id); rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid), (const struct dt_rec *)oi_id, (const struct dt_key *)oi_fid, th, false); if (rc != 0) return rc; if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE)) rc = osd_obj_spec_update(info, osd, fid, id, th); return rc; }
/* * The transaction passed to this routine must have * dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT) called and then assigned * to a transaction group. */ int __osd_object_create(const struct lu_env *env, struct osd_object *obj, dmu_buf_t **dbp, dmu_tx_t *tx, struct lu_attr *la) { uint64_t oid; int rc; struct osd_device *osd = osd_obj2dev(obj); const struct lu_fid *fid = lu_object_fid(&obj->oo_dt.do_lu); dmu_object_type_t type = DMU_OT_PLAIN_FILE_CONTENTS; /* Use DMU_OTN_UINT8_METADATA for local objects so their data blocks * would get an additional ditto copy */ if (unlikely(S_ISREG(la->la_mode) && fid_seq_is_local_file(fid_seq(fid)))) type = DMU_OTN_UINT8_METADATA; /* Create a new DMU object using the default dnode size. */ oid = osd_dmu_object_alloc(osd->od_os, type, 0, 0, tx); rc = -sa_buf_hold(osd->od_os, oid, osd_obj_tag, dbp); LASSERTF(rc == 0, "sa_buf_hold %llu failed: %d\n", oid, rc); LASSERT(la->la_valid & LA_MODE); la->la_size = 0; la->la_nlink = 1; return 0; }
int osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd, const struct lu_fid *fid, struct osd_inode_id *id, enum oi_check_flags flags) { if (unlikely(fid_is_last_id(fid))) return osd_obj_spec_lookup(info, osd, fid, id); if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid)) return osd_obj_map_lookup(info, osd, fid, id); if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE)) { int rc; if (fid_is_fs_root(fid)) { osd_id_gen(id, osd_sb(osd)->s_root->d_inode->i_ino, osd_sb(osd)->s_root->d_inode->i_generation); return 0; } if (unlikely(fid_is_acct(fid))) return osd_acct_obj_lookup(info, osd, fid, id); /* For other special FIDs, try OI first, then do spec lookup */ rc = __osd_oi_lookup(info, osd, fid, id); if (rc == -ENOENT) return osd_obj_spec_lookup(info, osd, fid, id); return rc; } if (!osd->od_igif_inoi && fid_is_igif(fid)) { osd_id_gen(id, lu_igif_ino(fid), lu_igif_gen(fid)); return 0; } return __osd_oi_lookup(info, osd, fid, id); }
void obdo_set_parent_fid(struct obdo *dst, const struct lu_fid *parent) { dst->o_parent_oid = fid_oid(parent); dst->o_parent_seq = fid_seq(parent); dst->o_parent_ver = fid_ver(parent); dst->o_valid |= OBD_MD_FLGENER | OBD_MD_FLFID; }
static int osp_rd_prealloc_last_seq(char *page, char **start, off_t off, int count, int *eof, void *data) { struct obd_device *obd = data; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); if (osp == NULL) return 0; return snprintf(page, count, LPX64"\n", fid_seq(&osp->opd_pre_last_created_fid)); }
/* compatibility with orphan files created in versions before 2.11 */ static struct dt_key *mdd_orphan_key_fill_20(const struct lu_env *env, const struct lu_fid *lf) { char *key = mdd_env_info(env)->mti_key; LASSERT(key); snprintf(key, sizeof(mdd_env_info(env)->mti_key), ORPHAN_FILE_NAME_FORMAT_20, fid_seq(lf), fid_oid(lf), fid_ver(lf), ORPH_OP_UNLINK); return (struct dt_key *)key; }
int osp_precreate_rollover_new_seq(struct lu_env *env, struct osp_device *osp) { struct lu_fid *fid = &osp_env_info(env)->osi_fid; struct lu_fid *last_fid = &osp->opd_last_used_fid; int rc; ENTRY; rc = seq_client_get_seq(env, osp->opd_obd->u.cli.cl_seq, &fid->f_seq); if (rc != 0) { CERROR("%s: alloc fid error: rc = %d\n", osp->opd_obd->obd_name, rc); RETURN(rc); } fid->f_oid = 1; fid->f_ver = 0; LASSERTF(fid_seq(fid) != fid_seq(last_fid), "fid "DFID", last_fid "DFID"\n", PFID(fid), PFID(last_fid)); rc = osp_write_last_oid_seq_files(env, osp, fid, 1); if (rc != 0) { CERROR("%s: Can not update oid/seq file: rc = %d\n", osp->opd_obd->obd_name, rc); RETURN(rc); } LCONSOLE_INFO("%s: update sequence from "LPX64" to "LPX64"\n", osp->opd_obd->obd_name, fid_seq(last_fid), fid_seq(fid)); /* Update last_xxx to the new seq */ spin_lock(&osp->opd_pre_lock); osp->opd_last_used_fid = *fid; osp->opd_gap_start_fid = *fid; osp->opd_pre_used_fid = *fid; osp->opd_pre_last_created_fid = *fid; spin_unlock(&osp->opd_pre_lock); RETURN(rc); }
static struct dt_key* orph_key_fill_18(const struct lu_env *env, const struct lu_fid *lf) { char *key = mdd_env_info(env)->mti_key; int rc; LASSERT(key); rc = snprintf(key, NAME_MAX + 1, ORPHAN_FILE_NAME_FORMAT_18, (unsigned long long)fid_seq(lf), fid_oid(lf)); if (rc > 0) return (struct dt_key*) key; else return ERR_PTR(rc); }
static inline int osp_objs_precreated(const struct lu_env *env, struct osp_device *osp) { struct lu_fid *fid1 = &osp->opd_pre_last_created_fid; struct lu_fid *fid2 = &osp->opd_pre_used_fid; LASSERTF(fid_seq(fid1) == fid_seq(fid2), "Created fid"DFID" Next fid "DFID"\n", PFID(fid1), PFID(fid2)); if (fid_is_idif(fid1)) { struct ost_id *oi1 = &osp_env_info(env)->osi_oi; struct ost_id *oi2 = &osp_env_info(env)->osi_oi2; LASSERT(fid_is_idif(fid1) && fid_is_idif(fid2)); fid_to_ostid(fid1, oi1); fid_to_ostid(fid2, oi2); LASSERT(ostid_id(oi1) >= ostid_id(oi2)); return ostid_id(oi1) - ostid_id(oi2); } return fid_oid(fid1) - fid_oid(fid2); }
int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, mdsno_t *mds) { int rc; ENTRY; LASSERTF(fid_is_sane(fid), DFID" is insane!\n", PFID(fid)); /* FIXME: Because ZFS still use LOCAL fid sequence for root, * and root will always be in MDT0, for local fid, it will * return 0 directly. And it should be removed once the root * FID has been assigned with special sequence */ if (fid_seq(fid) == FID_SEQ_LOCAL_FILE) { *mds = 0; RETURN(0); } rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds, LU_SEQ_RANGE_MDT, NULL); if (rc) { CERROR("Error while looking for mds number. Seq "LPX64 ", err = %d\n", fid_seq(fid), rc); RETURN(rc); } CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n", *mds, PFID(fid)); if (*mds >= lmv->desc.ld_tgt_count) { CERROR("FLD lookup got invalid mds #%x (max: %x) " "for fid="DFID"\n", *mds, lmv->desc.ld_tgt_count, PFID(fid)); rc = -EINVAL; } RETURN(rc); }
/* * The transaction passed to this routine must have * dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT) called and then assigned * to a transaction group. */ int __osd_object_create(const struct lu_env *env, struct osd_object *obj, dmu_buf_t **dbp, dmu_tx_t *tx, struct lu_attr *la, uint64_t parent) { uint64_t oid; int rc; struct osd_device *osd = osd_obj2dev(obj); const struct lu_fid *fid = lu_object_fid(&obj->oo_dt.do_lu); dmu_object_type_t type = DMU_OT_PLAIN_FILE_CONTENTS; /* Assert that the transaction has been assigned to a transaction group. */ LASSERT(tx->tx_txg != 0); /* Use DMU_OTN_UINT8_METADATA for local objects so their data blocks * would get an additional ditto copy */ if (unlikely(S_ISREG(la->la_mode) && fid_seq_is_local_file(fid_seq(fid)))) type = DMU_OTN_UINT8_METADATA; /* Create a new DMU object. */ oid = dmu_object_alloc(osd->od_os, type, 0, DMU_OT_SA, DN_MAX_BONUSLEN, tx); rc = -sa_buf_hold(osd->od_os, oid, osd_obj_tag, dbp); LASSERTF(rc == 0, "sa_buf_hold "LPU64" failed: %d\n", oid, rc); LASSERT(la->la_valid & LA_MODE); la->la_size = 0; la->la_nlink = 1; rc = __osd_attr_init(env, osd, oid, tx, la, parent); if (rc != 0) { sa_buf_rele(*dbp, osd_obj_tag); *dbp = NULL; dmu_object_free(osd->od_os, oid, tx); return rc; } return 0; }
/* * Returns true, if fid is local to this server node. * * WARNING: this function is *not* guaranteed to return false if fid is * remote: it makes an educated conservative guess only. * * fid_is_local() is supposed to be used in assertion checks only. */ int fid_is_local(const struct lu_env *env, struct lu_site *site, const struct lu_fid *fid) { int result; struct seq_server_site *ss_site; struct lu_seq_range *range; struct fld_thread_info *info; ENTRY; info = lu_context_key_get(&env->le_ctx, &fld_thread_key); range = &info->fti_lrange; result = 1; /* conservatively assume fid is local */ ss_site = lu_site2seq(site); if (ss_site->ss_client_fld != NULL) { int rc; rc = fld_cache_lookup(ss_site->ss_client_fld->lcf_cache, fid_seq(fid), range); if (rc == 0) result = (range->lsr_index == ss_site->ss_node_id); } return result; }
static int osp_precreate_thread(void *_arg) { struct osp_device *d = _arg; struct ptlrpc_thread *thread = &d->opd_pre_thread; struct l_wait_info lwi = { 0 }; struct lu_env env; int rc; ENTRY; rc = lu_env_init(&env, d->opd_dt_dev.dd_lu_dev.ld_type->ldt_ctx_tags); if (rc) { CERROR("%s: init env error: rc = %d\n", d->opd_obd->obd_name, rc); RETURN(rc); } spin_lock(&d->opd_pre_lock); thread->t_flags = SVC_RUNNING; spin_unlock(&d->opd_pre_lock); wake_up(&thread->t_ctl_waitq); while (osp_precreate_running(d)) { /* * need to be connected to OST */ while (osp_precreate_running(d)) { l_wait_event(d->opd_pre_waitq, !osp_precreate_running(d) || d->opd_new_connection, &lwi); if (!d->opd_new_connection) continue; d->opd_new_connection = 0; d->opd_got_disconnected = 0; break; } if (!osp_precreate_running(d)) break; LASSERT(d->opd_obd->u.cli.cl_seq != NULL); if (d->opd_obd->u.cli.cl_seq->lcs_exp == NULL) { /* Get new sequence for client first */ LASSERT(d->opd_exp != NULL); d->opd_obd->u.cli.cl_seq->lcs_exp = class_export_get(d->opd_exp); rc = osp_init_pre_fid(d); if (rc != 0) { class_export_put(d->opd_exp); d->opd_obd->u.cli.cl_seq->lcs_exp = NULL; CERROR("%s: init pre fid error: rc = %d\n", d->opd_obd->obd_name, rc); continue; } } osp_statfs_update(d); /* * Clean up orphans or recreate missing objects. */ rc = osp_precreate_cleanup_orphans(&env, d); if (rc != 0) continue; /* * connected, can handle precreates now */ while (osp_precreate_running(d)) { l_wait_event(d->opd_pre_waitq, !osp_precreate_running(d) || osp_precreate_near_empty(&env, d) || osp_statfs_need_update(d) || d->opd_got_disconnected, &lwi); if (!osp_precreate_running(d)) break; /* something happened to the connection * have to start from the beginning */ if (d->opd_got_disconnected) break; if (osp_statfs_need_update(d)) osp_statfs_update(d); /* To avoid handling different seq in precreate/orphan * cleanup, it will hold precreate until current seq is * used up. */ if (unlikely(osp_precreate_end_seq(&env, d) && !osp_create_end_seq(&env, d))) continue; if (unlikely(osp_precreate_end_seq(&env, d) && osp_create_end_seq(&env, d))) { LCONSOLE_INFO("%s:"LPX64" is used up." " Update to new seq\n", d->opd_obd->obd_name, fid_seq(&d->opd_pre_last_created_fid)); rc = osp_precreate_rollover_new_seq(&env, d); if (rc) continue; } if (osp_precreate_near_empty(&env, d)) { rc = osp_precreate_send(&env, d); /* osp_precreate_send() sets opd_pre_status * in case of error, that prevent the using of * failed device. */ if (rc < 0 && rc != -ENOSPC && rc != -ETIMEDOUT && rc != -ENOTCONN) CERROR("%s: cannot precreate objects:" " rc = %d\n", d->opd_obd->obd_name, rc); } } } thread->t_flags = SVC_STOPPED; lu_env_fini(&env); wake_up(&thread->t_ctl_waitq); RETURN(0); }
int mdd_compat_fixes(const struct lu_env *env, struct mdd_device *mdd) { struct mdd_thread_info *info = mdd_env_info(env); struct mdd_object *root; struct dt_object *o; struct lustre_mdt_attrs *lma; struct lu_buf buf; int rc; ENTRY; /* IGIF FIDS are valid for old 1.8 and 2.[123] ROOT and are kept. * Normal FIDs used by Xyratex 1.8->2.1 upgrade tool are also kept. */ if (fid_is_igif(&mdd->mdd_root_fid) || fid_is_norm(&mdd->mdd_root_fid)) RETURN(0); /* * FID is supposed to be FID_SEQ_ROOT for: * - new ldiskfs fs * - new ZFS fs * - old ZFS fs, by now processed with osd_convert_root_to_new_seq() */ if (fid_seq(&mdd->mdd_root_fid) != FID_SEQ_ROOT) { CERROR("%s: wrong FID "DFID" is used for /ROOT\n", mdd2obd_dev(mdd)->obd_name, PFID(&mdd->mdd_root_fid)); RETURN(-EINVAL); } root = mdd_object_find(env, mdd, &mdd->mdd_root_fid); if (IS_ERR(root)) RETURN(PTR_ERR(root)); o = mdd_object_child(root); CDEBUG(D_OTHER, "/ROOT = "DFID"\n", PFID(&mdd->mdd_root_fid)); if (dt_try_as_dir(env, o) == 0) { CERROR("%s: not a directory\n", mdd2obd_dev(mdd)->obd_name); GOTO(out, rc = -ENOTDIR); } lma = (struct lustre_mdt_attrs *)&info->mti_xattr_buf; CLASSERT(sizeof(info->mti_xattr_buf) >= LMA_OLD_SIZE); buf.lb_len = LMA_OLD_SIZE; buf.lb_buf = lma; rc = mdo_xattr_get(env, root, &buf, XATTR_NAME_LMA, BYPASS_CAPA); if (rc < 0 && rc != -ENODATA) { CERROR("%s: can't fetch LMA: rc = %d\n", mdd2obd_dev(mdd)->obd_name, rc); GOTO(out, rc); } lustre_lma_swab(lma); if (lu_fid_eq(&lma->lma_self_fid, &mdd->mdd_root_fid)) { /* /ROOT has been converted already * or was correct from the beginning */ CDEBUG(D_OTHER, "%s: converted already\n", mdd2obd_dev(mdd)->obd_name); GOTO(out, rc = 0); } /* this is supposed to happen only on pre-production ZFS backend */ if (strcmp(mdd->mdd_bottom->dd_lu_dev.ld_type->ldt_name, LUSTRE_OSD_ZFS_NAME) != 0) { CERROR("%s: "DFID" is used on ldiskfs?!\n", mdd2obd_dev(mdd)->obd_name, PFID(&mdd->mdd_root_fid)); GOTO(out, rc = -ENOTSUPP); } LCONSOLE_INFO("%s: FID of /ROOT has been changed. " "Please remount the clients.\n", mdd2obd_dev(mdd)->obd_name); /* Fill FLDB first */ rc = mdd_fill_fldb(env, mdd); if (rc) GOTO(out, rc); /* remove ./.. from /ROOT */ rc = mdd_convert_remove_dots(env, mdd, root); if (rc) GOTO(out, rc); /* go over the directory, fix all the objects */ rc = mdd_fix_children(env, mdd, o); if (rc) GOTO(out, rc); /* Update LMA on /ROOT. Done for simplicity in MDD, not in osd-zfs. * Correct LMA will imply the whole directory has been coverted * successfully, otherwise it will be retried on next mount. */ rc = mdd_convert_lma(env, mdd, root); out: mdd_object_put(env, root); RETURN(rc); }
static int lfsck_master_oit_engine(const struct lu_env *env, struct lfsck_instance *lfsck) { struct lfsck_thread_info *info = lfsck_env_info(env); const struct dt_it_ops *iops = &lfsck->li_obj_oit->do_index_ops->dio_it; struct dt_it *di = lfsck->li_di_oit; struct lu_fid *fid = &info->lti_fid; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; struct ptlrpc_thread *thread = &lfsck->li_thread; __u32 idx = lfsck_dev_idx(lfsck->li_bottom); int rc; ENTRY; do { struct dt_object *target; bool update_lma = false; if (lfsck->li_di_dir != NULL) { rc = lfsck_master_dir_engine(env, lfsck); if (rc <= 0) RETURN(rc); } if (unlikely(lfsck->li_oit_over)) RETURN(1); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DELAY1) && cfs_fail_val > 0) { struct l_wait_info lwi; lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val), NULL, NULL); l_wait_event(thread->t_ctl_waitq, !thread_is_running(thread), &lwi); } if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH)) RETURN(0); lfsck->li_current_oit_processed = 1; lfsck->li_new_scanned++; rc = iops->rec(env, di, (struct dt_rec *)fid, 0); if (rc != 0) { lfsck_fail(env, lfsck, true); if (rc < 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); else goto checkpoint; } if (fid_is_idif(fid)) { __u32 idx1 = fid_idif_ost_idx(fid); LASSERT(!lfsck->li_master); /* It is an old format device, update the LMA. */ if (idx != idx1) { struct ost_id *oi = &info->lti_oi; fid_to_ostid(fid, oi); ostid_to_fid(fid, oi, idx); update_lma = true; } } else if (!fid_is_norm(fid) && !fid_is_igif(fid) && !fid_is_last_id(fid) && !fid_is_root(fid) && !fid_seq_is_dot(fid_seq(fid))) { /* If the FID/object is only used locally and invisible * to external nodes, then LFSCK will not handle it. */ goto checkpoint; } target = lfsck_object_find(env, lfsck, fid); if (target == NULL) { goto checkpoint; } else if (IS_ERR(target)) { lfsck_fail(env, lfsck, true); if (bk->lb_param & LPF_FAILOUT) RETURN(PTR_ERR(target)); else goto checkpoint; } /* XXX: Currently, skip remote object, the consistency for * remote object will be processed in LFSCK phase III. */ if (dt_object_exists(target) && !dt_object_remote(target)) { if (update_lma) rc = lfsck_update_lma(env, lfsck, target); if (rc == 0) rc = lfsck_exec_oit(env, lfsck, target); } lfsck_object_put(env, target); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); checkpoint: rc = lfsck_checkpoint(env, lfsck); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); /* Rate control. */ lfsck_control_speed(lfsck); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_FATAL1)) { spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_STOPPING); spin_unlock(&lfsck->li_lock); RETURN(-EINVAL); } rc = iops->next(env, di); if (unlikely(rc > 0)) lfsck->li_oit_over = 1; else if (likely(rc == 0)) lfsck->li_current_oit_processed = 0; if (unlikely(!thread_is_running(thread))) RETURN(0); } while (rc == 0 || lfsck->li_di_dir != NULL); 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; }
/** * Implementation of ldlm_valblock_ops::lvbo_init for OFD. * * This function allocates and initializes new LVB data for the given * LDLM resource if it is not allocated yet. New LVB is filled with attributes * of the object associated with that resource. Function does nothing if LVB * for the given LDLM resource is allocated already. * * Called with res->lr_lvb_sem held. * * \param[in] lock LDLM lock on resource * * \retval 0 on successful setup * \retval negative value on error */ static int ofd_lvbo_init(const struct lu_env *env, struct ldlm_resource *res) { struct ost_lvb *lvb; struct ofd_device *ofd; struct ofd_object *fo; struct ofd_thread_info *info; struct lu_env _env; int rc = 0; ENTRY; LASSERT(res); LASSERT(mutex_is_locked(&res->lr_lvb_mutex)); if (res->lr_lvb_data != NULL) RETURN(0); ofd = ldlm_res_to_ns(res)->ns_lvbp; LASSERT(ofd != NULL); if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_OST_LVB)) RETURN(-ENOMEM); if (!env) { rc = lu_env_init(&_env, LCT_DT_THREAD); if (rc) RETURN(rc); env = &_env; } OBD_ALLOC_PTR(lvb); if (lvb == NULL) GOTO(out, rc = -ENOMEM); info = ofd_info(env); res->lr_lvb_data = lvb; res->lr_lvb_len = sizeof(*lvb); ost_fid_from_resid(&info->fti_fid, &res->lr_name, ofd->ofd_lut.lut_lsd.lsd_osd_index); fo = ofd_object_find(env, ofd, &info->fti_fid); if (IS_ERR(fo)) GOTO(out_lvb, rc = PTR_ERR(fo)); rc = ofd_attr_get(env, fo, &info->fti_attr); if (rc) { struct ofd_seq *oseq; __u64 seq; /* Object could be recreated during the first * CLEANUP_ORPHAN request. */ if (rc == -ENOENT) { seq = fid_seq(&info->fti_fid); oseq = ofd_seq_load(env, ofd, fid_seq_is_idif(seq) ? FID_SEQ_OST_MDT0 : seq); if (!IS_ERR_OR_NULL(oseq)) { if (!oseq->os_last_id_synced) rc = -EAGAIN; ofd_seq_put(env, oseq); } } GOTO(out_obj, rc); } lvb->lvb_size = info->fti_attr.la_size; lvb->lvb_blocks = info->fti_attr.la_blocks; lvb->lvb_mtime = info->fti_attr.la_mtime; lvb->lvb_atime = info->fti_attr.la_atime; lvb->lvb_ctime = info->fti_attr.la_ctime; CDEBUG(D_DLMTRACE, "res: "DFID" initial lvb size: %llu, " "mtime: %#llx, blocks: %#llx\n", PFID(&info->fti_fid), lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_blocks); info->fti_attr.la_valid = 0; EXIT; out_obj: ofd_object_put(env, fo); out_lvb: if (rc != 0) OST_LVB_SET_ERR(lvb->lvb_blocks, rc); out: /* Don't free lvb data on lookup error */ if (env && env == &_env) lu_env_fini(&_env); return rc; }
int osd_oi_insert(struct osd_thread_info *info, struct osd_device *osd, const struct lu_fid *fid, const struct osd_inode_id *id, handle_t *th, enum oi_check_flags flags) { struct lu_fid *oi_fid = &info->oti_fid2; struct osd_inode_id *oi_id = &info->oti_id2; int rc = 0; if (unlikely(fid_is_last_id(fid))) return osd_obj_spec_insert(info, osd, fid, id, th); if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid)) return osd_obj_map_insert(info, osd, fid, id, th); fid_cpu_to_be(oi_fid, fid); osd_id_pack(oi_id, id); rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid), (const struct dt_rec *)oi_id, (const struct dt_key *)oi_fid, th, true); if (rc != 0) { struct inode *inode; struct lustre_mdt_attrs *lma = &info->oti_mdt_attrs; if (rc != -EEXIST) return rc; rc = osd_oi_lookup(info, osd, fid, oi_id, 0); if (rc != 0) return rc; if (unlikely(osd_id_eq(id, oi_id))) return 1; /* Check whether the mapping for oi_id is valid or not. */ inode = osd_iget(info, osd, oi_id); if (IS_ERR(inode)) { rc = PTR_ERR(inode); if (rc == -ENOENT || rc == -ESTALE) goto update; return rc; } /* The EA inode should NOT be in OI, old OI scrub may added * such OI mapping by wrong, replace it. */ if (unlikely(osd_is_ea_inode(inode))) { iput(inode); goto update; } rc = osd_get_lma(info, inode, &info->oti_obj_dentry, lma); iput(inode); if (rc == -ENODATA) goto update; if (rc != 0) return rc; if (!(lma->lma_compat & LMAC_NOT_IN_OI) && lu_fid_eq(fid, &lma->lma_self_fid)) { CERROR("%.16s: the FID "DFID" is used by two objects: " "%u/%u %u/%u\n", LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name, PFID(fid), oi_id->oii_ino, oi_id->oii_gen, id->oii_ino, id->oii_gen); return -EEXIST; } update: osd_id_pack(oi_id, id); rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid), (const struct dt_rec *)oi_id, (const struct dt_key *)oi_fid, th, false); if (rc != 0) return rc; } if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE)) rc = osd_obj_spec_insert(info, osd, fid, id, th); return rc; }
static inline int fid_is_fs_root(const struct lu_fid *fid) { /* Map root inode to special local object FID */ return (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE && fid_oid(fid) == OSD_FS_ROOT_OID)); }