Whamcloud - gitweb
d8517b8d2ee670e2daa8dae4f97d7dd421a847e1
[fs/lustre-release.git] / lustre / obdclass / confobd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 #ifndef EXPORT_SYMTAB
22 # define EXPORT_SYMTAB
23 #endif
24 #define DEBUG_SUBSYSTEM S_CONFOBD
25
26 #include <linux/version.h>
27 #include <linux/init.h>
28 #include <linux/obd_support.h>
29 #include <linux/lustre_lib.h>
30 #include <linux/lustre_net.h>
31 #include <linux/lustre_idl.h>
32 #include <linux/lustre_log.h>
33 #include <linux/lustre_fsfilt.h>
34 #include <linux/obd_class.h>
35 #include <linux/lprocfs_status.h>
36
37 #define LUSTRE_CONFOBD_NAME "confobd"
38
39 static struct lprocfs_vars lprocfs_module_vars[] = { {0} };
40 static struct lprocfs_vars lprocfs_obd_vars[] = { {0} };
41
42 LPROCFS_INIT_VARS(confobd, lprocfs_module_vars, lprocfs_obd_vars)
43
44 static int confobd_fs_setup(struct obd_device *obd, 
45                             struct lvfs_obd_ctxt *lvfs_ctxt)
46 {
47         struct conf_obd *confobd = &obd->u.conf;
48         struct lvfs_run_ctxt saved;
49         struct dentry *dentry;
50         int rc = 0;
51         ENTRY;
52
53         OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
54         obd->obd_lvfs_ctxt.pwdmnt = lvfs_ctxt->loc_mnt;
55         obd->obd_lvfs_ctxt.pwd = lvfs_ctxt->loc_mnt->mnt_root;
56         obd->obd_lvfs_ctxt.fs = get_ds();
57         /*Now we did not set cb_ops of CONFOBD FIXME later*/ 
58         
59         /*setup llog ctxt*/
60         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
61         
62         dentry = simple_mkdir(current->fs->pwd, "LOGS", 0777, 1);
63         if (IS_ERR(dentry)) {
64                 rc = PTR_ERR(dentry);
65                 CERROR("cannot create LOGS directory: rc = %d\n", rc);
66                 GOTO(err_out, rc);
67         }
68         confobd->cfobd_logs_dir = dentry;
69
70         dentry = simple_mkdir(current->fs->pwd, "OBJECTS", 0777, 1);
71         if (IS_ERR(dentry)) {
72                 rc = PTR_ERR(dentry);
73                 CERROR("cannot create OBJECTS directory: rc = %d\n", rc);
74                 GOTO(err_logs, rc);
75         }
76         confobd->cfobd_objects_dir = dentry;
77
78         dentry = simple_mkdir(current->fs->pwd, "PENDING", 0777, 1);
79         if (IS_ERR(dentry)) {
80                 rc = PTR_ERR(dentry);
81                 CERROR("cannot create PENDING directory: rc = %d\n", rc);
82                 GOTO(err_logs, rc);
83         }
84         confobd->cfobd_pending_dir = dentry;
85
86 err_logs:
87         if (rc) 
88                l_dput(confobd->cfobd_logs_dir);
89 err_out:
90         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
91         RETURN(rc);
92 }
93  
94 static int confobd_fs_cleanup(struct obd_device *obd, int flags)
95 {
96         struct conf_obd *confobd = &obd->u.conf;
97         struct lvfs_run_ctxt saved;
98         int rc = 0;
99         ENTRY;
100
101         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
102         if (confobd->cfobd_logs_dir != NULL) {
103                 l_dput(confobd->cfobd_logs_dir);
104                 confobd->cfobd_logs_dir = NULL; 
105         }
106         if (confobd->cfobd_objects_dir != NULL) {
107                 l_dput(confobd->cfobd_objects_dir);
108                 confobd->cfobd_objects_dir = NULL; 
109         }
110         if (confobd->cfobd_pending_dir != NULL) {
111                 l_dput(confobd->cfobd_pending_dir);
112                 confobd->cfobd_pending_dir = NULL;
113         }
114
115         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
116         RETURN(rc);
117 }
118
119 int confobd_attach(struct obd_device *dev, obd_count len, void *data)
120 {
121         struct lprocfs_static_vars lvars;
122         int rc = 0;
123         ENTRY;
124
125         lprocfs_init_vars(confobd, &lvars);
126         rc = lprocfs_obd_attach(dev, lvars.obd_vars);
127         if (rc)
128                 RETURN(rc);
129
130         rc = lprocfs_alloc_md_stats(dev, 0);
131         RETURN(rc);
132 }
133
134 int confobd_detach(struct obd_device *dev)
135 {
136         int rc;
137         ENTRY;
138         
139         lprocfs_free_md_stats(dev);
140         rc = lprocfs_obd_detach(dev);
141         RETURN(rc);
142 }
143
144 static int confobd_setup(struct obd_device *obd, obd_count len, void *buf)
145 {
146         struct conf_obd *confobd = &obd->u.conf;
147         struct lustre_cfg* lcfg = buf;
148         struct lvfs_obd_ctxt *lvfs_ctxt = NULL;
149         char *name = NULL;
150         char *fstype = NULL;
151         char *mountoption = NULL;
152         int rc = 0;
153         ENTRY;
154
155         if (lcfg->lcfg_inllen1 < 1 || !lcfg->lcfg_inlbuf1) {
156                 CERROR("CONFOBD setup requires device name\n");
157                 RETURN(-EINVAL);
158         }
159         if (lcfg->lcfg_inllen2 < 1 || !lcfg->lcfg_inlbuf2) {
160                 CERROR("CONFOBD setup requires fstype\n");
161                 RETURN(-EINVAL);
162         }
163
164         OBD_ALLOC(name, lcfg->lcfg_inllen1 + 1);
165         if (!name) {
166                 CERROR("No Memory\n");
167                 GOTO(out, rc = -ENOMEM);
168         }
169         memcpy(name, lcfg->lcfg_inlbuf1, lcfg->lcfg_inllen1);
170
171         OBD_ALLOC(fstype, lcfg->lcfg_inllen2 + 1);
172         if (!fstype) {
173                 CERROR("No Memory\n");
174                 GOTO(out, rc = -ENOMEM);
175         }
176         memcpy(fstype, lcfg->lcfg_inlbuf2, lcfg->lcfg_inllen2);
177
178         obd->obd_fsops = fsfilt_get_ops(fstype);
179         if (IS_ERR(obd->obd_fsops)) {
180                CERROR("No fstype %s rc=%ld\n", fstype, PTR_ERR(obd->obd_fsops));
181                GOTO(err_ops, rc = PTR_ERR(obd->obd_fsops));
182         }
183
184         if (lcfg->lcfg_inllen3 >= 1 && lcfg->lcfg_inlbuf3) {
185                 OBD_ALLOC(mountoption, lcfg->lcfg_inllen3 + 1);
186                 if (!mountoption) {
187                         CERROR("No Memory\n");
188                         GOTO(err_ops, rc = -ENOMEM);
189                 }
190                 memcpy(mountoption, lcfg->lcfg_inlbuf3, lcfg->lcfg_inllen3); 
191         }
192         rc = lvfs_mount_fs(name, fstype, mountoption, 0, &lvfs_ctxt);
193         if (rc)
194                 GOTO(err_ops, rc);
195         LASSERT(lvfs_ctxt);
196
197         confobd->cfobd_lvfs_ctxt = lvfs_ctxt;
198
199         rc = confobd_fs_setup(obd, lvfs_ctxt);
200         if (rc)
201                 GOTO(err_ops, rc);
202
203         rc = obd_llog_setup(obd, &obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT, 
204                             obd, 0, NULL, &llog_lvfs_ops);
205         if (rc)
206                 GOTO(err_ops, rc);
207
208         EXIT;
209 out:
210         if (rc && lvfs_ctxt)
211                 lvfs_umount_fs(lvfs_ctxt);
212         if (name)
213                 OBD_FREE(name, lcfg->lcfg_inllen1 + 1);
214         if (fstype)
215                 OBD_FREE(fstype, lcfg->lcfg_inllen2 + 1);
216         if (mountoption)
217                 OBD_FREE(mountoption, lcfg->lcfg_inllen3 + 1);
218
219         return rc;
220 err_ops:
221         fsfilt_put_ops(obd->obd_fsops);
222         goto out;
223 }
224
225 static int confobd_cleanup(struct obd_device *obd, int flags)
226 {
227         struct conf_obd *confobd = &obd->u.conf;
228         ENTRY;
229
230         /* stop recording any log in case lconf didn't do that for us */
231         if (confobd->cfobd_cfg_llh) {
232                 struct lvfs_run_ctxt saved;
233                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
234                 llog_close(confobd->cfobd_cfg_llh);
235                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
236         }
237
238         obd_llog_cleanup(llog_get_context(&obd->obd_llogs, 
239                                           LLOG_CONFIG_ORIG_CTXT));
240         confobd_fs_cleanup(obd, flags);
241         if (confobd->cfobd_lvfs_ctxt)
242                 lvfs_umount_fs(confobd->cfobd_lvfs_ctxt);
243
244         if (!list_empty(&obd->obd_exports))
245                 return (-EBUSY);
246         fsfilt_put_ops(obd->obd_fsops);
247         RETURN(0);
248 }
249
250 static int confobd_iocontrol(unsigned int cmd, struct obd_export *exp, 
251                              int len, void *karg, void *uarg)
252 {
253         static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
254         struct obd_device *obd = exp->exp_obd;
255         struct conf_obd *confobd = &obd->u.conf;
256         struct obd_ioctl_data *data = karg;
257         struct lvfs_run_ctxt saved;
258         int rc = 0;
259         ENTRY;
260
261         CDEBUG(D_INFO, "ioctl cmd %x\n", cmd);
262         switch (cmd) {
263         case OBD_IOC_CLEAR_LOG: {
264                 char *name = data->ioc_inlbuf1;
265                 if (confobd->cfobd_cfg_llh)
266                         RETURN(-EBUSY);
267
268                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
269                 rc = llog_open(llog_get_context(&obd->obd_llogs, 
270                                                 LLOG_CONFIG_ORIG_CTXT),
271                                &confobd->cfobd_cfg_llh, NULL, name,
272                                OBD_LLOG_FL_CREATE);
273                 if (rc == 0) {
274                         llog_init_handle(confobd->cfobd_cfg_llh,
275                                          LLOG_F_IS_PLAIN, NULL);
276
277                         rc = llog_destroy(confobd->cfobd_cfg_llh);
278                         llog_free_handle(confobd->cfobd_cfg_llh);
279                 }
280                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
281
282                 confobd->cfobd_cfg_llh = NULL;
283                 RETURN(rc);
284         }
285         case OBD_IOC_RECORD: {
286                 char *name = data->ioc_inlbuf1;
287                 if (confobd->cfobd_cfg_llh)
288                         RETURN(-EBUSY);
289
290                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
291                 rc = llog_open(llog_get_context(&obd->obd_llogs, 
292                                                 LLOG_CONFIG_ORIG_CTXT),
293                                &confobd->cfobd_cfg_llh, NULL, name,
294                                OBD_LLOG_FL_CREATE);
295                 if (rc == 0)
296                         llog_init_handle(confobd->cfobd_cfg_llh,
297                                          LLOG_F_IS_PLAIN, &cfg_uuid);
298                 else
299                         confobd->cfobd_cfg_llh = NULL;
300                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
301
302                 RETURN(rc);
303         }
304         case OBD_IOC_ENDRECORD: {
305                 if (!confobd->cfobd_cfg_llh)
306                         RETURN(-EBADF);
307
308                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
309                 rc = llog_close(confobd->cfobd_cfg_llh);
310                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
311
312                 confobd->cfobd_cfg_llh = NULL;
313                 RETURN(rc);
314         }
315         case OBD_IOC_DORECORD: {
316                 char *cfg_buf;
317                 struct llog_rec_hdr rec;
318                 if (!confobd->cfobd_cfg_llh)
319                         RETURN(-EBADF);
320
321                 rec.lrh_len = llog_data_len(data->ioc_plen1);
322
323                 switch(data->ioc_type) {
324                 case LUSTRE_CFG_TYPE:
325                         rec.lrh_type = OBD_CFG_REC;
326                         break;
327                 case PORTALS_CFG_TYPE:
328                         rec.lrh_type = PTL_CFG_REC;
329                         break;
330                 default:
331                         CERROR("unknown cfg record type:%d \n", data->ioc_type);
332                         RETURN(-EINVAL);
333                 }
334
335                 OBD_ALLOC(cfg_buf, data->ioc_plen1);
336                 if (cfg_buf == NULL) {
337                         CERROR("No Memory\n");
338                         RETURN(-ENOMEM);
339                 }
340                 if (copy_from_user(cfg_buf, data->ioc_pbuf1, data->ioc_plen1)) {
341                         OBD_FREE(cfg_buf, data->ioc_plen1);
342                         RETURN(-EFAULT);
343                 }
344
345                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
346                 rc = llog_write_rec(confobd->cfobd_cfg_llh, &rec, NULL, 0,
347                                     cfg_buf, -1);
348                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
349
350                 OBD_FREE(cfg_buf, data->ioc_plen1);
351                 RETURN(rc);
352         }
353         case OBD_IOC_DUMP_LOG: {
354                 struct llog_ctxt *ctxt =
355                         llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
356                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
357                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
358                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
359                 if (rc)
360                         RETURN(rc);
361
362                 RETURN(rc);
363         }
364
365         case OBD_IOC_START: {
366                 struct llog_ctxt *ctxt;
367                 char *conf_prof;
368                 char *name = data->ioc_inlbuf1;
369                 int len = strlen(name) + sizeof("-conf");
370
371                 OBD_ALLOC(conf_prof, len);
372                 if (!conf_prof) {
373                         CERROR("no memory\n");
374                         RETURN(-ENOMEM);
375                 }
376                 sprintf(conf_prof, "%s-conf", name);
377
378                 ctxt = llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
379                 rc = class_config_process_llog(ctxt, conf_prof, NULL);
380                 if (rc < 0)
381                         CERROR("Unable to process log: %s\n", conf_prof);
382                 OBD_FREE(conf_prof, len);
383
384                 RETURN(rc);
385         }
386
387         default:
388                 CDEBUG(D_INFO, "unknown command %x\n", cmd);
389                 RETURN(-EINVAL);
390         }
391         RETURN(0);
392 }
393
394 static struct obd_ops conf_obd_ops = {
395         .o_owner         = THIS_MODULE,
396         .o_setup         = confobd_setup,
397         .o_cleanup       = confobd_cleanup,
398         .o_attach        = confobd_attach,
399         .o_detach        = confobd_detach,
400         .o_iocontrol     = confobd_iocontrol,
401 };
402
403 static int __init confobd_init(void)
404 {
405         struct lprocfs_static_vars lvars;
406         ENTRY;
407
408         lprocfs_init_vars(confobd, &lvars);
409         RETURN(class_register_type(&conf_obd_ops, NULL, lvars.module_vars,
410                                    LUSTRE_CONFOBD_NAME));
411 }
412
413 static void __exit confobd_exit(void)
414 {
415         class_unregister_type(LUSTRE_CONFOBD_NAME);
416 }
417
418 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
419 MODULE_DESCRIPTION("Lustre Config OBD driver");
420 MODULE_LICENSE("GPL");
421
422 module_init(confobd_init);
423 module_exit(confobd_exit);