Whamcloud - gitweb
f0c1bcc20f775a9999c2c606d92a007ccd86b9c7
[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 extern struct lu_device_type mdc_device_type;
97
98 /* add new MDC to the CMM, create MDC lu_device and connect it to mdc_obd */
99 static int cmm_add_mdc(struct lu_context *ctx,
100                        struct cmm_device * cm, struct lustre_cfg *cfg)
101 {
102         struct lu_device_type *ldt = &mdc_device_type;
103         struct lu_device *ld;
104         int rc;
105         ENTRY;
106
107         /*TODO check this MDC exists already */
108
109         ld = ldt->ldt_ops->ldto_device_alloc(ldt, cfg);
110
111         ld->ld_site = cmm2lu_dev(cm)->ld_site;
112
113         rc = ldt->ldt_ops->ldto_device_init(ctx, ld, NULL);
114         if (rc)
115                 ldt->ldt_ops->ldto_device_free(ld);
116
117         /* pass config to the just created MDC */
118         rc = ld->ld_ops->ldo_process_config(ctx, ld, cfg);
119         if (rc == 0) {
120                 struct mdc_device *mc = lu2mdc_dev(ld);
121                 list_add_tail(&mc->mc_linkage, &cm->cmm_targets);
122                 lu_device_get(cmm2lu_dev(cm));
123         }
124         RETURN(rc);
125 }
126
127
128 static int cmm_process_config(struct lu_context *ctx,
129                               struct lu_device *d, struct lustre_cfg *cfg)
130 {
131         struct cmm_device *m = lu2cmm_dev(d);
132         struct lu_device *next = md2lu_dev(m->cmm_child);
133         int err;
134
135         switch(cfg->lcfg_command) {
136         case LCFG_ADD_MDC:
137                 err = cmm_add_mdc(ctx, m, cfg);
138                 break;
139         case LCFG_SETUP:
140         {
141                 const char *index = lustre_cfg_string(cfg, 2);
142                 LASSERT(index);
143                 m->cmm_local_num = simple_strtol(index, NULL, 10);
144                 /* no break; to pass cfg further */
145         }
146         default:
147                 err = next->ld_ops->ldo_process_config(ctx, next, cfg);
148         }
149         RETURN(err);
150 }
151
152 static struct lu_device_operations cmm_lu_ops = {
153         .ldo_object_alloc   = cmm_object_alloc,
154         .ldo_object_free    = cmm_object_free,
155
156         .ldo_process_config = cmm_process_config
157 };
158
159 /* --- lu_device_type operations --- */
160
161 struct lu_device *cmm_device_alloc(struct lu_device_type *t,
162                                    struct lustre_cfg *cfg)
163 {
164         struct lu_device  *l;
165         struct cmm_device *m;
166
167         ENTRY;
168
169         OBD_ALLOC_PTR(m);
170         if (m == NULL) {
171                 l = ERR_PTR(-ENOMEM);
172         } else {
173                 md_device_init(&m->cmm_md_dev, t);
174                 m->cmm_md_dev.md_ops = &cmm_md_ops;
175                 l = cmm2lu_dev(m);
176                 l->ld_ops = &cmm_lu_ops;
177         }
178
179         EXIT;
180         return l;
181 }
182
183 void cmm_device_free(struct lu_device *d)
184 {
185         struct cmm_device *m = lu2cmm_dev(d);
186
187         LASSERT(atomic_read(&d->ld_ref) == 0);
188         md_device_fini(&m->cmm_md_dev);
189         OBD_FREE_PTR(m);
190 }
191
192 int cmm_type_init(struct lu_device_type *t)
193 {
194         return 0;
195 }
196
197 void cmm_type_fini(struct lu_device_type *t)
198 {
199         return;
200 }
201
202 static int cmm_device_init(struct lu_context *ctx,
203                            struct lu_device *d, struct lu_device *next)
204 {
205         struct cmm_device *m = lu2cmm_dev(d);
206         int err = 0;
207
208         ENTRY;
209
210         INIT_LIST_HEAD(&m->cmm_targets);
211         m->cmm_tgt_count = 0;
212         m->cmm_child = lu2md_dev(next);
213
214         RETURN(err);
215 }
216
217 static struct lu_device *cmm_device_fini(struct lu_context *ctx,
218                                          struct lu_device *ld)
219 {
220         struct cmm_device *cm = lu2cmm_dev(ld);
221         struct mdc_device *mc, *tmp;
222         ENTRY;
223
224         /* finish all mdc devices */
225         list_for_each_entry_safe(mc, tmp, &cm->cmm_targets, mc_linkage) {
226                 struct lu_device *ld_m = mdc2lu_dev(mc);
227
228                 list_del(&mc->mc_linkage);
229                 lu_device_put(cmm2lu_dev(cm));
230                 ld->ld_type->ldt_ops->ldto_device_fini(ctx, ld_m);
231                 ld->ld_type->ldt_ops->ldto_device_free(ld_m);
232         }
233
234         EXIT;
235         return md2lu_dev(cm->cmm_child);
236 }
237
238 static struct lu_device_type_operations cmm_device_type_ops = {
239         .ldto_init = cmm_type_init,
240         .ldto_fini = cmm_type_fini,
241
242         .ldto_device_alloc = cmm_device_alloc,
243         .ldto_device_free  = cmm_device_free,
244
245         .ldto_device_init = cmm_device_init,
246         .ldto_device_fini = cmm_device_fini
247 };
248
249 static struct lu_device_type cmm_device_type = {
250         .ldt_tags = LU_DEVICE_MD,
251         .ldt_name = LUSTRE_CMM0_NAME,
252         .ldt_ops  = &cmm_device_type_ops
253 };
254
255 struct lprocfs_vars lprocfs_cmm_obd_vars[] = {
256         { 0 }
257 };
258
259 struct lprocfs_vars lprocfs_cmm_module_vars[] = {
260         { 0 }
261 };
262
263 LPROCFS_INIT_VARS(cmm, lprocfs_cmm_module_vars, lprocfs_cmm_obd_vars);
264
265 static int __init cmm_mod_init(void)
266 {
267         struct lprocfs_static_vars lvars;
268
269         printk(KERN_INFO "Lustre: Clustered Metadata Manager; info@clusterfs.com\n");
270
271         lprocfs_init_vars(cmm, &lvars);
272         return class_register_type(&cmm_obd_device_ops, NULL, lvars.module_vars,
273                                    LUSTRE_CMM0_NAME, &cmm_device_type);
274 }
275
276 static void __exit cmm_mod_exit(void)
277 {
278         class_unregister_type(LUSTRE_CMM0_NAME);
279 }
280
281 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
282 MODULE_DESCRIPTION("Lustre Clustered Meta-data Manager Prototype ("LUSTRE_CMM0_NAME")");
283 MODULE_LICENSE("GPL");
284
285 cfs_module(cmm, "0.0.3", cmm_mod_init, cmm_mod_exit);