Whamcloud - gitweb
LU-909 osd: changes to osd api
[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
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  * Copyright (c) 2011 Whamcloud, Inc.
32  */
33 /*
34  * This file is part of Lustre, http://www.lustre.org/
35  * Lustre is a trademark of Sun Microsystems, Inc.
36  *
37  * lustre/obdclass/dt_object.c
38  *
39  * Dt Object.
40  * Generic functions from dt_object.h
41  *
42  * Author: Nikita Danilov <nikita@clusterfs.com>
43  */
44
45 #define DEBUG_SUBSYSTEM S_CLASS
46 #ifndef EXPORT_SYMTAB
47 # define EXPORT_SYMTAB
48 #endif
49
50 #include <obd.h>
51 #include <dt_object.h>
52 #include <libcfs/list.h>
53 /* fid_be_to_cpu() */
54 #include <lustre_fid.h>
55
56 struct dt_find_hint {
57         struct lu_fid        *dfh_fid;
58         struct dt_device     *dfh_dt;
59         struct dt_object     *dfh_o;
60 };
61
62 struct dt_thread_info {
63         char                    dti_buf[DT_MAX_PATH];
64         struct dt_find_hint     dti_dfh;
65 };
66
67 /* context key constructor/destructor: dt_global_key_init, dt_global_key_fini */
68 LU_KEY_INIT(dt_global, struct dt_thread_info);
69 LU_KEY_FINI(dt_global, struct dt_thread_info);
70
71 static struct lu_context_key dt_key = {
72         .lct_tags = LCT_MD_THREAD|LCT_DT_THREAD,
73         .lct_init = dt_global_key_init,
74         .lct_fini = dt_global_key_fini
75 };
76
77 /* no lock is necessary to protect the list, because call-backs
78  * are added during system startup. Please refer to "struct dt_device".
79  */
80 void dt_txn_callback_add(struct dt_device *dev, struct dt_txn_callback *cb)
81 {
82         cfs_list_add(&cb->dtc_linkage, &dev->dd_txn_callbacks);
83 }
84 EXPORT_SYMBOL(dt_txn_callback_add);
85
86 void dt_txn_callback_del(struct dt_device *dev, struct dt_txn_callback *cb)
87 {
88         cfs_list_del_init(&cb->dtc_linkage);
89 }
90 EXPORT_SYMBOL(dt_txn_callback_del);
91
92 int dt_txn_hook_start(const struct lu_env *env,
93                       struct dt_device *dev, struct thandle *th)
94 {
95         int rc = 0;
96         struct dt_txn_callback *cb;
97
98         if (th->th_local)
99                 return 0;
100
101         cfs_list_for_each_entry(cb, &dev->dd_txn_callbacks, dtc_linkage) {
102                 if (cb->dtc_txn_start == NULL ||
103                     !(cb->dtc_tag & env->le_ctx.lc_tags))
104                         continue;
105                 rc = cb->dtc_txn_start(env, th, cb->dtc_cookie);
106                 if (rc < 0)
107                         break;
108         }
109         return rc;
110 }
111 EXPORT_SYMBOL(dt_txn_hook_start);
112
113 int dt_txn_hook_stop(const struct lu_env *env, struct thandle *txn)
114 {
115         struct dt_device       *dev = txn->th_dev;
116         struct dt_txn_callback *cb;
117         int                     rc = 0;
118
119         if (txn->th_local)
120                 return 0;
121
122         cfs_list_for_each_entry(cb, &dev->dd_txn_callbacks, dtc_linkage) {
123                 if (cb->dtc_txn_stop == NULL ||
124                     !(cb->dtc_tag & env->le_ctx.lc_tags))
125                         continue;
126                 rc = cb->dtc_txn_stop(env, txn, cb->dtc_cookie);
127                 if (rc < 0)
128                         break;
129         }
130         return rc;
131 }
132 EXPORT_SYMBOL(dt_txn_hook_stop);
133
134 void dt_txn_hook_commit(struct thandle *txn)
135 {
136         struct dt_txn_callback *cb;
137
138         if (txn->th_local)
139                 return;
140
141         cfs_list_for_each_entry(cb, &txn->th_dev->dd_txn_callbacks,
142                                 dtc_linkage) {
143                 if (cb->dtc_txn_commit)
144                         cb->dtc_txn_commit(txn, cb->dtc_cookie);
145         }
146 }
147 EXPORT_SYMBOL(dt_txn_hook_commit);
148
149 int dt_device_init(struct dt_device *dev, struct lu_device_type *t)
150 {
151
152         CFS_INIT_LIST_HEAD(&dev->dd_txn_callbacks);
153         return lu_device_init(&dev->dd_lu_dev, t);
154 }
155 EXPORT_SYMBOL(dt_device_init);
156
157 void dt_device_fini(struct dt_device *dev)
158 {
159         lu_device_fini(&dev->dd_lu_dev);
160 }
161 EXPORT_SYMBOL(dt_device_fini);
162
163 int dt_object_init(struct dt_object *obj,
164                    struct lu_object_header *h, struct lu_device *d)
165
166 {
167         return lu_object_init(&obj->do_lu, h, d);
168 }
169 EXPORT_SYMBOL(dt_object_init);
170
171 void dt_object_fini(struct dt_object *obj)
172 {
173         lu_object_fini(&obj->do_lu);
174 }
175 EXPORT_SYMBOL(dt_object_fini);
176
177 int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj)
178 {
179         if (obj->do_index_ops == NULL)
180                 obj->do_ops->do_index_try(env, obj, &dt_directory_features);
181         return obj->do_index_ops != NULL;
182 }
183 EXPORT_SYMBOL(dt_try_as_dir);
184
185 enum dt_format_type dt_mode_to_dft(__u32 mode)
186 {
187         enum dt_format_type result;
188
189         switch (mode & S_IFMT) {
190         case S_IFDIR:
191                 result = DFT_DIR;
192                 break;
193         case S_IFREG:
194                 result = DFT_REGULAR;
195                 break;
196         case S_IFLNK:
197                 result = DFT_SYM;
198                 break;
199         case S_IFCHR:
200         case S_IFBLK:
201         case S_IFIFO:
202         case S_IFSOCK:
203                 result = DFT_NODE;
204                 break;
205         default:
206                 LBUG();
207                 break;
208         }
209         return result;
210 }
211 EXPORT_SYMBOL(dt_mode_to_dft);
212
213 /**
214  * lookup fid for object named \a name in directory \a dir.
215  */
216
217 int dt_lookup_dir(const struct lu_env *env, struct dt_object *dir,
218                   const char *name, struct lu_fid *fid)
219 {
220         if (dt_try_as_dir(env, dir))
221                 return dt_lookup(env, dir, (struct dt_rec *)fid,
222                                  (const struct dt_key *)name, BYPASS_CAPA);
223         return -ENOTDIR;
224 }
225 EXPORT_SYMBOL(dt_lookup_dir);
226 /**
227  * get object for given \a fid.
228  */
229 struct dt_object *dt_locate(const struct lu_env *env,
230                             struct dt_device *dev,
231                             const struct lu_fid *fid)
232 {
233         struct lu_object *obj;
234         struct dt_object *dt;
235
236         obj = lu_object_find(env, &dev->dd_lu_dev, fid, NULL);
237         if (!IS_ERR(obj)) {
238                 obj = lu_object_locate(obj->lo_header, dev->dd_lu_dev.ld_type);
239                 LASSERT(obj != NULL);
240                 dt = container_of(obj, struct dt_object, do_lu);
241         } else
242                 dt = (struct dt_object *)obj;
243         return dt;
244 }
245 EXPORT_SYMBOL(dt_locate);
246
247 /**
248  * find a object named \a entry in given \a dfh->dfh_o directory.
249  */
250 static int dt_find_entry(const struct lu_env *env, const char *entry, void *data)
251 {
252         struct dt_find_hint  *dfh = data;
253         struct dt_device     *dt = dfh->dfh_dt;
254         struct lu_fid        *fid = dfh->dfh_fid;
255         struct dt_object     *obj = dfh->dfh_o;
256         int                   result;
257
258         result = dt_lookup_dir(env, obj, entry, fid);
259         lu_object_put(env, &obj->do_lu);
260         if (result == 0) {
261                 obj = dt_locate(env, dt, fid);
262                 if (IS_ERR(obj))
263                         result = PTR_ERR(obj);
264         }
265         dfh->dfh_o = obj;
266         return result;
267 }
268
269 /**
270  * Abstract function which parses path name. This function feeds
271  * path component to \a entry_func.
272  */
273 int dt_path_parser(const struct lu_env *env,
274                    char *path, dt_entry_func_t entry_func,
275                    void *data)
276 {
277         char *e;
278         int rc = 0;
279
280         while (1) {
281                 e = strsep(&path, "/");
282                 if (e == NULL)
283                         break;
284
285                 if (e[0] == 0) {
286                         if (!path || path[0] == '\0')
287                                 break;
288                         continue;
289                 }
290                 rc = entry_func(env, e, data);
291                 if (rc)
292                         break;
293         }
294
295         return rc;
296 }
297
298 static struct dt_object *dt_store_resolve(const struct lu_env *env,
299                                           struct dt_device *dt,
300                                           const char *path,
301                                           struct lu_fid *fid)
302 {
303         struct dt_thread_info *info = lu_context_key_get(&env->le_ctx,
304                                                          &dt_key);
305         struct dt_find_hint *dfh = &info->dti_dfh;
306         struct dt_object     *obj;
307         char *local = info->dti_buf;
308         int result;
309
310         dfh->dfh_dt = dt;
311         dfh->dfh_fid = fid;
312
313         strncpy(local, path, DT_MAX_PATH);
314         local[DT_MAX_PATH - 1] = '\0';
315
316         result = dt->dd_ops->dt_root_get(env, dt, fid);
317         if (result == 0) {
318                 obj = dt_locate(env, dt, fid);
319                 if (!IS_ERR(obj)) {
320                         dfh->dfh_o = obj;
321                         result = dt_path_parser(env, local, dt_find_entry, dfh);
322                         if (result != 0)
323                                 obj = ERR_PTR(result);
324                         else
325                                 obj = dfh->dfh_o;
326                 }
327         } else {
328                 obj = ERR_PTR(result);
329         }
330         return obj;
331 }
332
333 static struct dt_object *dt_reg_open(const struct lu_env *env,
334                                      struct dt_device *dt,
335                                      struct dt_object *p,
336                                      const char *name,
337                                      struct lu_fid *fid)
338 {
339         struct dt_object *o;
340         int result;
341
342         result = dt_lookup_dir(env, p, name, fid);
343         if (result == 0){
344                 o = dt_locate(env, dt, fid);
345         }
346         else
347                 o = ERR_PTR(result);
348
349         return o;
350 }
351
352 /**
353  * Open dt object named \a filename from \a dirname directory.
354  *      \param  dt      dt device
355  *      \param  fid     on success, object fid is stored in *fid
356  */
357 struct dt_object *dt_store_open(const struct lu_env *env,
358                                 struct dt_device *dt,
359                                 const char *dirname,
360                                 const char *filename,
361                                 struct lu_fid *fid)
362 {
363         struct dt_object *file;
364         struct dt_object *dir;
365
366         dir = dt_store_resolve(env, dt, dirname, fid);
367         if (!IS_ERR(dir)) {
368                 file = dt_reg_open(env, dt, dir,
369                                    filename, fid);
370                 lu_object_put(env, &dir->do_lu);
371         } else {
372                 file = dir;
373         }
374         return file;
375 }
376 EXPORT_SYMBOL(dt_store_open);
377
378 /* dt class init function. */
379 int dt_global_init(void)
380 {
381         int result;
382
383         LU_CONTEXT_KEY_INIT(&dt_key);
384         result = lu_context_key_register(&dt_key);
385         return result;
386 }
387
388 void dt_global_fini(void)
389 {
390         lu_context_key_degister(&dt_key);
391 }
392
393 int dt_record_read(const struct lu_env *env, struct dt_object *dt,
394                    struct lu_buf *buf, loff_t *pos)
395 {
396         int rc;
397
398         LASSERTF(dt != NULL, "dt is NULL when we want to read record\n");
399
400         rc = dt->do_body_ops->dbo_read(env, dt, buf, pos, BYPASS_CAPA);
401
402         if (rc == buf->lb_len)
403                 rc = 0;
404         else if (rc >= 0)
405                 rc = -EFAULT;
406         return rc;
407 }
408 EXPORT_SYMBOL(dt_record_read);
409
410 int dt_record_write(const struct lu_env *env, struct dt_object *dt,
411                     const struct lu_buf *buf, loff_t *pos, struct thandle *th)
412 {
413         int rc;
414
415         LASSERTF(dt != NULL, "dt is NULL when we want to write record\n");
416         LASSERT(th != NULL);
417         LASSERT(dt->do_body_ops);
418         LASSERT(dt->do_body_ops->dbo_write);
419         rc = dt->do_body_ops->dbo_write(env, dt, buf, pos, th, BYPASS_CAPA, 1);
420         if (rc == buf->lb_len)
421                 rc = 0;
422         else if (rc >= 0)
423                 rc = -EFAULT;
424         return rc;
425 }
426 EXPORT_SYMBOL(dt_record_write);
427
428 int dt_declare_version_set(const struct lu_env *env, struct dt_object *o,
429                            struct thandle *th)
430 {
431         struct lu_buf vbuf;
432         char *xname = XATTR_NAME_VERSION;
433
434         LASSERT(o);
435         vbuf.lb_buf = NULL;
436         vbuf.lb_len = sizeof(dt_obj_version_t);
437         return dt_declare_xattr_set(env, o, &vbuf, xname, 0, th);
438
439 }
440 EXPORT_SYMBOL(dt_declare_version_set);
441
442 void dt_version_set(const struct lu_env *env, struct dt_object *o,
443                     dt_obj_version_t version, struct thandle *th)
444 {
445         struct lu_buf vbuf;
446         char *xname = XATTR_NAME_VERSION;
447         int rc;
448
449         LASSERT(o);
450         vbuf.lb_buf = &version;
451         vbuf.lb_len = sizeof(version);
452
453         rc = dt_xattr_set(env, o, &vbuf, xname, 0, th, BYPASS_CAPA);
454         if (rc != 0)
455                 CDEBUG(D_INODE, "Can't set version, rc %d\n", rc);
456         return;
457 }
458 EXPORT_SYMBOL(dt_version_set);
459
460 dt_obj_version_t dt_version_get(const struct lu_env *env, struct dt_object *o)
461 {
462         struct lu_buf vbuf;
463         char *xname = XATTR_NAME_VERSION;
464         dt_obj_version_t version;
465         int rc;
466
467         LASSERT(o);
468         vbuf.lb_buf = &version;
469         vbuf.lb_len = sizeof(version);
470         rc = dt_xattr_get(env, o, &vbuf, xname, BYPASS_CAPA);
471         if (rc != sizeof(version)) {
472                 CDEBUG(D_INODE, "Can't get version, rc %d\n", rc);
473                 version = 0;
474         }
475         return version;
476 }
477 EXPORT_SYMBOL(dt_version_get);
478
479 const struct dt_index_features dt_directory_features;
480 EXPORT_SYMBOL(dt_directory_features);