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