Whamcloud - gitweb
LU-1267 lfsck: framework (3) for MDT-OST consistency
[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) 2012, 2013, 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 const char lfsck_bookmark_name[] = "lfsck_bookmark";
43
44 static void lfsck_bookmark_le_to_cpu(struct lfsck_bookmark *des,
45                                      struct lfsck_bookmark *src)
46 {
47         des->lb_magic = le32_to_cpu(src->lb_magic);
48         des->lb_version = le16_to_cpu(src->lb_version);
49         des->lb_param = le16_to_cpu(src->lb_param);
50         des->lb_speed_limit = le32_to_cpu(src->lb_speed_limit);
51         des->lb_async_windows = le16_to_cpu(src->lb_async_windows);
52 }
53
54 static 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 }
63
64 static int lfsck_bookmark_load(const struct lu_env *env,
65                                struct lfsck_instance *lfsck)
66 {
67         loff_t pos = 0;
68         int    len = sizeof(struct lfsck_bookmark);
69         int    rc;
70
71         rc = dt_record_read(env, lfsck->li_bookmark_obj,
72                             lfsck_buf_get(env, &lfsck->li_bookmark_disk, len),
73                             &pos);
74         if (rc == 0) {
75                 struct lfsck_bookmark *bm = &lfsck->li_bookmark_ram;
76
77                 lfsck_bookmark_le_to_cpu(bm, &lfsck->li_bookmark_disk);
78                 if (bm->lb_magic != LFSCK_BOOKMARK_MAGIC) {
79                         CWARN("%s: invalid lfsck_bookmark magic %#x != %#x\n",
80                               lfsck_lfsck2name(lfsck), bm->lb_magic,
81                               LFSCK_BOOKMARK_MAGIC);
82                         /* Process it as new lfsck_bookmark. */
83                         rc = -ENODATA;
84                 }
85         } else {
86                 if (rc == -EFAULT && pos == 0)
87                         /* return -ENODATA for empty lfsck_bookmark. */
88                         rc = -ENODATA;
89                 else
90                         CERROR("%s: fail to load lfsck_bookmark: "
91                                "expected = %d, rc = %d\n",
92                                lfsck_lfsck2name(lfsck), len, rc);
93         }
94         return rc;
95 }
96
97 int lfsck_bookmark_store(const struct lu_env *env, struct lfsck_instance *lfsck)
98 {
99         struct thandle    *handle;
100         struct dt_object  *obj    = lfsck->li_bookmark_obj;
101         loff_t             pos    = 0;
102         int                len    = sizeof(struct lfsck_bookmark);
103         int                rc;
104         ENTRY;
105
106         lfsck_bookmark_cpu_to_le(&lfsck->li_bookmark_disk,
107                                  &lfsck->li_bookmark_ram);
108         handle = dt_trans_create(env, lfsck->li_bottom);
109         if (IS_ERR(handle)) {
110                 rc = PTR_ERR(handle);
111                 CERROR("%s: fail to create trans for storing lfsck_bookmark: "
112                        "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
113                 RETURN(rc);
114         }
115
116         rc = dt_declare_record_write(env, obj, len, 0, handle);
117         if (rc != 0) {
118                 CERROR("%s: fail to declare trans for storing lfsck_bookmark: "
119                        "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
120                 GOTO(out, rc);
121         }
122
123         rc = dt_trans_start_local(env, lfsck->li_bottom, handle);
124         if (rc != 0) {
125                 CERROR("%s: fail to start trans for storing lfsck_bookmark: "
126                        "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
127                 GOTO(out, rc);
128         }
129
130         rc = dt_record_write(env, obj,
131                              lfsck_buf_get(env, &lfsck->li_bookmark_disk, len),
132                              &pos, handle);
133         if (rc != 0)
134                 CERROR("%s: fail to store lfsck_bookmark: expected = %d, "
135                        "rc = %d\n", lfsck_lfsck2name(lfsck), len, rc);
136
137         GOTO(out, rc);
138
139 out:
140         dt_trans_stop(env, lfsck->li_bottom, handle);
141         return rc;
142 }
143
144 static int lfsck_bookmark_init(const struct lu_env *env,
145                                struct lfsck_instance *lfsck)
146 {
147         struct lfsck_bookmark *mb = &lfsck->li_bookmark_ram;
148         int rc;
149
150         memset(mb, 0, sizeof(*mb));
151         mb->lb_magic = LFSCK_BOOKMARK_MAGIC;
152         mb->lb_version = LFSCK_VERSION_V2;
153         mb->lb_async_windows = LFSCK_ASYNC_WIN_DEFAULT;
154         mutex_lock(&lfsck->li_mutex);
155         rc = lfsck_bookmark_store(env, lfsck);
156         mutex_unlock(&lfsck->li_mutex);
157         return rc;
158 }
159
160 int lfsck_bookmark_setup(const struct lu_env *env,
161                          struct lfsck_instance *lfsck)
162 {
163         struct dt_object *root;
164         struct dt_object *obj;
165         int               rc;
166         ENTRY;
167
168         root = dt_locate(env, lfsck->li_bottom, &lfsck->li_local_root_fid);
169         if (IS_ERR(root))
170                 RETURN(PTR_ERR(root));
171
172         if (unlikely(!dt_try_as_dir(env, root))) {
173                 lu_object_put(env, &root->do_lu);
174
175                 RETURN(-ENOTDIR);
176         }
177
178         obj = local_file_find_or_create(env, lfsck->li_los, root,
179                                         lfsck_bookmark_name,
180                                         S_IFREG | S_IRUGO | S_IWUSR);
181         lu_object_put(env, &root->do_lu);
182         if (IS_ERR(obj))
183                 RETURN(PTR_ERR(obj));
184
185         lfsck->li_bookmark_obj = obj;
186         rc = lfsck_bookmark_load(env, lfsck);
187         if (rc == -ENODATA)
188                 rc = lfsck_bookmark_init(env, lfsck);
189
190         RETURN(rc);
191 }