Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / osd / osd_oi.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/osd/osd_oi.c
37  *
38  * Object Index.
39  *
40  * Author: Nikita Danilov <nikita@clusterfs.com>
41  */
42
43 /*
44  * oi uses two mechanisms to implement fid->cookie mapping:
45  *
46  *     - persistent index, where cookie is a record and fid is a key, and
47  *
48  *     - algorithmic mapping for "igif" fids.
49  *
50  */
51
52 #ifndef EXPORT_SYMTAB
53 # define EXPORT_SYMTAB
54 #endif
55 #define DEBUG_SUBSYSTEM S_MDS
56
57 #include <linux/module.h>
58
59 /* LUSTRE_VERSION_CODE */
60 #include <lustre_ver.h>
61 /*
62  * struct OBD_{ALLOC,FREE}*()
63  * OBD_FAIL_CHECK
64  */
65 #include <obd.h>
66 #include <obd_support.h>
67
68 /* fid_cpu_to_be() */
69 #include <lustre_fid.h>
70
71 #include "osd_oi.h"
72 /* osd_lookup(), struct osd_thread_info */
73 #include "osd_internal.h"
74 #include "osd_igif.h"
75 #include "dt_object.h"
76
77 struct oi_descr {
78         int   fid_size;
79         char *name;
80         __u32 oid;
81 };
82
83 /** to serialize concurrent OI index initialization */
84 static struct mutex oi_init_lock;
85
86 static struct dt_index_features oi_feat = {
87         .dif_flags       = DT_IND_UPDATE,
88         .dif_recsize_min = sizeof(struct osd_inode_id),
89         .dif_recsize_max = sizeof(struct osd_inode_id),
90         .dif_ptrsize     = 4
91 };
92
93 static const struct oi_descr oi_descr[OSD_OI_FID_NR] = {
94         [OSD_OI_FID_SMALL] = {
95                 .fid_size = 5,
96                 .name     = "oi.5",
97                 .oid      = OSD_OI_FID_SMALL_OID
98         },
99         [OSD_OI_FID_OTHER] = {
100                 .fid_size = sizeof(struct lu_fid),
101                 .name     = "oi.16",
102                 .oid      = OSD_OI_FID_OTHER_OID
103         }
104 };
105
106 static int osd_oi_index_create(struct osd_thread_info *info,
107                                struct dt_device *dev,
108                                struct md_device *mdev)
109 {
110         const struct lu_env *env;
111         struct lu_fid *oi_fid = &info->oti_fid;
112         struct md_object *mdo;
113         int i;
114         int rc;
115
116         env = info->oti_env;
117
118         for (i = rc = 0; i < OSD_OI_FID_NR && rc == 0; ++i) {
119                 char *name;
120                 name = oi_descr[i].name;
121                 lu_local_obj_fid(oi_fid, oi_descr[i].oid);
122                 oi_feat.dif_keysize_min = oi_descr[i].fid_size,
123                 oi_feat.dif_keysize_max = oi_descr[i].fid_size,
124
125                 mdo = llo_store_create_index(env, mdev, dev,
126                                              "", name,
127                                              oi_fid, &oi_feat);
128
129                 if (IS_ERR(mdo))
130                         RETURN(PTR_ERR(mdo));
131
132                 lu_object_put(env, &mdo->mo_lu);
133         }
134         return 0;
135 }
136
137 int osd_oi_init(struct osd_thread_info *info,
138                 struct osd_oi *oi,
139                 struct dt_device *dev,
140                 struct md_device *mdev)
141 {
142         const struct lu_env *env;
143         int rc;
144         int i;
145
146         CLASSERT(ARRAY_SIZE(oi->oi_dir) == ARRAY_SIZE(oi_descr));
147
148         env = info->oti_env;
149         mutex_lock(&oi_init_lock);
150         memset(oi, 0, sizeof *oi);
151 retry:
152         for (i = rc = 0; i < OSD_OI_FID_NR && rc == 0; ++i) {
153                 const char       *name;
154                 struct dt_object *obj;
155
156                 name = oi_descr[i].name;
157                 oi_feat.dif_keysize_min = oi_descr[i].fid_size,
158                 oi_feat.dif_keysize_max = oi_descr[i].fid_size,
159
160                 obj = dt_store_open(env, dev, "", name, &info->oti_fid);
161                 if (!IS_ERR(obj)) {
162                         rc = obj->do_ops->do_index_try(env, obj, &oi_feat);
163                         if (rc == 0) {
164                                 LASSERT(obj->do_index_ops != NULL);
165                                 oi->oi_dir[i] = obj;
166                         } else {
167                                 CERROR("Wrong index \"%s\": %d\n", name, rc);
168                                 lu_object_put(env, &obj->do_lu);
169                         }
170                 } else {
171                         rc = PTR_ERR(obj);
172                         if (rc == -ENOENT) {
173                                 rc = osd_oi_index_create(info, dev, mdev);
174                                 if (!rc)
175                                         goto retry;
176                         }
177                         CERROR("Cannot open \"%s\": %d\n", name, rc);
178                 }
179         }
180         if (rc != 0)
181                 osd_oi_fini(info, oi);
182
183         mutex_unlock(&oi_init_lock);
184         return rc;
185 }
186
187 void osd_oi_fini(struct osd_thread_info *info, struct osd_oi *oi)
188 {
189         int i;
190
191         for (i = 0; i < ARRAY_SIZE(oi->oi_dir); ++i) {
192                 if (oi->oi_dir[i] != NULL) {
193                         lu_object_put(info->oti_env, &oi->oi_dir[i]->do_lu);
194                         oi->oi_dir[i] = NULL;
195                 }
196         }
197 }
198
199 static const struct dt_key *oi_fid_key(struct osd_thread_info *info,
200                                        struct osd_oi *oi,
201                                        const struct lu_fid *fid,
202                                        struct dt_object **idx)
203 {
204         int i;
205         struct lu_fid_pack *pack;
206
207         pack = &info->oti_pack;
208         fid_pack(pack, fid, &info->oti_fid);
209         for (i = 0; i < ARRAY_SIZE(oi->oi_dir); ++i) {
210                 if (pack->fp_len == oi_descr[i].fid_size + sizeof pack->fp_len){
211                         *idx = oi->oi_dir[i];
212                         return (const struct dt_key *)&pack->fp_area;
213                 }
214         }
215         CERROR("Unsupported packed fid size: %d ("DFID")\n",
216                pack->fp_len, PFID(fid));
217         LBUG();
218         return NULL;
219 }
220
221 static inline int fid_is_oi_fid(const struct lu_fid *fid)
222 {
223         /* We need to filter-out oi obj's fid. As we can not store it, while
224          * oi-index create operation.
225          */
226         return (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE &&
227                (fid_oid(fid) == OSD_OI_FID_SMALL_OID ||
228                 fid_oid(fid) == OSD_OI_FID_OTHER_OID)));
229 }
230
231 int osd_oi_lookup(struct osd_thread_info *info, struct osd_oi *oi,
232                   const struct lu_fid *fid, struct osd_inode_id *id)
233 {
234         int rc;
235
236         if (fid_is_igif(fid)) {
237                 lu_igif_to_id(fid, id);
238                 rc = 0;
239         } else {
240                 struct dt_object    *idx;
241                 const struct dt_key *key;
242
243                 if (fid_is_oi_fid(fid))
244                         return -ENOENT;
245
246                 key = oi_fid_key(info, oi, fid, &idx);
247                 rc = idx->do_index_ops->dio_lookup(info->oti_env, idx,
248                                                    (struct dt_rec *)id, key,
249                                                    BYPASS_CAPA);
250                 if (rc > 0) {
251                         id->oii_ino = be32_to_cpu(id->oii_ino);
252                         id->oii_gen = be32_to_cpu(id->oii_gen);
253                         rc = 0;
254                 } else if (rc == 0)
255                         rc = -ENOENT;
256         }
257         return rc;
258 }
259
260 int osd_oi_insert(struct osd_thread_info *info, struct osd_oi *oi,
261                   const struct lu_fid *fid, const struct osd_inode_id *id0,
262                   struct thandle *th, int ignore_quota)
263 {
264         struct dt_object    *idx;
265         struct osd_inode_id *id;
266         const struct dt_key *key;
267
268         if (fid_is_igif(fid))
269                 return 0;
270
271         if (fid_is_oi_fid(fid))
272                 return 0;
273
274         key = oi_fid_key(info, oi, fid, &idx);
275         id  = &info->oti_id;
276         id->oii_ino = cpu_to_be32(id0->oii_ino);
277         id->oii_gen = cpu_to_be32(id0->oii_gen);
278         return idx->do_index_ops->dio_insert(info->oti_env, idx,
279                                              (const struct dt_rec *)id,
280                                              key, th, BYPASS_CAPA,
281                                              ignore_quota);
282 }
283
284 int osd_oi_delete(struct osd_thread_info *info,
285                   struct osd_oi *oi, const struct lu_fid *fid,
286                   struct thandle *th)
287 {
288         struct dt_object    *idx;
289         const struct dt_key *key;
290
291         if (fid_is_igif(fid))
292                 return 0;
293
294         key = oi_fid_key(info, oi, fid, &idx);
295         return idx->do_index_ops->dio_delete(info->oti_env, idx,
296                                              key, th, BYPASS_CAPA);
297 }
298
299 int osd_oi_mod_init()
300 {
301         mutex_init(&oi_init_lock);
302         return 0;
303 }