+static int
+lfsck_layout_slave_async_interpret(const struct lu_env *env,
+ struct ptlrpc_request *req,
+ void *args, int rc)
+{
+ struct lfsck_layout_slave_async_args *llsaa = args;
+ struct obd_export *exp = llsaa->llsaa_exp;
+ struct lfsck_component *com = llsaa->llsaa_com;
+ struct lfsck_layout_slave_target *llst = llsaa->llsaa_llst;
+ struct lfsck_layout_slave_data *llsd = com->lc_data;
+ bool done = false;
+
+ if (rc != 0) {
+ /* It is quite probably caused by target crash,
+ * to make the LFSCK can go ahead, assume that
+ * the target finished the LFSCK prcoessing. */
+ done = true;
+ } else {
+ struct lfsck_reply *lr;
+
+ lr = req_capsule_server_get(&req->rq_pill, &RMF_LFSCK_REPLY);
+ if (lr->lr_status != LS_SCANNING_PHASE1 &&
+ lr->lr_status != LS_SCANNING_PHASE2)
+ done = true;
+ }
+ if (done)
+ lfsck_layout_llst_del(llsd, llst);
+ lfsck_layout_llst_put(llst);
+ lfsck_component_put(env, com);
+ class_export_put(exp);
+
+ return 0;
+}
+
+static int lfsck_layout_async_query(const struct lu_env *env,
+ struct lfsck_component *com,
+ struct obd_export *exp,
+ struct lfsck_layout_slave_target *llst,
+ struct lfsck_request *lr,
+ struct ptlrpc_request_set *set)
+{
+ struct lfsck_layout_slave_async_args *llsaa;
+ struct ptlrpc_request *req;
+ struct lfsck_request *tmp;
+ int rc;
+ ENTRY;
+
+ req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LFSCK_QUERY);
+ if (req == NULL)
+ RETURN(-ENOMEM);
+
+ rc = ptlrpc_request_pack(req, LUSTRE_OBD_VERSION, LFSCK_QUERY);
+ if (rc != 0) {
+ ptlrpc_request_free(req);
+ RETURN(rc);
+ }
+
+ tmp = req_capsule_client_get(&req->rq_pill, &RMF_LFSCK_REQUEST);
+ *tmp = *lr;
+ ptlrpc_request_set_replen(req);
+
+ llsaa = ptlrpc_req_async_args(req);
+ llsaa->llsaa_exp = exp;
+ llsaa->llsaa_com = lfsck_component_get(com);
+ llsaa->llsaa_llst = llst;
+ req->rq_interpret_reply = lfsck_layout_slave_async_interpret;
+ ptlrpc_set_add_req(set, req);
+
+ RETURN(0);
+}
+
+static int lfsck_layout_async_notify(const struct lu_env *env,
+ struct obd_export *exp,
+ struct lfsck_request *lr,
+ struct ptlrpc_request_set *set)
+{
+ struct ptlrpc_request *req;
+ struct lfsck_request *tmp;
+ int rc;
+ ENTRY;
+
+ req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LFSCK_NOTIFY);
+ if (req == NULL)
+ RETURN(-ENOMEM);
+
+ rc = ptlrpc_request_pack(req, LUSTRE_OBD_VERSION, LFSCK_NOTIFY);
+ if (rc != 0) {
+ ptlrpc_request_free(req);
+ RETURN(rc);
+ }
+
+ tmp = req_capsule_client_get(&req->rq_pill, &RMF_LFSCK_REQUEST);
+ *tmp = *lr;
+ ptlrpc_request_set_replen(req);
+ ptlrpc_set_add_req(set, req);
+
+ RETURN(0);
+}
+
+static int
+lfsck_layout_slave_query_master(const struct lu_env *env,
+ struct lfsck_component *com)
+{
+ struct lfsck_request *lr = &lfsck_env_info(env)->lti_lr;
+ struct lfsck_instance *lfsck = com->lc_lfsck;
+ struct lfsck_layout_slave_data *llsd = com->lc_data;
+ 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;
+
+ set = ptlrpc_prep_set();
+ if (set == NULL)
+ RETURN(-ENOMEM);
+
+ memset(lr, 0, sizeof(*lr));
+ lr->lr_index = lfsck_dev_idx(lfsck->li_bottom);
+ lr->lr_event = LE_QUERY;
+ lr->lr_active = LT_LAYOUT;
+
+ llsd->llsd_touch_gen++;
+ 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);
+ if (llst->llst_gen == llsd->llsd_touch_gen)
+ break;
+
+ llst->llst_gen = llsd->llsd_touch_gen;
+ list_del(&llst->llst_list);
+ list_add_tail(&llst->llst_list,
+ &llsd->llsd_master_list);
+ atomic_inc(&llst->llst_ref);
+ spin_unlock(&llsd->llsd_lock);
+
+ exp = lustre_find_lwp_by_index(lfsck->li_obd->obd_name,
+ llst->llst_index);
+ if (exp == NULL) {
+ lfsck_layout_llst_del(llsd, llst);
+ lfsck_layout_llst_put(llst);
+ spin_lock(&llsd->llsd_lock);
+ continue;
+ }
+
+ rc = lfsck_layout_async_query(env, com, exp, llst, lr, set);
+ if (rc != 0) {
+ CERROR("%s: slave fail to query %s for layout: "
+ "rc = %d\n", lfsck_lfsck2name(lfsck),
+ exp->exp_obd->obd_name, rc);
+ 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);
+ ptlrpc_set_destroy(set);
+
+ RETURN(rc1 != 0 ? rc1 : rc);
+}
+
+static void
+lfsck_layout_slave_notify_master(const struct lu_env *env,
+ struct lfsck_component *com,
+ enum lfsck_events event, int result)
+{
+ struct lfsck_instance *lfsck = com->lc_lfsck;
+ struct lfsck_layout_slave_data *llsd = com->lc_data;
+ struct lfsck_request *lr = &lfsck_env_info(env)->lti_lr;
+ struct lfsck_layout_slave_target *llst;
+ struct obd_export *exp;
+ struct ptlrpc_request_set *set;
+ int cnt = 0;
+ int rc;
+ ENTRY;
+
+ set = ptlrpc_prep_set();
+ if (set == NULL)
+ RETURN_EXIT;
+
+ memset(lr, 0, sizeof(*lr));
+ lr->lr_event = event;
+ lr->lr_status = result;
+ lr->lr_index = lfsck_dev_idx(lfsck->li_bottom);
+ lr->lr_active = LT_LAYOUT;
+ llsd->llsd_touch_gen++;
+ 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);
+ if (llst->llst_gen == llsd->llsd_touch_gen)
+ break;
+
+ llst->llst_gen = llsd->llsd_touch_gen;
+ list_del(&llst->llst_list);
+ list_add_tail(&llst->llst_list,
+ &llsd->llsd_master_list);
+ atomic_inc(&llst->llst_ref);
+ spin_unlock(&llsd->llsd_lock);
+
+ exp = lustre_find_lwp_by_index(lfsck->li_obd->obd_name,
+ llst->llst_index);
+ if (exp == NULL) {
+ lfsck_layout_llst_del(llsd, llst);
+ lfsck_layout_llst_put(llst);
+ spin_lock(&llsd->llsd_lock);
+ continue;
+ }
+
+ rc = lfsck_layout_async_notify(env, exp, lr, set);
+ if (rc != 0)
+ 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_destroy(set);
+
+ RETURN_EXIT;
+}
+