+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);
+}
+