1 /* -*- MODE: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Lustre Metadata Server (mdd) routines
7 * Copyright (C) 2006 Cluster File Systems, Inc.
8 * Author: Wang Di <wangdi@clusterfs.com>
10 * This file is part of the Lustre file system, http://www.lustre.org
11 * Lustre is a trademark of Cluster File Systems, Inc.
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.
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.
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.
29 # define EXPORT_SYMTAB
31 #define DEBUG_SUBSYSTEM S_MDS
33 #include <linux/module.h>
35 #include <linux/obd.h>
36 #include <linux/obd_class.h>
37 #include <linux/lustre_ver.h>
38 #include <linux/obd_support.h>
39 #include <linux/lprocfs_status.h>
42 #include <linux/lu_object.h>
43 #include <linux/md_object.h>
44 #include <linux/dt_object.h>
46 #include "mdd_internal.h"
49 static struct thandle* mdd_trans_start(struct lu_context *ctxt,
51 static void mdd_trans_stop(struct lu_context *ctxt,
52 struct mdd_device *mdd, struct thandle *handle);
53 static struct dt_object* mdd_object_child(struct mdd_object *o);
54 static struct lu_device_operations mdd_lu_ops;
55 static void mdd_lock(struct lu_context *ctx,
56 struct mdd_object *obj, enum dt_lock_mode mode);
57 static void mdd_unlock(struct lu_context *ctx,
58 struct mdd_object *obj, enum dt_lock_mode mode);
60 static struct md_object_operations mdd_obj_ops;
61 static struct md_dir_operations mdd_dir_ops;
62 static struct lu_object_operations mdd_lu_obj_ops;
64 static struct lu_context_key mdd_thread_key;
66 struct mdd_thread_info {
67 struct txn_param mti_param;
68 struct lu_fid mti_fid;
71 const char *mdd_root_dir_name = "ROOT";
73 static struct mdd_thread_info *mdd_ctx_info(struct lu_context *ctx)
75 struct mdd_thread_info *info;
77 info = lu_context_key_get(ctx, &mdd_thread_key);
78 LASSERT(info != NULL);
82 static int lu_device_is_mdd(struct lu_device *d)
85 * XXX for now. Tags in lu_device_type->ldt_something are needed.
87 return ergo(d != NULL && d->ld_ops != NULL, d->ld_ops == &mdd_lu_ops);
90 static struct mdd_device* lu2mdd_dev(struct lu_device *d)
92 LASSERT(lu_device_is_mdd(d));
93 return container_of0(d, struct mdd_device, mdd_md_dev.md_lu_dev);
96 static inline struct lu_device *mdd2lu_dev(struct mdd_device *d)
98 return (&d->mdd_md_dev.md_lu_dev);
101 static struct mdd_object *mdd_obj(struct lu_object *o)
103 LASSERT(lu_device_is_mdd(o->lo_dev));
104 return container_of0(o, struct mdd_object, mod_obj.mo_lu);
107 static struct mdd_device* mdo2mdd(struct md_object *mdo)
109 return lu2mdd_dev(mdo->mo_lu.lo_dev);
112 static struct mdd_object* mdo2mddo(struct md_object *mdo)
114 return container_of0(mdo, struct mdd_object, mod_obj);
117 static inline struct dt_device_operations *mdd_child_ops(struct mdd_device *d)
119 return d->mdd_child->dd_ops;
122 static struct lu_object *mdd_object_alloc(struct lu_context *ctxt,
125 struct mdd_object *mdo;
132 o = &mdo->mod_obj.mo_lu;
133 lu_object_init(o, NULL, d);
134 mdo->mod_obj.mo_ops = &mdd_obj_ops;
135 mdo->mod_obj.mo_dir_ops = &mdd_dir_ops;
136 o->lo_ops = &mdd_lu_obj_ops;
137 return &mdo->mod_obj.mo_lu;
142 static int mdd_object_init(struct lu_context *ctxt, struct lu_object *o)
144 struct mdd_device *d = lu2mdd_dev(o->lo_dev);
145 struct lu_object *below;
146 struct lu_device *under;
149 under = &d->mdd_child->dd_lu_dev;
150 below = under->ld_ops->ldo_object_alloc(ctxt, under);
155 lu_object_add(o, below);
159 static void mdd_object_free(struct lu_context *ctxt, struct lu_object *o)
161 struct lu_object_header *h;
162 struct mdd_object *mdd = mdd_obj(o);
170 mdd_attr_get(struct lu_context *ctxt,
171 struct md_object *obj, struct lu_attr *attr)
173 struct mdd_object *mdd_obj = mdo2mddo(obj);
174 struct dt_object *next = mdd_object_child(mdd_obj);
179 rc = next->do_ops->do_attr_get(ctxt, next, attr);
184 mdd_xattr_get(struct lu_context *ctxt, struct md_object *obj, void *buf,
185 int buf_len, const char *name)
187 struct mdd_object *mdd_obj = mdo2mddo(obj);
188 struct dt_object *next = mdd_object_child(mdd_obj);
193 rc = next->do_ops->do_xattr_get(ctxt, next, buf, buf_len, name);
198 __mdd_object_destroy(struct lu_context *ctxt, struct mdd_object *obj,
199 struct thandle *handle)
201 struct dt_object *next = mdd_object_child(obj);
203 rc = next->do_ops->do_object_destroy(ctxt, next, handle);
207 static int mdd_add_orphan(struct mdd_device *mdd, struct mdd_object *obj,
208 struct thandle *handle)
217 open_orphan(struct mdd_object *obj)
223 mdd_add_unlink_log(struct mdd_device *mdd, struct mdd_object *obj,
224 struct thandle *handle)
230 MDD_TXN_OBJECT_DESTROY_OP,
231 MDD_TXN_OBJECT_CREATE_OP,
233 MDD_TXN_XATTR_SET_OP,
234 MDD_TXN_INDEX_INSERT_OP,
235 MDD_TXN_INDEX_DELETE_OP,
241 struct mdd_txn_op_descr {
242 enum mdd_txn_op mod_op;
243 unsigned int mod_credits;
247 MDD_TXN_OBJECT_DESTROY_CREDITS = 10,
248 MDD_TXN_OBJECT_CREATE_CREDITS = 10,
249 MDD_TXN_ATTR_SET_CREDITS = 10,
250 MDD_TXN_XATTR_SET_CREDITS = 10,
251 MDD_TXN_INDEX_INSERT_CREDITS = 10,
252 MDD_TXN_INDEX_DELETE_CREDITS = 10,
253 MDD_TXN_LINK_CREDITS = 10,
254 MDD_TXN_RENAME_CREDITS = 10,
255 MDD_TXN_MKDIR_CREDITS = 10
258 #define DEFINE_MDD_TXN_OP_DESC(opname) \
259 static const struct mdd_txn_op_descr opname = { \
260 .mod_op = opname ## _OP, \
261 .mod_credits = opname ## _CREDITS, \
265 * number of blocks to reserve for particular operations. Should be function
266 * of ... something. Stub for now.
268 DEFINE_MDD_TXN_OP_DESC(MDD_TXN_OBJECT_DESTROY);
269 DEFINE_MDD_TXN_OP_DESC(MDD_TXN_OBJECT_CREATE);
270 DEFINE_MDD_TXN_OP_DESC(MDD_TXN_ATTR_SET);
271 DEFINE_MDD_TXN_OP_DESC(MDD_TXN_XATTR_SET);
272 DEFINE_MDD_TXN_OP_DESC(MDD_TXN_INDEX_INSERT);
273 DEFINE_MDD_TXN_OP_DESC(MDD_TXN_INDEX_DELETE);
274 DEFINE_MDD_TXN_OP_DESC(MDD_TXN_LINK);
275 DEFINE_MDD_TXN_OP_DESC(MDD_TXN_RENAME);
276 DEFINE_MDD_TXN_OP_DESC(MDD_TXN_MKDIR);
278 static void mdd_txn_param_build(struct lu_context *ctx,
279 const struct mdd_txn_op_descr *opd)
281 mdd_ctx_info(ctx)->mti_param.tp_credits = opd->mod_credits;
285 mdd_object_destroy(struct lu_context *ctxt, struct md_object *obj)
287 struct mdd_device *mdd = mdo2mdd(obj);
288 struct mdd_object *mdd_obj = mdo2mddo(obj);
289 struct thandle *handle;
293 mdd_txn_param_build(ctxt, &MDD_TXN_OBJECT_DESTROY);
294 handle = mdd_trans_start(ctxt, mdd);
296 RETURN(PTR_ERR(handle));
298 mdd_lock(ctxt, mdd_obj, DT_WRITE_LOCK);
299 if (open_orphan(mdd_obj))
300 rc = mdd_add_orphan(mdd, mdd_obj, handle);
302 rc = __mdd_object_destroy(ctxt, mdd_obj, handle);
304 rc = mdd_add_unlink_log(mdd, mdd_obj, handle);
307 mdd_unlock(ctxt, mdd_obj, DT_WRITE_LOCK);
308 mdd_trans_stop(ctxt, mdd, handle);
312 static void mdd_object_release(struct lu_context *ctxt, struct lu_object *o)
316 static int mdd_object_exists(struct lu_context *ctx, struct lu_object *o)
318 return lu_object_exists(ctx, lu_object_next(o));
321 static int mdd_object_print(struct lu_context *ctxt,
322 struct seq_file *f, const struct lu_object *o)
324 return seq_printf(f, LUSTRE_MDD0_NAME"-object@%p", o);
327 static int mdd_dt_lookup(struct lu_context *ctx, struct mdd_device *mdd,
328 struct mdd_object *obj, const char *name,
331 struct dt_object *dir = mdd_object_child(obj);
332 struct dt_rec *rec = (struct dt_rec *)fid;
333 const struct dt_key *key = (const struct dt_key *)name;
336 if (dir->do_index_ops != NULL)
337 result = dir->do_index_ops->dio_lookup(ctx, dir, rec, key);
343 static int mdd_mount(struct lu_context *ctx, struct mdd_device *mdd)
346 struct mdd_thread_info *info = lu_context_key_get(ctx,
348 struct lu_device *dev = &mdd->mdd_md_dev.md_lu_dev;
350 result = mdd_child_ops(mdd)->dt_root_get(ctx, mdd->mdd_child,
353 struct lu_object *root;
355 root = lu_object_find(ctx, dev->ld_site, &info->mti_fid);
357 struct mdd_object *obj;
359 obj = mdd_obj(lu_object_locate(root->lo_header,
362 result = mdd_dt_lookup(ctx, mdd, obj,
366 CERROR("No slice\n");
369 lu_object_put(ctx, root);
372 result = PTR_ERR(root);
378 static int mdd_fs_setup(struct lu_context *ctx, struct mdd_device *mdd)
383 static int mdd_fs_cleanup(struct mdd_device *mdd)
388 static int mdd_device_init(struct lu_context *ctx,
389 struct lu_device *d, struct lu_device *next)
391 struct mdd_device *mdd = lu2mdd_dev(d);
396 mdd->mdd_child = lu2dt_dev(next);
398 rc = mdd_fs_setup(ctx, mdd);
408 static struct lu_device *mdd_device_fini(struct lu_context *ctx,
411 struct mdd_device *m = lu2mdd_dev(d);
412 struct lu_device *next = &m->mdd_child->dd_lu_dev;
417 static int mdd_process_config(struct lu_context *ctx,
418 struct lu_device *d, struct lustre_cfg *cfg)
420 struct mdd_device *m = lu2mdd_dev(d);
421 struct lu_device *next = &m->mdd_child->dd_lu_dev;
424 switch(cfg->lcfg_command) {
427 err = next->ld_ops->ldo_process_config(ctx, next, cfg);
428 if (err == 0 && cfg->lcfg_command == LCFG_SETUP)
429 err = mdd_mount(ctx, m);
435 static struct lu_device_operations mdd_lu_ops = {
436 .ldo_object_alloc = mdd_object_alloc,
437 .ldo_object_free = mdd_object_free,
438 .ldo_process_config = mdd_process_config
441 static struct lu_object_operations mdd_lu_obj_ops = {
442 .loo_object_init = mdd_object_init,
443 .loo_object_release = mdd_object_release,
444 .loo_object_print = mdd_object_print,
445 .loo_object_exists = mdd_object_exists
448 static struct dt_object* mdd_object_child(struct mdd_object *o)
450 return container_of0(lu_object_next(&o->mod_obj.mo_lu),
451 struct dt_object, do_lu);
454 static void mdd_lock(struct lu_context *ctxt,
455 struct mdd_object *obj, enum dt_lock_mode mode)
457 struct dt_object *next = mdd_object_child(obj);
459 next->do_ops->do_object_lock(ctxt, next, mode);
462 static void mdd_unlock(struct lu_context *ctxt,
463 struct mdd_object *obj, enum dt_lock_mode mode)
465 struct dt_object *next = mdd_object_child(obj);
467 next->do_ops->do_object_unlock(ctxt, next, mode);
470 static void mdd_lock2(struct lu_context *ctxt,
471 struct mdd_object *o0, struct mdd_object *o1)
473 mdd_lock(ctxt, o0, DT_WRITE_LOCK);
474 mdd_lock(ctxt, o1, DT_WRITE_LOCK);
477 static void mdd_unlock2(struct lu_context *ctxt,
478 struct mdd_object *o0, struct mdd_object *o1)
480 mdd_unlock(ctxt, o0, DT_WRITE_LOCK);
481 mdd_unlock(ctxt, o1, DT_WRITE_LOCK);
484 static struct thandle* mdd_trans_start(struct lu_context *ctxt,
485 struct mdd_device *mdd)
487 struct txn_param *p = &mdd_ctx_info(ctxt)->mti_param;
489 return mdd_child_ops(mdd)->dt_trans_start(ctxt, mdd->mdd_child, p);
492 static void mdd_trans_stop(struct lu_context *ctxt,
493 struct mdd_device *mdd, struct thandle *handle)
495 mdd_child_ops(mdd)->dt_trans_stop(ctxt, handle);
499 __mdd_object_create(struct lu_context *ctxt, struct mdd_object *obj,
500 struct lu_attr *attr, struct thandle *handle)
502 struct dt_object *next = mdd_object_child(obj);
506 rc = next->do_ops->do_object_create(ctxt, next, attr, handle);
507 /*XXX increase the refcount of the object or not?*/
511 static int mdd_object_create(struct lu_context *ctxt, struct md_object *obj,
512 struct lu_attr *attr)
515 struct mdd_device *mdd = mdo2mdd(obj);
516 struct thandle *handle;
520 mdd_txn_param_build(ctxt, &MDD_TXN_OBJECT_CREATE);
521 handle = mdd_trans_start(ctxt, mdd);
523 RETURN(PTR_ERR(handle));
525 rc = __mdd_object_create(ctxt, mdo2mddo(obj), attr, handle);
527 mdd_trans_stop(ctxt, mdd, handle);
534 __mdd_attr_set(struct lu_context *ctxt, struct md_object *obj,
535 struct lu_attr *attr, struct thandle *handle)
537 struct dt_object *next = mdd_object_child(mdo2mddo(obj));
538 return next->do_ops->do_attr_set(ctxt, next, attr, handle);
542 mdd_attr_set(struct lu_context *ctxt,
543 struct md_object *obj, struct lu_attr *attr)
545 struct mdd_device *mdd = mdo2mdd(obj);
546 struct thandle *handle;
550 mdd_txn_param_build(ctxt, &MDD_TXN_ATTR_SET);
551 handle = mdd_trans_start(ctxt, mdd);
555 rc = __mdd_attr_set(ctxt, obj, attr, handle);
557 mdd_trans_stop(ctxt, mdd, handle);
565 __mdd_xattr_set(struct lu_context *ctxt, struct mdd_device *mdd,
566 struct mdd_object *obj, void *buf,
567 int buf_len, const char *name, struct thandle *handle)
569 struct dt_object *next = mdd_object_child(obj);
570 return next->do_ops->do_xattr_set(ctxt, next, buf, buf_len,
575 mdd_xattr_set(struct lu_context *ctxt, struct md_object *obj, void *buf,
576 int buf_len, const char *name)
578 struct mdd_device *mdd = mdo2mdd(obj);
579 struct thandle *handle;
583 mdd_txn_param_build(ctxt, &MDD_TXN_XATTR_SET);
584 handle = mdd_trans_start(ctxt, mdd);
588 rc = __mdd_xattr_set(ctxt, mdd, mdo2mddo(obj), buf, buf_len, name,
591 mdd_trans_stop(ctxt, mdd, handle);
596 static const struct lu_fid *mdd_object_getfid(struct mdd_object *obj)
598 return lu_object_fid(&obj->mod_obj.mo_lu);
602 __mdd_index_insert(struct lu_context *ctxt, struct mdd_object *pobj,
603 const struct lu_fid *lf, const char *name,
604 struct thandle *handle)
607 struct dt_object *next = mdd_object_child(pobj);
609 rc = next->do_index_ops->dio_insert(ctxt, next, (struct dt_rec *)lf,
610 (struct dt_key *)name, handle);
615 __mdd_index_delete(struct lu_context *ctxt, struct mdd_device *mdd,
616 struct mdd_object *pobj,
617 struct mdd_object *obj, const char *name,
618 struct thandle *handle)
621 struct dt_object *next = mdd_object_child(pobj);
624 mdd_lock2(ctxt, pobj, obj);
626 rc = next->do_index_ops->dio_delete(ctxt, next,
627 (const struct dt_rec *)mdd_object_getfid(obj),
628 (struct dt_key *)name, handle);
629 mdd_unlock2(ctxt, pobj, obj);
635 mdd_index_delete(struct lu_context *ctxt, struct md_object *pobj,
636 struct md_object *obj, const char *name)
638 struct mdd_object *mdd_pobj = mdo2mddo(pobj);
639 struct mdd_object *mdd_obj = mdo2mddo(obj);
640 struct mdd_device *mdd = mdo2mdd(obj);
641 struct thandle *handle;
645 mdd_txn_param_build(ctxt, &MDD_TXN_INDEX_DELETE);
646 handle = mdd_trans_start(ctxt, mdd);
648 RETURN(PTR_ERR(handle));
650 rc = __mdd_index_delete(ctxt, mdd, mdd_pobj, mdd_obj, name, handle);
652 mdd_trans_stop(ctxt, mdd, handle);
658 mdd_link(struct lu_context *ctxt, struct md_object *tgt_obj,
659 struct md_object *src_obj, const char *name)
661 struct mdd_object *mdd_tobj = mdo2mddo(tgt_obj);
662 struct mdd_object *mdd_sobj = mdo2mddo(src_obj);
663 struct mdd_device *mdd = mdo2mdd(src_obj);
664 struct thandle *handle;
668 mdd_txn_param_build(ctxt, &MDD_TXN_LINK);
669 handle = mdd_trans_start(ctxt, mdd);
671 RETURN(PTR_ERR(handle));
673 mdd_lock2(ctxt, mdd_tobj, mdd_sobj);
675 rc = __mdd_index_insert(ctxt, mdd_tobj, lu_object_fid(&src_obj->mo_lu),
680 rc = mdd_xattr_get(ctxt, src_obj, &nlink, sizeof(nlink), "NLINK");
683 rc = __mdd_xattr_set(ctxt, mdd, mdd_sobj,
684 &nlink, sizeof(nlink), "NLINK", handle);
686 mdd_unlock2(ctxt, mdd_tobj, mdd_sobj);
688 mdd_trans_stop(ctxt, mdd, handle);
692 static void mdd_rename_lock(struct mdd_device *mdd,
693 struct mdd_object *src_pobj,
694 struct mdd_object *tgt_pobj,
695 struct mdd_object *sobj,
696 struct mdd_object *tobj)
701 static void mdd_rename_unlock(struct mdd_device *mdd, struct mdd_object *src_pobj,
702 struct mdd_object *tgt_pobj, struct mdd_object *sobj,
703 struct mdd_object *tobj)
709 mdd_rename(struct lu_context *ctxt, struct md_object *src_pobj,
710 struct md_object *tgt_pobj, struct md_object *sobj,
711 const char *sname, struct md_object *tobj, const char *tname)
713 struct mdd_device *mdd = mdo2mdd(src_pobj);
714 struct mdd_object *mdd_spobj = mdo2mddo(src_pobj);
715 struct mdd_object *mdd_tpobj = mdo2mddo(tgt_pobj);
716 struct mdd_object *mdd_sobj = mdo2mddo(sobj);
717 struct mdd_object *mdd_tobj = mdo2mddo(tobj);
719 struct thandle *handle;
721 mdd_txn_param_build(ctxt, &MDD_TXN_RENAME);
722 handle = mdd_trans_start(ctxt, mdd);
724 RETURN(PTR_ERR(handle));
726 mdd_rename_lock(mdd, mdd_spobj, mdd_tpobj, mdd_sobj, mdd_tobj);
728 rc = __mdd_index_delete(ctxt, mdd, mdd_spobj, mdd_sobj, sname, handle);
732 rc = __mdd_index_delete(ctxt, mdd, mdd_tpobj, mdd_tobj, tname, handle);
736 rc = __mdd_index_insert(ctxt, mdd_spobj, lu_object_fid(&tobj->mo_lu),
742 * XXX nikita: huh? What is this?
744 rc = __mdd_object_destroy(ctxt, mdd_sobj, handle);
748 mdd_rename_unlock(mdd, mdd_spobj, mdd_tpobj, mdd_sobj, mdd_tobj);
749 mdd_trans_stop(ctxt, mdd, handle);
753 static int mdd_lookup(struct lu_context *ctxt, struct md_object *pobj,
754 const char *name, struct lu_fid* fid)
756 struct dt_object *next = mdd_object_child(mdo2mddo(pobj));
758 return next->do_index_ops->dio_lookup(ctxt, next, fid, name);
761 static int mdd_mkdir(struct lu_context *ctxt, struct lu_attr* attr,
762 struct md_object *pobj, const char *name,
763 struct md_object *child)
765 struct mdd_device *mdd = mdo2mdd(pobj);
766 struct mdd_object *mdo = mdo2mddo(pobj);
767 struct thandle *handle;
771 mdd_txn_param_build(ctxt, &MDD_TXN_MKDIR);
772 handle = mdd_trans_start(ctxt, mdd);
774 RETURN(PTR_ERR(handle));
776 mdd_lock(ctxt, mdo, DT_WRITE_LOCK);
778 rc = __mdd_object_create(ctxt, mdo2mddo(child), attr, handle);
782 rc = __mdd_index_insert(ctxt, mdo, lu_object_fid(&child->mo_lu),
787 mdd_unlock(ctxt, mdo, DT_WRITE_LOCK);
788 mdd_trans_stop(ctxt, mdd, handle);
792 static int mdd_mkname(struct lu_context *ctxt, struct md_object *pobj,
793 const char *name, const struct lu_fid *fid, struct lu_attr *attr)
795 struct mdd_device *mdd = mdo2mdd(pobj);
796 struct mdd_object *mdo = mdo2mddo(pobj);
797 struct thandle *handle;
801 mdd_txn_param_build(ctxt, &MDD_TXN_INDEX_INSERT);
802 handle = mdd_trans_start(ctxt, mdd);
804 RETURN(PTR_ERR(handle));
806 mdd_lock(ctxt, mdo, DT_WRITE_LOCK);
808 rc = __mdd_index_insert(ctxt, mdo, fid, name, handle);
810 mdd_unlock(ctxt, mdo, DT_WRITE_LOCK);
811 mdd_trans_stop(ctxt, mdd, handle);
815 static int mdd_root_get(struct lu_context *ctx,
816 struct md_device *m, struct lu_fid *f)
818 struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
821 *f = mdd->mdd_root_fid;
825 static int mdd_config(struct lu_context *ctx, struct md_device *m,
826 const char *name, void *buf, int size, int mode)
828 struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
832 rc = mdd_child_ops(mdd)->dt_config(ctx, mdd->mdd_child,
833 name, buf, size, mode);
837 static int mdd_statfs(struct lu_context *ctx,
838 struct md_device *m, struct kstatfs *sfs) {
839 struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
844 rc = mdd_child_ops(mdd)->dt_statfs(ctx, mdd->mdd_child, sfs);
849 struct md_device_operations mdd_ops = {
850 .mdo_root_get = mdd_root_get,
851 .mdo_config = mdd_config,
852 .mdo_statfs = mdd_statfs,
855 static struct md_dir_operations mdd_dir_ops = {
856 .mdo_lookup = mdd_lookup,
857 .mdo_mkdir = mdd_mkdir,
858 .mdo_rename = mdd_rename,
859 .mdo_link = mdd_link,
860 .mdo_name_insert = mdd_mkname
863 static struct md_object_operations mdd_obj_ops = {
864 .moo_attr_get = mdd_attr_get,
865 .moo_attr_set = mdd_attr_set,
866 .moo_xattr_get = mdd_xattr_get,
867 .moo_xattr_set = mdd_xattr_set,
868 .moo_object_create = mdd_object_create
871 static struct obd_ops mdd_obd_device_ops = {
872 .o_owner = THIS_MODULE
875 struct lu_device *mdd_device_alloc(struct lu_context *ctx,
876 struct lu_device_type *t,
877 struct lustre_cfg *lcfg)
880 struct mdd_device *m;
884 l = ERR_PTR(-ENOMEM);
886 md_device_init(&m->mdd_md_dev, t);
888 l->ld_ops = &mdd_lu_ops;
889 m->mdd_md_dev.md_ops = &mdd_ops;
895 static void mdd_device_free(struct lu_context *ctx, struct lu_device *lu)
897 struct mdd_device *m = lu2mdd_dev(lu);
899 LASSERT(atomic_read(&lu->ld_ref) == 0);
900 md_device_fini(&m->mdd_md_dev);
905 static int mdd_type_init(struct lu_device_type *t)
907 return lu_context_key_register(&mdd_thread_key);
910 static void mdd_type_fini(struct lu_device_type *t)
912 lu_context_key_degister(&mdd_thread_key);
915 static struct lu_device_type_operations mdd_device_type_ops = {
916 .ldto_init = mdd_type_init,
917 .ldto_fini = mdd_type_fini,
919 .ldto_device_alloc = mdd_device_alloc,
920 .ldto_device_free = mdd_device_free,
922 .ldto_device_init = mdd_device_init,
923 .ldto_device_fini = mdd_device_fini
926 static struct lu_device_type mdd_device_type = {
927 .ldt_tags = LU_DEVICE_MD,
928 .ldt_name = LUSTRE_MDD0_NAME,
929 .ldt_ops = &mdd_device_type_ops
932 static void *mdd_key_init(struct lu_context *ctx)
934 struct mdd_thread_info *info;
938 info = ERR_PTR(-ENOMEM);
942 static void mdd_key_fini(struct lu_context *ctx, void *data)
944 struct mdd_thread_info *info = data;
948 static struct lu_context_key mdd_thread_key = {
949 .lct_init = mdd_key_init,
950 .lct_fini = mdd_key_fini
953 struct lprocfs_vars lprocfs_mdd_obd_vars[] = {
957 struct lprocfs_vars lprocfs_mdd_module_vars[] = {
961 LPROCFS_INIT_VARS(mdd, lprocfs_mdd_module_vars, lprocfs_mdd_obd_vars);
963 static int __init mdd_mod_init(void)
965 struct lprocfs_static_vars lvars;
967 lprocfs_init_vars(mdd, &lvars);
968 return class_register_type(&mdd_obd_device_ops, NULL, lvars.module_vars,
969 LUSTRE_MDD0_NAME, &mdd_device_type);
972 static void __exit mdd_mod_exit(void)
974 class_unregister_type(LUSTRE_MDD0_NAME);
977 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
978 MODULE_DESCRIPTION("Lustre Meta-data Device Prototype ("LUSTRE_MDD0_NAME")");
979 MODULE_LICENSE("GPL");
981 cfs_module(mdd, "0.0.2", mdd_mod_init, mdd_mod_exit);