Whamcloud - gitweb
current branches now use lnet from HEAD
[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 static struct lprocfs_vars lprocfs_module_vars[] = { {0} };
38 static struct lprocfs_vars lprocfs_obd_vars[] = { {0} };
39
40 LPROCFS_INIT_VARS(confobd, lprocfs_module_vars, lprocfs_obd_vars)
41
42 static int confobd_fs_setup(struct obd_device *obd, 
43                             struct lvfs_obd_ctxt *lvfs_ctxt)
44 {
45         struct conf_obd *confobd = &obd->u.conf;
46         struct lvfs_run_ctxt saved;
47         struct dentry *dentry;
48         int rc = 0;
49         ENTRY;
50
51         OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
52         obd->obd_lvfs_ctxt.pwdmnt = lvfs_ctxt->loc_mnt;
53         obd->obd_lvfs_ctxt.pwd = lvfs_ctxt->loc_mnt->mnt_root;
54         obd->obd_lvfs_ctxt.fs = get_ds();
55         /*Now we did not set cb_ops of CONFOBD FIXME later*/ 
56         
57         /*setup llog ctxt*/
58         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
59         
60         dentry = simple_mkdir(current->fs->pwd, "LOGS", 0777, 1);
61         if (IS_ERR(dentry)) {
62                 rc = PTR_ERR(dentry);
63                 CERROR("cannot create LOGS directory: rc = %d\n", rc);
64                 GOTO(err_out, rc);
65         }
66         confobd->cfobd_logs_dir = dentry;
67
68         dentry = simple_mkdir(current->fs->pwd, "OBJECTS", 0777, 1);
69         if (IS_ERR(dentry)) {
70                 rc = PTR_ERR(dentry);
71                 CERROR("cannot create OBJECTS directory: rc = %d\n", rc);
72                 GOTO(err_logs, rc);
73         }
74         confobd->cfobd_objects_dir = dentry;
75
76         dentry = simple_mkdir(current->fs->pwd, "PENDING", 0777, 1);
77         if (IS_ERR(dentry)) {
78                 rc = PTR_ERR(dentry);
79                 CERROR("cannot create PENDING directory: rc = %d\n", rc);
80                 GOTO(err_logs, rc);
81         }
82         confobd->cfobd_pending_dir = dentry;
83
84 err_logs:
85         if (rc) 
86                l_dput(confobd->cfobd_logs_dir);
87 err_out:
88         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
89         RETURN(rc);
90 }
91  
92 static int confobd_fs_cleanup(struct obd_device *obd, int flags)
93 {
94         struct conf_obd *confobd = &obd->u.conf;
95         struct lvfs_run_ctxt saved;
96         int rc = 0;
97         ENTRY;
98
99         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
100         if (confobd->cfobd_logs_dir != NULL) {
101                 l_dput(confobd->cfobd_logs_dir);
102                 confobd->cfobd_logs_dir = NULL; 
103         }
104         if (confobd->cfobd_objects_dir != NULL) {
105                 l_dput(confobd->cfobd_objects_dir);
106                 confobd->cfobd_objects_dir = NULL; 
107         }
108         if (confobd->cfobd_pending_dir != NULL) {
109                 l_dput(confobd->cfobd_pending_dir);
110                 confobd->cfobd_pending_dir = NULL;
111         }
112
113         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
114         RETURN(rc);
115 }
116
117 int confobd_attach(struct obd_device *dev, obd_count len, void *data)
118 {
119         struct lprocfs_static_vars lvars;
120         int rc = 0;
121         ENTRY;
122
123         lprocfs_init_vars(confobd, &lvars);
124         rc = lprocfs_obd_attach(dev, lvars.obd_vars);
125         if (rc)
126                 RETURN(rc);
127
128         rc = lprocfs_alloc_md_stats(dev, 0);
129         RETURN(rc);
130 }
131
132 int confobd_detach(struct obd_device *dev)
133 {
134         int rc;
135         ENTRY;
136         
137         lprocfs_free_md_stats(dev);
138         rc = lprocfs_obd_detach(dev);
139         RETURN(rc);
140 }
141
142 static int confobd_setup(struct obd_device *obd, obd_count len, void *buf)
143 {
144         struct conf_obd *confobd = &obd->u.conf;
145         struct lvfs_obd_ctxt *lvfs_ctxt = NULL;
146         struct lustre_cfg* lcfg = buf;
147         char *mountoptions = NULL;
148         unsigned long page = 0;
149         char *fstype = NULL;
150         char *name = NULL;
151         int rc = 0;
152         ENTRY;
153
154         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
155             lustre_cfg_buf(lcfg, 1) == NULL) { 
156                 CERROR("CONFOBD setup requires device name\n");
157                 RETURN(-EINVAL);
158         }
159         if (LUSTRE_CFG_BUFLEN(lcfg, 2) < 1 ||
160             lustre_cfg_buf(lcfg, 2) == NULL) { 
161                 CERROR("CONFOBD setup requires fstype\n");
162                 RETURN(-EINVAL);
163         }
164
165         OBD_ALLOC(name, LUSTRE_CFG_BUFLEN(lcfg, 1));
166         if (!name) {
167                 CERROR("No memory\n");
168                 GOTO(out, rc = -ENOMEM);
169         }
170         memcpy(name, lustre_cfg_string(lcfg, 1), LUSTRE_CFG_BUFLEN(lcfg, 1));
171
172         OBD_ALLOC(fstype, LUSTRE_CFG_BUFLEN(lcfg, 2));
173         if (!fstype) {
174                 CERROR("No memory\n");
175                 GOTO(out, rc = -ENOMEM);
176         }
177         memcpy(fstype, lustre_cfg_string(lcfg, 2), 
178                LUSTRE_CFG_BUFLEN(lcfg, 2));
179
180         obd->obd_fsops = fsfilt_get_ops(fstype);
181         if (IS_ERR(obd->obd_fsops)) {
182                CERROR("No fstype %s rc=%ld\n", fstype, PTR_ERR(obd->obd_fsops));
183                GOTO(err_ops, rc = PTR_ERR(obd->obd_fsops));
184         }
185
186         if (LUSTRE_CFG_BUFLEN(lcfg, 3) >= 1 && lustre_cfg_buf(lcfg, 3)) {
187                 /* 2.6.9 selinux wants a full option page for do_kern_mount
188                  * (bug6471) */
189                 page = get_zeroed_page(GFP_KERNEL);
190                 if (!page) {
191                         CERROR("No memory\n");
192                         GOTO(err_ops, rc = -ENOMEM);
193                 }
194                 mountoptions = (char *)page;
195                 
196                 memcpy(mountoptions, lustre_cfg_string(lcfg, 3), 
197                        LUSTRE_CFG_BUFLEN(lcfg, 3)); 
198         }
199         
200         rc = lvfs_mount_fs(name, fstype, mountoptions, 0, &lvfs_ctxt);
201
202         if (page) {
203                 free_page(page);
204                 page = 0;
205         }
206
207         if (rc)
208                 GOTO(err_ops, rc);
209
210         LASSERT(lvfs_ctxt);
211         confobd->cfobd_lvfs_ctxt = lvfs_ctxt;
212
213         rc = confobd_fs_setup(obd, lvfs_ctxt);
214         if (rc)
215                 GOTO(err_ops, rc);
216
217         rc = obd_llog_setup(obd, &obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT, 
218                             obd, 0, NULL, &llog_lvfs_ops);
219         if (rc)
220                 GOTO(err_ops, rc);
221
222         EXIT;
223 out:
224         if (rc && lvfs_ctxt)
225                 lvfs_umount_fs(lvfs_ctxt);
226         if (name)
227                 OBD_FREE(name, LUSTRE_CFG_BUFLEN(lcfg, 1));
228         if (fstype)
229                 OBD_FREE(fstype, LUSTRE_CFG_BUFLEN(lcfg, 2));
230
231         return rc;
232 err_ops:
233         fsfilt_put_ops(obd->obd_fsops);
234         goto out;
235 }
236
237 static int confobd_cleanup(struct obd_device *obd, int flags)
238 {
239         struct conf_obd *confobd = &obd->u.conf;
240         ENTRY;
241
242         /* stop recording any log in case lconf didn't do that for us */
243         if (confobd->cfobd_cfg_llh) {
244                 struct lvfs_run_ctxt saved;
245                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
246                 llog_close(confobd->cfobd_cfg_llh);
247                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
248         }
249
250         obd_llog_cleanup(llog_get_context(&obd->obd_llogs, 
251                                           LLOG_CONFIG_ORIG_CTXT));
252         confobd_fs_cleanup(obd, flags);
253         if (confobd->cfobd_lvfs_ctxt)
254                 lvfs_umount_fs(confobd->cfobd_lvfs_ctxt);
255
256         if (!list_empty(&obd->obd_exports))
257                 return (-EBUSY);
258         fsfilt_put_ops(obd->obd_fsops);
259         RETURN(0);
260 }
261
262 static int confobd_iocontrol(unsigned int cmd, struct obd_export *exp, 
263                              int len, void *karg, void *uarg)
264 {
265         static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
266         struct obd_device *obd = exp->exp_obd;
267         struct conf_obd *confobd = &obd->u.conf;
268         struct obd_ioctl_data *data = karg;
269         struct lvfs_run_ctxt saved;
270         int rc = 0;
271         ENTRY;
272
273         CDEBUG(D_INFO, "ioctl cmd %x\n", cmd);
274         switch (cmd) {
275         case OBD_IOC_CLEAR_LOG: {
276                 char *name = data->ioc_inlbuf1;
277                 if (confobd->cfobd_cfg_llh)
278                         RETURN(-EBUSY);
279
280                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
281                 rc = llog_open(llog_get_context(&obd->obd_llogs, 
282                                                 LLOG_CONFIG_ORIG_CTXT),
283                                &confobd->cfobd_cfg_llh, NULL, name,
284                                OBD_LLOG_FL_CREATE);
285                 if (rc == 0) {
286                         llog_init_handle(confobd->cfobd_cfg_llh,
287                                          LLOG_F_IS_PLAIN, NULL);
288
289                         rc = llog_destroy(confobd->cfobd_cfg_llh);
290                         llog_free_handle(confobd->cfobd_cfg_llh);
291                 }
292                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
293
294                 confobd->cfobd_cfg_llh = NULL;
295                 RETURN(rc);
296         }
297         case OBD_IOC_RECORD: {
298                 char *name = data->ioc_inlbuf1;
299                 if (confobd->cfobd_cfg_llh)
300                         RETURN(-EBUSY);
301
302                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
303                 rc = llog_open(llog_get_context(&obd->obd_llogs, 
304                                                 LLOG_CONFIG_ORIG_CTXT),
305                                &confobd->cfobd_cfg_llh, NULL, name,
306                                OBD_LLOG_FL_CREATE);
307                 if (rc == 0)
308                         llog_init_handle(confobd->cfobd_cfg_llh,
309                                          LLOG_F_IS_PLAIN, &cfg_uuid);
310                 else
311                         confobd->cfobd_cfg_llh = NULL;
312                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
313
314                 RETURN(rc);
315         }
316         case OBD_IOC_ENDRECORD: {
317                 if (!confobd->cfobd_cfg_llh)
318                         RETURN(-EBADF);
319
320                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
321                 rc = llog_close(confobd->cfobd_cfg_llh);
322                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
323
324                 confobd->cfobd_cfg_llh = NULL;
325                 RETURN(rc);
326         }
327         case OBD_IOC_DORECORD: {
328                 char *cfg_buf;
329                 struct llog_rec_hdr rec;
330                 if (!confobd->cfobd_cfg_llh)
331                         RETURN(-EBADF);
332
333                 rec.lrh_len = llog_data_len(data->ioc_plen1);
334
335                 switch(data->ioc_type) {
336                 case LUSTRE_CFG_TYPE:
337                         rec.lrh_type = OBD_CFG_REC;
338                         break;
339                 case PORTALS_CFG_TYPE:
340                         rec.lrh_type = PTL_CFG_REC;
341                         break;
342                 default:
343                         CERROR("unknown cfg record type:%d \n", data->ioc_type);
344                         RETURN(-EINVAL);
345                 }
346
347                 OBD_ALLOC(cfg_buf, data->ioc_plen1);
348                 if (cfg_buf == NULL) {
349                         CERROR("No Memory\n");
350                         RETURN(-ENOMEM);
351                 }
352                 if (copy_from_user(cfg_buf, data->ioc_pbuf1, data->ioc_plen1)) {
353                         OBD_FREE(cfg_buf, data->ioc_plen1);
354                         RETURN(-EFAULT);
355                 }
356
357                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
358                 rc = llog_write_rec(confobd->cfobd_cfg_llh, &rec, NULL, 0,
359                                     cfg_buf, -1);
360                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
361
362                 OBD_FREE(cfg_buf, data->ioc_plen1);
363                 RETURN(rc);
364         }
365         case OBD_IOC_DUMP_LOG: {
366                 struct llog_ctxt *ctxt =
367                         llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
368                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
369                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
370                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
371                 if (rc)
372                         RETURN(rc);
373
374                 RETURN(rc);
375         }
376
377         case OBD_IOC_START: {
378                 struct llog_ctxt *ctxt;
379                 char *conf_prof;
380                 char *name = data->ioc_inlbuf1;
381                 int len = strlen(name) + sizeof("-conf");
382
383                 OBD_ALLOC(conf_prof, len);
384                 if (!conf_prof) {
385                         CERROR("no memory\n");
386                         RETURN(-ENOMEM);
387                 }
388                 sprintf(conf_prof, "%s-conf", name);
389
390                 ctxt = llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
391                 rc = class_config_process_llog(ctxt, conf_prof, NULL);
392                 if (rc < 0)
393                         CERROR("Unable to process log: %s\n", conf_prof);
394                 OBD_FREE(conf_prof, len);
395
396                 RETURN(rc);
397         }
398
399         default:
400                 CDEBUG(D_INFO, "unknown command %x\n", cmd);
401                 RETURN(-EINVAL);
402         }
403         RETURN(0);
404 }
405
406 static struct obd_ops conf_obd_ops = {
407         .o_owner         = THIS_MODULE,
408         .o_setup         = confobd_setup,
409         .o_cleanup       = confobd_cleanup,
410         .o_attach        = confobd_attach,
411         .o_detach        = confobd_detach,
412         .o_iocontrol     = confobd_iocontrol,
413 };
414
415 static int __init confobd_init(void)
416 {
417         struct lprocfs_static_vars lvars;
418         ENTRY;
419
420         lprocfs_init_vars(confobd, &lvars);
421         RETURN(class_register_type(&conf_obd_ops, NULL,
422                                    lvars.module_vars,
423                                    OBD_CONF_DEVICENAME));
424 }
425
426 static void __exit confobd_exit(void)
427 {
428         class_unregister_type(OBD_CONF_DEVICENAME);
429 }
430
431 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
432 MODULE_DESCRIPTION("Lustre Config OBD driver");
433 MODULE_LICENSE("GPL");
434
435 module_init(confobd_init);
436 module_exit(confobd_exit);