* \param[in] env pointer to the thread context
* \param[in] com pointer to the lfsck component
*
- * \retval positive number for data corruption
* \retval 0 for success
- * \retval negative error number on failure
+ * \retval negative error number on failure or data corruption
*/
static int lfsck_layout_load_bitmap(const struct lu_env *env,
struct lfsck_component *com)
size = (lo->ll_bitmap_size + 7) >> 3;
rc = dt_read(env, obj, lfsck_buf_get(env, bitmap->data, size), &pos);
- if (rc == 0) {
- RETURN(-ENOENT);
- } else if (rc != size) {
- CDEBUG(D_LFSCK, "%s: lfsck_layout bitmap size %u != %u\n",
- lfsck_lfsck2name(com->lc_lfsck),
- (unsigned int)size, rc);
-
- RETURN(rc);
- }
+ if (rc != size)
+ RETURN(rc >= 0 ? -EINVAL : rc);
if (cfs_bitmap_check_empty(bitmap))
lad->lad_incomplete = 0;
lo->ll_time_last_complete = lo->ll_time_last_checkpoint;
lo->ll_success_count++;
} else if (rc == 0) {
- lo->ll_status = lfsck->li_status;
- if (lo->ll_status == 0)
+ if (lfsck->li_status != 0)
+ lo->ll_status = lfsck->li_status;
+ else
lo->ll_status = LS_STOPPED;
} else {
lo->ll_status = LS_FAILED;
* but does not know the position (the file name) in the
* layout.
*
+ * type "D": The MDT-object is a directory, it may knows its parent
+ * but because there is no valid linkEA, the LFSCK cannot
+ * know where to put it back to the namespace.
+ * type "O": The MDT-object has no linkEA, and there is no name
+ * entry that references the MDT-object.
+ *
+ * type "P": The orphan object to be created was a parent directory
+ * of some MDT-object which linkEA shows that the @orphan
+ * object is missing.
+ *
* The orphan name will be like:
* ${FID}-${infix}-${type}-${conflict_version}
*
/* layout APIs */
+static void lfsck_layout_slave_quit(const struct lu_env *env,
+ struct lfsck_component *com);
+
static int lfsck_layout_reset(const struct lu_env *env,
struct lfsck_component *com, bool init)
{
ENTRY;
rc = lfsck_layout_load_bitmap(env, com);
- if (rc > 0) {
+ if (rc != 0) {
rc = lfsck_layout_reset(env, com, false);
if (rc == 0)
rc = lfsck_set_param(env, com->lc_lfsck,
lsp->lsp_start, true);
- }
- if (rc != 0)
- GOTO(log, rc);
+ if (rc != 0)
+ GOTO(log, rc);
+ }
rc = lfsck_layout_prep(env, com, lsp->lsp_start);
if (rc != 0)
log:
CDEBUG(D_LFSCK, "%s: layout LFSCK master prep done, start pos ["
- LPU64"\n", lfsck_lfsck2name(com->lc_lfsck),
+ LPU64"]\n", lfsck_lfsck2name(com->lc_lfsck),
com->lc_pos_start.lp_oit_cookie);
return 0;
lo->ll_flags &= ~LF_UPGRADE;
list_move_tail(&com->lc_link, &lfsck->li_list_double_scan);
} else if (result == 0) {
- lo->ll_status = lfsck->li_status;
- if (lo->ll_status == 0)
+ if (lfsck->li_status != 0)
+ lo->ll_status = lfsck->li_status;
+ else
lo->ll_status = LS_STOPPED;
- if (lo->ll_status != LS_PAUSED) {
+ if (lo->ll_status != LS_PAUSED)
list_move_tail(&com->lc_link, &lfsck->li_list_idle);
- }
} else {
lo->ll_status = LS_FAILED;
list_move_tail(&com->lc_link, &lfsck->li_list_idle);
lfsck->li_pos_checkpoint.lp_oit_cookie;
if (result > 0) {
- if (lo->ll_flags & LF_INCOMPLETE)
- lo->ll_status = LS_PARTIAL;
- else
- lo->ll_status = LS_SCANNING_PHASE2;
+ lo->ll_status = LS_SCANNING_PHASE2;
lo->ll_flags |= LF_SCANNED_ONCE;
if (lo->ll_flags & LF_CRASHED_LASTID) {
done = true;
lo->ll_flags &= ~LF_UPGRADE;
list_move_tail(&com->lc_link, &lfsck->li_list_double_scan);
} else if (result == 0) {
- lo->ll_status = lfsck->li_status;
- if (lo->ll_status == 0)
+ if (lfsck->li_status != 0)
+ lo->ll_status = lfsck->li_status;
+ else
lo->ll_status = LS_STOPPED;
if (lo->ll_status != LS_PAUSED)
list_move_tail(&com->lc_link, &lfsck->li_list_idle);
lfsck_layout_slave_notify_master(env, com, LE_PHASE1_DONE, result);
- if (result <= 0)
- lfsck_rbtree_cleanup(env, com);
-
CDEBUG(D_LFSCK, "%s: layout LFSCK slave post done: rc = %d\n",
lfsck_lfsck2name(lfsck), rc);
static int lfsck_layout_master_double_scan(const struct lu_env *env,
struct lfsck_component *com)
{
- struct lfsck_layout *lo = com->lc_file_ram;
+ struct lfsck_layout *lo = com->lc_file_ram;
+ struct lfsck_assistant_data *lad = com->lc_data;
+ struct lfsck_instance *lfsck = com->lc_lfsck;
+ struct lfsck_tgt_descs *ltds;
+ struct lfsck_tgt_desc *ltd;
+ struct lfsck_tgt_desc *next;
+ int rc;
+
+ rc = lfsck_double_scan_generic(env, com, lo->ll_status);
+
+ if (thread_is_stopped(&lad->lad_thread)) {
+ LASSERT(list_empty(&lad->lad_req_list));
+ LASSERT(list_empty(&lad->lad_ost_phase1_list));
+ LASSERT(list_empty(&lad->lad_mdt_phase1_list));
+
+ ltds = &lfsck->li_ost_descs;
+ spin_lock(<ds->ltd_lock);
+ list_for_each_entry_safe(ltd, next, &lad->lad_ost_phase2_list,
+ ltd_layout_phase_list) {
+ list_del_init(<d->ltd_layout_phase_list);
+ }
+ spin_unlock(<ds->ltd_lock);
+
+ ltds = &lfsck->li_mdt_descs;
+ spin_lock(<ds->ltd_lock);
+ list_for_each_entry_safe(ltd, next, &lad->lad_mdt_phase2_list,
+ ltd_layout_phase_list) {
+ list_del_init(<d->ltd_layout_phase_list);
+ }
+ spin_unlock(<ds->ltd_lock);
+ }
- return lfsck_double_scan_generic(env, com, lo->ll_status);
+ return rc;
}
static int lfsck_layout_slave_double_scan(const struct lu_env *env,
int rc;
ENTRY;
- if (unlikely(lo->ll_status != LS_SCANNING_PHASE2)) {
- lfsck_rbtree_cleanup(env, com);
- lfsck_layout_slave_notify_master(env, com, LE_PHASE2_DONE, 0);
- RETURN(0);
- }
-
CDEBUG(D_LFSCK, "%s: layout LFSCK slave phase2 scan start\n",
lfsck_lfsck2name(lfsck));
+ if (lo->ll_flags & LF_INCOMPLETE)
+ GOTO(done, rc = 1);
+
atomic_inc(&lfsck->li_double_scan_count);
com->lc_new_checked = 0;
done:
rc = lfsck_layout_double_scan_result(env, com, rc);
-
- lfsck_rbtree_cleanup(env, com);
- lfsck_layout_slave_notify_master(env, com, LE_PHASE2_DONE, rc);
+ lfsck_layout_slave_notify_master(env, com, LE_PHASE2_DONE,
+ (rc > 0 && lo->ll_flags & LF_INCOMPLETE) ? 0 : rc);
+ lfsck_layout_slave_quit(env, com);
if (atomic_dec_and_test(&lfsck->li_double_scan_count))
wake_up_all(&lfsck->li_thread.t_ctl_waitq);
}
spin_unlock(<ds->ltd_lock);
- CFS_FREE_BITMAP(lad->lad_bitmap);
+ if (likely(lad->lad_bitmap != NULL))
+ CFS_FREE_BITMAP(lad->lad_bitmap);
OBD_FREE_PTR(lad);
}
static void lfsck_layout_slave_data_release(const struct lu_env *env,
struct lfsck_component *com)
{
+ struct lfsck_layout_slave_data *llsd = com->lc_data;
+
+ lfsck_layout_slave_quit(env, com);
+ com->lc_data = NULL;
+ OBD_FREE_PTR(llsd);
+}
+
+static void lfsck_layout_master_quit(const struct lu_env *env,
+ struct lfsck_component *com)
+{
+ struct lfsck_assistant_data *lad = com->lc_data;
+ struct lfsck_instance *lfsck = com->lc_lfsck;
+ struct lfsck_tgt_descs *ltds;
+ struct lfsck_tgt_desc *ltd;
+ struct lfsck_tgt_desc *next;
+
+ LASSERT(lad != NULL);
+
+ lfsck_quit_generic(env, com);
+
+ LASSERT(thread_is_init(&lad->lad_thread) ||
+ thread_is_stopped(&lad->lad_thread));
+ LASSERT(list_empty(&lad->lad_req_list));
+
+ ltds = &lfsck->li_ost_descs;
+ spin_lock(<ds->ltd_lock);
+ list_for_each_entry_safe(ltd, next, &lad->lad_ost_phase1_list,
+ ltd_layout_phase_list) {
+ list_del_init(<d->ltd_layout_phase_list);
+ }
+ list_for_each_entry_safe(ltd, next, &lad->lad_ost_phase2_list,
+ ltd_layout_phase_list) {
+ list_del_init(<d->ltd_layout_phase_list);
+ }
+ spin_unlock(<ds->ltd_lock);
+
+ ltds = &lfsck->li_mdt_descs;
+ spin_lock(<ds->ltd_lock);
+ list_for_each_entry_safe(ltd, next, &lad->lad_mdt_phase1_list,
+ ltd_layout_phase_list) {
+ list_del_init(<d->ltd_layout_phase_list);
+ }
+ list_for_each_entry_safe(ltd, next, &lad->lad_mdt_phase2_list,
+ ltd_layout_phase_list) {
+ list_del_init(<d->ltd_layout_phase_list);
+ }
+ spin_unlock(<ds->ltd_lock);
+}
+
+static void lfsck_layout_slave_quit(const struct lu_env *env,
+ struct lfsck_component *com)
+{
struct lfsck_layout_slave_data *llsd = com->lc_data;
struct lfsck_layout_seq *lls;
struct lfsck_layout_seq *next;
struct lfsck_layout_slave_target *llst;
- struct lfsck_layout_slave_target *tmp;
LASSERT(llsd != NULL);
list_for_each_entry_safe(lls, next, &llsd->llsd_seq_list,
- lls_list) {
+ lls_list) {
list_del_init(&lls->lls_list);
lfsck_object_put(env, lls->lls_lastid_obj);
OBD_FREE_PTR(lls);
}
- list_for_each_entry_safe(llst, tmp, &llsd->llsd_master_list,
- llst_list) {
+ spin_lock(&llsd->llsd_lock);
+ while (!list_empty(&llsd->llsd_master_list)) {
+ llst = list_entry(llsd->llsd_master_list.next,
+ struct lfsck_layout_slave_target, llst_list);
list_del_init(&llst->llst_list);
- OBD_FREE_PTR(llst);
+ spin_unlock(&llsd->llsd_lock);
+ lfsck_layout_llst_put(llst);
}
+ spin_unlock(&llsd->llsd_lock);
lfsck_rbtree_cleanup(env, com);
- com->lc_data = NULL;
- OBD_FREE_PTR(llsd);
-}
-
-static void lfsck_layout_slave_quit(const struct lu_env *env,
- struct lfsck_component *com)
-{
- lfsck_rbtree_cleanup(env, com);
}
static int lfsck_layout_master_in_notify(const struct lu_env *env,
struct lfsck_component *com,
- struct lfsck_request *lr)
+ struct lfsck_request *lr,
+ struct thandle *th)
{
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_layout *lo = com->lc_file_ram;
}
CDEBUG(D_LFSCK, "%s: layout LFSCK master handles notify %u "
- "from %s %x, status %d\n", lfsck_lfsck2name(lfsck),
- lr->lr_event, (lr->lr_flags & LEF_TO_OST) ? "OST" : "MDT",
- lr->lr_index, lr->lr_status);
+ "from %s %x, status %d, flags %x, flags2 %x\n",
+ lfsck_lfsck2name(lfsck), lr->lr_event,
+ (lr->lr_flags & LEF_TO_OST) ? "OST" : "MDT",
+ lr->lr_index, lr->lr_status, lr->lr_flags, lr->lr_flags2);
if (lr->lr_event != LE_PHASE1_DONE &&
lr->lr_event != LE_PHASE2_DONE &&
static int lfsck_layout_slave_in_notify(const struct lu_env *env,
struct lfsck_component *com,
- struct lfsck_request *lr)
+ struct lfsck_request *lr,
+ struct thandle *th)
{
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_layout_slave_data *llsd = com->lc_data;
.lfsck_dump = lfsck_layout_dump,
.lfsck_double_scan = lfsck_layout_master_double_scan,
.lfsck_data_release = lfsck_layout_master_data_release,
- .lfsck_quit = lfsck_quit_generic,
+ .lfsck_quit = lfsck_layout_master_quit,
.lfsck_in_notify = lfsck_layout_master_in_notify,
.lfsck_query = lfsck_layout_query,
};