Whamcloud - gitweb
LU-8929 lfsck: dumper gets current position properly
[fs/lustre-release.git] / lustre / lfsck / lfsck_bookmark.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9
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.
15
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
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2013, 2015, Intel Corporation.
24  */
25 /*
26  * lustre/lfsck/lfsck_bookmark.c
27  *
28  * Author: Fan, Yong <fan.yong@intel.com>
29  */
30
31 #define DEBUG_SUBSYSTEM S_LFSCK
32
33 #include <lu_object.h>
34 #include <dt_object.h>
35 #include <lustre_fid.h>
36 #include <lustre/lustre_user.h>
37
38 #include "lfsck_internal.h"
39
40 #define LFSCK_BOOKMARK_MAGIC    0x20130C1D
41
42 static void lfsck_bookmark_le_to_cpu(struct lfsck_bookmark *des,
43                                      struct lfsck_bookmark *src)
44 {
45         des->lb_magic = le32_to_cpu(src->lb_magic);
46         des->lb_version = le16_to_cpu(src->lb_version);
47         des->lb_param = le16_to_cpu(src->lb_param);
48         des->lb_speed_limit = le32_to_cpu(src->lb_speed_limit);
49         des->lb_async_windows = le16_to_cpu(src->lb_async_windows);
50         fid_le_to_cpu(&des->lb_lpf_fid, &src->lb_lpf_fid);
51         fid_le_to_cpu(&des->lb_last_fid, &src->lb_last_fid);
52 }
53
54 void lfsck_bookmark_cpu_to_le(struct lfsck_bookmark *des,
55                               struct lfsck_bookmark *src)
56 {
57         des->lb_magic = cpu_to_le32(src->lb_magic);
58         des->lb_version = cpu_to_le16(src->lb_version);
59         des->lb_param = cpu_to_le16(src->lb_param);
60         des->lb_speed_limit = cpu_to_le32(src->lb_speed_limit);
61         des->lb_async_windows = cpu_to_le16(src->lb_async_windows);
62         fid_cpu_to_le(&des->lb_lpf_fid, &src->lb_lpf_fid);
63         fid_cpu_to_le(&des->lb_last_fid, &src->lb_last_fid);
64 }
65
66 static int lfsck_bookmark_load(const struct lu_env *env,
67                                struct lfsck_instance *lfsck)
68 {
69         loff_t pos = 0;
70         int    len = sizeof(struct lfsck_bookmark);
71         int    rc;
72
73         rc = dt_record_read(env, lfsck->li_bookmark_obj,
74                             lfsck_buf_get(env, &lfsck->li_bookmark_disk, len),
75                             &pos);
76         if (rc == 0) {
77                 struct lfsck_bookmark *bm = &lfsck->li_bookmark_ram;
78
79                 lfsck_bookmark_le_to_cpu(bm, &lfsck->li_bookmark_disk);
80                 if (bm->lb_magic != LFSCK_BOOKMARK_MAGIC) {
81                         CDEBUG(D_LFSCK, "%s: invalid lfsck_bookmark magic "
82                               "%#x != %#x\n", lfsck_lfsck2name(lfsck),
83                               bm->lb_magic, LFSCK_BOOKMARK_MAGIC);
84                         /* Process it as new lfsck_bookmark. */
85                         rc = -ENODATA;
86                 }
87         } else {
88                 if (rc == -EFAULT && pos == 0)
89                         /* return -ENODATA for empty lfsck_bookmark. */
90                         rc = -ENODATA;
91                 else
92                         CDEBUG(D_LFSCK, "%s: fail to load lfsck_bookmark, "
93                                "expected = %d: rc = %d\n",
94                                lfsck_lfsck2name(lfsck), len, rc);
95         }
96         return rc;
97 }
98
99 int lfsck_bookmark_store(const struct lu_env *env, struct lfsck_instance *lfsck)
100 {
101         struct thandle    *handle;
102         struct dt_object  *obj    = lfsck->li_bookmark_obj;
103         struct dt_device  *dev    = lfsck_obj2dev(obj);
104         loff_t             pos    = 0;
105         int                len    = sizeof(struct lfsck_bookmark);
106         int                rc;
107         ENTRY;
108
109         lfsck_bookmark_cpu_to_le(&lfsck->li_bookmark_disk,
110                                  &lfsck->li_bookmark_ram);
111         handle = dt_trans_create(env, dev);
112         if (IS_ERR(handle))
113                 GOTO(log, rc = PTR_ERR(handle));
114
115         rc = dt_declare_record_write(env, obj,
116                                      lfsck_buf_get(env,
117                                      &lfsck->li_bookmark_disk, len),
118                                      0, handle);
119         if (rc != 0)
120                 GOTO(out, rc);
121
122         rc = dt_trans_start_local(env, dev, handle);
123         if (rc != 0)
124                 GOTO(out, rc);
125
126         rc = dt_record_write(env, obj,
127                              lfsck_buf_get(env, &lfsck->li_bookmark_disk, len),
128                              &pos, handle);
129
130         GOTO(out, rc);
131
132 out:
133         dt_trans_stop(env, dev, handle);
134
135 log:
136         if (rc != 0)
137                 CDEBUG(D_LFSCK, "%s: fail to store lfsck_bookmark: rc = %d\n",
138                        lfsck_lfsck2name(lfsck), rc);
139         return rc;
140 }
141
142 static int lfsck_bookmark_init(const struct lu_env *env,
143                                struct lfsck_instance *lfsck)
144 {
145         struct lfsck_bookmark *mb = &lfsck->li_bookmark_ram;
146         int rc;
147
148         memset(mb, 0, sizeof(*mb));
149         mb->lb_magic = LFSCK_BOOKMARK_MAGIC;
150         mb->lb_version = LFSCK_VERSION_V2;
151         mb->lb_async_windows = LFSCK_ASYNC_WIN_DEFAULT;
152         mutex_lock(&lfsck->li_mutex);
153         rc = lfsck_bookmark_store(env, lfsck);
154         mutex_unlock(&lfsck->li_mutex);
155         return rc;
156 }
157
158 int lfsck_bookmark_setup(const struct lu_env *env,
159                          struct lfsck_instance *lfsck)
160 {
161         struct dt_object *root;
162         struct dt_object *obj;
163         int               rc;
164         ENTRY;
165
166         root = dt_locate(env, lfsck->li_bottom, &lfsck->li_local_root_fid);
167         if (IS_ERR(root))
168                 RETURN(PTR_ERR(root));
169
170         if (unlikely(!dt_try_as_dir(env, root))) {
171                 lfsck_object_put(env, root);
172
173                 RETURN(-ENOTDIR);
174         }
175
176         obj = local_file_find_or_create(env, lfsck->li_los, root,
177                                         LFSCK_BOOKMARK,
178                                         S_IFREG | S_IRUGO | S_IWUSR);
179         lfsck_object_put(env, root);
180         if (IS_ERR(obj))
181                 RETURN(PTR_ERR(obj));
182
183         lfsck->li_bookmark_obj = obj;
184         rc = lfsck_bookmark_load(env, lfsck);
185         if (rc == 0) {
186                 struct lfsck_bookmark *mb = &lfsck->li_bookmark_ram;
187
188                 /* It is upgraded from old release, set it as
189                  * LFSCK_ASYNC_WIN_DEFAULT to avoid memory pressure. */
190                 if (unlikely(mb->lb_async_windows == 0)) {
191                         mb->lb_async_windows = LFSCK_ASYNC_WIN_DEFAULT;
192                         mutex_lock(&lfsck->li_mutex);
193                         rc = lfsck_bookmark_store(env, lfsck);
194                         mutex_unlock(&lfsck->li_mutex);
195                 }
196         } else if (rc == -ENODATA) {
197                 rc = lfsck_bookmark_init(env, lfsck);
198         }
199
200         RETURN(rc);
201 }
202
203 int lfsck_set_param(const struct lu_env *env, struct lfsck_instance *lfsck,
204                     struct lfsck_start *start, bool reset)
205 {
206         struct lfsck_bookmark   *bk     = &lfsck->li_bookmark_ram;
207         int                      rc     = 0;
208         bool                     dirty  = false;
209
210         if (start == NULL) {
211                 LASSERT(reset);
212
213                 if (bk->lb_param & LPF_ALL_TGT) {
214                         bk->lb_param &= ~LPF_ALL_TGT;
215                         dirty = true;
216                 }
217
218                 if (bk->lb_param & LPF_CREATE_OSTOBJ) {
219                         bk->lb_param &= ~LPF_CREATE_OSTOBJ;
220                         dirty = true;
221                 }
222
223                 if (bk->lb_param & LPF_CREATE_MDTOBJ) {
224                         bk->lb_param &= ~LPF_CREATE_MDTOBJ;
225                         dirty = true;
226                 }
227
228                 if (bk->lb_param & LPF_DELAY_CREATE_OSTOBJ) {
229                         bk->lb_param &= ~LPF_DELAY_CREATE_OSTOBJ;
230                         dirty = true;
231                 }
232
233                 if (bk->lb_param & LPF_FAILOUT) {
234                         bk->lb_param &= ~LPF_FAILOUT;
235                         dirty = true;
236                 }
237
238                 if (bk->lb_param & LPF_DRYRUN) {
239                         bk->lb_param &= ~LPF_DRYRUN;
240                         dirty = true;
241                 }
242
243                 if (bk->lb_param & LPF_OST_ORPHAN) {
244                         bk->lb_param &= ~LPF_OST_ORPHAN;
245                         dirty = true;
246                 }
247
248                 if (__lfsck_set_speed(lfsck, LFSCK_SPEED_NO_LIMIT))
249                         dirty = true;
250
251                 if (bk->lb_async_windows != LFSCK_ASYNC_WIN_DEFAULT) {
252                         bk->lb_async_windows = LFSCK_ASYNC_WIN_DEFAULT;
253                         dirty = true;
254                 }
255         } else {
256                 if ((bk->lb_param & LPF_ALL_TGT) &&
257                     !(start->ls_flags & LPF_ALL_TGT)) {
258                         bk->lb_param &= ~LPF_ALL_TGT;
259                         dirty = true;
260                 } else if (!(bk->lb_param & LPF_ALL_TGT) &&
261                            (start->ls_flags & LPF_ALL_TGT)) {
262                         bk->lb_param |= LPF_ALL_TGT;
263                         dirty = true;
264                 }
265
266                 if ((start->ls_valid & LSV_CREATE_OSTOBJ) || reset) {
267                         if ((bk->lb_param & LPF_CREATE_OSTOBJ) &&
268                             !(start->ls_valid & LSV_CREATE_OSTOBJ)) {
269                                 bk->lb_param &= ~LPF_CREATE_OSTOBJ;
270                                 dirty = true;
271                         } else if (!(bk->lb_param & LPF_CREATE_OSTOBJ) &&
272                                    (start->ls_flags & LPF_CREATE_OSTOBJ)) {
273                                 bk->lb_param |= LPF_CREATE_OSTOBJ;
274                                 dirty = true;
275                         }
276                 }
277
278                 if ((start->ls_valid & LSV_CREATE_MDTOBJ) || reset) {
279                         if ((bk->lb_param & LPF_CREATE_MDTOBJ) &&
280                             !(start->ls_valid & LSV_CREATE_MDTOBJ)) {
281                                 bk->lb_param &= ~LPF_CREATE_MDTOBJ;
282                                 dirty = true;
283                         } else if (!(bk->lb_param & LPF_CREATE_MDTOBJ) &&
284                                    (start->ls_flags & LPF_CREATE_MDTOBJ)) {
285                                 bk->lb_param |= LPF_CREATE_MDTOBJ;
286                                 dirty = true;
287                         }
288                 }
289
290                 if ((start->ls_valid & LSV_DELAY_CREATE_OSTOBJ) || reset) {
291                         if ((bk->lb_param & LPF_DELAY_CREATE_OSTOBJ) &&
292                             !(start->ls_valid & LSV_DELAY_CREATE_OSTOBJ)) {
293                                 bk->lb_param &= ~LPF_DELAY_CREATE_OSTOBJ;
294                                 dirty = true;
295                         } else if (!(bk->lb_param & LPF_DELAY_CREATE_OSTOBJ) &&
296                                    start->ls_flags & LPF_DELAY_CREATE_OSTOBJ) {
297                                 bk->lb_param |= LPF_DELAY_CREATE_OSTOBJ;
298                                 dirty = true;
299                         }
300                 }
301
302                 if ((start->ls_valid & LSV_ERROR_HANDLE) || reset) {
303                         if ((bk->lb_param & LPF_FAILOUT) &&
304                             !(start->ls_valid & LSV_ERROR_HANDLE)) {
305                                 bk->lb_param &= ~LPF_FAILOUT;
306                                 dirty = true;
307                         } else if (!(start->ls_flags & LPF_FAILOUT) &&
308                                    (bk->lb_param & LPF_FAILOUT)) {
309                                 bk->lb_param &= ~LPF_FAILOUT;
310                                 dirty = true;
311                         }
312                 }
313
314                 if ((start->ls_valid & LSV_DRYRUN) || reset) {
315                         if ((bk->lb_param & LPF_DRYRUN) &&
316                            !(start->ls_valid & LSV_DRYRUN)) {
317                                 bk->lb_param &= ~LPF_DRYRUN;
318                                 dirty = true;
319                         } else if (!(start->ls_flags & LPF_DRYRUN) &&
320                                    (bk->lb_param & LPF_DRYRUN)) {
321                                 bk->lb_param &= ~LPF_DRYRUN;
322                                 lfsck->li_drop_dryrun = 1;
323                                 dirty = true;
324                         }
325                 }
326
327                 if ((bk->lb_param & LPF_OST_ORPHAN) &&
328                     !(start->ls_flags & LPF_OST_ORPHAN)) {
329                         bk->lb_param &= ~LPF_OST_ORPHAN;
330                         dirty = true;
331                 } else if (!(bk->lb_param & LPF_OST_ORPHAN) &&
332                            (start->ls_flags & LPF_OST_ORPHAN)) {
333                         bk->lb_param |= LPF_OST_ORPHAN;
334                         dirty = true;
335                 }
336
337                 if (start->ls_valid & LSV_SPEED_LIMIT) {
338                         if (__lfsck_set_speed(lfsck, start->ls_speed_limit))
339                                 dirty = true;
340                 } else if (reset) {
341                         if (__lfsck_set_speed(lfsck, LFSCK_SPEED_NO_LIMIT))
342                                 dirty = true;
343                 }
344
345                 if (start->ls_valid & LSV_ASYNC_WINDOWS) {
346                         if (start->ls_async_windows < 1 ||
347                             start->ls_async_windows > LFSCK_ASYNC_WIN_MAX)
348                                 return -EINVAL;
349
350                         if (bk->lb_async_windows != start->ls_async_windows) {
351                                 bk->lb_async_windows = start->ls_async_windows;
352                                 dirty = true;
353                         }
354                 } else if (reset &&
355                            bk->lb_async_windows != LFSCK_ASYNC_WIN_DEFAULT) {
356                         bk->lb_async_windows = LFSCK_ASYNC_WIN_DEFAULT;
357                         dirty = true;
358                 }
359         }
360
361         if (dirty)
362                 rc = lfsck_bookmark_store(env, lfsck);
363
364         return rc;
365 }