int tgt_brw_read(struct tgt_session_info *tsi);
int tgt_brw_write(struct tgt_session_info *tsi);
int tgt_hpreq_handler(struct ptlrpc_request *req);
-void tgt_register_lfsck_start(int (*start)(const struct lu_env *,
- struct dt_device *,
- struct lfsck_start_param *));
void tgt_register_lfsck_in_notify(int (*notify)(const struct lu_env *,
struct dt_device *,
struct lfsck_request *));
/* Dryrun mode, only check without modification */
LPF_DRYRUN = 0x0004,
- /* Start/stop LFSCK on all MDT devices. */
- LPF_ALL_MDT = 0x0008,
+ /* LFSCK runs on all targets. */
+ LPF_ALL_TGT = 0x0008,
- /* Broadcast the command to other MDTs. */
+ /* Broadcast the command to other MDTs. Only valid on the sponsor MDT */
LPF_BROADCAST = 0x0010,
+
+ /* Handle orphan objects. */
+ LPF_ORPHAN = 0x0020,
};
enum lfsck_type {
};
struct lfsck_start_param {
- struct ldlm_namespace *lsp_namespace;
struct lfsck_start *lsp_start;
__u32 lsp_index;
unsigned int lsp_index_valid:1;
LE_STOP = 6,
LE_QUERY = 7,
LE_FID_ACCESSED = 8,
+ LE_PEER_EXIT = 9,
};
enum lfsck_event_flags {
LEF_TO_OST = 0x00000001,
LEF_FROM_OST = 0x00000002,
- LEF_FORCE_STOP = 0x00000004,
};
typedef int (*lfsck_out_notify)(const struct lu_env *env, void *data,
enum lfsck_events event);
+int lfsck_register_namespace(const struct lu_env *env, struct dt_device *key,
+ struct ldlm_namespace *ns);
int lfsck_register(const struct lu_env *env, struct dt_device *key,
struct dt_device *next, struct obd_device *obd,
lfsck_out_notify notify, void *notify_data, bool master);
struct dt_object *oit_obj = lfsck->li_obj_oit;
const struct dt_it_ops *oit_iops = &oit_obj->do_index_ops->dio_it;
struct dt_it *oit_di;
+ struct l_wait_info lwi = { 0 };
int rc;
ENTRY;
spin_unlock(&lfsck->li_lock);
wake_up_all(&thread->t_ctl_waitq);
+ l_wait_event(thread->t_ctl_waitq,
+ lfsck->li_start_unplug ||
+ !thread_is_running(thread),
+ &lwi);
+ if (!thread_is_running(thread))
+ GOTO(fini_oit, rc = 0);
+
if (!cfs_list_empty(&lfsck->li_list_scan) ||
cfs_list_empty(&lfsck->li_list_double_scan))
rc = lfsck_master_oit_engine(env, lfsck);
int result,
bool init);
+ int (*lfsck_interpret)(const struct lu_env *env,
+ struct ptlrpc_request *req,
+ void *args,
+ int rc);
+
int (*lfsck_dump)(const struct lu_env *env,
struct lfsck_component *com,
char *buf,
unsigned int li_oit_over:1, /* oit is finished. */
li_drop_dryrun:1, /* Ever dryrun, not now. */
li_master:1, /* Master instance or not. */
- li_current_oit_processed:1;
+ li_current_oit_processed:1,
+ li_start_unplug:1;
};
enum lfsck_linkea_flags {
struct lfsck_tgt_descs *laia_ltds;
struct lfsck_tgt_desc *laia_ltd;
struct lfsck_request *laia_lr;
+ int laia_result;
+ unsigned int laia_shared:1;
};
struct lfsck_thread_args {
char lti_key[NAME_MAX + 16];
struct lfsck_request lti_lr;
struct lfsck_async_interpret_args lti_laia;
+ struct lfsck_start lti_start;
struct lfsck_stop lti_stop;
ldlm_policy_data_t lti_policy;
struct ldlm_res_id lti_resid;
if (rc != 0) {
struct lfsck_layout *lo = com->lc_file_ram;
+ CERROR("%s: fail to notify %s %x for layout start: "
+ "rc = %d\n", lfsck_lfsck2name(com->lc_lfsck),
+ (lr->lr_flags & LEF_TO_OST) ? "OST" : "MDT",
+ ltd->ltd_index, rc);
lo->ll_flags |= LF_INCOMPLETE;
- lfsck_tgt_put(ltd);
break;
}
spin_lock(<ds->ltd_lock);
if (ltd->ltd_dead || ltd->ltd_layout_done) {
spin_unlock(<ds->ltd_lock);
- lfsck_tgt_put(ltd);
break;
}
&llmd->llmd_mdt_phase1_list);
}
spin_unlock(<ds->ltd_lock);
- lfsck_tgt_put(ltd);
break;
case LE_STOP:
case LE_PHASE1_DONE:
case LE_PHASE2_DONE:
- if (rc != 0)
- CERROR("%s: fail to notify %s %x for layout: "
- "event = %d, rc = %d\n",
- lfsck_lfsck2name(com->lc_lfsck),
- (lr->lr_flags & LEF_TO_OST) ? "OST" : "MDT",
- ltd->ltd_index, lr->lr_event, rc);
+ case LE_PEER_EXIT:
+ if (rc != 0 && rc != -EALREADY)
+ CWARN("%s: fail to notify %s %x for layout: "
+ "event = %d, rc = %d\n",
+ lfsck_lfsck2name(com->lc_lfsck),
+ (lr->lr_flags & LEF_TO_OST) ? "OST" : "MDT",
+ ltd->ltd_index, lr->lr_event, rc);
break;
case LE_QUERY: {
struct lfsck_reply *reply;
list_del_init(<d->ltd_layout_phase_list);
list_del_init(<d->ltd_layout_list);
spin_unlock(<ds->ltd_lock);
- lfsck_tgt_put(ltd);
break;
}
list_del_init(<d->ltd_layout_phase_list);
list_del_init(<d->ltd_layout_list);
spin_unlock(<ds->ltd_lock);
- lfsck_tgt_put(ltd);
break;
}
spin_unlock(<ds->ltd_lock);
break;
}
- lfsck_tgt_put(ltd);
break;
}
default:
break;
}
- lfsck_component_put(env, com);
+ if (!laia->laia_shared) {
+ lfsck_tgt_put(ltd);
+ lfsck_component_put(env, com);
+ }
return 0;
}
struct lfsck_tgt_descs *ltds;
struct lfsck_tgt_desc *ltd;
struct list_head *head;
- __u32 cnt = 0;
int rc = 0;
int rc1 = 0;
ENTRY;
lr->lr_active = LT_LAYOUT;
laia->laia_com = com;
laia->laia_lr = lr;
+ laia->laia_shared = 0;
if (!list_empty(&llmd->llmd_mdt_phase1_list)) {
ltds = &lfsck->li_mdt_descs;
ltd->ltd_index, rc);
lfsck_tgt_put(ltd);
rc1 = rc;
- } else {
- cnt++;
}
spin_lock(<ds->ltd_lock);
}
spin_unlock(<ds->ltd_lock);
- if (cnt > 0) {
- rc = ptlrpc_set_wait(set);
- if (rc < 0) {
- ptlrpc_set_destroy(set);
- RETURN(rc);
- }
- cnt = 0;
+ rc = ptlrpc_set_wait(set);
+ if (rc < 0) {
+ ptlrpc_set_destroy(set);
+ RETURN(rc);
}
if (!(lr->lr_flags & LEF_TO_OST) &&
static int lfsck_layout_master_notify_others(const struct lu_env *env,
struct lfsck_component *com,
- struct lfsck_request *lr,
- __u32 flags)
+ struct lfsck_request *lr)
{
struct lfsck_thread_info *info = lfsck_env_info(env);
struct lfsck_async_interpret_args *laia = &info->lti_laia;
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_layout_master_data *llmd = com->lc_data;
struct lfsck_layout *lo = com->lc_file_ram;
+ struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
struct ptlrpc_request_set *set;
struct lfsck_tgt_descs *ltds;
struct lfsck_tgt_desc *ltd;
struct lfsck_tgt_desc *next;
struct list_head *head;
__u32 idx;
- __u32 cnt = 0;
int rc = 0;
ENTRY;
if (set == NULL)
RETURN(-ENOMEM);
+ lr->lr_index = lfsck_dev_idx(lfsck->li_bottom);
lr->lr_active = LT_LAYOUT;
laia->laia_com = com;
laia->laia_lr = lr;
- lr->lr_flags = 0;
+ laia->laia_shared = 0;
switch (lr->lr_event) {
case LE_START:
- /* Notify OSTs firstly, then other MDTs if needed. */
- lr->lr_flags |= LEF_TO_OST;
+ /* Notify OSTs firstly, then handle other MDTs if needed. */
ltds = &lfsck->li_ost_descs;
-
-lable1:
laia->laia_ltds = ltds;
down_read(<ds->ltd_rw_sem);
cfs_foreach_bit(ltds->ltd_tgts_bitmap, idx) {
"MDT", idx, rc);
lfsck_tgt_put(ltd);
lo->ll_flags |= LF_INCOMPLETE;
- } else {
- cnt++;
}
}
up_read(<ds->ltd_rw_sem);
/* Sync up */
- if (cnt > 0) {
- rc = ptlrpc_set_wait(set);
- if (rc < 0) {
- ptlrpc_set_destroy(set);
- RETURN(rc);
- }
- cnt = 0;
+ rc = ptlrpc_set_wait(set);
+ if (rc < 0) {
+ ptlrpc_set_destroy(set);
+ RETURN(rc);
}
- if (!(flags & LPF_ALL_MDT))
+ if (!(bk->lb_param & LPF_ALL_TGT))
break;
- ltds = &lfsck->li_mdt_descs;
- /* The sponsor broadcasts the request to other MDTs. */
- if (flags & LPF_BROADCAST) {
- flags &= ~LPF_ALL_MDT;
- lr->lr_flags &= ~LEF_TO_OST;
- goto lable1;
- }
-
- /* non-sponsors link other MDT targets locallly. */
+ /* link other MDT targets locallly. */
spin_lock(<ds->ltd_lock);
cfs_foreach_bit(ltds->ltd_tgts_bitmap, idx) {
ltd = LTD_TGT(ltds, idx);
&llmd->llmd_mdt_phase1_list);
}
spin_unlock(<ds->ltd_lock);
-
break;
case LE_STOP:
- if (flags & LPF_BROADCAST)
- lr->lr_flags |= LEF_FORCE_STOP;
case LE_PHASE2_DONE:
- /* Notify other MDTs if needed, then the OSTs. */
- if (flags & LPF_ALL_MDT) {
- /* The sponsor broadcasts the request to other MDTs. */
- if (flags & LPF_BROADCAST) {
- lr->lr_flags &= ~LEF_TO_OST;
- head = &llmd->llmd_mdt_list;
- ltds = &lfsck->li_mdt_descs;
- goto lable3;
- }
-
- /* non-sponsors unlink other MDT targets locallly. */
+ case LE_PEER_EXIT: {
+ /* Handle other MDTs firstly if needed, then notify the OSTs. */
+ if (bk->lb_param & LPF_ALL_TGT) {
+ head = &llmd->llmd_mdt_list;
ltds = &lfsck->li_mdt_descs;
- spin_lock(<ds->ltd_lock);
- list_for_each_entry_safe(ltd, next,
- &llmd->llmd_mdt_list,
- ltd_layout_list) {
- list_del_init(<d->ltd_layout_phase_list);
- list_del_init(<d->ltd_layout_list);
+ if (lr->lr_event == LE_STOP) {
+ /* unlink other MDT targets locallly. */
+ spin_lock(<ds->ltd_lock);
+ list_for_each_entry_safe(ltd, next, head,
+ ltd_layout_list) {
+ list_del_init(<d->ltd_layout_phase_list);
+ list_del_init(<d->ltd_layout_list);
+ }
+ spin_unlock(<ds->ltd_lock);
+
+ lr->lr_flags |= LEF_TO_OST;
+ head = &llmd->llmd_ost_list;
+ ltds = &lfsck->li_ost_descs;
+ } else {
+ lr->lr_flags &= ~LEF_TO_OST;
}
- spin_unlock(<ds->ltd_lock);
+ } else {
+ lr->lr_flags |= LEF_TO_OST;
+ head = &llmd->llmd_ost_list;
+ ltds = &lfsck->li_ost_descs;
}
-lable2:
- lr->lr_flags |= LEF_TO_OST;
- head = &llmd->llmd_ost_list;
- ltds = &lfsck->li_ost_descs;
-
-lable3:
+again:
laia->laia_ltds = ltds;
spin_lock(<ds->ltd_lock);
while (!list_empty(head)) {
if (!list_empty(<d->ltd_layout_phase_list))
list_del_init(<d->ltd_layout_phase_list);
list_del_init(<d->ltd_layout_list);
+ atomic_inc(<d->ltd_ref);
laia->laia_ltd = ltd;
spin_unlock(<ds->ltd_lock);
rc = lfsck_async_request(env, ltd->ltd_exp, lr, set,
lfsck_layout_master_async_interpret,
laia, LFSCK_NOTIFY);
- if (rc != 0)
+ if (rc != 0) {
CERROR("%s: fail to notify %s %x for layout "
"stop/phase2: rc = %d\n",
lfsck_lfsck2name(lfsck),
(lr->lr_flags & LEF_TO_OST) ? "OST" :
"MDT", ltd->ltd_index, rc);
- else
- cnt++;
+ lfsck_tgt_put(ltd);
+ }
spin_lock(<ds->ltd_lock);
}
spin_unlock(<ds->ltd_lock);
- if (!(flags & LPF_BROADCAST))
- break;
-
- /* Sync up */
- if (cnt > 0) {
- rc = ptlrpc_set_wait(set);
- if (rc < 0) {
- ptlrpc_set_destroy(set);
- RETURN(rc);
- }
- cnt = 0;
+ rc = ptlrpc_set_wait(set);
+ if (rc < 0) {
+ ptlrpc_set_destroy(set);
+ RETURN(rc);
}
- flags &= ~LPF_BROADCAST;
- goto lable2;
+ if (!(lr->lr_flags & LEF_TO_OST)) {
+ lr->lr_flags |= LEF_TO_OST;
+ head = &llmd->llmd_ost_list;
+ ltds = &lfsck->li_ost_descs;
+ goto again;
+ }
+ break;
+ }
case LE_PHASE1_DONE:
llmd->llmd_touch_gen++;
- lr->lr_flags &= ~LEF_TO_OST;
ltds = &lfsck->li_mdt_descs;
laia->laia_ltds = ltds;
spin_lock(<ds->ltd_lock);
list_del_init(<d->ltd_layout_phase_list);
list_add_tail(<d->ltd_layout_phase_list,
&llmd->llmd_mdt_phase1_list);
+ atomic_inc(<d->ltd_ref);
laia->laia_ltd = ltd;
spin_unlock(<ds->ltd_lock);
rc = lfsck_async_request(env, ltd->ltd_exp, lr, set,
lfsck_layout_master_async_interpret,
laia, LFSCK_NOTIFY);
- if (rc != 0)
+ if (rc != 0) {
CERROR("%s: fail to notify MDT %x for layout "
"phase1 done: rc = %d\n",
lfsck_lfsck2name(lfsck),
ltd->ltd_index, rc);
- else
- cnt++;
+ lfsck_tgt_put(ltd);
+ }
spin_lock(<ds->ltd_lock);
}
spin_unlock(<ds->ltd_lock);
break;
}
- if (cnt > 0)
- rc = ptlrpc_set_wait(set);
+ rc = ptlrpc_set_wait(set);
ptlrpc_set_destroy(set);
- if (rc == 0 && lr->lr_event == LE_START &&
- list_empty(&llmd->llmd_ost_list))
- rc = -ENODEV;
-
RETURN(rc);
}
* mark the LFSCK as INCOMPLETE. */
if (rc == -ENOTCONN || rc == -ESHUTDOWN || rc == -ETIMEDOUT ||
rc == -EHOSTDOWN || rc == -EHOSTUNREACH) {
+ CERROR("%s: Fail to take with OST %x: rc = %d.\n",
+ lfsck_lfsck2name(lfsck), llr->llr_ost_idx, rc);
lo->ll_flags |= LF_INCOMPLETE;
lo->ll_objs_skipped++;
rc = 0;
struct l_wait_info lwi = { 0 };
int rc = 0;
int rc1 = 0;
- __u32 flags;
ENTRY;
- if (lta->lta_lsp->lsp_start != NULL)
- flags = lta->lta_lsp->lsp_start->ls_flags;
- else
- flags = bk->lb_param;
memset(lr, 0, sizeof(*lr));
lr->lr_event = LE_START;
- lr->lr_index = lfsck_dev_idx(lfsck->li_bottom);
lr->lr_valid = LSV_SPEED_LIMIT | LSV_ERROR_HANDLE | LSV_DRYRUN |
LSV_ASYNC_WINDOWS;
lr->lr_speed = bk->lb_speed_limit;
lr->lr_version = bk->lb_version;
lr->lr_param = bk->lb_param;
lr->lr_async_windows = bk->lb_async_windows;
+ lr->lr_flags = LEF_TO_OST;
if (pos->lp_oit_cookie <= 1)
lr->lr_param |= LPF_RESET;
- rc = lfsck_layout_master_notify_others(env, com, lr, flags);
+ rc = lfsck_layout_master_notify_others(env, com, lr);
if (rc != 0) {
CERROR("%s: fail to notify others for layout start: rc = %d\n",
lfsck_lfsck2name(lfsck), rc);
LASSERT(llmd->llmd_post_result > 0);
memset(lr, 0, sizeof(*lr));
- lr->lr_index = lfsck_dev_idx(lfsck->li_bottom);
lr->lr_event = LE_PHASE1_DONE;
lr->lr_status = llmd->llmd_post_result;
- rc = lfsck_layout_master_notify_others(env, com, lr, 0);
+ rc = lfsck_layout_master_notify_others(env, com, lr);
if (rc != 0)
CERROR("%s: failed to notify others "
"for layout post: rc = %d\n",
cleanup2:
memset(lr, 0, sizeof(*lr));
- lr->lr_index = lfsck_dev_idx(lfsck->li_bottom);
if (rc > 0) {
lr->lr_event = LE_PHASE2_DONE;
- flags = 0;
lr->lr_status = rc;
} else if (rc == 0) {
- lr->lr_event = LE_STOP;
- if (lfsck->li_status == LS_PAUSED ||
- lfsck->li_status == LS_CO_PAUSED) {
- flags = 0;
- lr->lr_status = LS_CO_PAUSED;
- } else if (lfsck->li_status == LS_STOPPED ||
- lfsck->li_status == LS_CO_STOPPED) {
- flags = lfsck->li_flags;
- if (flags & LPF_BROADCAST)
- lr->lr_status = LS_STOPPED;
- else
- lr->lr_status = LS_CO_STOPPED;
+ if (lfsck->li_flags & LPF_ALL_TGT) {
+ lr->lr_event = LE_STOP;
+ lr->lr_status = LS_STOPPED;
} else {
- LBUG();
+ lr->lr_event = LE_PEER_EXIT;
+ switch (lfsck->li_status) {
+ case LS_PAUSED:
+ case LS_CO_PAUSED:
+ lr->lr_status = LS_CO_PAUSED;
+ break;
+ case LS_STOPPED:
+ case LS_CO_STOPPED:
+ lr->lr_status = LS_CO_STOPPED;
+ break;
+ default:
+ CERROR("%s: unknown status: rc = %d\n",
+ lfsck_lfsck2name(lfsck),
+ lfsck->li_status);
+ lr->lr_status = LS_CO_FAILED;
+ break;
+ }
}
} else {
- lr->lr_event = LE_STOP;
- flags = 0;
- lr->lr_status = LS_CO_FAILED;
+ if (lfsck->li_flags & LPF_ALL_TGT) {
+ lr->lr_event = LE_STOP;
+ lr->lr_status = LS_FAILED;
+ } else {
+ lr->lr_event = LE_PEER_EXIT;
+ lr->lr_status = LS_CO_FAILED;
+ }
}
- rc1 = lfsck_layout_master_notify_others(env, com, lr, flags);
+ rc1 = lfsck_layout_master_notify_others(env, com, lr);
if (rc1 != 0) {
CERROR("%s: failed to notify others for layout quit: rc = %d\n",
lfsck_lfsck2name(lfsck), rc1);
struct lfsck_layout_slave_target *llst;
struct obd_export *exp;
struct ptlrpc_request_set *set;
- int cnt = 0;
int rc = 0;
int rc1 = 0;
ENTRY;
rc1 = rc;
lfsck_layout_llst_put(llst);
class_export_put(exp);
- } else {
- cnt++;
}
spin_lock(&llsd->llsd_lock);
}
spin_unlock(&llsd->llsd_lock);
- if (cnt > 0)
- rc = ptlrpc_set_wait(set);
+ rc = ptlrpc_set_wait(set);
ptlrpc_set_destroy(set);
RETURN(rc1 != 0 ? rc1 : rc);
struct lfsck_layout_slave_target *llst;
struct obd_export *exp;
struct ptlrpc_request_set *set;
- int cnt = 0;
int rc;
ENTRY;
CERROR("%s: slave fail to notify %s for layout: "
"rc = %d\n", lfsck_lfsck2name(lfsck),
exp->exp_obd->obd_name, rc);
- else
- cnt++;
lfsck_layout_llst_put(llst);
class_export_put(exp);
spin_lock(&llsd->llsd_lock);
}
spin_unlock(&llsd->llsd_lock);
- if (cnt > 0)
- rc = ptlrpc_set_wait(set);
-
+ ptlrpc_set_wait(set);
ptlrpc_set_destroy(set);
RETURN_EXIT;
}
static int lfsck_layout_prep(const struct lu_env *env,
- struct lfsck_component *com)
+ struct lfsck_component *com,
+ struct lfsck_start *start)
{
struct lfsck_instance *lfsck = com->lc_lfsck;
struct lfsck_layout *lo = com->lc_file_ram;
fid_zero(&pos->lp_dir_parent);
pos->lp_dir_cookie = 0;
if (lo->ll_status == LS_COMPLETED ||
- lo->ll_status == LS_PARTIAL) {
+ lo->ll_status == LS_PARTIAL ||
+ /* To handle orphan, must scan from the beginning. */
+ (start != NULL && start->ls_flags & LPF_ORPHAN)) {
int rc;
rc = lfsck_layout_reset(env, com, false);
}
down_write(&com->lc_sem);
-
lo->ll_time_latest_start = cfs_time_current_sec();
-
spin_lock(&lfsck->li_lock);
if (lo->ll_flags & LF_SCANNED_ONCE) {
if (!lfsck->li_drop_dryrun ||
pos->lp_oit_cookie = lo->ll_pos_first_inconsistent;
}
spin_unlock(&lfsck->li_lock);
-
up_write(&com->lc_sem);
return 0;
struct lfsck_component *com,
struct lfsck_start_param *lsp)
{
- struct lfsck_layout *lo = com->lc_file_ram;
struct lfsck_layout_slave_data *llsd = com->lc_data;
+ struct lfsck_start *start = lsp->lsp_start;
int rc;
- rc = lfsck_layout_prep(env, com);
- if (rc != 0 || lo->ll_status != LS_SCANNING_PHASE1 ||
- !lsp->lsp_index_valid)
+ rc = lfsck_layout_prep(env, com, start);
+ if (rc != 0 || !lsp->lsp_index_valid)
return rc;
rc = lfsck_layout_llst_add(llsd, lsp->lsp_index);
- if (rc == 0 && !(lo->ll_flags & LF_INCOMPLETE)) {
+ if (rc == 0 && start != NULL && start->ls_flags & LPF_ORPHAN) {
LASSERT(!llsd->llsd_rbtree_valid);
write_lock(&llsd->llsd_rb_lock);
long rc;
ENTRY;
- rc = lfsck_layout_prep(env, com);
+ rc = lfsck_layout_prep(env, com, lsp->lsp_start);
if (rc != 0)
RETURN(rc);
ostid_to_fid(fid, oi, index);
tgt = lfsck_tgt_get(ltds, index);
if (unlikely(tgt == NULL)) {
+ CERROR("%s: Cannot talk with OST %x which is not join "
+ "the layout LFSCK.\n",
+ lfsck_lfsck2name(lfsck), index);
lo->ll_flags |= LF_INCOMPLETE;
goto next;
}
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);
}
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);
if (atomic_dec_and_test(&lfsck->li_double_scan_count))
wake_up_all(&lfsck->li_thread.t_ctl_waitq);
struct lfsck_layout_master_data *llmd = com->lc_data;
struct lfsck_tgt_descs *ltds;
struct lfsck_tgt_desc *ltd;
+ bool fail = false;
ENTRY;
if (lr->lr_event != LE_PHASE1_DONE &&
lr->lr_event != LE_PHASE2_DONE &&
- lr->lr_event != LE_STOP)
+ lr->lr_event != LE_PEER_EXIT)
RETURN(-EINVAL);
if (lr->lr_flags & LEF_FROM_OST)
if (lr->lr_status <= 0) {
ltd->ltd_layout_done = 1;
list_del_init(<d->ltd_layout_list);
+ CWARN("%s: %s %x failed/stopped at phase1: rc = %d.\n",
+ lfsck_lfsck2name(lfsck),
+ (lr->lr_flags & LEF_TO_OST) ? "OST" : "MDT",
+ ltd->ltd_index, lr->lr_status);
lo->ll_flags |= LF_INCOMPLETE;
+ fail = true;
break;
}
ltd->ltd_layout_done = 1;
list_del_init(<d->ltd_layout_list);
break;
- case LE_STOP:
+ case LE_PEER_EXIT:
+ fail = true;
ltd->ltd_layout_done = 1;
list_del_init(<d->ltd_layout_list);
- if (!(lr->lr_flags & LEF_FORCE_STOP))
+ if (!(lfsck->li_bookmark_ram.lb_param & LPF_FAILOUT)) {
+ CWARN("%s: the peer %s %x exit layout LFSCK.\n",
+ lfsck_lfsck2name(lfsck),
+ (lr->lr_flags & LEF_TO_OST) ? "OST" : "MDT",
+ ltd->ltd_index);
lo->ll_flags |= LF_INCOMPLETE;
+ }
break;
default:
break;
}
spin_unlock(<ds->ltd_lock);
- if (lr->lr_flags & LEF_FORCE_STOP) {
+ if (fail && lfsck->li_bookmark_ram.lb_param & LPF_FAILOUT) {
struct lfsck_stop *stop = &lfsck_env_info(env)->lti_stop;
memset(stop, 0, sizeof(*stop));
stop->ls_status = lr->lr_status;
- stop->ls_flags = lr->lr_param;
+ stop->ls_flags = lr->lr_param & ~LPF_BROADCAST;
lfsck_stop(env, lfsck->li_bottom, stop);
} else if (lfsck_layout_master_to_orphan(llmd)) {
wake_up_all(&llmd->llmd_thread.t_ctl_waitq);
RETURN(0);
}
- if (lr->lr_event != LE_PHASE2_DONE &&
- lr->lr_event != LE_STOP)
+ if (lr->lr_event != LE_PHASE2_DONE && lr->lr_event != LE_PEER_EXIT)
RETURN(-EINVAL);
llst = lfsck_layout_llst_find_and_del(llsd, lr->lr_index);
RETURN(-ENODEV);
lfsck_layout_llst_put(llst);
- if (list_empty(&llsd->llsd_master_list)) {
- switch (lr->lr_event) {
- case LE_PHASE2_DONE:
- wake_up_all(&lfsck->li_thread.t_ctl_waitq);
- break;
- case LE_STOP: {
- struct lfsck_stop *stop = &lfsck_env_info(env)->lti_stop;
+ if (list_empty(&llsd->llsd_master_list))
+ wake_up_all(&lfsck->li_thread.t_ctl_waitq);
- memset(stop, 0, sizeof(*stop));
- stop->ls_status = lr->lr_status;
- stop->ls_flags = lr->lr_param;
- lfsck_stop(env, lfsck->li_bottom, stop);
- break;
- }
- default:
- break;
- }
+ if (lr->lr_event == LE_PEER_EXIT &&
+ lfsck->li_bookmark_ram.lb_param & LPF_FAILOUT) {
+ struct lfsck_stop *stop = &lfsck_env_info(env)->lti_stop;
+
+ memset(stop, 0, sizeof(*stop));
+ stop->ls_status = lr->lr_status;
+ stop->ls_flags = lr->lr_param & ~LPF_BROADCAST;
+ lfsck_stop(env, lfsck->li_bottom, stop);
}
RETURN(0);
struct lfsck_instance *lfsck = com->lc_lfsck;
int rc;
- LASSERT(list_empty(<d->ltd_layout_list));
- LASSERT(list_empty(<d->ltd_layout_phase_list));
+ spin_lock(<ds->ltd_lock);
+ if (list_empty(<d->ltd_layout_list)) {
+ LASSERT(list_empty(<d->ltd_layout_phase_list));
+ spin_unlock(<ds->ltd_lock);
+
+ return 0;
+ }
+
+ list_del_init(<d->ltd_layout_phase_list);
+ list_del_init(<d->ltd_layout_list);
+ spin_unlock(<ds->ltd_lock);
memset(lr, 0, sizeof(*lr));
lr->lr_index = lfsck_dev_idx(lfsck->li_bottom);
- lr->lr_event = LE_STOP;
+ lr->lr_event = LE_PEER_EXIT;
lr->lr_active = LT_LAYOUT;
- if (ltds == &lfsck->li_ost_descs) {
+ lr->lr_status = LS_CO_PAUSED;
+ if (ltds == &lfsck->li_ost_descs)
lr->lr_flags = LEF_TO_OST;
- } else {
- if (ltd->ltd_index == lfsck_dev_idx(lfsck->li_bottom))
- return 0;
-
- lr->lr_flags = 0;
- }
- lr->lr_status = LS_CO_STOPPED;
laia->laia_com = com;
laia->laia_ltds = ltds;
+ atomic_inc(<d->ltd_ref);
laia->laia_ltd = ltd;
laia->laia_lr = lr;
+ laia->laia_shared = 0;
rc = lfsck_async_request(env, ltd->ltd_exp, lr, set,
lfsck_layout_master_async_interpret,
laia, LFSCK_NOTIFY);
- if (rc != 0)
+ if (rc != 0) {
CERROR("%s: Fail to notify %s %x for co-stop: rc = %d\n",
lfsck_lfsck2name(lfsck),
(lr->lr_flags & LEF_TO_OST) ? "OST" : "MDT",
ltd->ltd_index, rc);
+ lfsck_tgt_put(ltd);
+ }
return rc;
}
ENTRY;
if (!lsp->lsp_index_valid || start == NULL ||
- !(start->ls_flags & LPF_ALL_MDT))
+ !(start->ls_flags & LPF_ALL_TGT) ||
+ !(lfsck->li_bookmark_ram.lb_param & LPF_ALL_TGT))
RETURN(-EALREADY);
spin_unlock(&lfsck->li_lock);
.lfsck_exec_oit = lfsck_layout_master_exec_oit,
.lfsck_exec_dir = lfsck_layout_exec_dir,
.lfsck_post = lfsck_layout_master_post,
+ .lfsck_interpret = lfsck_layout_master_async_interpret,
.lfsck_dump = lfsck_layout_dump,
.lfsck_double_scan = lfsck_layout_master_double_scan,
.lfsck_data_release = lfsck_layout_master_data_release,
return result;
}
+static void lfsck_interpret(const struct lu_env *env,
+ struct lfsck_instance *lfsck,
+ struct ptlrpc_request *req, void *args, int result)
+{
+ struct lfsck_async_interpret_args *laia = args;
+ struct lfsck_component *com;
+
+ LASSERT(laia->laia_shared);
+
+ spin_lock(&lfsck->li_lock);
+ list_for_each_entry(com, &lfsck->li_list_scan, lc_link) {
+ if (com->lc_ops->lfsck_interpret != NULL) {
+ laia->laia_com = com;
+ com->lc_ops->lfsck_interpret(env, req, laia, result);
+ }
+ }
+
+ list_for_each_entry(com, &lfsck->li_list_double_scan, lc_link) {
+ if (com->lc_ops->lfsck_interpret != NULL) {
+ laia->laia_com = com;
+ com->lc_ops->lfsck_interpret(env, req, laia, result);
+ }
+ }
+ spin_unlock(&lfsck->li_lock);
+}
+
int lfsck_double_scan(const struct lu_env *env, struct lfsck_instance *lfsck)
{
struct lfsck_component *com;
return rc1 != 0 ? rc1 : rc;
}
-int lfsck_stop_notify(const struct lu_env *env, struct lfsck_instance *lfsck,
- struct lfsck_tgt_descs *ltds, struct lfsck_tgt_desc *ltd)
+static int lfsck_stop_notify(const struct lu_env *env,
+ struct lfsck_instance *lfsck,
+ struct lfsck_tgt_descs *ltds,
+ struct lfsck_tgt_desc *ltd, __u16 type)
{
struct ptlrpc_request_set *set;
struct lfsck_component *com;
- int cnt = 0;
int rc = 0;
- int rc1 = 0;
+ ENTRY;
- set = ptlrpc_prep_set();
- if (set == NULL)
- return -ENOMEM;
+ spin_lock(&lfsck->li_lock);
+ com = __lfsck_component_find(lfsck, type, &lfsck->li_list_scan);
+ if (com == NULL)
+ com = __lfsck_component_find(lfsck, type,
+ &lfsck->li_list_double_scan);
+ if (com != NULL)
+ lfsck_component_get(com);
+ spin_lock(&lfsck->li_lock);
- list_for_each_entry(com, &lfsck->li_list_scan, lc_link) {
+ if (com != NULL) {
if (com->lc_ops->lfsck_stop_notify != NULL) {
- rc = com->lc_ops->lfsck_stop_notify(env, com, ltds,
- ltd, set);
- if (rc != 0)
- rc1 = rc;
- else
- cnt++;
- }
- }
+ set = ptlrpc_prep_set();
+ if (set == NULL) {
+ lfsck_component_put(env, com);
+
+ RETURN(-ENOMEM);
+ }
- list_for_each_entry(com, &lfsck->li_list_double_scan, lc_link) {
- if (com->lc_ops->lfsck_stop_notify != NULL) {
rc = com->lc_ops->lfsck_stop_notify(env, com, ltds,
ltd, set);
- if (rc != 0)
- rc1 = rc;
- else
- cnt++;
+ if (rc == 0)
+ rc = ptlrpc_set_wait(set);
+
+ ptlrpc_set_destroy(set);
}
- }
- if (cnt > 0)
- rc = ptlrpc_set_wait(set);
- ptlrpc_set_destroy(set);
+ lfsck_component_put(env, com);
+ }
- return rc1 != 0 ? rc1 : rc;
+ RETURN(rc);
}
void lfsck_quit(const struct lu_env *env, struct lfsck_instance *lfsck)
}
}
+static int lfsck_async_interpret(const struct lu_env *env,
+ struct ptlrpc_request *req,
+ void *args, int rc)
+{
+ struct lfsck_async_interpret_args *laia = args;
+ struct lfsck_instance *lfsck;
+
+ lfsck = container_of0(laia->laia_ltds, struct lfsck_instance,
+ li_mdt_descs);
+ lfsck_interpret(env, lfsck, req, laia, rc);
+ lfsck_tgt_put(laia->laia_ltd);
+ if (rc != 0 && laia->laia_result != -EALREADY)
+ laia->laia_result = rc;
+
+ return 0;
+}
+
int lfsck_async_request(const struct lu_env *env, struct obd_export *exp,
struct lfsck_request *lr,
struct ptlrpc_request_set *set,
laia = ptlrpc_req_async_args(req);
*laia = *(struct lfsck_async_interpret_args *)args;
- lfsck_component_get(laia->laia_com);
+ if (laia->laia_com != NULL)
+ lfsck_component_get(laia->laia_com);
req->rq_interpret_reply = interpreter;
ptlrpc_set_add_req(set, req);
}
EXPORT_SYMBOL(lfsck_dump);
+static int lfsck_stop_all(const struct lu_env *env,
+ struct lfsck_instance *lfsck,
+ struct lfsck_stop *stop)
+{
+ struct lfsck_thread_info *info = lfsck_env_info(env);
+ struct lfsck_request *lr = &info->lti_lr;
+ struct lfsck_async_interpret_args *laia = &info->lti_laia;
+ struct ptlrpc_request_set *set;
+ struct lfsck_tgt_descs *ltds = &lfsck->li_mdt_descs;
+ struct lfsck_tgt_desc *ltd;
+ struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
+ __u32 idx;
+ int rc = 0;
+ int rc1 = 0;
+ ENTRY;
+
+ LASSERT(stop->ls_flags & LPF_BROADCAST);
+
+ set = ptlrpc_prep_set();
+ if (unlikely(set == NULL)) {
+ CERROR("%s: cannot allocate memory for stop LFSCK on "
+ "all targets\n", lfsck_lfsck2name(lfsck));
+
+ RETURN(-ENOMEM);
+ }
+
+ memset(lr, 0, sizeof(*lr));
+ lr->lr_event = LE_STOP;
+ lr->lr_index = lfsck_dev_idx(lfsck->li_bottom);
+ lr->lr_status = stop->ls_status;
+ lr->lr_version = bk->lb_version;
+ lr->lr_active = LFSCK_TYPES_ALL;
+ lr->lr_param = stop->ls_flags;
+
+ laia->laia_com = NULL;
+ laia->laia_ltds = ltds;
+ laia->laia_lr = lr;
+ laia->laia_result = 0;
+ laia->laia_shared = 1;
+
+ down_read(<ds->ltd_rw_sem);
+ cfs_foreach_bit(ltds->ltd_tgts_bitmap, idx) {
+ ltd = lfsck_tgt_get(ltds, idx);
+ LASSERT(ltd != NULL);
+
+ laia->laia_ltd = ltd;
+ rc = lfsck_async_request(env, ltd->ltd_exp, lr, set,
+ lfsck_async_interpret, laia,
+ LFSCK_NOTIFY);
+ if (rc != 0) {
+ lfsck_interpret(env, lfsck, NULL, laia, rc);
+ lfsck_tgt_put(ltd);
+ CWARN("%s: cannot notify MDT %x for LFSCK stop: "
+ "rc = %d\n", lfsck_lfsck2name(lfsck), idx, rc);
+ rc1 = rc;
+ }
+ }
+ up_read(<ds->ltd_rw_sem);
+
+ rc = ptlrpc_set_wait(set);
+ ptlrpc_set_destroy(set);
+
+ if (rc == 0)
+ rc = laia->laia_result;
+
+ if (rc == -EALREADY)
+ rc = 0;
+
+ if (rc != 0)
+ CWARN("%s: fail to stop LFSCK on some MDTs: rc = %d\n",
+ lfsck_lfsck2name(lfsck), rc);
+
+ RETURN(rc != 0 ? rc : rc1);
+}
+
+static int lfsck_start_all(const struct lu_env *env,
+ struct lfsck_instance *lfsck,
+ struct lfsck_start *start)
+{
+ struct lfsck_thread_info *info = lfsck_env_info(env);
+ struct lfsck_request *lr = &info->lti_lr;
+ struct lfsck_async_interpret_args *laia = &info->lti_laia;
+ struct ptlrpc_request_set *set;
+ struct lfsck_tgt_descs *ltds = &lfsck->li_mdt_descs;
+ struct lfsck_tgt_desc *ltd;
+ struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
+ __u32 idx;
+ int rc = 0;
+ ENTRY;
+
+ LASSERT(start->ls_flags & LPF_BROADCAST);
+
+ set = ptlrpc_prep_set();
+ if (unlikely(set == NULL)) {
+ if (bk->lb_param & LPF_FAILOUT) {
+ CERROR("%s: cannot allocate memory for start LFSCK on "
+ "all targets, failout.\n",
+ lfsck_lfsck2name(lfsck));
+
+ RETURN(-ENOMEM);
+ } else {
+ CWARN("%s: cannot allocate memory for start LFSCK on "
+ "all targets, partly scan.\n",
+ lfsck_lfsck2name(lfsck));
+
+ RETURN(0);
+ }
+ }
+
+ memset(lr, 0, sizeof(*lr));
+ lr->lr_event = LE_START;
+ lr->lr_index = lfsck_dev_idx(lfsck->li_bottom);
+ lr->lr_speed = bk->lb_speed_limit;
+ lr->lr_version = bk->lb_version;
+ lr->lr_active = start->ls_active;
+ lr->lr_param = start->ls_flags;
+ lr->lr_async_windows = bk->lb_async_windows;
+ lr->lr_valid = LSV_SPEED_LIMIT | LSV_ERROR_HANDLE | LSV_DRYRUN |
+ LSV_ASYNC_WINDOWS;
+
+ laia->laia_com = NULL;
+ laia->laia_ltds = ltds;
+ laia->laia_lr = lr;
+ laia->laia_result = 0;
+ laia->laia_shared = 1;
+
+ down_read(<ds->ltd_rw_sem);
+ cfs_foreach_bit(ltds->ltd_tgts_bitmap, idx) {
+ ltd = lfsck_tgt_get(ltds, idx);
+ LASSERT(ltd != NULL);
+
+ laia->laia_ltd = ltd;
+ ltd->ltd_layout_done = 0;
+ rc = lfsck_async_request(env, ltd->ltd_exp, lr, set,
+ lfsck_async_interpret, laia,
+ LFSCK_NOTIFY);
+ if (rc != 0) {
+ lfsck_interpret(env, lfsck, NULL, laia, rc);
+ lfsck_tgt_put(ltd);
+ if (bk->lb_param & LPF_FAILOUT) {
+ CERROR("%s: cannot notify MDT %x for LFSCK "
+ "start, failout: rc = %d\n",
+ lfsck_lfsck2name(lfsck), idx, rc);
+ break;
+ } else {
+ CWARN("%s: cannot notify MDT %x for LFSCK "
+ "start, partly scan: rc = %d\n",
+ lfsck_lfsck2name(lfsck), idx, rc);
+ rc = 0;
+ }
+ }
+ }
+ up_read(<ds->ltd_rw_sem);
+
+ if (rc != 0) {
+ ptlrpc_set_destroy(set);
+
+ RETURN(rc);
+ }
+
+ rc = ptlrpc_set_wait(set);
+ ptlrpc_set_destroy(set);
+
+ if (rc == 0)
+ rc = laia->laia_result;
+
+ if (rc != 0) {
+ if (bk->lb_param & LPF_FAILOUT) {
+ struct lfsck_stop *stop = &info->lti_stop;
+
+ CERROR("%s: cannot start LFSCK on some MDTs, "
+ "stop all: rc = %d\n",
+ lfsck_lfsck2name(lfsck), rc);
+ if (rc != -EALREADY) {
+ stop->ls_status = LS_FAILED;
+ stop->ls_flags = LPF_ALL_TGT | LPF_BROADCAST;
+ lfsck_stop_all(env, lfsck, stop);
+ }
+ } else {
+ CWARN("%s: cannot start LFSCK on some MDTs, "
+ "partly scan: rc = %d\n",
+ lfsck_lfsck2name(lfsck), rc);
+ rc = 0;
+ }
+ }
+
+ RETURN(rc);
+}
+
int lfsck_start(const struct lu_env *env, struct dt_device *key,
struct lfsck_start_param *lsp)
{
if (unlikely(lfsck == NULL))
RETURN(-ENODEV);
+ /* System is not ready, try again later. */
+ if (unlikely(lfsck->li_namespace == NULL))
+ GOTO(put, rc = -EAGAIN);
+
/* start == NULL means auto trigger paused LFSCK. */
if ((start == NULL) &&
(cfs_list_empty(&lfsck->li_list_scan) ||
}
spin_unlock(&lfsck->li_lock);
- lfsck->li_namespace = lsp->lsp_namespace;
lfsck->li_status = 0;
lfsck->li_oit_over = 0;
+ lfsck->li_start_unplug = 0;
lfsck->li_drop_dryrun = 0;
lfsck->li_new_scanned = 0;
if (start == NULL)
goto trigger;
+ if (start->ls_flags & LPF_BROADCAST && !lfsck->li_master) {
+ CERROR("%s: only allow to specify '-A | -o' via MDS\n",
+ lfsck_lfsck2name(lfsck));
+
+ GOTO(out, rc = -EPERM);
+ }
+
start->ls_version = bk->lb_version;
if (start->ls_valid & LSV_SPEED_LIMIT) {
__lfsck_set_speed(lfsck, start->ls_speed_limit);
}
}
- if (bk->lb_param & LPF_ALL_MDT &&
- !(start->ls_flags & LPF_ALL_MDT)) {
- bk->lb_param &= ~LPF_ALL_MDT;
+ if (bk->lb_param & LPF_ALL_TGT &&
+ !(start->ls_flags & LPF_ALL_TGT)) {
+ bk->lb_param &= ~LPF_ALL_TGT;
+ dirty = true;
+ } else if (!(bk->lb_param & LPF_ALL_TGT) &&
+ start->ls_flags & LPF_ALL_TGT) {
+ bk->lb_param |= LPF_ALL_TGT;
+ dirty = true;
+ }
+
+ if (bk->lb_param & LPF_ORPHAN &&
+ !(start->ls_flags & LPF_ORPHAN)) {
+ bk->lb_param &= ~LPF_ORPHAN;
dirty = true;
- } else if (!(bk->lb_param & LPF_ALL_MDT) &&
- start->ls_flags & LPF_ALL_MDT) {
- bk->lb_param |= LPF_ALL_MDT;
+ } else if (!(bk->lb_param & LPF_ORPHAN) &&
+ start->ls_flags & LPF_ORPHAN) {
+ bk->lb_param |= LPF_ORPHAN;
dirty = true;
}
CERROR("%s: cannot start LFSCK thread: rc = %ld\n",
lfsck_lfsck2name(lfsck), rc);
lfsck_thread_args_fini(lta);
+
+ GOTO(out, rc);
+ }
+
+ l_wait_event(thread->t_ctl_waitq,
+ thread_is_running(thread) ||
+ thread_is_stopped(thread),
+ &lwi);
+ if (start == NULL || !(start->ls_flags & LPF_BROADCAST)) {
+ lfsck->li_start_unplug = 1;
+ wake_up_all(&thread->t_ctl_waitq);
+
+ GOTO(out, rc = 0);
+ }
+
+ /* release lfsck::li_mutex to avoid deadlock. */
+ mutex_unlock(&lfsck->li_mutex);
+ rc = lfsck_start_all(env, lfsck, start);
+ if (rc != 0) {
+ spin_lock(&lfsck->li_lock);
+ if (thread_is_stopped(thread)) {
+ spin_unlock(&lfsck->li_lock);
+ } else {
+ lfsck->li_status = LS_FAILED;
+ lfsck->li_flags = 0;
+ thread_set_flags(thread, SVC_STOPPING);
+ spin_unlock(&lfsck->li_lock);
+
+ lfsck->li_start_unplug = 1;
+ wake_up_all(&thread->t_ctl_waitq);
+ l_wait_event(thread->t_ctl_waitq,
+ thread_is_stopped(thread),
+ &lwi);
+ }
} else {
- rc = 0;
- l_wait_event(thread->t_ctl_waitq,
- thread_is_running(thread) ||
- thread_is_stopped(thread),
- &lwi);
+ lfsck->li_start_unplug = 1;
+ wake_up_all(&thread->t_ctl_waitq);
}
- GOTO(out, rc);
+ GOTO(put, rc);
out:
mutex_unlock(&lfsck->li_mutex);
+
put:
lfsck_instance_put(env, lfsck);
- return (rc < 0 ? rc : 0);
+
+ return rc < 0 ? rc : 0;
}
EXPORT_SYMBOL(lfsck_start);
struct ptlrpc_thread *thread;
struct l_wait_info lwi = { 0 };
int rc = 0;
+ int rc1 = 0;
ENTRY;
lfsck = lfsck_instance_find(key, true, false);
RETURN(-ENODEV);
thread = &lfsck->li_thread;
+ /* release lfsck::li_mutex to avoid deadlock. */
+ if (stop != NULL && stop->ls_flags & LPF_BROADCAST) {
+ if (!lfsck->li_master) {
+ CERROR("%s: only allow to specify '-A' via MDS\n",
+ lfsck_lfsck2name(lfsck));
+
+ GOTO(out, rc = -EPERM);
+ }
+
+ rc1 = lfsck_stop_all(env, lfsck, stop);
+ }
+
mutex_lock(&lfsck->li_mutex);
spin_lock(&lfsck->li_lock);
if (thread_is_init(thread) || thread_is_stopped(thread)) {
mutex_unlock(&lfsck->li_mutex);
lfsck_instance_put(env, lfsck);
- return rc;
+ return rc != 0 ? rc : rc1;
}
EXPORT_SYMBOL(lfsck_stop);
int lfsck_in_notify(const struct lu_env *env, struct dt_device *key,
struct lfsck_request *lr)
{
- struct lfsck_instance *lfsck;
- struct lfsck_component *com;
- int rc;
+ int rc = -EOPNOTSUPP;
ENTRY;
switch (lr->lr_event) {
- case LE_STOP:
+ case LE_START: {
+ struct lfsck_start *start = &lfsck_env_info(env)->lti_start;
+ struct lfsck_start_param lsp;
+
+ memset(start, 0, sizeof(*start));
+ start->ls_valid = lr->lr_valid;
+ start->ls_speed_limit = lr->lr_speed;
+ start->ls_version = lr->lr_version;
+ start->ls_active = lr->lr_active;
+ start->ls_flags = lr->lr_param & ~LPF_BROADCAST;
+ start->ls_async_windows = lr->lr_async_windows;
+
+ lsp.lsp_start = start;
+ lsp.lsp_index = lr->lr_index;
+ lsp.lsp_index_valid = 1;
+ rc = lfsck_start(env, key, &lsp);
+ break;
+ }
+ case LE_STOP: {
+ struct lfsck_stop *stop = &lfsck_env_info(env)->lti_stop;
+
+ memset(stop, 0, sizeof(*stop));
+ stop->ls_status = lr->lr_status;
+ stop->ls_flags = lr->lr_param & ~LPF_BROADCAST;
+ rc = lfsck_stop(env, key, stop);
+ break;
+ }
case LE_PHASE1_DONE:
case LE_PHASE2_DONE:
case LE_FID_ACCESSED:
- break;
- default:
- RETURN(-EOPNOTSUPP);
- }
+ case LE_PEER_EXIT: {
+ struct lfsck_instance *lfsck;
+ struct lfsck_component *com;
- lfsck = lfsck_instance_find(key, true, false);
- if (unlikely(lfsck == NULL))
- RETURN(-ENODEV);
+ lfsck = lfsck_instance_find(key, true, false);
+ if (unlikely(lfsck == NULL))
+ RETURN(-ENODEV);
- com = lfsck_component_find(lfsck, lr->lr_active);
- if (likely(com != NULL)) {
- rc = com->lc_ops->lfsck_in_notify(env, com, lr);
- lfsck_component_put(env, com);
- } else {
- rc = -ENOTSUPP;
- }
+ com = lfsck_component_find(lfsck, lr->lr_active);
+ if (likely(com != NULL)) {
+ rc = com->lc_ops->lfsck_in_notify(env, com, lr);
+ lfsck_component_put(env, com);
+ }
- lfsck_instance_put(env, lfsck);
+ lfsck_instance_put(env, lfsck);
+ break;
+ }
+ default:
+ break;
+ }
RETURN(rc);
}
}
EXPORT_SYMBOL(lfsck_query);
+int lfsck_register_namespace(const struct lu_env *env, struct dt_device *key,
+ struct ldlm_namespace *ns)
+{
+ struct lfsck_instance *lfsck;
+ int rc = -ENODEV;
+
+ lfsck = lfsck_instance_find(key, true, false);
+ if (likely(lfsck != NULL)) {
+ lfsck->li_namespace = ns;
+ lfsck_instance_put(env, lfsck);
+ rc = 0;
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL(lfsck_register_namespace);
+
int lfsck_register(const struct lu_env *env, struct dt_device *key,
struct dt_device *next, struct obd_device *obd,
lfsck_out_notify notify, void *notify_data, bool master)
{
struct lfsck_instance *lfsck;
struct lfsck_tgt_descs *ltds;
- struct lfsck_tgt_desc *ltd;
+ struct lfsck_tgt_desc *ltd = NULL;
struct list_head *head;
- bool found = false;
- bool stop = false;
if (for_ost)
head = &lfsck_ost_orphan_list;
ltds = &lfsck->li_mdt_descs;
down_write(<ds->ltd_rw_sem);
-
LASSERT(ltds->ltd_tgts_bitmap != NULL);
if (unlikely(index >= ltds->ltd_tgts_bitmap->size))
if (unlikely(ltd == NULL))
goto unlock;
- found = true;
- spin_lock(<ds->ltd_lock);
- ltd->ltd_dead = 1;
- if (!list_empty(<d->ltd_layout_list)) {
- list_del_init(<d->ltd_layout_phase_list);
- list_del_init(<d->ltd_layout_list);
- stop = true;
- } else {
- LASSERT(list_empty(<d->ltd_layout_phase_list));
- }
- spin_unlock(<ds->ltd_lock);
-
- if (stop && lfsck->li_master)
- lfsck_stop_notify(env, lfsck, ltds, ltd);
-
LASSERT(ltds->ltd_tgtnr > 0);
ltds->ltd_tgtnr--;
cfs_bitmap_clear(ltds->ltd_tgts_bitmap, index);
LTD_TGT(ltds, index) = NULL;
- lfsck_tgt_put(ltd);
unlock:
- if (!found) {
+ if (ltd == NULL) {
if (for_ost)
head = &lfsck->li_ost_descs.ltd_orphan;
else
list_for_each_entry(ltd, head, ltd_orphan_list) {
if (ltd->ltd_tgt == tgt) {
list_del_init(<d->ltd_orphan_list);
- lfsck_tgt_put(ltd);
break;
}
}
}
up_write(<ds->ltd_rw_sem);
+ if (ltd != NULL) {
+ spin_lock(<ds->ltd_lock);
+ ltd->ltd_dead = 1;
+ spin_unlock(<ds->ltd_lock);
+ lfsck_stop_notify(env, lfsck, ltds, ltd, LT_LAYOUT);
+ lfsck_tgt_put(ltd);
+ }
+
lfsck_instance_put(env, lfsck);
}
EXPORT_SYMBOL(lfsck_del_target);
lfsck_key_init_generic(&lfsck_thread_key, NULL);
rc = lu_context_key_register(&lfsck_thread_key);
if (rc == 0) {
- tgt_register_lfsck_start(lfsck_start);
tgt_register_lfsck_in_notify(lfsck_in_notify);
tgt_register_lfsck_query(lfsck_query);
}
if (rc)
RETURN(rc);
- lsp.lsp_namespace = mdt->mdt_namespace;
+ rc = lfsck_register_namespace(env, mdt->mdt_bottom, mdt->mdt_namespace);
+ LASSERTF(rc == 0, "register namespace failed: rc = %d\n", rc);
+
lsp.lsp_start = NULL;
lsp.lsp_index_valid = 0;
rc = mdt->mdt_child->md_ops->mdo_iocontrol(env, mdt->mdt_child,
break;
}
- lsp.lsp_namespace = mdt->mdt_namespace;
lsp.lsp_start = (struct lfsck_start *)(data->ioc_inlbuf1);
lsp.lsp_index_valid = 0;
rc = next->md_ops->mdo_iocontrol(&env, next, cmd, 0, &lsp);
case OBD_IOC_STOP_LFSCK: {
struct md_device *next = mdt->mdt_child;
struct obd_ioctl_data *data = karg;
- struct lfsck_stop *stop =
- (struct lfsck_stop *)(data->ioc_inlbuf1);
+ struct lfsck_stop stop;
+
+ stop.ls_status = LS_STOPPED;
+ /* Old lfsck utils may pass NULL @stop. */
+ if (data->ioc_inlbuf1 == NULL)
+ stop.ls_flags = 0;
+ else
+ stop.ls_flags =
+ ((struct lfsck_stop *)(data->ioc_inlbuf1))->ls_flags;
- stop->ls_status = LS_STOPPED;
- rc = next->md_ops->mdo_iocontrol(&env, next, cmd, 0, stop);
+ rc = next->md_ops->mdo_iocontrol(&env, next, cmd, 0, &stop);
break;
}
case OBD_IOC_GET_OBJ_VERSION: {
RETURN(rc);
}
- lsp.lsp_namespace = ofd->ofd_namespace;
+ rc = lfsck_register_namespace(env, ofd->ofd_osd, ofd->ofd_namespace);
+ LASSERTF(rc == 0, "register namespace failed: rc = %d\n", rc);
+
lsp.lsp_start = NULL;
lsp.lsp_index_valid = 0;
rc = lfsck_start(env, ofd->ofd_osd, &lsp);
break;
}
- lsp.lsp_namespace = ofd->ofd_namespace;
lsp.lsp_start = (struct lfsck_start *)(data->ioc_inlbuf1);
lsp.lsp_index_valid = 0;
rc = lfsck_start(&env, ofd->ofd_osd, &lsp);
}
case OBD_IOC_STOP_LFSCK: {
struct obd_ioctl_data *data = karg;
+ struct lfsck_stop stop;
- rc = lfsck_stop(&env, ofd->ofd_osd,
- (struct lfsck_stop *)(data->ioc_inlbuf1));
+ stop.ls_status = LS_STOPPED;
+ /* Old lfsck utils may pass NULL @stop. */
+ if (data->ioc_inlbuf1 == NULL)
+ stop.ls_flags = 0;
+ else
+ stop.ls_flags =
+ ((struct lfsck_stop *)(data->ioc_inlbuf1))->ls_flags;
+
+ rc = lfsck_stop(&env, ofd->ofd_osd, &stop);
break;
}
case OBD_IOC_GET_OBJ_VERSION:
};
EXPORT_SYMBOL(tgt_sec_ctx_handlers);
-static int (*tgt_lfsck_start)(const struct lu_env *env,
- struct dt_device *key,
- struct lfsck_start_param *lsp) = NULL;
-
-void tgt_register_lfsck_start(int (*start)(const struct lu_env *,
- struct dt_device *,
- struct lfsck_start_param *))
-{
- tgt_lfsck_start = start;
-}
-EXPORT_SYMBOL(tgt_register_lfsck_start);
-
int (*tgt_lfsck_in_notify)(const struct lu_env *env,
struct dt_device *key,
struct lfsck_request *lr) = NULL;
if (lr == NULL)
RETURN(-EPROTO);
- switch (lr->lr_event) {
- case LE_START: {
- struct lfsck_start start;
- struct lfsck_start_param lsp;
-
- start.ls_valid = lr->lr_valid;
- start.ls_speed_limit = lr->lr_speed;
- start.ls_version = lr->lr_version;
- start.ls_active = lr->lr_active;
- start.ls_flags = lr->lr_param;
- start.ls_async_windows = lr->lr_async_windows;
-
- lsp.lsp_namespace = tsi->tsi_exp->exp_obd->obd_namespace;
- lsp.lsp_start = &start;
- lsp.lsp_index = lr->lr_index;
- if (lr->lr_flags & LEF_TO_OST)
- lsp.lsp_index_valid = 1;
- else
- lsp.lsp_index_valid = 0;
- rc = tgt_lfsck_start(env, key, &lsp);
- break;
- }
- case LE_STOP:
- case LE_PHASE1_DONE:
- case LE_PHASE2_DONE:
- rc = tgt_lfsck_in_notify(env, key, lr);
- break;
- default:
- CERROR("%s: unsupported lfsck_event: rc = %d\n",
- tgt_name(tsi->tsi_tgt), lr->lr_event);
- rc = -EOPNOTSUPP;
- break;
- }
+ rc = tgt_lfsck_in_notify(env, key, lr);
RETURN(rc);
}
createmany -o $DIR/${k}/f 100
done
- echo "Trigger LFSCK on all targets by single command (limited speed)."
- do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t layout -A \
+ echo "Start namespace LFSCK on all targets by single command (-s 10)."
+ do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t namespace -A \
-s 10 || error "(2) Fail to start LFSCK on all devices!"
echo "All the LFSCK targets should be in 'scanning-phase1' status."
for k in $(seq $MDSCOUNT); do
local STATUS=$(do_facet mds${k} $LCTL get_param -n \
- mdd.$(facet_svc mds${k}).lfsck_layout |
+ mdd.$(facet_svc mds${k}).lfsck_namespace |
awk '/^status/ { print $2 }')
[ "$STATUS" == "scanning-phase1" ] ||
error "(3) MDS${k} Expect 'scanning-phase1', but got '$STATUS'"
done
- echo "Stop layout LFSCK on all targets by single lctl command."
+ echo "Stop namespace LFSCK on all targets by single lctl command."
do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 -A ||
error "(4) Fail to stop LFSCK on all devices!"
echo "All the LFSCK targets should be in 'stopped' status."
for k in $(seq $MDSCOUNT); do
local STATUS=$(do_facet mds${k} $LCTL get_param -n \
- mdd.$(facet_svc mds${k}).lfsck_layout |
+ mdd.$(facet_svc mds${k}).lfsck_namespace |
awk '/^status/ { print $2 }')
[ "$STATUS" == "stopped" ] ||
error "(5) MDS${k} Expect 'stopped', but got '$STATUS'"
done
+ echo "Re-start namespace LFSCK on all targets by single command (-s 0)."
+ do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t namespace -A \
+ -s 0 -r || error "(6) Fail to start LFSCK on all devices!"
+
+ echo "All the LFSCK targets should be in 'completed' status."
+ for k in $(seq $MDSCOUNT); do
+ wait_update_facet mds${k} "$LCTL get_param -n \
+ mdd.$(facet_svc mds${k}).lfsck_namespace |
+ awk '/^status/ { print \\\$2 }'" "completed" 8 ||
+ error "(7) MDS${k} is not the expected 'completed'"
+ done
+
+ echo "Start layout LFSCK on all targets by single command (-s 10)."
+ do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t layout -A \
+ -s 10 || error "(8) Fail to start LFSCK on all devices!"
+
+ echo "All the LFSCK targets should be in 'scanning-phase1' status."
+ for k in $(seq $MDSCOUNT); do
+ local STATUS=$(do_facet mds${k} $LCTL get_param -n \
+ mdd.$(facet_svc mds${k}).lfsck_layout |
+ awk '/^status/ { print $2 }')
+ [ "$STATUS" == "scanning-phase1" ] ||
+ error "(9) MDS${k} Expect 'scanning-phase1', but got '$STATUS'"
+ done
+
+ echo "Stop layout LFSCK on all targets by single lctl command."
+ do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 -A ||
+ error "(10) Fail to stop LFSCK on all devices!"
+
+ echo "All the LFSCK targets should be in 'stopped' status."
+ for k in $(seq $MDSCOUNT); do
+ local STATUS=$(do_facet mds${k} $LCTL get_param -n \
+ mdd.$(facet_svc mds${k}).lfsck_layout |
+ awk '/^status/ { print $2 }')
+ [ "$STATUS" == "stopped" ] ||
+ error "(11) MDS${k} Expect 'stopped', but got '$STATUS'"
+ done
+
for k in $(seq $OSTCOUNT); do
local STATUS=$(do_facet ost${k} $LCTL get_param -n \
obdfilter.$(facet_svc ost${k}).lfsck_layout |
awk '/^status/ { print $2 }')
[ "$STATUS" == "stopped" ] ||
- error "(6) OST${k} Expect 'stopped', but got '$STATUS'"
+ error "(12) OST${k} Expect 'stopped', but got '$STATUS'"
done
- echo "Re-trigger LFSCK on all targets by single command (full speed)."
+ echo "Re-start layout LFSCK on all targets by single command (-s 0)."
do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t layout -A \
- -s 0 || error "(7) Fail to start LFSCK on all devices!"
+ -s 0 -r || error "(13) Fail to start LFSCK on all devices!"
echo "All the LFSCK targets should be in 'completed' status."
for k in $(seq $MDSCOUNT); do
wait_update_facet mds${k} "$LCTL get_param -n \
mdd.$(facet_svc mds${k}).lfsck_layout |
awk '/^status/ { print \\\$2 }'" "completed" 32 ||
- error "(8) MDS${k} is not the expected 'completed'"
+ error "(14) MDS${k} is not the expected 'completed'"
done
}
run_test 12 "single command to trigger LFSCK on all devices"
" [-n | --dryrun switch] [-r | --reset]\n"
" [-s | --speed speed_limit] [-A | --all]\n"
" [-t | --type lfsck_type[,lfsck_type...]]\n"
- " [-w | --windows win_size]"},
+ " [-w | --windows win_size] [-o | --orphan]"},
{"lfsck_stop", jt_lfsck_stop, 0, "stop lfsck(s)\n"
"usage: lfsck_stop <-M | --device [MDT,OST]_device>\n"
" [-A | --all] [-h | --help]"},
{"all", no_argument, 0, 'A'},
{"type", required_argument, 0, 't'},
{"windows", required_argument, 0, 'w'},
+ {"orphan", no_argument, 0, 'o'},
{0, 0, 0, 0}
};
" [-n | --dryrun switch] [-r | --reset]\n"
" [-s | --speed speed_limit] [-A | --all]\n"
" [-t | --type lfsck_type[,lfsck_type...]]\n"
- " [-w | --windows win_size]\n"
+ " [-w | --windows win_size] [-o | --orphan]\n"
"OPTIONS:\n"
"-M: The device to start LFSCK/scrub on.\n"
"-e: Error handle, 'continue'(default) or 'abort'.\n"
"'%d' means no limit (default).\n"
"-A: Start LFSCK on all MDT devices.\n"
"-t: The LFSCK type(s) to be started.\n"
- "-w: The windows size for async requests pipeline.\n",
+ "-w: The windows size for async requests pipeline.\n"
+ "-o: handle orphan objects.\n",
LFSCK_SPEED_NO_LIMIT);
}
char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
char device[MAX_OBD_NAME];
struct lfsck_start start;
- char *optstring = "M:e:hn:rs:At:w:";
+ char *optstring = "M:e:hn:rs:At:w:o";
int opt, index, rc, val, i, type;
memset(&data, 0, sizeof(data));
start.ls_valid |= LSV_SPEED_LIMIT;
break;
case 'A':
- start.ls_flags |= LPF_ALL_MDT | LPF_BROADCAST;
+ start.ls_flags |= LPF_ALL_TGT | LPF_BROADCAST;
break;
case 't': {
char *str = optarg, *p, c;
start.ls_async_windows = val;
start.ls_valid |= LSV_ASYNC_WINDOWS;
break;
+ case 'o':
+ start.ls_flags |= LPF_ALL_TGT | LPF_BROADCAST |
+ LPF_ORPHAN;
+ break;
default:
fprintf(stderr, "Invalid option, '-h' for help.\n");
return -EINVAL;
return rc;
break;
case 'A':
- stop.ls_flags |= LPF_ALL_MDT | LPF_BROADCAST;
+ stop.ls_flags |= LPF_ALL_TGT | LPF_BROADCAST;
break;
case 'h':
usage_stop();