return ERR_PTR(-ENOMEM);
}
- rb_init_node(&lrn->lrn_node);
+ RB_CLEAR_NODE(&lrn->lrn_node);
lrn->lrn_seq = fid_seq(fid);
lrn->lrn_first_oid = fid_oid(fid) & ~LFSCK_RBTREE_BITMAP_MASK;
atomic_set(&lrn->lrn_known_count, 0);
break;
/* link other MDT targets locallly. */
+ ltds = &lfsck->li_mdt_descs;
spin_lock(<ds->ltd_lock);
cfs_foreach_bit(ltds->ltd_tgts_bitmap, idx) {
ltd = LTD_TGT(ltds, idx);
}
/**
- * \retval +1: repaired
- * \retval 0: did nothing
- * \retval -ve: on error
+ * This function will create the MDT-object will the given (partial) LOV EA.
+ *
+ * Under some data corruption cases, the MDT-object of the file may be lost,
+ * but its OST-objects, or some of them are there. The layout LFSCK needs to
+ * re-create the MDT-object with the orphan OST-object(s) information.
+ *
+ * On the other hand, the LFSCK may has created some OST-object for repairing
+ * dangling LOV EA reference, but as the LFSCK processing, it may find that
+ * the old OST-object is there and should replace the former new created OST
+ * object. Unfortunately, some others have modified such newly created object.
+ * To keep the data (both new and old), the LFSCK will create MDT-object with
+ * new FID to reference the original OST-object.
+ *
+ * \param[in] env pointer to the thread context
+ * \param[in] com pointer to the lfsck component
+ * \param[in] ltd pointer to target device descriptor
+ * \param[in] rec pointer to the record for the orphan OST-object
+ * \param[in] cfid pointer to FID for the orphan OST-object
+ * \param[in] infix additional information, such as the FID for original
+ * MDT-object and the stripe offset in the LOV EA
+ * \param[in] type the type for describing why the orphan MDT-object is
+ * created. The rules are as following:
+ *
+ * type "C": Multiple OST-objects claim the same MDT-object and the
+ * same slot in the layout EA. Then the LFSCK will create
+ * new MDT-object(s) to hold the conflict OST-object(s).
+ *
+ * type "N": The orphan OST-object does not know which one was the
+ * real parent MDT-object, so the LFSCK uses new FID for
+ * its parent MDT-object.
+ *
+ * type "R": The orphan OST-object knows its parent MDT-object FID,
+ * but does not know the position (the file name) in the
+ * namespace.
+ *
+ * The orphan name will be like:
+ * ${FID}-${infix}-${type}-${conflict_version}
+ *
+ * \param[in] ea_off the stripe offset in the LOV EA
+ *
+ * \retval positive on repaired something
+ * \retval if needs to repair nothing
+ * \retval negative error number on failure
*/
static int lfsck_layout_recreate_parent(const struct lu_env *env,
struct lfsck_component *com,
struct lfsck_tgt_desc *ltd,
struct lu_orphan_rec *rec,
struct lu_fid *cfid,
- const char *prefix,
- const char *postfix,
+ const char *infix,
+ const char *type,
__u32 ea_off)
{
struct lfsck_thread_info *info = lfsck_env_info(env);
RETURN(PTR_ERR(cobj));
}
- CDEBUG(D_LFSCK, "Re-create the lost MDT-object: parent "
- DFID", child "DFID", OST-index %u, stripe-index %u, "
- "prefix %s, postfix %s\n",
- PFID(pfid), PFID(cfid), ltd->ltd_index, ea_off, prefix, postfix);
+ CDEBUG(D_LFSCK, "Re-create the lost MDT-object: parent "DFID", child "
+ DFID", OST-index %u, stripe-index %u, infix %s, type %s\n",
+ PFID(pfid), PFID(cfid), ltd->ltd_index, ea_off, infix, type);
pobj = lfsck_object_find_by_dev(env, lfsck->li_bottom, pfid);
if (IS_ERR(pobj))
GOTO(put, rc = PTR_ERR(pobj));
- LASSERT(prefix != NULL);
- LASSERT(postfix != NULL);
+ LASSERT(infix != NULL);
+ LASSERT(type != NULL);
- /** name rules:
- *
- * 1. Use the MDT-object's FID as the name with prefix and postfix.
- *
- * 1.1 prefix "C-": More than one OST-objects claim the same
- * MDT-object and the same slot in the layout EA.
- * It may be created for dangling referenced MDT
- * object or may be not.
- * 1.2 prefix "N-": The orphan OST-object does not know which one
- * is the real parent, so the LFSCK assign a new
- * FID as its parent.
- * 1.3 prefix "R-": The orphan OST-object know its parent FID but
- * does not know the position in the namespace.
- *
- * 2. If there is name conflict, append more index for new name. */
- sprintf(name, "%s"DFID"%s", prefix, PFID(pfid), postfix);
do {
+ snprintf(name, NAME_MAX, DFID"%s-%s-%d", PFID(pfid), infix,
+ type, idx++);
rc = dt_lookup(env, lfsck->li_lpf_obj, (struct dt_rec *)tfid,
(const struct dt_key *)name, BYPASS_CAPA);
if (rc != 0 && rc != -ENOENT)
GOTO(put, rc);
-
- if (unlikely(rc == 0)) {
- CWARN("%s: The name %s under lost+found has been used "
- "by the "DFID". Try to increase the FID version "
- "for the new file name.\n",
- lfsck_lfsck2name(lfsck), name, PFID(tfid));
- sprintf(name, "%s"DFID"%s-%d", prefix, PFID(pfid),
- postfix, ++idx);
- }
} while (rc == 0);
memset(la, 0, sizeof(*la));
struct lfsck_thread_info *info = lfsck_env_info(env);
struct lu_fid *cfid2 = &info->lti_fid2;
struct ost_id *oi = &info->lti_oi;
- char *postfix = info->lti_tmpbuf;
+ char *infix = info->lti_tmpbuf;
struct lov_mds_md_v1 *lmm = ea_buf->lb_buf;
struct dt_device *dev = com->lc_lfsck->li_bottom;
struct thandle *th = NULL;
ea_buf->lb_len = ori_len;
fid_zero(&rec->lor_fid);
- snprintf(postfix, LFSCK_TMPBUF_LEN, "-"DFID"-%x",
+ snprintf(infix, LFSCK_TMPBUF_LEN, "-"DFID"-%x",
PFID(lu_object_fid(&parent->do_lu)), ea_off);
rc = lfsck_layout_recreate_parent(env, com, ltd, rec, cfid,
- "C-", postfix, ea_off);
+ infix, "C", ea_off);
RETURN(rc);
}
if (fid_is_zero(pfid)) {
rc = lfsck_layout_recreate_parent(env, com, ltd, rec, cfid,
- "N-", "", ea_off);
+ "", "N", ea_off);
GOTO(out, rc);
}
if (dt_object_exists(parent) == 0) {
lu_object_put(env, &parent->do_lu);
rc = lfsck_layout_recreate_parent(env, com, ltd, rec, cfid,
- "R-", "", ea_off);
+ "", "R", ea_off);
GOTO(out, rc);
}
}
static int lfsck_layout_dump(const struct lu_env *env,
- struct lfsck_component *com, char *buf, int len)
+ struct lfsck_component *com, struct seq_file *m)
{
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
struct lfsck_layout *lo = com->lc_file_ram;
- int save = len;
- int ret = -ENOSPC;
int rc;
down_read(&com->lc_sem);
- rc = snprintf(buf, len,
- "name: lfsck_layout\n"
+ seq_printf(m, "name: lfsck_layout\n"
"magic: %#x\n"
"version: %d\n"
"status: %s\n",
lo->ll_magic,
bk->lb_version,
lfsck_status2names(lo->ll_status));
- if (rc <= 0)
- goto out;
- buf += rc;
- len -= rc;
- rc = lfsck_bits_dump(&buf, &len, lo->ll_flags, lfsck_flags_names,
- "flags");
+ rc = lfsck_bits_dump(m, lo->ll_flags, lfsck_flags_names, "flags");
if (rc < 0)
goto out;
- rc = lfsck_bits_dump(&buf, &len, bk->lb_param, lfsck_param_names,
- "param");
+ rc = lfsck_bits_dump(m, bk->lb_param, lfsck_param_names, "param");
if (rc < 0)
goto out;
- rc = lfsck_time_dump(&buf, &len, lo->ll_time_last_complete,
+ rc = lfsck_time_dump(m, lo->ll_time_last_complete,
"time_since_last_completed");
if (rc < 0)
goto out;
- rc = lfsck_time_dump(&buf, &len, lo->ll_time_latest_start,
+ rc = lfsck_time_dump(m, lo->ll_time_latest_start,
"time_since_latest_start");
if (rc < 0)
goto out;
- rc = lfsck_time_dump(&buf, &len, lo->ll_time_last_checkpoint,
+ rc = lfsck_time_dump(m, lo->ll_time_last_checkpoint,
"time_since_last_checkpoint");
if (rc < 0)
goto out;
- rc = snprintf(buf, len,
- "latest_start_position: "LPU64"\n"
+ seq_printf(m, "latest_start_position: "LPU64"\n"
"last_checkpoint_position: "LPU64"\n"
"first_failure_position: "LPU64"\n",
lo->ll_pos_latest_start,
lo->ll_pos_last_checkpoint,
lo->ll_pos_first_inconsistent);
- if (rc <= 0)
- goto out;
- buf += rc;
- len -= rc;
-
- rc = snprintf(buf, len,
- "success_count: %u\n"
+ seq_printf(m, "success_count: %u\n"
"repaired_dangling: "LPU64"\n"
"repaired_unmatched_pair: "LPU64"\n"
"repaired_multiple_referenced: "LPU64"\n"
lo->ll_objs_skipped,
lo->ll_objs_failed_phase1,
lo->ll_objs_failed_phase2);
- if (rc <= 0)
- goto out;
-
- buf += rc;
- len -= rc;
if (lo->ll_status == LS_SCANNING_PHASE1) {
__u64 pos;
do_div(new_checked, duration);
if (rtime != 0)
do_div(speed, rtime);
- rc = snprintf(buf, len,
- "checked_phase1: "LPU64"\n"
+ seq_printf(m, "checked_phase1: "LPU64"\n"
"checked_phase2: "LPU64"\n"
"run_time_phase1: %u seconds\n"
"run_time_phase2: %u seconds\n"
lo->ll_run_time_phase2,
speed,
new_checked);
- if (rc <= 0)
- goto out;
-
- buf += rc;
- len -= rc;
LASSERT(lfsck->li_di_oit != NULL);
pos = iops->store(env, lfsck->li_di_oit);
if (!lfsck->li_current_oit_processed)
pos--;
- rc = snprintf(buf, len, "current_position: "LPU64"\n", pos);
- if (rc <= 0)
- goto out;
+ seq_printf(m, "current_position: "LPU64"\n", pos);
- buf += rc;
- len -= rc;
} else if (lo->ll_status == LS_SCANNING_PHASE2) {
cfs_duration_t duration = cfs_time_current() -
lfsck->li_time_last_checkpoint;
do_div(speed1, lo->ll_run_time_phase1);
if (rtime != 0)
do_div(speed2, rtime);
- rc = snprintf(buf, len,
- "checked_phase1: "LPU64"\n"
- "checked_phase2: "LPU64"\n"
- "run_time_phase1: %u seconds\n"
- "run_time_phase2: %u seconds\n"
- "average_speed_phase1: "LPU64" items/sec\n"
- "average_speed_phase2: "LPU64" items/sec\n"
- "real-time_speed_phase1: N/A\n"
- "real-time_speed_phase2: "LPU64" items/sec\n"
- "current_position: "DFID"\n",
- lo->ll_objs_checked_phase1,
- checked,
- lo->ll_run_time_phase1,
- rtime,
- speed1,
- speed2,
- new_checked,
- PFID(&com->lc_fid_latest_scanned_phase2));
+ rc = seq_printf(m, "checked_phase1: "LPU64"\n"
+ "checked_phase2: "LPU64"\n"
+ "run_time_phase1: %u seconds\n"
+ "run_time_phase2: %u seconds\n"
+ "average_speed_phase1: "LPU64" items/sec\n"
+ "average_speed_phase2: "LPU64" items/sec\n"
+ "real-time_speed_phase1: N/A\n"
+ "real-time_speed_phase2: "LPU64" items/sec\n"
+ "current_position: "DFID"\n",
+ lo->ll_objs_checked_phase1,
+ checked,
+ lo->ll_run_time_phase1,
+ rtime,
+ speed1,
+ speed2,
+ new_checked,
+ PFID(&com->lc_fid_latest_scanned_phase2));
if (rc <= 0)
goto out;
- buf += rc;
- len -= rc;
} else {
__u64 speed1 = lo->ll_objs_checked_phase1;
__u64 speed2 = lo->ll_objs_checked_phase2;
do_div(speed1, lo->ll_run_time_phase1);
if (lo->ll_run_time_phase2 != 0)
do_div(speed2, lo->ll_run_time_phase2);
- rc = snprintf(buf, len,
- "checked_phase1: "LPU64"\n"
- "checked_phase2: "LPU64"\n"
- "run_time_phase1: %u seconds\n"
- "run_time_phase2: %u seconds\n"
- "average_speed_phase1: "LPU64" items/sec\n"
- "average_speed_phase2: "LPU64" objs/sec\n"
- "real-time_speed_phase1: N/A\n"
- "real-time_speed_phase2: N/A\n"
- "current_position: N/A\n",
- lo->ll_objs_checked_phase1,
- lo->ll_objs_checked_phase2,
- lo->ll_run_time_phase1,
- lo->ll_run_time_phase2,
- speed1,
- speed2);
- if (rc <= 0)
- goto out;
-
- buf += rc;
- len -= rc;
+ seq_printf(m, "checked_phase1: "LPU64"\n"
+ "checked_phase2: "LPU64"\n"
+ "run_time_phase1: %u seconds\n"
+ "run_time_phase2: %u seconds\n"
+ "average_speed_phase1: "LPU64" items/sec\n"
+ "average_speed_phase2: "LPU64" objs/sec\n"
+ "real-time_speed_phase1: N/A\n"
+ "real-time_speed_phase2: N/A\n"
+ "current_position: N/A\n",
+ lo->ll_objs_checked_phase1,
+ lo->ll_objs_checked_phase2,
+ lo->ll_run_time_phase1,
+ lo->ll_run_time_phase2,
+ speed1,
+ speed2);
}
- ret = save - len;
-
out:
up_read(&com->lc_sem);
- return ret;
+ return rc;
}
static int lfsck_layout_master_double_scan(const struct lu_env *env,
ltd_layout_list) {
list_del_init(<d->ltd_layout_list);
}
+ spin_unlock(<ds->ltd_lock);
+
+ ltds = &lfsck->li_mdt_descs;
+ spin_lock(<ds->ltd_lock);
list_for_each_entry_safe(ltd, next, &llmd->llmd_mdt_phase1_list,
ltd_layout_phase_list) {
list_del_init(<d->ltd_layout_phase_list);