[LS_STOPPED] = "stopped",
[LS_PAUSED] = "paused",
[LS_CRASHED] = "crashed",
- [LS_PARTIAL] = "partial"
+ [LS_PARTIAL] = "partial",
+ [LS_CO_FAILED] = "co-failed",
+ [LS_CO_STOPPED] = "co-stopped",
+ [LS_CO_PAUSED] = "co-paused"
};
const char *lfsck_flags_names[] = {
{
struct lfsck_component *com;
struct lfsck_component *next;
- int rc;
+ struct l_wait_info lwi = { 0 };
+ int rc = 0;
+ int rc1 = 0;
cfs_list_for_each_entry_safe(com, next, &lfsck->li_list_double_scan,
lc_link) {
rc = com->lc_ops->lfsck_double_scan(env, com);
if (rc != 0)
- return rc;
+ rc1 = rc;
+ }
+
+ l_wait_event(lfsck->li_thread.t_ctl_waitq,
+ atomic_read(&lfsck->li_double_scan_count) == 0,
+ &lwi);
+
+ return (rc1 != 0 ? rc1 : rc);
+}
+
+void lfsck_quit(const struct lu_env *env, struct lfsck_instance *lfsck)
+{
+ struct lfsck_component *com;
+ struct lfsck_component *next;
+
+ list_for_each_entry_safe(com, next, &lfsck->li_list_scan,
+ lc_link) {
+ if (com->lc_ops->lfsck_quit != NULL)
+ com->lc_ops->lfsck_quit(env, com);
+ }
+
+ list_for_each_entry_safe(com, next, &lfsck->li_list_double_scan,
+ lc_link) {
+ if (com->lc_ops->lfsck_quit != NULL)
+ com->lc_ops->lfsck_quit(env, com);
}
- return 0;
}
/* external interfaces */
}
EXPORT_SYMBOL(lfsck_set_speed);
+int lfsck_get_windows(struct dt_device *key, void *buf, int len)
+{
+ struct lu_env env;
+ struct lfsck_instance *lfsck;
+ int rc;
+ ENTRY;
+
+ rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD);
+ if (rc != 0)
+ RETURN(rc);
+
+ lfsck = lfsck_instance_find(key, true, false);
+ if (likely(lfsck != NULL)) {
+ rc = snprintf(buf, len, "%u\n",
+ lfsck->li_bookmark_ram.lb_async_windows);
+ lfsck_instance_put(&env, lfsck);
+ } else {
+ rc = -ENODEV;
+ }
+
+ lu_env_fini(&env);
+
+ RETURN(rc);
+}
+EXPORT_SYMBOL(lfsck_get_windows);
+
+int lfsck_set_windows(struct dt_device *key, int val)
+{
+ struct lu_env env;
+ struct lfsck_instance *lfsck;
+ int rc;
+ ENTRY;
+
+ rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD);
+ if (rc != 0)
+ RETURN(rc);
+
+ lfsck = lfsck_instance_find(key, true, false);
+ if (likely(lfsck != NULL)) {
+ if (val > LFSCK_ASYNC_WIN_MAX) {
+ CERROR("%s: Too large async windows size, which "
+ "may cause memory issues. The valid range "
+ "is [0 - %u]. If you do not want to restrict "
+ "the windows size for async requests pipeline, "
+ "just set it as 0.\n",
+ lfsck_lfsck2name(lfsck), LFSCK_ASYNC_WIN_MAX);
+ rc = -EINVAL;
+ } else if (lfsck->li_bookmark_ram.lb_async_windows != val) {
+ mutex_lock(&lfsck->li_mutex);
+ lfsck->li_bookmark_ram.lb_async_windows = val;
+ rc = lfsck_bookmark_store(&env, lfsck);
+ mutex_unlock(&lfsck->li_mutex);
+ }
+ lfsck_instance_put(&env, lfsck);
+ } else {
+ rc = -ENODEV;
+ }
+
+ lu_env_fini(&env);
+
+ RETURN(rc);
+}
+EXPORT_SYMBOL(lfsck_set_windows);
+
int lfsck_dump(struct dt_device *key, void *buf, int len, enum lfsck_type type)
{
struct lu_env env;
dirty = true;
}
+ if (start->ls_valid & LSV_ASYNC_WINDOWS &&
+ bk->lb_async_windows != start->ls_async_windows) {
+ bk->lb_async_windows = start->ls_async_windows;
+ dirty = true;
+ }
+
if (start->ls_valid & LSV_ERROR_HANDLE) {
valid |= DOIV_ERROR_HANDLE;
if (start->ls_flags & LPF_FAILOUT)
CFS_INIT_LIST_HEAD(&lfsck->li_list_double_scan);
CFS_INIT_LIST_HEAD(&lfsck->li_list_idle);
atomic_set(&lfsck->li_ref, 1);
+ atomic_set(&lfsck->li_double_scan_count, 0);
init_waitqueue_head(&lfsck->li_thread.t_ctl_waitq);
lfsck->li_out_notify = notify;
lfsck->li_out_notify_data = notify_data;