Whamcloud - gitweb
- protect export's held locks list by spin lock while adding there fixed up lock...
[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_cpu_to_be() */
54 #include <lustre_fid.h>
55
56 #include "osd_oi.h"
57 /* osd_lookup(), struct osd_thread_info */
58 #include "osd_internal.h"
59 #include "osd_igif.h"
60 #include "dt_object.h"
61
62 static const struct dt_key *oi_fid_key(struct osd_thread_info *info,
63                                        const struct lu_fid *fid);
64 static const char oi_dirname[] = "oi";
65
66 static const struct dt_index_features oi_index_features = {
67         .dif_flags       = DT_IND_UPDATE,
68         .dif_keysize_min = sizeof(struct lu_fid),
69         .dif_keysize_max = sizeof(struct lu_fid),
70         .dif_recsize_min = sizeof(struct osd_inode_id),
71         .dif_recsize_max = sizeof(struct osd_inode_id)
72 };
73
74 int osd_oi_init(struct osd_thread_info *info,
75                 struct osd_oi *oi, struct dt_device *dev)
76 {
77         int rc;
78         struct dt_object    *obj;
79         const struct lu_env *env;
80
81         env = info->oti_env;
82         /*
83          * Initialize ->oi_lock first, because of possible oi re-entrance in
84          * dt_store_open().
85          */
86         init_rwsem(&oi->oi_lock);
87
88         obj = dt_store_open(env, dev, oi_dirname, &info->oti_fid);
89         if (!IS_ERR(obj)) {
90                 rc = obj->do_ops->do_index_try(env, obj, &oi_index_features);
91                 if (rc == 0) {
92                         LASSERT(obj->do_index_ops != NULL);
93                         oi->oi_dir = obj;
94                 } else {
95                         CERROR("Wrong index \"%s\": %d\n", oi_dirname, rc);
96                         lu_object_put(env, &obj->do_lu);
97                 }
98         } else {
99                 rc = PTR_ERR(obj);
100                 CERROR("Cannot open \"%s\": %d\n", oi_dirname, rc);
101         }
102         return rc;
103 }
104
105 void osd_oi_fini(struct osd_thread_info *info, struct osd_oi *oi)
106 {
107         if (oi->oi_dir != NULL) {
108                 lu_object_put(info->oti_env, &oi->oi_dir->do_lu);
109                 oi->oi_dir = NULL;
110         }
111 }
112
113 void osd_oi_read_lock(struct osd_oi *oi)
114 {
115         down_read(&oi->oi_lock);
116 }
117
118 void osd_oi_read_unlock(struct osd_oi *oi)
119 {
120         up_read(&oi->oi_lock);
121 }
122
123 void osd_oi_write_lock(struct osd_oi *oi)
124 {
125         down_write(&oi->oi_lock);
126 }
127
128 void osd_oi_write_unlock(struct osd_oi *oi)
129 {
130         up_write(&oi->oi_lock);
131 }
132
133 static const struct dt_key *oi_fid_key(struct osd_thread_info *info,
134                                        const struct lu_fid *fid)
135 {
136         fid_cpu_to_be(&info->oti_fid, fid);
137         return (const struct dt_key *)&info->oti_fid;
138 }
139
140 enum {
141         OI_TXN_INSERT_CREDITS = 20,
142         OI_TXN_DELETE_CREDITS = 20
143 };
144
145 static inline void oid_lookup_init(struct osd_inode_id *id,
146                                    __u64 ino, __u32 gen)
147 {
148         id->oii_ino = be64_to_cpu(ino);
149         id->oii_gen = be32_to_cpu(gen);
150 }
151
152 static inline void oid_insert_init(struct osd_inode_id *id,
153                                    __u64 ino, __u32 gen)
154 {
155         id->oii_ino = cpu_to_be64(ino);
156         id->oii_gen = cpu_to_be32(gen);
157 }
158 /*
159  * Locking: requires at least read lock on oi.
160  */
161 int osd_oi_lookup(struct osd_thread_info *info, struct osd_oi *oi,
162                   const struct lu_fid *fid, struct osd_inode_id *id)
163 {
164         int rc;
165
166         if (fid_is_igif(fid)) {
167                 lu_igif_to_id(fid, id);
168                 rc = 0;
169         } else {
170                 rc = oi->oi_dir->do_index_ops->dio_lookup
171                         (info->oti_env, oi->oi_dir,
172                          (struct dt_rec *)id, oi_fid_key(info, fid),
173                          BYPASS_CAPA);
174                 oid_lookup_init(id, id->oii_ino, id->oii_gen);
175         }
176         return rc;
177 }
178
179 /*
180  * Locking: requires write lock on oi.
181  */
182 int osd_oi_insert(struct osd_thread_info *info, struct osd_oi *oi,
183                   const struct lu_fid *fid, const struct osd_inode_id *id0,
184                   struct thandle *th)
185 {
186         struct dt_object    *idx;
187         struct dt_device    *dev;
188         struct osd_inode_id *id;
189
190         if (fid_is_igif(fid))
191                 return 0;
192
193         idx = oi->oi_dir;
194         dev = lu2dt_dev(idx->do_lu.lo_dev);
195         id = &info->oti_id;
196         oid_insert_init(id, id0->oii_ino, id0->oii_gen);
197         return idx->do_index_ops->dio_insert(info->oti_env, idx,
198                                              (const struct dt_rec *)id,
199                                              oi_fid_key(info, fid), th,
200                                              BYPASS_CAPA);
201 }
202
203 /*
204  * Locking: requires write lock on oi.
205  */
206 int osd_oi_delete(struct osd_thread_info *info,
207                   struct osd_oi *oi, const struct lu_fid *fid,
208                   struct thandle *th)
209 {
210         struct dt_object *idx;
211         struct dt_device *dev;
212
213         if (fid_is_igif(fid))
214                 return 0;
215
216         idx = oi->oi_dir;
217         dev = lu2dt_dev(idx->do_lu.lo_dev);
218         return idx->do_index_ops->dio_delete(info->oti_env, idx,
219                                              oi_fid_key(info, fid), th,
220                                              BYPASS_CAPA);
221 }
222