Whamcloud - gitweb
add lu_context to various operations
[fs/lustre-release.git] / lustre / osd / osd_handler.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/osd/osd_handler.c
5  *  Top-level entry points into osd module
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 #ifndef EXPORT_SYMTAB
30 # define EXPORT_SYMTAB
31 #endif
32 #define DEBUG_SUBSYSTEM S_MDS
33
34 #include <linux/module.h>
35
36 /* LUSTRE_VERSION_CODE */
37 #include <linux/lustre_ver.h>
38 /*
39  * XXX temporary stuff: direct access to ldiskfs/jdb. Interface between osd
40  * and file system is not yet specified.
41  */
42 /* handle_t, journal_start(), journal_stop() */
43 #include <linux/jbd.h>
44 /* LDISKFS_SB() */
45 #include <linux/ldiskfs_fs.h>
46 /* simple_mkdir() */
47 #include <linux/lvfs.h>
48
49 /*
50  * struct OBD_{ALLOC,FREE}*()
51  * OBD_FAIL_CHECK
52  */
53 #include <linux/obd_support.h>
54 /* struct ptlrpc_thread */
55 #include <linux/lustre_net.h>
56 /* LUSTRE_OSD0_NAME */
57 #include <linux/obd.h>
58 /* class_register_type(), class_unregister_type(), class_get_type() */
59 #include <linux/obd_class.h>
60 #include <linux/lustre_disk.h>
61
62 /* fid_is_local() */
63 #include <linux/lustre_fid.h>
64 #include <linux/lustre_iam.h>
65
66 #include "osd_internal.h"
67
68 static int   osd_root_get      (struct lu_context *ctxt,
69                                 struct dt_device *dev, struct lu_fid *f);
70 static int   osd_statfs        (struct lu_context *ctxt,
71                                 struct dt_device *dev, struct kstatfs *sfs);
72
73 static int   lu_device_is_osd  (const struct lu_device *d);
74 static void  osd_mod_exit      (void) __exit;
75 static int   osd_mod_init      (void) __init;
76 static int   osd_type_init     (struct lu_device_type *t);
77 static void  osd_type_fini     (struct lu_device_type *t);
78 static int   osd_object_init   (struct lu_context *ctxt, struct lu_object *l);
79 static void  osd_object_release(struct lu_context *ctxt, struct lu_object *l);
80 static int   osd_object_exists (struct lu_context *ctx, struct lu_object *o);
81 static int   osd_object_print  (struct lu_context *ctx,
82                                 struct seq_file *f, const struct lu_object *o);
83 static void  osd_device_free   (struct lu_device *m);
84 static void *osd_key_init      (struct lu_context *ctx);
85 static void  osd_key_fini      (struct lu_context *ctx, void *data);
86 static int   osd_has_index     (struct osd_object *obj);
87 static void  osd_object_init0  (struct osd_object *obj);
88 static int   osd_device_init   (struct lu_context *ctx,
89                                 struct lu_device *d, struct lu_device *);
90 static int   osd_fid_lookup    (struct lu_context *ctx, struct osd_object *obj,
91                                 const struct lu_fid *fid);
92 static int   osd_inode_getattr (struct lu_context *ctx,
93                                 struct inode *inode, struct lu_attr *attr);
94 static int   osd_inode_get_fid (struct osd_device *d, const struct inode *inode,
95                                 struct lu_fid *fid);
96 static int   osd_param_is_sane (const struct osd_device *dev,
97                                 const struct txn_param *param);
98 static int   osd_index_lookup  (struct lu_context *ctxt, struct dt_object *dt,
99                                 struct dt_rec *rec, const struct dt_key *key);
100 static int   osd_index_insert  (struct lu_context *ctxt, struct dt_object *dt,
101                                 const struct dt_rec *rec,
102                                 const struct dt_key *key,
103                                 struct thandle *handle);
104 static int   osd_index_probe   (struct lu_context *ctxt, struct dt_object *dt,
105                                 const struct dt_index_features *feat);
106
107 static struct osd_object  *osd_obj          (const struct lu_object *o);
108 static struct osd_device  *osd_dev          (const struct lu_device *d);
109 static struct osd_device  *osd_dt_dev       (const struct dt_device *d);
110 static struct osd_object  *osd_dt_obj       (const struct dt_object *d);
111 static struct osd_device  *osd_obj2dev      (struct osd_object *o);
112 static struct lu_device   *osd2lu_dev       (struct osd_device * osd);
113 static struct lu_device   *osd_device_fini  (struct lu_context *ctx,
114                                              struct lu_device *d);
115 static struct lu_device   *osd_device_alloc (struct lu_device_type *t,
116                                              struct lustre_cfg *cfg);
117 static struct lu_object   *osd_object_alloc (struct lu_context *ctx,
118                                              struct lu_device *d);
119 static struct inode       *osd_iget         (struct osd_thread_info *info,
120                                              struct osd_device *dev,
121                                              const struct osd_inode_id *id);
122 static struct super_block *osd_sb           (const struct osd_device *dev);
123 static journal_t          *osd_journal      (const struct osd_device *dev);
124
125 static struct lu_device_type_operations osd_device_type_ops;
126 static struct lu_device_type            osd_device_type;
127 static struct lu_object_operations      osd_lu_obj_ops;
128 static struct obd_ops                   osd_obd_device_ops;
129 static struct lprocfs_vars              lprocfs_osd_module_vars[];
130 static struct lprocfs_vars              lprocfs_osd_obd_vars[];
131 static struct lu_device_operations      osd_lu_ops;
132 static struct lu_context_key            osd_key;
133 static struct dt_object_operations      osd_obj_ops;
134 static struct dt_body_operations        osd_body_ops;
135 static struct dt_index_operations       osd_index_ops;
136
137 struct osd_thandle {
138         struct thandle  ot_super;
139         handle_t       *ot_handle;
140 };
141
142 /*
143  * DT methods.
144  */
145 static int osd_root_get(struct lu_context *ctx,
146                         struct dt_device *dev, struct lu_fid *f)
147 {
148         struct osd_device *d = osd_dt_dev(dev);
149
150         return osd_inode_get_fid(d, d->od_root_dir->d_inode, f);
151 }
152
153
154 /*
155  * OSD object methods.
156  */
157
158 static struct lu_object *osd_object_alloc(struct lu_context *ctx,
159                                           struct lu_device *d)
160 {
161         struct osd_object *mo;
162
163         OBD_ALLOC_PTR(mo);
164         if (mo != NULL) {
165                 struct lu_object *l;
166
167                 l = &mo->oo_dt.do_lu;
168                 lu_object_init(l, NULL, d);
169                 mo->oo_dt.do_ops = &osd_obj_ops;
170                 l->lo_ops = &osd_lu_obj_ops;
171                 init_rwsem(&mo->oo_sem);
172                 return l;
173         } else
174                 return NULL;
175 }
176
177 static void osd_object_init0(struct osd_object *obj)
178 {
179         LASSERT(obj->oo_inode != NULL);
180
181         if (osd_has_index(obj))
182                 obj->oo_dt.do_index_ops = &osd_index_ops;
183         else
184                 obj->oo_dt.do_body_ops = &osd_body_ops;
185 }
186
187 static int osd_object_init(struct lu_context *ctxt, struct lu_object *l)
188 {
189         struct osd_object *obj = osd_obj(l);
190         int result;
191
192         result = osd_fid_lookup(ctxt, obj, lu_object_fid(l));
193         if (result == 0) {
194                 if (obj->oo_inode != NULL)
195                         osd_object_init0(obj);
196         }
197         return result;
198 }
199
200 static void osd_object_free(struct lu_context *ctx, struct lu_object *l)
201 {
202         struct osd_object *obj = osd_obj(l);
203         OBD_FREE_PTR(obj);
204 }
205
206 static void osd_object_delete(struct lu_context *ctx, struct lu_object *l)
207 {
208         struct osd_object *o = osd_obj(l);
209
210         if (o->oo_inode != NULL)
211                 iput(o->oo_inode);
212 }
213
214 static int osd_inode_unlinked(const struct inode *inode)
215 {
216         return inode->i_nlink == !!S_ISDIR(inode->i_mode);
217 }
218
219 static void osd_object_release(struct lu_context *ctxt, struct lu_object *l)
220 {
221         struct osd_object *o = osd_obj(l);
222
223         if (o->oo_inode != NULL && osd_inode_unlinked(o->oo_inode))
224                 set_bit(LU_OBJECT_HEARD_BANSHEE, &l->lo_header->loh_flags);
225 }
226
227 static int osd_object_exists(struct lu_context *ctx, struct lu_object *o)
228 {
229         return osd_obj(o)->oo_inode != NULL;
230 }
231
232 static int osd_object_print(struct lu_context *ctx,
233                             struct seq_file *f, const struct lu_object *l)
234 {
235         struct osd_object  *o = osd_obj(l);
236
237         return seq_printf(f, LUSTRE_OSD0_NAME"-object@%p(i:%p:%lu/%u)",
238                           o, o->oo_inode,
239                           o->oo_inode ? o->oo_inode->i_ino : 0UL,
240                           o->oo_inode ? o->oo_inode->i_generation : 0);
241 }
242
243 static int osd_config(struct lu_context *ctx,
244                       struct dt_device *d, const char *name,
245                       void *buf, int size, int mode)
246 {
247         if (mode == LUSTRE_CONFIG_GET) {
248                 /* to be continued */
249                 return 0;
250         } else {
251                 /* to be continued */
252                 return 0;
253         }
254 }
255
256 static int osd_statfs(struct lu_context *ctx,
257                       struct dt_device *d, struct kstatfs *sfs)
258 {
259         struct osd_device *osd = osd_dt_dev(d);
260         struct super_block *sb = osd_sb(osd);
261         int result;
262
263         ENTRY;
264
265         memset(sfs, 0, sizeof *sfs);
266         result = sb->s_op->statfs(sb, sfs);
267
268         RETURN (result);
269 }
270
271 /*
272  * Journal
273  */
274
275 static int osd_param_is_sane(const struct osd_device *dev,
276                              const struct txn_param *param)
277 {
278         return param->tp_credits <= osd_journal(dev)->j_max_transaction_buffers;
279 }
280
281 static struct thandle *osd_trans_start(struct lu_context *ctx,
282                                        struct dt_device *d,
283                                        struct txn_param *p)
284 {
285         struct osd_device  *dev = osd_dt_dev(d);
286         handle_t           *jh;
287         struct osd_thandle *oh;
288         struct thandle     *th;
289         int hook_res;
290
291         ENTRY;
292
293         hook_res = dt_txn_hook_start(ctx, d, p);
294         if (hook_res != 0)
295                 RETURN(ERR_PTR(hook_res));
296
297         if (osd_param_is_sane(dev, p)) {
298                 OBD_ALLOC_PTR(oh);
299                 if (oh != NULL) {
300                         /*
301                          * XXX temporary stuff. Some abstraction layer should
302                          * be used.
303                          */
304                         jh = journal_start(osd_journal(dev), p->tp_credits);
305                         if (!IS_ERR(jh)) {
306                                 oh->ot_handle = jh;
307                                 th = &oh->ot_super;
308                                 th->th_dev = d;
309                                 lu_device_get(&d->dd_lu_dev);
310                         } else {
311                                 OBD_FREE_PTR(oh);
312                                 th = (void *)jh;
313                         }
314                 } else
315                         th = ERR_PTR(-ENOMEM);
316         } else {
317                 CERROR("Invalid transaction parameters\n");
318                 th = ERR_PTR(-EINVAL);
319         }
320
321         RETURN(th);
322 }
323
324 static void osd_trans_stop(struct lu_context *ctx, struct thandle *th)
325 {
326         int result;
327         struct osd_thandle *oh;
328
329         ENTRY;
330
331         oh = container_of0(th, struct osd_thandle, ot_super);
332         if (oh->ot_handle != NULL) {
333                 /*
334                  * XXX temporary stuff. Some abstraction layer should be used.
335                  */
336                 result = dt_txn_hook_stop(ctx, th->th_dev, th);
337                 if (result != 0)
338                         CERROR("Failure in transaction hook: %d\n", result);
339                 result = journal_stop(oh->ot_handle);
340                 if (result != 0)
341                         CERROR("Failure to stop transaction: %d\n", result);
342                 oh->ot_handle = NULL;
343         }
344         if (th->th_dev != NULL) {
345                 lu_device_put(&th->th_dev->dd_lu_dev);
346                 th->th_dev = NULL;
347         }
348         EXIT;
349 }
350
351 static struct dt_device_operations osd_dt_ops = {
352         .dt_root_get    = osd_root_get,
353         .dt_config      = osd_config,
354         .dt_statfs      = osd_statfs,
355         .dt_trans_start = osd_trans_start,
356         .dt_trans_stop  = osd_trans_stop,
357 };
358
359 static void osd_object_lock(struct lu_context *ctx, struct dt_object *dt,
360                             enum dt_lock_mode mode)
361 {
362         struct osd_object *obj = osd_dt_obj(dt);
363
364         LASSERT(mode == DT_WRITE_LOCK || mode == DT_READ_LOCK);
365         if (mode == DT_WRITE_LOCK)
366                 down_write(&obj->oo_sem);
367         else
368                 down_read(&obj->oo_sem);
369 }
370
371 static void osd_object_unlock(struct lu_context *ctx, struct dt_object *dt,
372                               enum dt_lock_mode mode)
373 {
374         struct osd_object *obj = osd_dt_obj(dt);
375
376         LASSERT(mode == DT_WRITE_LOCK || mode == DT_READ_LOCK);
377         if (mode == DT_WRITE_LOCK)
378                 up_write(&obj->oo_sem);
379         else
380                 up_read(&obj->oo_sem);
381 }
382
383 static int osd_attr_get(struct lu_context *ctxt, struct dt_object *dt,
384                         struct lu_attr *attr)
385 {
386         LASSERT(lu_object_exists(ctxt, &dt->do_lu));
387         return osd_inode_getattr(ctxt, osd_dt_obj(dt)->oo_inode, attr);
388 }
389
390 /*
391  * Object creation.
392  *
393  * XXX temporary solution.
394  */
395
396 static int osd_create_pre(struct osd_thread_info *info, struct osd_object *obj,
397                           struct lu_attr *attr, struct thandle *th)
398 {
399         return 0;
400 }
401
402 static int osd_create_post(struct osd_thread_info *info, struct osd_object *obj,
403                            struct lu_attr *attr, struct thandle *th)
404 {
405         LASSERT(obj->oo_inode != NULL);
406
407         osd_object_init0(obj);
408         return 0;
409 }
410
411 static void osd_fid_build_name(const struct lu_fid *fid, char *name)
412 {
413         static const char *qfmt = LPX64":%lx:%lx";
414
415         sprintf(name, qfmt, fid_seq(fid), fid_oid(fid), fid_ver(fid));
416 }
417
418 static int osd_mkdir(struct osd_thread_info *info, struct osd_object *obj,
419                      struct lu_attr *attr, struct thandle *th)
420 {
421         int result;
422         struct osd_device *osd = osd_obj2dev(obj);
423         struct inode      *dir;
424
425         /*
426          * XXX temporary solution.
427          */
428         struct dentry     *dentry;
429         char               name[32];
430         struct qstr        str = {
431                 .name = name
432         };
433
434         LASSERT(obj->oo_inode == NULL);
435         LASSERT(S_ISDIR(attr->la_mode));
436         LASSERT(osd->od_obj_area != NULL);
437
438         dir = osd->od_obj_area->d_inode;
439         LASSERT(dir->i_op != NULL && dir->i_op->mkdir != NULL);
440
441         osd_fid_build_name(lu_object_fid(&obj->oo_dt.do_lu), name);
442         str.len = strlen(name);
443
444         dentry = d_alloc(osd->od_obj_area, &str);
445         if (dentry != NULL) {
446                 result = dir->i_op->mkdir(dir, dentry,
447                                           attr->la_mode & (S_IRWXUGO|S_ISVTX));
448                 if (result == 0) {
449                         LASSERT(dentry->d_inode != NULL);
450                         obj->oo_inode = dentry->d_inode;
451                         igrab(obj->oo_inode);
452                 }
453                 dput(dentry);
454         } else
455                 result = -ENOMEM;
456         return result;
457 }
458
459 typedef int (*osd_obj_type_f)(struct osd_thread_info *, struct osd_object *,
460                               struct lu_attr *, struct thandle *);
461
462 osd_obj_type_f osd_mkreg = NULL;
463 osd_obj_type_f osd_mksym = NULL;
464 osd_obj_type_f osd_mknod = NULL;
465
466 static osd_obj_type_f osd_create_type_f(__u32 mode)
467 {
468         osd_obj_type_f result;
469
470         switch (mode) {
471         case S_IFDIR:
472                 result = osd_mkdir;
473                 break;
474         case S_IFREG:
475                 result = osd_mkreg;
476                 break;
477         case S_IFLNK:
478                 result = osd_mksym;
479                 break;
480         case S_IFCHR:
481         case S_IFBLK:
482         case S_IFIFO:
483         case S_IFSOCK:
484                 result = osd_mknod;
485                 break;
486         default:
487                 LBUG();
488                 break;
489         }
490         return result;
491  }
492
493 static int osd_object_create(struct lu_context *ctx, struct dt_object *dt,
494                              struct lu_attr *attr, struct thandle *th)
495 {
496         const struct lu_fid    *fid  = lu_object_fid(&dt->do_lu);
497         struct osd_object      *obj  = osd_dt_obj(dt);
498         struct osd_device      *osd  = osd_obj2dev(obj);
499         struct osd_thread_info *info = lu_context_key_get(ctx, &osd_key);
500         int result;
501
502         ENTRY;
503
504         LASSERT(!lu_object_exists(ctx, &dt->do_lu));
505
506         /*
507          * XXX missing: permission checks.
508          */
509
510         /*
511          * XXX missing: sanity checks (valid ->la_mode, etc.)
512          */
513
514         /*
515          * XXX missing: Quote handling.
516          */
517
518         result = osd_create_pre(info, obj, attr, th);
519         if (result == 0) {
520                 osd_create_type_f(attr->la_mode & S_IFMT)(info, obj, attr, th);
521                 if (result == 0)
522                         result = osd_create_post(info, obj, attr, th);
523         }
524         if (result == 0) {
525                 struct osd_inode_id *id = &info->oti_id;
526
527                 LASSERT(obj->oo_inode != NULL);
528
529                 id->oii_ino = obj->oo_inode->i_ino;
530                 id->oii_gen = obj->oo_inode->i_generation;
531
532                 osd_oi_write_lock(&osd->od_oi);
533                 result = osd_oi_insert(info, &osd->od_oi, fid, id, th);
534                 osd_oi_write_unlock(&osd->od_oi);
535         }
536
537         LASSERT(ergo(result == 0, lu_object_exists(ctx, &dt->do_lu)));
538         return result;
539 }
540
541 static struct dt_object_operations osd_obj_ops = {
542         .do_object_lock   = osd_object_lock,
543         .do_object_unlock = osd_object_unlock,
544         .do_attr_get      = osd_attr_get,
545         .do_object_create = osd_object_create,
546 };
547
548 static struct dt_body_operations osd_body_ops = {
549 };
550
551 /*
552  * Index operations.
553  */
554
555 /*
556  * XXX This is temporary solution: inode operations are used until iam is
557  * ready.
558  */
559 static int osd_index_lookup(struct lu_context *ctxt, struct dt_object *dt,
560                             struct dt_rec *rec, const struct dt_key *key)
561 {
562         struct osd_object *obj = osd_dt_obj(dt);
563         struct osd_device *osd = osd_obj2dev(obj);
564         struct inode      *dir;
565
566         int result;
567
568         /*
569          * XXX temporary solution.
570          */
571         struct dentry     *dentry;
572         struct qstr        str = {
573                 .name = (const char *)key,
574                 .len  = strlen((const char *)key)
575         };
576
577         LASSERT(osd_has_index(obj));
578         LASSERT(osd->od_obj_area != NULL);
579
580         dir = obj->oo_inode;
581         LASSERT(dir->i_op != NULL && dir->i_op->lookup != NULL);
582
583         dentry = d_alloc(NULL, &str);
584         if (dentry != NULL) {
585                 struct dentry *d;
586
587                 /*
588                  * XXX passing NULL for nameidata should work for
589                  * ext3/ldiskfs.
590                  */
591                 d = dir->i_op->lookup(dir, dentry, NULL);
592                 if (d == NULL) {
593                         /*
594                          * normal case, result is in @dentry.
595                          */
596                         if (dentry->d_inode != NULL) {
597                                 struct lu_fid *fid = (struct lu_fid *)rec;
598                                 /*
599                                  * Build fid from inode.
600                                  */
601                                 fid->f_seq = 0; /* XXX hard-coded */
602                                 fid->f_oid = dentry->d_inode->i_ino;
603                                 fid->f_ver = dentry->d_inode->i_generation;
604                                 result = 0;
605                         } else
606                                 result = -ENOENT;
607                 } else {
608                         /* What? Disconnected alias? Ppheeeww... */
609                         CERROR("Aliasing where not expected\n");
610                         result = -EIO;
611                         dput(d);
612                 }
613                 dput(dentry);
614         } else
615                 result = -ENOMEM;
616         return result;
617 }
618
619 static int osd_index_insert(struct lu_context *ctxt, struct dt_object *dt,
620                             const struct dt_rec *rec, const struct dt_key *key,
621                             struct thandle *handle)
622 {
623         return 0;
624 }
625
626 const struct dt_index_features dt_directory_features;
627
628 static int osd_index_probe(struct lu_context *ctxt, struct dt_object *dt,
629                            const struct dt_index_features *feat)
630 {
631         struct osd_object *obj = osd_dt_obj(dt);
632
633         if (feat == &dt_directory_features)
634                 return 1;
635         else
636                 return 0; /* nothing yet is supported */
637 }
638
639 static struct dt_index_operations osd_index_ops = {
640         .dio_lookup = osd_index_lookup,
641         .dio_insert = osd_index_insert,
642         .dio_probe  = osd_index_probe
643 };
644
645 /*
646  * OSD device type methods
647  */
648 static int osd_type_init(struct lu_device_type *t)
649 {
650         return lu_context_key_register(&osd_key);
651 }
652
653 static void osd_type_fini(struct lu_device_type *t)
654 {
655         lu_context_key_degister(&osd_key);
656 }
657
658 static struct lu_context_key osd_key = {
659         .lct_init = osd_key_init,
660         .lct_fini = osd_key_fini
661 };
662
663 static void *osd_key_init(struct lu_context *ctx)
664 {
665         struct osd_thread_info *info;
666
667         OBD_ALLOC_PTR(info);
668         if (info == NULL)
669                 info = ERR_PTR(-ENOMEM);
670         return info;
671 }
672
673 static void osd_key_fini(struct lu_context *ctx, void *data)
674 {
675         struct osd_thread_info *info = data;
676         OBD_FREE_PTR(info);
677 }
678
679 static int osd_device_init(struct lu_context *ctx,
680                            struct lu_device *d, struct lu_device *next)
681 {
682         return 0;
683 }
684
685 extern void osd_oi_init0(struct osd_oi *oi, __u64 root_ino, __u32 root_gen);
686 extern int osd_oi_find_fid(struct osd_oi *oi,
687                            __u64 ino, __u32 gen, struct lu_fid *fid);
688
689 static int osd_mount(struct lu_context *ctx,
690                      struct osd_device *o, struct lustre_cfg *cfg)
691 {
692         struct lustre_mount_info *lmi;
693         const char *dev = lustre_cfg_string(cfg, 0);
694         int result;
695
696         ENTRY;
697
698         if (o->od_mount != NULL) {
699                 CERROR("Already mounted (%s)\n", dev);
700                 RETURN(-EEXIST);
701         }
702
703         /* get mount */
704         lmi = server_get_mount(dev);
705         if (lmi == NULL) {
706                 CERROR("Cannot get mount info for %s!\n", dev);
707                 RETURN(-EFAULT);
708         }
709
710         LASSERT(lmi != NULL);
711         /* save lustre_mount_info in dt_device */
712         o->od_mount = lmi;
713         result = osd_oi_init(&o->od_oi, osd_sb(o)->s_root,
714                              osd2lu_dev(o)->ld_site);
715         if (result == 0) {
716                 struct dentry *d;
717
718                 d = simple_mkdir(osd_sb(o)->s_root, "*OBJ-TEMP*", 0777, 1);
719                 if (!IS_ERR(d)) {
720                         o->od_obj_area = d;
721
722                         d = simple_mkdir(osd_sb(o)->s_root, "ROOT", 0777, 1);
723                         if (!IS_ERR(d)) {
724                                 osd_oi_init0(&o->od_oi, d->d_inode->i_ino,
725                                              d->d_inode->i_generation);
726                                 o->od_root_dir = d;
727                         } else
728                                 result = PTR_ERR(d);
729                 } else
730                         result = PTR_ERR(d);
731         }
732         if (result != 0)
733                 osd_device_fini(ctx, osd2lu_dev(o));
734         RETURN(result);
735 }
736
737 static struct lu_device *osd_device_fini(struct lu_context *ctx,
738                                          struct lu_device *d)
739 {
740         struct osd_device *o = osd_dev(d);
741
742         ENTRY;
743         if (o->od_obj_area != NULL) {
744                 dput(o->od_obj_area);
745                 o->od_obj_area = NULL;
746         }
747         if (o->od_root_dir != NULL) {
748                 dput(o->od_root_dir);
749                 o->od_root_dir = NULL;
750         }
751         osd_oi_fini(&o->od_oi);
752
753         if (o->od_mount)
754                 server_put_mount(o->od_mount->lmi_name, o->od_mount->lmi_mnt);
755
756         o->od_mount = NULL;
757         RETURN(NULL);
758 }
759
760 static struct lu_device *osd_device_alloc(struct lu_device_type *t,
761                                           struct lustre_cfg *cfg)
762 {
763         struct lu_device  *l;
764         struct osd_device *o;
765
766         OBD_ALLOC_PTR(o);
767         if (o != NULL) {
768                 int result;
769
770                 result = dt_device_init(&o->od_dt_dev, t);
771                 if (result == 0) {
772                         l = osd2lu_dev(o);
773                         l->ld_ops = &osd_lu_ops;
774                         o->od_dt_dev.dd_ops = &osd_dt_ops;
775                 } else
776                         l = ERR_PTR(result);
777         } else
778                 l = ERR_PTR(-ENOMEM);
779         return l;
780 }
781
782 static void osd_device_free(struct lu_device *d)
783 {
784         struct osd_device *o = osd_dev(d);
785
786         dt_device_fini(&o->od_dt_dev);
787         OBD_FREE_PTR(o);
788 }
789
790 static int osd_process_config(struct lu_context *ctx,
791                               struct lu_device *d, struct lustre_cfg *cfg)
792 {
793         struct osd_device *o = osd_dev(d);
794         int err;
795
796         switch(cfg->lcfg_command) {
797         case LCFG_SETUP:
798                 err = osd_mount(ctx, o, cfg);
799                 break;
800         default:
801                 err = -ENOTTY;
802         }
803
804         RETURN(err);
805 }
806
807 /*
808  * fid<->inode<->object functions.
809  */
810
811 static int osd_inode_get_fid(struct osd_device *d, const struct inode *inode,
812                              struct lu_fid *fid)
813 {
814         int result;
815
816         /*
817          * XXX: Should return fid stored together with inode in memory.
818          */
819         if (OI_IN_MEMORY) {
820                 result = osd_oi_find_fid(&d->od_oi, inode->i_ino,
821                                          inode->i_generation, fid);
822         } else {
823                 fid->f_seq = inode->i_ino;
824                 fid->f_oid = inode->i_generation;
825                 result = 0;
826         }
827         return result;
828 }
829
830 struct dentry *osd_open(struct dentry *parent, const char *name, mode_t mode)
831 {
832         struct dentry *dentry;
833         struct dentry *result;
834
835         result = dentry = osd_lookup(parent, name);
836         if (IS_ERR(dentry)) {
837                 CERROR("Error opening %s: %ld\n", name, PTR_ERR(dentry));
838                 dentry = NULL; /* dput(NULL) below is OK */
839         } else if (dentry->d_inode == NULL) {
840                 CERROR("Not found: %s\n", name);
841                 result = ERR_PTR(-ENOENT);
842         } else if ((dentry->d_inode->i_mode & S_IFMT) != mode) {
843                 CERROR("Wrong mode: %s: %o != %o\n", name,
844                        dentry->d_inode->i_mode, mode);
845                 result = ERR_PTR(mode == S_IFDIR ? -ENOTDIR : -EISDIR);
846         }
847
848         if (IS_ERR(result))
849                 dput(dentry);
850         return result;
851 }
852
853 struct dentry *osd_lookup(struct dentry *parent, const char *name)
854 {
855         struct dentry *dentry;
856
857         CDEBUG(D_INODE, "looking up object %s\n", name);
858         down(&parent->d_inode->i_sem);
859         dentry = lookup_one_len(name, parent, strlen(name));
860         up(&parent->d_inode->i_sem);
861
862         if (IS_ERR(dentry)) {
863                 CERROR("error getting %s: %ld\n", name, PTR_ERR(dentry));
864         } else if (dentry->d_inode != NULL && is_bad_inode(dentry->d_inode)) {
865                 CERROR("got bad object %s inode %lu\n",
866                        name, dentry->d_inode->i_ino);
867                 dput(dentry);
868                 dentry = ERR_PTR(-ENOENT);
869         }
870         return dentry;
871 }
872
873 static struct inode *osd_iget(struct osd_thread_info *info,
874                               struct osd_device *dev,
875                               const struct osd_inode_id *id)
876 {
877         struct inode *inode;
878
879         inode = iget(osd_sb(dev), id->oii_ino);
880         if (inode == NULL) {
881                 CERROR("no inode\n");
882                 inode = ERR_PTR(-EACCES);
883         } else if (is_bad_inode(inode)) {
884                 CERROR("bad inode\n");
885                 iput(inode);
886                 inode = ERR_PTR(-ENOENT);
887         } else if (inode->i_generation != id->oii_gen &&
888                    id->oii_gen != OSD_GEN_IGNORE) {
889                 CERROR("stale inode\n");
890                 iput(inode);
891                 inode = ERR_PTR(-ESTALE);
892         }
893         return inode;
894
895 }
896
897 static int osd_fid_lookup(struct lu_context *ctx,
898                           struct osd_object *obj, const struct lu_fid *fid)
899 {
900         struct osd_thread_info *info;
901         struct lu_device       *ldev = obj->oo_dt.do_lu.lo_dev;
902         struct osd_device      *dev;
903         struct osd_inode_id     id;
904         struct inode           *inode;
905         int                     result;
906
907         LASSERT(obj->oo_inode == NULL);
908         LASSERT(fid_is_sane(fid));
909         LASSERT(fid_is_local(ldev->ld_site, fid));
910
911         ENTRY;
912
913         info = lu_context_key_get(ctx, &osd_key);
914         dev  = osd_dev(ldev);
915
916         if (OBD_FAIL_CHECK(OBD_FAIL_OST_ENOENT))
917                 RETURN(-ENOENT);
918
919         osd_oi_read_lock(&dev->od_oi);
920         result = osd_oi_lookup(info, &dev->od_oi, fid, &id);
921         if (result == 0) {
922                 inode = osd_iget(info, dev, &id);
923                 if (!IS_ERR(inode)) {
924                         obj->oo_inode = inode;
925                         result = 0;
926                 } else
927                         result = PTR_ERR(inode);
928         } else if (result == -ENOENT)
929                 result = 0;
930         osd_oi_read_unlock(&dev->od_oi);
931         RETURN(result);
932 }
933
934 static int osd_inode_getattr(struct lu_context *ctx,
935                              struct inode *inode, struct lu_attr *attr)
936 {
937         //attr->la_atime      = inode->i_atime;
938         //attr->la_mtime      = inode->i_mtime;
939         //attr->la_ctime      = inode->i_ctime;
940         attr->la_mode       = inode->i_mode;
941         attr->la_size       = inode->i_size;
942         attr->la_blocks     = inode->i_blocks;
943         attr->la_uid        = inode->i_uid;
944         attr->la_gid        = inode->i_gid;
945         attr->la_flags      = inode->i_flags;
946         attr->la_nlink      = inode->i_nlink;
947         return 0;
948 }
949
950 /*
951  * Helpers.
952  */
953
954 static int lu_device_is_osd(const struct lu_device *d)
955 {
956         /*
957          * XXX for now. Tags in lu_device_type->ldt_something are needed.
958          */
959         return ergo(d != NULL && d->ld_ops != NULL, d->ld_ops == &osd_lu_ops);
960 }
961
962 static struct osd_object *osd_obj(const struct lu_object *o)
963 {
964         LASSERT(lu_device_is_osd(o->lo_dev));
965         return container_of0(o, struct osd_object, oo_dt.do_lu);
966 }
967
968 static struct osd_device *osd_dt_dev(const struct dt_device *d)
969 {
970         LASSERT(lu_device_is_osd(&d->dd_lu_dev));
971         return container_of0(d, struct osd_device, od_dt_dev);
972 }
973
974 static struct osd_device *osd_dev(const struct lu_device *d)
975 {
976         LASSERT(lu_device_is_osd(d));
977         return osd_dt_dev(container_of0(d, struct dt_device, dd_lu_dev));
978 }
979
980 static struct osd_object *osd_dt_obj(const struct dt_object *d)
981 {
982         return osd_obj(&d->do_lu);
983 }
984
985 static struct osd_device *osd_obj2dev(struct osd_object *o)
986 {
987         return osd_dev(o->oo_dt.do_lu.lo_dev);
988 }
989
990 static struct lu_device *osd2lu_dev(struct osd_device * osd)
991 {
992         return &osd->od_dt_dev.dd_lu_dev;
993 }
994
995 static struct super_block *osd_sb(const struct osd_device *dev)
996 {
997         return dev->od_mount->lmi_mnt->mnt_sb;
998 }
999
1000 static journal_t *osd_journal(const struct osd_device *dev)
1001 {
1002         return LDISKFS_SB(osd_sb(dev))->s_journal;
1003 }
1004
1005 static int osd_has_index(struct osd_object *obj)
1006 {
1007         return S_ISDIR(obj->oo_inode->i_mode);
1008 }
1009
1010 static struct lu_object_operations osd_lu_obj_ops = {
1011         .loo_object_init    = osd_object_init,
1012         .loo_object_delete  = osd_object_delete,
1013         .loo_object_release = osd_object_release,
1014         .loo_object_print   = osd_object_print,
1015         .loo_object_exists  = osd_object_exists
1016 };
1017
1018 static struct lu_device_operations osd_lu_ops = {
1019         .ldo_object_alloc   = osd_object_alloc,
1020         .ldo_object_free    = osd_object_free,
1021         .ldo_process_config = osd_process_config
1022 };
1023
1024 static struct lu_device_type_operations osd_device_type_ops = {
1025         .ldto_init = osd_type_init,
1026         .ldto_fini = osd_type_fini,
1027
1028         .ldto_device_alloc = osd_device_alloc,
1029         .ldto_device_free  = osd_device_free,
1030
1031         .ldto_device_init    = osd_device_init,
1032         .ldto_device_fini    = osd_device_fini
1033 };
1034
1035 static struct lu_device_type osd_device_type = {
1036         .ldt_tags = LU_DEVICE_DT,
1037         .ldt_name = LUSTRE_OSD0_NAME,
1038         .ldt_ops  = &osd_device_type_ops
1039 };
1040
1041 /*
1042  * lprocfs legacy support.
1043  */
1044 static struct lprocfs_vars lprocfs_osd_obd_vars[] = {
1045         { 0 }
1046 };
1047
1048 static struct lprocfs_vars lprocfs_osd_module_vars[] = {
1049         { 0 }
1050 };
1051
1052 static struct obd_ops osd_obd_device_ops = {
1053         .o_owner = THIS_MODULE
1054 };
1055
1056 LPROCFS_INIT_VARS(osd, lprocfs_osd_module_vars, lprocfs_osd_obd_vars);
1057
1058 static int __init osd_mod_init(void)
1059 {
1060         struct lprocfs_static_vars lvars;
1061
1062         lprocfs_init_vars(osd, &lvars);
1063         return class_register_type(&osd_obd_device_ops, NULL, lvars.module_vars,
1064                                    LUSTRE_OSD0_NAME, &osd_device_type);
1065 }
1066
1067 static void __exit osd_mod_exit(void)
1068 {
1069         class_unregister_type(LUSTRE_OSD0_NAME);
1070 }
1071
1072 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1073 MODULE_DESCRIPTION("Lustre Object Storage Device ("LUSTRE_OSD0_NAME")");
1074 MODULE_LICENSE("GPL");
1075
1076 cfs_module(osd, "0.0.2", osd_mod_init, osd_mod_exit);