Whamcloud - gitweb
1051f0e67b4b5987b2a8de77ad77472beb2f8986
[fs/lustre-release.git] / lustre / mdd / mdd_compat.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, 2014, Intel Corporation.
24  */
25 #define DEBUG_SUBSYSTEM S_MDS
26
27 #include <lustre/lustre_idl.h>
28 #include <lustre_fid.h>
29 #include <obd_support.h>
30
31 #include "mdd_internal.h"
32
33 /*
34  * To enable DNE functionality we need FID of /ROOT directory
35  * (which is / as seen by the clients) to belong to MDT0 and
36  * not to FID_SEQ_LOCAL_FILE or some other local sequence,
37  * which can be used by any node, so can't be part of FLDB.
38  *
39  * Pre-production code was using FID_SEQ_LOCAL_FILE for /ROOT
40  * making few existing setups incompatibile with DNE. This
41  * applies to ZFS-based setups only as ldiskfs-based setups
42  * are still using IGIF to identify /ROOT.
43  *
44  * The intention of this code is to fix on-disk state to use
45  * FID_SEQ_ROOT for /ROOT:
46  *  - "." and ".." references in /ROOT itself and it`s subdirectories
47  *  - LinkEA in all the objects listed in /ROOT
48  *
49  * Given only ZFS is affected where "." and ".." are not stored, we need to:
50  *  - delete "." and ".." from /ROOT and its subdirectories
51  *  - rename references in LinkEA in all the objects listed in /ROOT
52  *
53  * This code is subject for removal in 2.5
54  */
55 static int mdd_convert_remove_dots(const struct lu_env *env,
56                                    struct mdd_device *mdd,
57                                    struct mdd_object *o)
58 {
59         struct thandle          *th;
60         const struct dt_key     *dot = (const struct dt_key *)".";
61         const struct dt_key     *dotdot = (const struct dt_key *)"..";
62         int                      rc;
63
64         if (dt_try_as_dir(env, mdd_object_child(o)) == 0)
65                 RETURN(-ENOTDIR);
66
67         /* remove "."/".." and do not insert them back - not stored in ZFS */
68         th = dt_trans_create(env, mdd->mdd_child);
69         if (IS_ERR(th))
70                 RETURN(PTR_ERR(th));
71
72         rc = dt_declare_delete(env, mdd_object_child(o), dot, th);
73         if (rc)
74                 GOTO(out, rc);
75         rc = dt_declare_delete(env, mdd_object_child(o), dotdot, th);
76         if (rc)
77                 GOTO(out, rc);
78         rc = dt_trans_start_local(env, mdd->mdd_child, th);
79         if (rc)
80                 GOTO(out, rc);
81         /* ignore non-existing "."/".." - we stored them on disk for
82          * pre-production systems, but this is not how regular ZFS works */
83         rc = dt_delete(env, mdd_object_child(o), dot, th, BYPASS_CAPA);
84         if (rc == -ENOENT)
85                 rc = 0;
86         if (rc)
87                 GOTO(out, rc);
88         rc = dt_delete(env, mdd_object_child(o), dotdot, th, BYPASS_CAPA);
89         if (rc == -ENOENT)
90                 rc = 0;
91         if (rc)
92                 GOTO(out, rc);
93
94 out:
95         dt_trans_stop(env, mdd->mdd_child, th);
96         RETURN(rc);
97 }
98
99 static int mdd_convert_linkea(const struct lu_env *env,
100                               struct mdd_device *mdd,
101                               struct mdd_object *o,
102                               const struct lu_name *name)
103 {
104         struct thandle  *th;
105         struct lu_fid    oldfid;
106         int              rc;
107         ENTRY;
108
109         th = dt_trans_create(env, mdd->mdd_child);
110         if (IS_ERR(th))
111                 RETURN(PTR_ERR(th));
112
113         rc = mdd_declare_links_add(env, o, th, NULL, MLAO_IGNORE);
114         if (rc)
115                 GOTO(out, rc);
116         rc = dt_trans_start_local(env, mdd->mdd_child, th);
117         if (rc)
118                 GOTO(out, rc);
119
120         oldfid.f_seq = FID_SEQ_LOCAL_FILE;
121         oldfid.f_oid = MDD_ROOT_INDEX_OID;
122         oldfid.f_ver = 0;
123         rc = mdd_links_rename(env, o, &oldfid, name, &mdd->mdd_root_fid,
124                               name, th, NULL, 0, 1);
125         if (rc == -ENOENT || rc == -EEXIST)
126                 rc = 0;
127
128 out:
129         dt_trans_stop(env, mdd->mdd_child, th);
130         RETURN(rc);
131 }
132
133 static int mdd_convert_object(const struct lu_env *env,
134                               struct mdd_device *mdd,
135                               const struct lu_fid *fid,
136                               const struct lu_name *name)
137 {
138         struct mdd_object       *o;
139         struct lu_attr          *la = MDD_ENV_VAR(env, cattr);
140         int                      rc;
141         ENTRY;
142
143         o = mdd_object_find(env, mdd, fid);
144         if (IS_ERR(o)) {
145                 CERROR("%s: can't access the object: rc = %d\n",
146                        mdd2obd_dev(mdd)->obd_name, (int)PTR_ERR(o));
147                 RETURN(PTR_ERR(o));
148         }
149
150         rc = mdo_attr_get(env, o, la, BYPASS_CAPA);
151         if (rc)
152                 GOTO(out, rc);
153
154         if (S_ISDIR(la->la_mode)) {
155                 /* remove "." and ".." if a directory */
156                 rc = mdd_convert_remove_dots(env, mdd, o);
157                 if (rc)
158                         GOTO(out, rc);
159         }
160
161         /* update linkEA */
162         rc = mdd_convert_linkea(env, mdd, o, name);
163         if (rc)
164                 CERROR("%s: can't convert: rc = %d\n",
165                        mdd2obd_dev(mdd)->obd_name, rc);
166
167 out:
168         mdd_object_put(env, o);
169         RETURN(0);
170 }
171
172 static int mdd_convert_lma(const struct lu_env *env, struct mdd_device *mdd,
173                            struct mdd_object *o)
174 {
175         struct lustre_mdt_attrs *lma;
176         struct thandle          *th;
177         struct lu_fid            fid;
178         struct lu_buf            buf;
179         int                      rc;
180         ENTRY;
181
182         lu_root_fid(&fid);
183
184         lma = (struct lustre_mdt_attrs *)&mdd_env_info(env)->mti_xattr_buf;
185         lustre_lma_init(lma, &fid, 0, 0);
186         lustre_lma_swab(lma);
187         buf.lb_buf = lma;
188         buf.lb_len = sizeof(*lma);
189
190         th = dt_trans_create(env, mdd->mdd_child);
191         if (IS_ERR(th))
192                 RETURN(PTR_ERR(th));
193         rc = mdo_declare_xattr_set(env, o, &buf, XATTR_NAME_LMA, 0, th);
194         if (rc)
195                 GOTO(out, rc);
196         rc = dt_trans_start_local(env, mdd->mdd_child, th);
197         if (rc)
198                 GOTO(out, rc);
199         rc = mdo_xattr_set(env, o, &buf, XATTR_NAME_LMA, 0, th, BYPASS_CAPA);
200 out:
201         dt_trans_stop(env, mdd->mdd_child, th);
202         RETURN(rc);
203 }
204
205 static int mdd_fix_children(const struct lu_env *env,
206                             struct mdd_device *mdd,
207                             struct dt_object *o)
208 {
209         struct mdd_thread_info *info = mdd_env_info(env);
210         const struct dt_it_ops *iops;
211         struct lu_name          name;
212         struct dt_it           *it;
213         struct lu_dirent       *ent;
214         int                     rc;
215         ENTRY;
216
217         /* scan /ROOT and update all ".." and linkEAs */
218         ent = (struct lu_dirent *)&info->mti_xattr_buf;
219         iops = &o->do_index_ops->dio_it;
220
221         it = iops->init(env, o, LUDA_64BITHASH, BYPASS_CAPA);
222         if (IS_ERR(it)) {
223                 rc = PTR_ERR(it);
224                 CERROR("%s: can't initialize the iterator: rc = %d\n",
225                        mdd2obd_dev(mdd)->obd_name, rc);
226                 GOTO(out, rc);
227         }
228
229         rc = iops->load(env, it, 0);
230         if (rc <= 0)
231                 GOTO(out_put, rc);
232
233         do {
234                 size_t lu_dirent_size;
235
236                 rc = iops->key_size(env, it);
237                 if (rc == 0)
238                         goto next;
239
240                 /* calculate max space required for lu_dirent */
241                 lu_dirent_size = lu_dirent_calc_size(rc, 0);
242                 LASSERT(lu_dirent_size <= sizeof(info->mti_xattr_buf));
243
244                 rc = iops->rec(env, it, (struct dt_rec *)ent, LUDA_TYPE);
245                 if (rc == 0) {
246                         CDEBUG(D_OTHER, "convert %*s -> "DFID"\n",
247                                ent->lde_namelen, ent->lde_name,
248                                PFID(&ent->lde_fid));
249                         name.ln_namelen = ent->lde_namelen;
250                         name.ln_name = ent->lde_name;
251                         rc = mdd_convert_object(env, mdd, &ent->lde_fid, &name);
252                         if (rc) {
253                                 CERROR("%s: can't convert "DFID": rc = %d\n",
254                                        mdd2obd_dev(mdd)->obd_name,
255                                        PFID(&ent->lde_fid), rc);
256                                 break;
257                         }
258                 }
259
260 next:
261                 rc = iops->next(env, it);
262         } while (rc == 0);
263         if (rc > 0)
264                 rc = 0;
265
266 out_put:
267         iops->put(env, it);
268         iops->fini(env, it);
269 out:
270         RETURN(rc);
271 }
272
273 static int mdd_fill_fldb(const struct lu_env *env, struct mdd_device *mdd)
274 {
275         struct seq_server_site *ss = mdd_seq_site(mdd);
276         struct lu_seq_range range;
277         int     rc;
278
279         LASSERT(ss->ss_server_seq != NULL);
280         LASSERT(ss->ss_server_fld != NULL);
281
282         if (ss->ss_server_seq->lss_space.lsr_end == 0)
283                 return 0;
284
285         memcpy(&range, &ss->ss_server_seq->lss_space, sizeof(range));
286
287         /* Pre-existing ZFS does not insert any entries to FLDB, we need
288          * to insert it to FLDB during convertion */
289         range.lsr_start = FID_SEQ_NORMAL;
290         fld_range_set_mdt(&range);
291
292         mutex_lock(&ss->ss_server_fld->lsf_lock);
293         rc = fld_insert_entry(env, ss->ss_server_fld, &range);
294         mutex_unlock(&ss->ss_server_fld->lsf_lock);
295
296         LCONSOLE_INFO("%s: insert missing range "DRANGE"\n",
297                       mdd2obd_dev(mdd)->obd_name, PRANGE(&range));
298         return rc;
299 }
300 int mdd_compat_fixes(const struct lu_env *env, struct mdd_device *mdd)
301 {
302         struct mdd_thread_info  *info = mdd_env_info(env);
303         struct mdd_object       *root;
304         struct dt_object        *o;
305         struct lustre_mdt_attrs *lma;
306         struct lu_buf            buf;
307         int                      rc;
308         ENTRY;
309
310         /* IGIF FIDS are valid for old 1.8 and 2.[123] ROOT and are kept.
311          * Normal FIDs used by Xyratex 1.8->2.1 upgrade tool are also kept. */
312         if (fid_is_igif(&mdd->mdd_root_fid) || fid_is_norm(&mdd->mdd_root_fid))
313                 RETURN(0);
314
315         /*
316          * FID is supposed to be FID_SEQ_ROOT for:
317          *  - new ldiskfs fs
318          *  - new ZFS fs
319          *  - old ZFS fs, by now processed with osd_convert_root_to_new_seq()
320          */
321         if (fid_seq(&mdd->mdd_root_fid) != FID_SEQ_ROOT) {
322                 CERROR("%s: wrong FID "DFID" is used for /ROOT\n",
323                        mdd2obd_dev(mdd)->obd_name,
324                        PFID(&mdd->mdd_root_fid));
325                 RETURN(-EINVAL);
326         }
327
328         root = mdd_object_find(env, mdd, &mdd->mdd_root_fid);
329         if (IS_ERR(root))
330                 RETURN(PTR_ERR(root));
331         o = mdd_object_child(root);
332
333         CDEBUG(D_OTHER, "/ROOT = "DFID"\n", PFID(&mdd->mdd_root_fid));
334
335         if (dt_try_as_dir(env, o) == 0) {
336                 CERROR("%s: not a directory\n", mdd2obd_dev(mdd)->obd_name);
337                 GOTO(out, rc = -ENOTDIR);
338         }
339
340         lma = (struct lustre_mdt_attrs *)&info->mti_xattr_buf;
341         CLASSERT(sizeof(info->mti_xattr_buf) >= LMA_OLD_SIZE);
342         buf.lb_len = LMA_OLD_SIZE;
343         buf.lb_buf = lma;
344         rc = mdo_xattr_get(env, root, &buf, XATTR_NAME_LMA, BYPASS_CAPA);
345         if (rc < 0 && rc != -ENODATA) {
346                 CERROR("%s: can't fetch LMA: rc = %d\n",
347                        mdd2obd_dev(mdd)->obd_name, rc);
348                 GOTO(out, rc);
349         }
350
351         lustre_lma_swab(lma);
352         if (lu_fid_eq(&lma->lma_self_fid, &mdd->mdd_root_fid)) {
353                 /* /ROOT has been converted already
354                  * or was correct from the beginning */
355                 CDEBUG(D_OTHER, "%s: converted already\n",
356                        mdd2obd_dev(mdd)->obd_name);
357                 GOTO(out, rc = 0);
358         }
359
360         /* this is supposed to happen only on pre-production ZFS backend */
361         if (strcmp(mdd->mdd_bottom->dd_lu_dev.ld_type->ldt_name,
362                    LUSTRE_OSD_ZFS_NAME) != 0) {
363                 CERROR("%s: "DFID" is used on ldiskfs?!\n",
364                        mdd2obd_dev(mdd)->obd_name, PFID(&mdd->mdd_root_fid));
365                 GOTO(out, rc = -ENOTSUPP);
366         }
367
368         LCONSOLE_INFO("%s: FID of /ROOT has been changed. "
369                       "Please remount the clients.\n",
370                       mdd2obd_dev(mdd)->obd_name);
371
372         /* Fill FLDB first */
373         rc = mdd_fill_fldb(env, mdd);
374         if (rc)
375                 GOTO(out, rc);
376
377         /* remove ./.. from /ROOT */
378         rc = mdd_convert_remove_dots(env, mdd, root);
379         if (rc)
380                 GOTO(out, rc);
381
382         /* go over the directory, fix all the objects */
383         rc = mdd_fix_children(env, mdd, o);
384         if (rc)
385                 GOTO(out, rc);
386
387         /* Update LMA on /ROOT.  Done for simplicity in MDD, not in osd-zfs.
388          * Correct LMA will imply the whole directory has been coverted
389          * successfully, otherwise it will be retried on next mount. */
390         rc = mdd_convert_lma(env, mdd, root);
391
392 out:
393         mdd_object_put(env, root);
394         RETURN(rc);
395 }