Whamcloud - gitweb
b=24037 Changes of 2.6.32 kernel.
[fs/lustre-release.git] / lustre / osd-ldiskfs / 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 (c) 2007, 2010, Oracle and/or its affiliates. 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 cfs_mutex_t 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_16] = {
95                 .fid_size = sizeof(struct lu_fid),
96                 .name     = "oi.16",
97                 .oid      = OSD_OI_FID_16_OID
98         }
99 };
100
101 static int osd_oi_index_create(struct osd_thread_info *info,
102                                struct dt_device *dev,
103                                struct md_device *mdev)
104 {
105         const struct lu_env *env;
106         struct lu_fid *oi_fid = &info->oti_fid;
107         struct md_object *mdo;
108         int i;
109         int rc;
110
111         env = info->oti_env;
112
113         for (i = rc = 0; i < OSD_OI_FID_NR && rc == 0; ++i) {
114                 char *name;
115                 name = oi_descr[i].name;
116                 lu_local_obj_fid(oi_fid, oi_descr[i].oid);
117                 oi_feat.dif_keysize_min = oi_descr[i].fid_size,
118                 oi_feat.dif_keysize_max = oi_descr[i].fid_size,
119
120                 mdo = llo_store_create_index(env, mdev, dev,
121                                              "", name,
122                                              oi_fid, &oi_feat);
123
124                 if (IS_ERR(mdo))
125                         RETURN(PTR_ERR(mdo));
126
127                 lu_object_put(env, &mdo->mo_lu);
128         }
129         return 0;
130 }
131
132 int osd_oi_init(struct osd_thread_info *info,
133                 struct osd_oi *oi,
134                 struct dt_device *dev,
135                 struct md_device *mdev)
136 {
137         const struct lu_env *env;
138         int rc;
139         int i;
140
141         env = info->oti_env;
142         cfs_mutex_lock(&oi_init_lock);
143         memset(oi, 0, sizeof *oi);
144 retry:
145         for (i = rc = 0; i < OSD_OI_FID_NR && rc == 0; ++i) {
146                 const char       *name;
147                 struct dt_object *obj;
148
149                 name = oi_descr[i].name;
150                 oi_feat.dif_keysize_min = oi_descr[i].fid_size,
151                 oi_feat.dif_keysize_max = oi_descr[i].fid_size,
152
153                 obj = dt_store_open(env, dev, "", name, &info->oti_fid);
154                 if (!IS_ERR(obj)) {
155                         rc = obj->do_ops->do_index_try(env, obj, &oi_feat);
156                         if (rc == 0) {
157                                 LASSERT(obj->do_index_ops != NULL);
158                                 oi->oi_dir = obj;
159                         } else {
160                                 CERROR("Wrong index \"%s\": %d\n", name, rc);
161                                 lu_object_put(env, &obj->do_lu);
162                         }
163                 } else {
164                         rc = PTR_ERR(obj);
165                         if (rc == -ENOENT) {
166                                 rc = osd_oi_index_create(info, dev, mdev);
167                                 if (!rc)
168                                         goto retry;
169                         }
170                         CERROR("Cannot open \"%s\": %d\n", name, rc);
171                 }
172         }
173         if (rc != 0)
174                 osd_oi_fini(info, oi);
175
176         cfs_mutex_unlock(&oi_init_lock);
177         return rc;
178 }
179
180 void osd_oi_fini(struct osd_thread_info *info, struct osd_oi *oi)
181 {
182         if (oi->oi_dir != NULL) {
183                 lu_object_put(info->oti_env, &oi->oi_dir->do_lu);
184                 oi->oi_dir = NULL;
185         }
186 }
187
188 static inline int fid_is_oi_fid(const struct lu_fid *fid)
189 {
190         /* We need to filter-out oi obj's fid. As we can not store it, while
191          * oi-index create operation.
192          */
193         return (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE &&
194                 fid_oid(fid) == OSD_OI_FID_16_OID));
195 }
196
197 int osd_oi_lookup(struct osd_thread_info *info, struct osd_oi *oi,
198                   const struct lu_fid *fid, struct osd_inode_id *id)
199 {
200         struct lu_fid *oi_fid = &info->oti_fid;
201         int rc;
202
203         if (osd_fid_is_igif(fid)) {
204                 lu_igif_to_id(fid, id);
205                 rc = 0;
206         } else {
207                 struct dt_object    *idx;
208                 const struct dt_key *key;
209
210                 if (fid_is_oi_fid(fid))
211                         return -ENOENT;
212
213                 idx = oi->oi_dir;
214                 fid_cpu_to_be(oi_fid, fid);
215                 key = (struct dt_key *) oi_fid;
216                 rc = idx->do_index_ops->dio_lookup(info->oti_env, idx,
217                                                    (struct dt_rec *)id, key,
218                                                    BYPASS_CAPA);
219                 if (rc > 0) {
220                         id->oii_ino = be32_to_cpu(id->oii_ino);
221                         id->oii_gen = be32_to_cpu(id->oii_gen);
222                         rc = 0;
223                 } else if (rc == 0)
224                         rc = -ENOENT;
225         }
226         return rc;
227 }
228
229 int osd_oi_insert(struct osd_thread_info *info, struct osd_oi *oi,
230                   const struct lu_fid *fid, const struct osd_inode_id *id0,
231                   struct thandle *th, int ignore_quota)
232 {
233         struct lu_fid *oi_fid = &info->oti_fid;
234         struct dt_object    *idx;
235         struct osd_inode_id *id;
236         const struct dt_key *key;
237
238         if (osd_fid_is_igif(fid))
239                 return 0;
240
241         if (fid_is_oi_fid(fid))
242                 return 0;
243
244         idx = oi->oi_dir;
245         fid_cpu_to_be(oi_fid, fid);
246         key = (struct dt_key *) oi_fid;
247
248         id  = &info->oti_id;
249         id->oii_ino = cpu_to_be32(id0->oii_ino);
250         id->oii_gen = cpu_to_be32(id0->oii_gen);
251         return idx->do_index_ops->dio_insert(info->oti_env, idx,
252                                              (struct dt_rec *)id,
253                                              key, th, BYPASS_CAPA,
254                                              ignore_quota);
255 }
256
257 int osd_oi_delete(struct osd_thread_info *info,
258                   struct osd_oi *oi, const struct lu_fid *fid,
259                   struct thandle *th)
260 {
261         struct lu_fid *oi_fid = &info->oti_fid;
262         struct dt_object    *idx;
263         const struct dt_key *key;
264
265         if (osd_fid_is_igif(fid))
266                 return 0;
267
268         idx = oi->oi_dir;
269         fid_cpu_to_be(oi_fid, fid);
270         key = (struct dt_key *) oi_fid;
271         return idx->do_index_ops->dio_delete(info->oti_env, idx,
272                                              key, th, BYPASS_CAPA);
273 }
274
275 int osd_oi_mod_init()
276 {
277         cfs_mutex_init(&oi_init_lock);
278         return 0;
279 }