Whamcloud - gitweb
b=16098
[fs/lustre-release.git] / lustre / obdclass / dt_object.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 [sun.com URL with a
20  * copy of GPLv2].
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/obdclass/dt_object.c
37  *
38  * Dt Object.
39  * Generic functions from dt_object.h
40  *
41  * Author: Nikita Danilov <nikita@clusterfs.com>
42  */
43
44 #define DEBUG_SUBSYSTEM S_CLASS
45 #ifndef EXPORT_SYMTAB
46 # define EXPORT_SYMTAB
47 #endif
48
49 #include <obd.h>
50 #include <dt_object.h>
51 #include <libcfs/list.h>
52 /* fid_be_to_cpu() */
53 #include <lustre_fid.h>
54
55 /* no lock is necessary to protect the list, because call-backs
56  * are added during system startup. Please refer to "struct dt_device".
57  */
58 void dt_txn_callback_add(struct dt_device *dev, struct dt_txn_callback *cb)
59 {
60         list_add(&cb->dtc_linkage, &dev->dd_txn_callbacks);
61 }
62 EXPORT_SYMBOL(dt_txn_callback_add);
63
64 void dt_txn_callback_del(struct dt_device *dev, struct dt_txn_callback *cb)
65 {
66         list_del_init(&cb->dtc_linkage);
67 }
68 EXPORT_SYMBOL(dt_txn_callback_del);
69
70 int dt_txn_hook_start(const struct lu_env *env,
71                       struct dt_device *dev, struct txn_param *param)
72 {
73         int result;
74         struct dt_txn_callback *cb;
75
76         result = 0;
77         list_for_each_entry(cb, &dev->dd_txn_callbacks, dtc_linkage) {
78                 if (cb->dtc_txn_start == NULL)
79                         continue;
80                 result = cb->dtc_txn_start(env, param, cb->dtc_cookie);
81                 if (result < 0)
82                         break;
83         }
84         return result;
85 }
86 EXPORT_SYMBOL(dt_txn_hook_start);
87
88 int dt_txn_hook_stop(const struct lu_env *env, struct thandle *txn)
89 {
90         struct dt_device       *dev = txn->th_dev;
91         struct dt_txn_callback *cb;
92         int                     result;
93
94         result = 0;
95         list_for_each_entry(cb, &dev->dd_txn_callbacks, dtc_linkage) {
96                 if (cb->dtc_txn_stop == NULL)
97                         continue;
98                 result = cb->dtc_txn_stop(env, txn, cb->dtc_cookie);
99                 if (result < 0)
100                         break;
101         }
102         return result;
103 }
104 EXPORT_SYMBOL(dt_txn_hook_stop);
105
106 int dt_txn_hook_commit(const struct lu_env *env, struct thandle *txn)
107 {
108         struct dt_device       *dev = txn->th_dev;
109         struct dt_txn_callback *cb;
110         int                     result;
111
112         result = 0;
113         list_for_each_entry(cb, &dev->dd_txn_callbacks, dtc_linkage) {
114                 if (cb->dtc_txn_commit == NULL)
115                         continue;
116                 result = cb->dtc_txn_commit(env, txn, cb->dtc_cookie);
117                 if (result < 0)
118                         break;
119         }
120         return result;
121 }
122 EXPORT_SYMBOL(dt_txn_hook_commit);
123
124 int dt_device_init(struct dt_device *dev, struct lu_device_type *t)
125 {
126
127         CFS_INIT_LIST_HEAD(&dev->dd_txn_callbacks);
128         return lu_device_init(&dev->dd_lu_dev, t);
129 }
130 EXPORT_SYMBOL(dt_device_init);
131
132 void dt_device_fini(struct dt_device *dev)
133 {
134         lu_device_fini(&dev->dd_lu_dev);
135 }
136 EXPORT_SYMBOL(dt_device_fini);
137
138 int dt_object_init(struct dt_object *obj,
139                    struct lu_object_header *h, struct lu_device *d)
140
141 {
142         return lu_object_init(&obj->do_lu, h, d);
143 }
144 EXPORT_SYMBOL(dt_object_init);
145
146 void dt_object_fini(struct dt_object *obj)
147 {
148         lu_object_fini(&obj->do_lu);
149 }
150 EXPORT_SYMBOL(dt_object_fini);
151
152 int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj)
153 {
154         if (obj->do_index_ops == NULL)
155                 obj->do_ops->do_index_try(env, obj, &dt_directory_features);
156         return obj->do_index_ops != NULL;
157 }
158 EXPORT_SYMBOL(dt_try_as_dir);
159
160 extern struct lu_context_key lu_global_key;
161
162 static int dt_lookup(const struct lu_env *env, struct dt_object *dir,
163                      const char *name, struct lu_fid *fid)
164 {
165         struct lu_fid_pack  *pack = lu_context_key_get(&env->le_ctx,
166                                                        &lu_global_key);
167         struct dt_rec       *rec = (struct dt_rec *)pack;
168         const struct dt_key *key = (const struct dt_key *)name;
169         int result;
170
171         if (dt_try_as_dir(env, dir)) {
172                 result = dir->do_index_ops->dio_lookup(env, dir, rec, key,
173                                                        BYPASS_CAPA);
174                 if (result == 0)
175                         result = fid_unpack(pack, fid);
176         } else
177                 result = -ENOTDIR;
178         return result;
179 }
180
181 static struct dt_object *dt_locate(const struct lu_env *env,
182                                    struct dt_device *dev,
183                                    const struct lu_fid *fid)
184 {
185         struct lu_object *obj;
186         struct dt_object *dt;
187
188         obj = lu_object_find(env, dev->dd_lu_dev.ld_site, fid);
189         if (!IS_ERR(obj)) {
190                 obj = lu_object_locate(obj->lo_header, dev->dd_lu_dev.ld_type);
191                 LASSERT(obj != NULL);
192                 dt = container_of(obj, struct dt_object, do_lu);
193         } else
194                 dt = (void *)obj;
195         return dt;
196 }
197
198 struct dt_object *dt_store_open(const struct lu_env *env,
199                                 struct dt_device *dt, const char *name,
200                                 struct lu_fid *fid)
201 {
202         int result;
203
204         struct dt_object *root;
205         struct dt_object *child;
206
207         result = dt->dd_ops->dt_root_get(env, dt, fid);
208         if (result == 0) {
209                 root = dt_locate(env, dt, fid);
210                 if (!IS_ERR(root)) {
211                         result = dt_lookup(env, root, name, fid);
212                         if (result == 0)
213                                 child = dt_locate(env, dt, fid);
214                         else
215                                 child = ERR_PTR(result);
216                         lu_object_put(env, &root->do_lu);
217                 } else {
218                         CERROR("No root\n");
219                         child = (void *)root;
220                 }
221         } else
222                 child = ERR_PTR(result);
223         return child;
224 }
225 EXPORT_SYMBOL(dt_store_open);
226
227 const struct dt_index_features dt_directory_features;
228 EXPORT_SYMBOL(dt_directory_features);