Whamcloud - gitweb
6baeb7ffef112ea9ea1969c754d735d9dde9caa4
[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 (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
156             lustre_cfg_buf(lcfg, 1) == NULL) { 
157                 CERROR("CONFOBD setup requires device name\n");
158                 RETURN(-EINVAL);
159         }
160         if (LUSTRE_CFG_BUFLEN(lcfg, 2) < 1 ||
161             lustre_cfg_buf(lcfg, 2) == NULL) { 
162                 CERROR("CONFOBD setup requires fstype\n");
163                 RETURN(-EINVAL);
164         }
165
166         OBD_ALLOC(name, LUSTRE_CFG_BUFLEN(lcfg, 1));
167         if (!name) {
168                 CERROR("No Memory\n");
169                 GOTO(out, rc = -ENOMEM);
170         }
171         memcpy(name, lustre_cfg_string(lcfg, 1), LUSTRE_CFG_BUFLEN(lcfg, 1));
172
173         OBD_ALLOC(fstype, LUSTRE_CFG_BUFLEN(lcfg, 2));
174         if (!fstype) {
175                 CERROR("No Memory\n");
176                 GOTO(out, rc = -ENOMEM);
177         }
178         memcpy(fstype, lustre_cfg_string(lcfg, 2), 
179                LUSTRE_CFG_BUFLEN(lcfg, 2));
180
181         obd->obd_fsops = fsfilt_get_ops(fstype);
182         if (IS_ERR(obd->obd_fsops)) {
183                CERROR("No fstype %s rc=%ld\n", fstype, PTR_ERR(obd->obd_fsops));
184                GOTO(err_ops, rc = PTR_ERR(obd->obd_fsops));
185         }
186
187         if (LUSTRE_CFG_BUFLEN(lcfg, 3) >= 1 && lustre_cfg_buf(lcfg, 3)) {
188                 OBD_ALLOC(mountoption, LUSTRE_CFG_BUFLEN(lcfg, 3));
189                 if (!mountoption) {
190                         CERROR("No Memory\n");
191                         GOTO(err_ops, rc = -ENOMEM);
192                 }
193                 memcpy(mountoption, lustre_cfg_string(lcfg, 3), 
194                        LUSTRE_CFG_BUFLEN(lcfg, 3)); 
195         }
196         rc = lvfs_mount_fs(name, fstype, mountoption, 0, &lvfs_ctxt);
197         if (rc)
198                 GOTO(err_ops, rc);
199         LASSERT(lvfs_ctxt);
200
201         confobd->cfobd_lvfs_ctxt = lvfs_ctxt;
202
203         rc = confobd_fs_setup(obd, lvfs_ctxt);
204         if (rc)
205                 GOTO(err_ops, rc);
206
207         rc = obd_llog_setup(obd, &obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT, 
208                             obd, 0, NULL, &llog_lvfs_ops);
209         if (rc)
210                 GOTO(err_ops, rc);
211
212         EXIT;
213 out:
214         if (rc && lvfs_ctxt)
215                 lvfs_umount_fs(lvfs_ctxt);
216         if (name)
217                 OBD_FREE(name, LUSTRE_CFG_BUFLEN(lcfg, 1));
218         if (fstype)
219                 OBD_FREE(fstype, LUSTRE_CFG_BUFLEN(lcfg, 2));
220         if (mountoption)
221                 OBD_FREE(mountoption, LUSTRE_CFG_BUFLEN(lcfg, 3));
222
223         return rc;
224 err_ops:
225         fsfilt_put_ops(obd->obd_fsops);
226         goto out;
227 }
228
229 static int confobd_cleanup(struct obd_device *obd, int flags)
230 {
231         struct conf_obd *confobd = &obd->u.conf;
232         ENTRY;
233
234         /* stop recording any log in case lconf didn't do that for us */
235         if (confobd->cfobd_cfg_llh) {
236                 struct lvfs_run_ctxt saved;
237                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
238                 llog_close(confobd->cfobd_cfg_llh);
239                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
240         }
241
242         obd_llog_cleanup(llog_get_context(&obd->obd_llogs, 
243                                           LLOG_CONFIG_ORIG_CTXT));
244         confobd_fs_cleanup(obd, flags);
245         if (confobd->cfobd_lvfs_ctxt)
246                 lvfs_umount_fs(confobd->cfobd_lvfs_ctxt);
247
248         if (!list_empty(&obd->obd_exports))
249                 return (-EBUSY);
250         fsfilt_put_ops(obd->obd_fsops);
251         RETURN(0);
252 }
253
254 static int confobd_iocontrol(unsigned int cmd, struct obd_export *exp, 
255                              int len, void *karg, void *uarg)
256 {
257         static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
258         struct obd_device *obd = exp->exp_obd;
259         struct conf_obd *confobd = &obd->u.conf;
260         struct obd_ioctl_data *data = karg;
261         struct lvfs_run_ctxt saved;
262         int rc = 0;
263         ENTRY;
264
265         CDEBUG(D_INFO, "ioctl cmd %x\n", cmd);
266         switch (cmd) {
267         case OBD_IOC_CLEAR_LOG: {
268                 char *name = data->ioc_inlbuf1;
269                 if (confobd->cfobd_cfg_llh)
270                         RETURN(-EBUSY);
271
272                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
273                 rc = llog_open(llog_get_context(&obd->obd_llogs, 
274                                                 LLOG_CONFIG_ORIG_CTXT),
275                                &confobd->cfobd_cfg_llh, NULL, name,
276                                OBD_LLOG_FL_CREATE);
277                 if (rc == 0) {
278                         llog_init_handle(confobd->cfobd_cfg_llh,
279                                          LLOG_F_IS_PLAIN, NULL);
280
281                         rc = llog_destroy(confobd->cfobd_cfg_llh);
282                         llog_free_handle(confobd->cfobd_cfg_llh);
283                 }
284                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
285
286                 confobd->cfobd_cfg_llh = NULL;
287                 RETURN(rc);
288         }
289         case OBD_IOC_RECORD: {
290                 char *name = data->ioc_inlbuf1;
291                 if (confobd->cfobd_cfg_llh)
292                         RETURN(-EBUSY);
293
294                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
295                 rc = llog_open(llog_get_context(&obd->obd_llogs, 
296                                                 LLOG_CONFIG_ORIG_CTXT),
297                                &confobd->cfobd_cfg_llh, NULL, name,
298                                OBD_LLOG_FL_CREATE);
299                 if (rc == 0)
300                         llog_init_handle(confobd->cfobd_cfg_llh,
301                                          LLOG_F_IS_PLAIN, &cfg_uuid);
302                 else
303                         confobd->cfobd_cfg_llh = NULL;
304                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
305
306                 RETURN(rc);
307         }
308         case OBD_IOC_ENDRECORD: {
309                 if (!confobd->cfobd_cfg_llh)
310                         RETURN(-EBADF);
311
312                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
313                 rc = llog_close(confobd->cfobd_cfg_llh);
314                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
315
316                 confobd->cfobd_cfg_llh = NULL;
317                 RETURN(rc);
318         }
319         case OBD_IOC_DORECORD: {
320                 char *cfg_buf;
321                 struct llog_rec_hdr rec;
322                 if (!confobd->cfobd_cfg_llh)
323                         RETURN(-EBADF);
324
325                 rec.lrh_len = llog_data_len(data->ioc_plen1);
326
327                 switch(data->ioc_type) {
328                 case LUSTRE_CFG_TYPE:
329                         rec.lrh_type = OBD_CFG_REC;
330                         break;
331                 case PORTALS_CFG_TYPE:
332                         rec.lrh_type = PTL_CFG_REC;
333                         break;
334                 default:
335                         CERROR("unknown cfg record type:%d \n", data->ioc_type);
336                         RETURN(-EINVAL);
337                 }
338
339                 OBD_ALLOC(cfg_buf, data->ioc_plen1);
340                 if (cfg_buf == NULL) {
341                         CERROR("No Memory\n");
342                         RETURN(-ENOMEM);
343                 }
344                 if (copy_from_user(cfg_buf, data->ioc_pbuf1, data->ioc_plen1)) {
345                         OBD_FREE(cfg_buf, data->ioc_plen1);
346                         RETURN(-EFAULT);
347                 }
348
349                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
350                 rc = llog_write_rec(confobd->cfobd_cfg_llh, &rec, NULL, 0,
351                                     cfg_buf, -1);
352                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
353
354                 OBD_FREE(cfg_buf, data->ioc_plen1);
355                 RETURN(rc);
356         }
357         case OBD_IOC_DUMP_LOG: {
358                 struct llog_ctxt *ctxt =
359                         llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
360                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
361                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
362                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
363                 if (rc)
364                         RETURN(rc);
365
366                 RETURN(rc);
367         }
368
369         case OBD_IOC_START: {
370                 struct llog_ctxt *ctxt;
371                 char *conf_prof;
372                 char *name = data->ioc_inlbuf1;
373                 int len = strlen(name) + sizeof("-conf");
374
375                 OBD_ALLOC(conf_prof, len);
376                 if (!conf_prof) {
377                         CERROR("no memory\n");
378                         RETURN(-ENOMEM);
379                 }
380                 sprintf(conf_prof, "%s-conf", name);
381
382                 ctxt = llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
383                 rc = class_config_process_llog(ctxt, conf_prof, NULL);
384                 if (rc < 0)
385                         CERROR("Unable to process log: %s\n", conf_prof);
386                 OBD_FREE(conf_prof, len);
387
388                 RETURN(rc);
389         }
390
391         default:
392                 CDEBUG(D_INFO, "unknown command %x\n", cmd);
393                 RETURN(-EINVAL);
394         }
395         RETURN(0);
396 }
397
398 static struct obd_ops conf_obd_ops = {
399         .o_owner         = THIS_MODULE,
400         .o_setup         = confobd_setup,
401         .o_cleanup       = confobd_cleanup,
402         .o_attach        = confobd_attach,
403         .o_detach        = confobd_detach,
404         .o_iocontrol     = confobd_iocontrol,
405 };
406
407 static int __init confobd_init(void)
408 {
409         struct lprocfs_static_vars lvars;
410         ENTRY;
411
412         lprocfs_init_vars(confobd, &lvars);
413         RETURN(class_register_type(&conf_obd_ops, NULL, lvars.module_vars,
414                                    LUSTRE_CONFOBD_NAME));
415 }
416
417 static void __exit confobd_exit(void)
418 {
419         class_unregister_type(LUSTRE_CONFOBD_NAME);
420 }
421
422 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
423 MODULE_DESCRIPTION("Lustre Config OBD driver");
424 MODULE_LICENSE("GPL");
425
426 module_init(confobd_init);
427 module_exit(confobd_exit);