Whamcloud - gitweb
cb448b2af48217c6b3caade800d165b820e8849c
[fs/lustre-release.git] / lustre / cmm / cmm_device.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/cmm/cmm_device.c
5  *  Lustre Cluster Metadata Manager (cmm)
6  *
7  *  Copyright (c) 2006 Cluster File Systems, Inc.
8  *   Author: Mike Pershin <tappro@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 #include <linux/obd.h>
37 #include <linux/obd_class.h>
38
39 #include "cmm_internal.h"
40 #include "mdc_internal.h"
41
42 #include <linux/lprocfs_status.h>
43 #include <linux/lustre_ver.h>
44
45 static struct obd_ops cmm_obd_device_ops = {
46         .o_owner           = THIS_MODULE
47 };
48
49 static struct lu_device_operations cmm_lu_ops;
50
51 static inline int lu_device_is_cmm(struct lu_device *d)
52 {
53         /*
54          * XXX for now. Tags in lu_device_type->ldt_something are needed.
55          */
56         return ergo(d != NULL && d->ld_ops != NULL, d->ld_ops == &cmm_lu_ops);
57 }
58
59 int cmm_root_get(struct lu_context *ctx, struct md_device *md,
60                  struct lu_fid *fid)
61 {
62         struct cmm_device *cmm_dev = md2cmm_dev(md);
63
64         return cmm_child_ops(cmm_dev)->mdo_root_get(ctx,
65                                                     cmm_dev->cmm_child, fid);
66 }
67
68 int cmm_config(struct lu_context *ctxt, struct md_device *md,
69                const char *name, void *buf, int size, int mode)
70 {
71         struct cmm_device *cmm_dev = md2cmm_dev(md);
72         int rc;
73         ENTRY;
74         rc = cmm_child_ops(cmm_dev)->mdo_config(ctxt, cmm_dev->cmm_child,
75                                                     name, buf, size, mode);
76         RETURN(rc);
77 }
78
79 int cmm_statfs(struct lu_context *ctxt, struct md_device *md,
80                struct kstatfs *sfs) {
81         struct cmm_device *cmm_dev = md2cmm_dev(md);
82         int rc;
83
84         ENTRY;
85         rc = cmm_child_ops(cmm_dev)->mdo_statfs(ctxt,
86                                                     cmm_dev->cmm_child, sfs);
87         RETURN (rc);
88 }
89
90 static struct md_device_operations cmm_md_ops = {
91         .mdo_root_get       = cmm_root_get,
92         .mdo_config         = cmm_config,
93         .mdo_statfs         = cmm_statfs,
94 };
95
96 /* add new MDC to the CMM, create MDC lu_device and connect it to mdc_obd */
97 static int cmm_add_mdc(struct cmm_device * cm, struct lustre_cfg *cfg)
98 {
99         struct lu_device_type *ldt;
100         struct lu_device *ld;
101         struct obd_device *obd;
102         const char *name = lustre_cfg_string(cfg, 1);
103         int rc;
104         ENTRY;
105         
106         /*TODO check this MDC exists already */
107         obd = class_name2obd(name);
108         if (obd) {
109                 ld = obd->obd_lu_dev;
110         } else {
111                 RETURN(-ENOENT);
112         }
113         
114         ldt = ld->ld_type;
115         ld->ld_site = cmm2lu_dev(cm)->ld_site;
116
117         rc = ldt->ldt_ops->ldto_device_init(ld, NULL);
118         if (rc)
119                 ldt->ldt_ops->ldto_device_free(ld);
120
121         /* pass config to the just created MDC */
122         rc = ld->ld_ops->ldo_process_config(ld, cfg);
123         if (rc == 0) {
124                 struct mdc_device *mc = lu2mdc_dev(ld);
125                 list_add_tail(&mc->mc_linkage, &cm->cmm_targets);
126                 lu_device_get(cmm2lu_dev(cm));
127         }
128         RETURN(rc);
129 }
130
131
132 static int cmm_process_config(struct lu_device *d, struct lustre_cfg *cfg)
133 {
134         struct cmm_device *m = lu2cmm_dev(d);
135         struct lu_device *next = md2lu_dev(m->cmm_child);
136         int err;
137
138         switch(cfg->lcfg_command) {
139         case LCFG_ADD_MDC:
140                 err = cmm_add_mdc(m, cfg);
141                 break;
142         default:
143                 err = next->ld_ops->ldo_process_config(next, cfg);
144         }
145         RETURN(err);
146 }
147
148 static struct lu_device_operations cmm_lu_ops = {
149         .ldo_object_alloc   = cmm_object_alloc,
150         .ldo_object_free    = cmm_object_free,
151
152         .ldo_process_config = cmm_process_config
153 };
154
155 /* --- lu_device_type operations --- */
156
157 struct lu_device *cmm_device_alloc(struct lu_device_type *t,
158                                    struct lustre_cfg *cfg)
159 {
160         struct lu_device  *l;
161         struct cmm_device *m;
162
163         ENTRY;
164
165         OBD_ALLOC_PTR(m);
166         if (m == NULL) {
167                 l = ERR_PTR(-ENOMEM);
168         } else {
169                 md_device_init(&m->cmm_md_dev, t);
170                 m->cmm_md_dev.md_ops = &cmm_md_ops;
171                 l = cmm2lu_dev(m);
172                 l->ld_ops = &cmm_lu_ops;
173         }
174
175         EXIT;
176         return l;
177 }
178
179 void cmm_device_free(struct lu_device *d)
180 {
181         struct cmm_device *m = lu2cmm_dev(d);
182
183         LASSERT(atomic_read(&d->ld_ref) == 0);
184         md_device_fini(&m->cmm_md_dev);
185         OBD_FREE_PTR(m);
186 }
187
188 int cmm_type_init(struct lu_device_type *t)
189 {
190         return 0;
191 }
192
193 void cmm_type_fini(struct lu_device_type *t)
194 {
195         return;
196 }
197
198 static int cmm_device_init(struct lu_device *d, struct lu_device *next)
199 {
200         struct cmm_device *m = lu2cmm_dev(d);
201         int err = 0;
202
203         ENTRY;
204
205         INIT_LIST_HEAD(&m->cmm_targets);
206         m->cmm_tgt_count = 0;
207         m->cmm_child = lu2md_dev(next);
208
209         RETURN(err);
210 }
211
212 static struct lu_device *cmm_device_fini(struct lu_device *ld)
213 {
214         struct cmm_device *cm = lu2cmm_dev(ld);
215         struct mdc_device *mc, *tmp;
216         ENTRY;
217         
218         /* finish all mdc devices */
219         list_for_each_entry_safe(mc, tmp, &cm->cmm_targets, mc_linkage) {
220                 struct lu_device *ld_m = mdc2lu_dev(mc);
221
222                 list_del(&mc->mc_linkage);
223                 lu_device_put(cmm2lu_dev(cm));
224                 ld->ld_type->ldt_ops->ldto_device_fini(ld_m);
225                 ld->ld_type->ldt_ops->ldto_device_free(ld_m);
226         }
227
228         EXIT;
229         return md2lu_dev(cm->cmm_child);
230 }
231
232 static struct lu_device_type_operations cmm_device_type_ops = {
233         .ldto_init = cmm_type_init,
234         .ldto_fini = cmm_type_fini,
235
236         .ldto_device_alloc = cmm_device_alloc,
237         .ldto_device_free  = cmm_device_free,
238
239         .ldto_device_init = cmm_device_init,
240         .ldto_device_fini = cmm_device_fini
241 };
242
243 static struct lu_device_type cmm_device_type = {
244         .ldt_tags = LU_DEVICE_MD,
245         .ldt_name = LUSTRE_CMM0_NAME,
246         .ldt_ops  = &cmm_device_type_ops
247 };
248
249 struct lprocfs_vars lprocfs_cmm_obd_vars[] = {
250         { 0 }
251 };
252
253 struct lprocfs_vars lprocfs_cmm_module_vars[] = {
254         { 0 }
255 };
256
257 LPROCFS_INIT_VARS(cmm, lprocfs_cmm_module_vars, lprocfs_cmm_obd_vars);
258
259 static int __init cmm_mod_init(void)
260 {
261         struct lprocfs_static_vars lvars;
262
263         printk(KERN_INFO "Lustre: Clustered Metadata Manager; info@clusterfs.com\n");
264
265         lprocfs_init_vars(cmm, &lvars);
266         return class_register_type(&cmm_obd_device_ops, NULL, lvars.module_vars,
267                                    LUSTRE_CMM0_NAME, &cmm_device_type);
268 }
269
270 static void __exit cmm_mod_exit(void)
271 {
272         class_unregister_type(LUSTRE_CMM0_NAME);
273 }
274
275 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
276 MODULE_DESCRIPTION("Lustre Clustered Meta-data Manager Prototype ("LUSTRE_CMM0_NAME")");
277 MODULE_LICENSE("GPL");
278
279 cfs_module(cmm, "0.0.3", cmm_mod_init, cmm_mod_exit);