4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License version 2 for more details. A copy is
14 * included in the COPYING file that accompanied this code.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Copyright (c) 2012 Whamcloud, Inc.
26 * lustre/mdd/mdd_lfsck.c
28 * Top-level entry points into mdd module
30 * LFSCK controller, which scans the whole device through low layer
31 * iteration APIs, drives all lfsck compeonents, controls the speed.
33 * Author: Fan Yong <yong.fan@whamcloud.com>
37 # define EXPORT_SYMTAB
39 #define DEBUG_SUBSYSTEM S_MDS
41 #include <lustre/lustre_idl.h>
42 #include <lustre_fid.h>
44 #include "mdd_internal.h"
46 static inline char *mdd_lfsck2name(struct md_lfsck *lfsck)
48 struct mdd_device *mdd;
50 mdd = container_of0(lfsck, struct mdd_device, mdd_lfsck);
51 return mdd2obd_dev(mdd)->obd_name;
54 void mdd_lfsck_set_speed(struct md_lfsck *lfsck, __u32 limit)
56 spin_lock(&lfsck->ml_lock);
57 lfsck->ml_speed_limit = limit;
58 if (limit != LFSCK_SPEED_NO_LIMIT) {
60 lfsck->ml_sleep_rate = limit / CFS_HZ;
61 lfsck->ml_sleep_jif = 1;
63 lfsck->ml_sleep_rate = 1;
64 lfsck->ml_sleep_jif = CFS_HZ / limit;
67 lfsck->ml_sleep_jif = 0;
68 lfsck->ml_sleep_rate = 0;
70 spin_unlock(&lfsck->ml_lock);
73 static void mdd_lfsck_control_speed(struct md_lfsck *lfsck)
75 struct ptlrpc_thread *thread = &lfsck->ml_thread;
76 struct l_wait_info lwi;
78 if (lfsck->ml_sleep_jif > 0 &&
79 lfsck->ml_new_scanned >= lfsck->ml_sleep_rate) {
80 spin_lock(&lfsck->ml_lock);
81 if (likely(lfsck->ml_sleep_jif > 0 &&
82 lfsck->ml_new_scanned >= lfsck->ml_sleep_rate)) {
83 lwi = LWI_TIMEOUT_INTR(lfsck->ml_sleep_jif, NULL,
84 LWI_ON_SIGNAL_NOOP, NULL);
85 spin_unlock(&lfsck->ml_lock);
87 l_wait_event(thread->t_ctl_waitq,
88 !thread_is_running(thread),
90 lfsck->ml_new_scanned = 0;
92 spin_unlock(&lfsck->ml_lock);
97 static int mdd_lfsck_main(void *args)
100 struct md_lfsck *lfsck = (struct md_lfsck *)args;
101 struct ptlrpc_thread *thread = &lfsck->ml_thread;
102 struct dt_object *obj = lfsck->ml_it_obj;
103 const struct dt_it_ops *iops = &obj->do_index_ops->dio_it;
109 cfs_daemonize("lfsck");
110 rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD);
112 CERROR("%s: LFSCK, fail to init env, rc = %d\n",
113 mdd_lfsck2name(lfsck), rc);
117 di = iops->init(&env, obj, lfsck->ml_args, BYPASS_CAPA);
120 CERROR("%s: LFSCK, fail to init iteration, rc = %d\n",
121 mdd_lfsck2name(lfsck), rc);
125 CDEBUG(D_LFSCK, "LFSCK: flags = 0x%x, pid = %d\n",
126 lfsck->ml_args, cfs_curproc_pid());
128 /* XXX: Prepare before wakeup the sponsor.
129 * Each lfsck component should call iops->get() API with
130 * every bookmark, then low layer module can decide the
131 * start point for current iteration. */
133 spin_lock(&lfsck->ml_lock);
134 thread_set_flags(thread, SVC_RUNNING);
135 spin_unlock(&lfsck->ml_lock);
136 cfs_waitq_broadcast(&thread->t_ctl_waitq);
138 /* Call iops->load() to finish the choosing start point. */
139 rc = iops->load(&env, di, 0);
143 CDEBUG(D_LFSCK, "LFSCK: iteration start: pos = %s\n",
144 (char *)iops->key(&env, di));
146 lfsck->ml_new_scanned = 0;
147 fid = &mdd_env_info(&env)->mti_fid;
149 iops->rec(&env, di, (struct dt_rec *)fid, 0);
151 /* XXX: here, perform LFSCK when some LFSCK component(s)
152 * introduced in the future. */
153 lfsck->ml_new_scanned++;
155 /* XXX: here, make checkpoint when some LFSCK component(s)
156 * introduced in the future. */
159 mdd_lfsck_control_speed(lfsck);
160 if (unlikely(!thread_is_running(thread)))
163 rc = iops->next(&env, di);
169 if (lfsck->ml_paused) {
170 /* XXX: It is hack here: if the lfsck is still running when MDS
171 * umounts, it should be restarted automatically after MDS
174 * To support that, we need to record the lfsck status in
175 * the lfsck on-disk bookmark file. But now, there is not
176 * lfsck component under the lfsck framework. To avoid to
177 * introduce unnecessary bookmark incompatibility issues,
178 * we write nothing to the lfsck bookmark file now.
180 * Instead, we will reuse dt_it_ops::put() method to notify
181 * low layer iterator to process such case.
183 * It is just temporary solution, and will be replaced when
184 * some lfsck component is introduced in the future. */
186 CDEBUG(D_LFSCK, "LFSCK: iteration pasued: pos = %s, rc = %d\n",
187 (char *)iops->key(&env, di), rc);
189 CDEBUG(D_LFSCK, "LFSCK: iteration stop: pos = %s, rc = %d\n",
190 (char *)iops->key(&env, di), rc);
192 iops->fini(&env, di);
198 spin_lock(&lfsck->ml_lock);
199 thread_set_flags(thread, SVC_STOPPED);
200 cfs_waitq_broadcast(&thread->t_ctl_waitq);
201 spin_unlock(&lfsck->ml_lock);
205 int mdd_lfsck_start(const struct lu_env *env, struct md_lfsck *lfsck,
206 struct lfsck_start *start)
208 struct ptlrpc_thread *thread = &lfsck->ml_thread;
209 struct l_wait_info lwi = { 0 };
215 if (lfsck->ml_it_obj == NULL)
218 mutex_lock(&lfsck->ml_mutex);
219 spin_lock(&lfsck->ml_lock);
220 if (thread_is_running(thread)) {
221 spin_unlock(&lfsck->ml_lock);
222 mutex_unlock(&lfsck->ml_mutex);
226 spin_unlock(&lfsck->ml_lock);
227 if (start->ls_valid & LSV_SPEED_LIMIT)
228 mdd_lfsck_set_speed(lfsck, start->ls_speed_limit);
230 if (start->ls_valid & LSV_ERROR_HANDLE) {
231 valid |= DOIV_ERROR_HANDLE;
232 if (start->ls_flags & LPF_FAILOUT)
233 flags |= DOIF_FAILOUT;
236 /* XXX: 1. low layer does not care 'dryrun'.
237 * 2. will process 'ls_active' when introduces LFSCK for layout
238 * consistency, DNE consistency, and so on in the future. */
239 start->ls_active = 0;
241 if (start->ls_flags & LPF_RESET)
244 if (start->ls_active != 0)
245 flags |= DOIF_OUTUSED;
247 lfsck->ml_args = (flags << DT_OTABLE_IT_FLAGS_SHIFT) | valid;
248 thread_set_flags(thread, 0);
249 rc = cfs_create_thread(mdd_lfsck_main, lfsck, 0);
251 CERROR("%s: cannot start LFSCK thread, rc = %d\n",
252 mdd_lfsck2name(lfsck), rc);
254 l_wait_event(thread->t_ctl_waitq,
255 thread_is_running(thread) ||
256 thread_is_stopped(thread),
258 mutex_unlock(&lfsck->ml_mutex);
260 RETURN(rc < 0 ? rc : 0);
263 int mdd_lfsck_stop(const struct lu_env *env, struct md_lfsck *lfsck)
265 struct ptlrpc_thread *thread = &lfsck->ml_thread;
266 struct l_wait_info lwi = { 0 };
269 mutex_lock(&lfsck->ml_mutex);
270 spin_lock(&lfsck->ml_lock);
271 if (thread_is_init(thread) || thread_is_stopped(thread)) {
272 spin_unlock(&lfsck->ml_lock);
273 mutex_unlock(&lfsck->ml_mutex);
277 thread_set_flags(thread, SVC_STOPPING);
278 spin_unlock(&lfsck->ml_lock);
280 cfs_waitq_broadcast(&thread->t_ctl_waitq);
281 l_wait_event(thread->t_ctl_waitq,
282 thread_is_stopped(thread),
284 mutex_unlock(&lfsck->ml_mutex);
289 const char lfsck_bookmark_name[] = "lfsck_bookmark";
291 static const struct lu_fid lfsck_it_fid = { .f_seq = FID_SEQ_LOCAL_FILE,
292 .f_oid = OTABLE_IT_OID,
295 int mdd_lfsck_setup(const struct lu_env *env, struct mdd_device *mdd)
297 struct md_lfsck *lfsck = &mdd->mdd_lfsck;
298 struct dt_object *obj;
301 memset(lfsck, 0, sizeof(*lfsck));
302 lfsck->ml_version = LFSCK_VERSION_V1;
303 cfs_waitq_init(&lfsck->ml_thread.t_ctl_waitq);
304 mutex_init(&lfsck->ml_mutex);
305 spin_lock_init(&lfsck->ml_lock);
307 obj = dt_store_open(env, mdd->mdd_child, "", lfsck_bookmark_name,
308 &mdd_env_info(env)->mti_fid);
312 lfsck->ml_bookmark_obj = obj;
314 obj = dt_locate(env, mdd->mdd_child, &lfsck_it_fid);
318 rc = obj->do_ops->do_index_try(env, obj, &dt_otable_features);
320 lu_object_put(env, &obj->do_lu);
326 lfsck->ml_it_obj = obj;
331 void mdd_lfsck_cleanup(const struct lu_env *env, struct mdd_device *mdd)
333 struct md_lfsck *lfsck = &mdd->mdd_lfsck;
335 if (lfsck->ml_it_obj != NULL) {
336 lfsck->ml_paused = 1;
337 mdd_lfsck_stop(env, lfsck);
338 lu_object_put(env, &lfsck->ml_it_obj->do_lu);
339 lfsck->ml_it_obj = NULL;
342 if (lfsck->ml_bookmark_obj != NULL) {
343 lu_object_put(env, &lfsck->ml_bookmark_obj->do_lu);
344 lfsck->ml_bookmark_obj = NULL;