Whamcloud - gitweb
be93d251b74d6648534d8b240fd555b5ff8bb9a4
[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  *  lustre/osd/osd_oi.c
5  *  Object Index.
6  *
7  *  Copyright (c) 2006 Cluster File Systems, Inc.
8  *   Author: Nikita Danilov <nikita@clusterfs.com>
9  *
10  *   This file is part of the Lustre file system, http://www.lustre.org
11  *   Lustre is a trademark of Cluster File Systems, Inc.
12  *
13  *   You may have signed or agreed to another license before downloading
14  *   this software.  If so, you are bound by the terms and conditions
15  *   of that agreement, and the following does not apply to you.  See the
16  *   LICENSE file included with this distribution for more information.
17  *
18  *   If you did not agree to a different license, then this copy of Lustre
19  *   is open source software; you can redistribute it and/or modify it
20  *   under the terms of version 2 of the GNU General Public License as
21  *   published by the Free Software Foundation.
22  *
23  *   In either case, Lustre is distributed in the hope that it will be
24  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *   license text for more details.
27  */
28 /*
29  * oi uses two mechanisms to implement fid->cookie mapping:
30  *
31  *     - persistent index, where cookie is a record and fid is a key, and
32  *
33  *     - algorithmic mapping for "igif" fids.
34  *
35  */
36
37 #ifndef EXPORT_SYMTAB
38 # define EXPORT_SYMTAB
39 #endif
40 #define DEBUG_SUBSYSTEM S_MDS
41
42 #include <linux/module.h>
43
44 /* LUSTRE_VERSION_CODE */
45 #include <lustre_ver.h>
46 /*
47  * struct OBD_{ALLOC,FREE}*()
48  * OBD_FAIL_CHECK
49  */
50 #include <obd.h>
51 #include <obd_support.h>
52
53 /* fid_is_local() */
54 #include <lustre_fid.h>
55
56 #include "osd_oi.h"
57 /* osd_lookup(), struct osd_thread_info */
58 #include "osd_internal.h"
59 /* lu_fid_is_igif() */
60 #include "osd_igif.h"
61 #include "dt_object.h"
62
63 static const struct dt_key *oi_fid_key(struct osd_thread_info *info,
64                                        const struct lu_fid *fid);
65 static const char oi_dirname[] = "oi";
66
67 static const struct dt_index_features oi_index_features = {
68         .dif_flags       = DT_IND_UPDATE,
69         .dif_keysize_min = sizeof(struct lu_fid),
70         .dif_keysize_max = sizeof(struct lu_fid),
71         .dif_recsize_min = sizeof(struct osd_inode_id),
72         .dif_recsize_max = sizeof(struct osd_inode_id)
73 };
74
75 int osd_oi_init(struct osd_thread_info *info,
76                 struct osd_oi *oi, struct dt_device *dev)
77 {
78         int rc;
79         struct dt_object        *obj;
80         const struct lu_context *ctx;
81
82         ctx = info->oti_ctx;
83         /*
84          * Initialize ->oi_lock first, because of possible oi re-entrance in
85          * dt_store_open().
86          */
87         init_rwsem(&oi->oi_lock);
88
89         obj = dt_store_open(ctx, dev, oi_dirname, &info->oti_fid);
90         if (!IS_ERR(obj)) {
91                 rc = obj->do_ops->do_index_try(ctx, obj, &oi_index_features);
92                 if (rc == 0) {
93                         LASSERT(obj->do_index_ops != NULL);
94                         oi->oi_dir = obj;
95                 } else {
96                         CERROR("Wrong index \"%s\": %d\n", oi_dirname, rc);
97                         lu_object_put(ctx, &obj->do_lu);
98                 }
99         } else {
100                 rc = PTR_ERR(obj);
101                 CERROR("Cannot open \"%s\": %d\n", oi_dirname, rc);
102         }
103         return rc;
104 }
105
106 void osd_oi_fini(struct osd_thread_info *info, struct osd_oi *oi)
107 {
108         if (oi->oi_dir != NULL) {
109                 lu_object_put(info->oti_ctx, &oi->oi_dir->do_lu);
110                 oi->oi_dir = NULL;
111         }
112 }
113
114 void osd_oi_read_lock(struct osd_oi *oi)
115 {
116         down_read(&oi->oi_lock);
117 }
118
119 void osd_oi_read_unlock(struct osd_oi *oi)
120 {
121         up_read(&oi->oi_lock);
122 }
123
124 void osd_oi_write_lock(struct osd_oi *oi)
125 {
126         down_write(&oi->oi_lock);
127 }
128
129 void osd_oi_write_unlock(struct osd_oi *oi)
130 {
131         up_write(&oi->oi_lock);
132 }
133
134 static const struct dt_key *oi_fid_key(struct osd_thread_info *info,
135                                        const struct lu_fid *fid)
136 {
137         fid_cpu_to_be(&info->oti_fid, fid);
138         return (const struct dt_key *)&info->oti_fid;
139 }
140
141 enum {
142         OI_TXN_INSERT_CREDITS = 20,
143         OI_TXN_DELETE_CREDITS = 20
144 };
145
146 static inline void osd_inode_id_init(struct osd_inode_id *id,
147                                      __u64 ino, __u32 gen)
148 {
149         id->oii_ino = be64_to_cpu(ino);
150         id->oii_gen = be32_to_cpu(gen);
151 }
152
153 /*
154  * Locking: requires at least read lock on oi.
155  */
156 int osd_oi_lookup(struct osd_thread_info *info, struct osd_oi *oi,
157                   const struct lu_fid *fid, struct osd_inode_id *id)
158 {
159         int rc;
160
161         if (lu_fid_is_igif(fid)) {
162                 lu_igif_to_id(fid, id);
163                 rc = 0;
164         } else {
165                 rc = oi->oi_dir->do_index_ops->dio_lookup
166                         (info->oti_ctx, oi->oi_dir,
167                          (struct dt_rec *)id, oi_fid_key(info, fid));
168                 osd_inode_id_init(id, id->oii_ino, id->oii_gen);
169         }
170         return rc;
171 }
172
173 /*
174  * Locking: requires write lock on oi.
175  */
176 int osd_oi_insert(struct osd_thread_info *info, struct osd_oi *oi,
177                   const struct lu_fid *fid, const struct osd_inode_id *id0,
178                   struct thandle *th)
179 {
180         struct dt_object    *idx;
181         struct dt_device    *dev;
182         struct osd_inode_id *id;
183
184         if (lu_fid_is_igif(fid))
185                 return 0;
186
187         idx = oi->oi_dir;
188         dev = lu2dt_dev(idx->do_lu.lo_dev);
189         id = &info->oti_id;
190         osd_inode_id_init(id, id0->oii_ino, id0->oii_gen);
191         return idx->do_index_ops->dio_insert(info->oti_ctx, idx,
192                                              (const struct dt_rec *)id,
193                                              oi_fid_key(info, fid), th);
194 }
195
196 /*
197  * Locking: requires write lock on oi.
198  */
199 int osd_oi_delete(struct osd_thread_info *info,
200                   struct osd_oi *oi, const struct lu_fid *fid,
201                   struct thandle *th)
202 {
203         struct dt_object *idx;
204         struct dt_device *dev;
205
206         if (lu_fid_is_igif(fid))
207                 return 0;
208
209         idx = oi->oi_dir;
210         dev = lu2dt_dev(idx->do_lu.lo_dev);
211         return idx->do_index_ops->dio_delete(info->oti_ctx, idx,
212                                              oi_fid_key(info, fid), th);
213 }
214