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