1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * An implementation of a loadable kernel mode driver providing
5 * multiple kernel/user space bidirectional communications links.
7 * Author: Alan Cox <alan@cymru.net>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
13 * Adapted to become the Linux 2.0 Coda pseudo device
14 * Peter Braam <braam@maths.ox.ac.uk>
15 * Michael Callahan <mjc@emmy.smith.edu>
17 * Changes for Linux 2.1
18 * Copyright (c) 1997 Carnegie-Mellon University
20 * Redone again for Intermezzo
21 * Copyright (c) 1998 Peter J. Braam
23 * Hacked up again for simulated OBD
24 * Copyright (c) 1999 Stelias Computing, Inc.
25 * (authors {pschwan,braam}@stelias.com)
26 * Copyright (C) 1999 Seagate Technology, Inc.
27 * Copyright (C) 2001 Cluster File Systems, Inc.
33 #include <linux/config.h> /* for CONFIG_PROC_FS */
34 #include <linux/module.h>
35 #include <linux/errno.h>
36 #include <linux/kernel.h>
37 #include <linux/major.h>
38 #include <linux/kmod.h> /* for request_module() */
39 #include <linux/sched.h>
41 #include <linux/slab.h>
42 #include <linux/ioport.h>
43 #include <linux/fcntl.h>
44 #include <linux/delay.h>
45 #include <linux/skbuff.h>
46 #include <linux/proc_fs.h>
48 #include <linux/poll.h>
49 #include <linux/init.h>
50 #include <linux/list.h>
52 #include <asm/system.h>
54 #include <asm/uaccess.h>
55 #include <linux/miscdevice.h>
57 #define DEBUG_SUBSYSTEM S_CLASS
59 #include <linux/obd_support.h>
60 #include <linux/obd_class.h>
62 static int obd_init_magic;
63 unsigned long obd_memory = 0;
64 unsigned long obd_fail_loc = 0;
65 struct obd_device obd_dev[MAX_OBD_DEVICES];
66 struct list_head obd_types;
68 /* opening /dev/obd */
69 static int obd_class_open(struct inode * inode, struct file * file)
73 file->private_data = NULL;
78 /* closing /dev/obd */
79 static int obd_class_release(struct inode * inode, struct file * file)
83 if (file->private_data)
84 file->private_data = NULL;
91 * support functions: we could use inter-module communication, but this
92 * is more portable to other OS's
94 static struct obd_type *obd_search_type(char *nm)
96 struct list_head *tmp;
97 struct obd_type *type;
98 CDEBUG(D_INFO, "SEARCH %s\n", nm);
101 while ( (tmp = tmp->next) != &obd_types ) {
102 type = list_entry(tmp, struct obd_type, typ_chain);
103 CDEBUG(D_INFO, "TYP %s\n", type->typ_name);
104 if (strlen(type->typ_name) == strlen(nm) &&
105 strcmp(type->typ_name, nm) == 0 ) {
112 static struct obd_type *obd_nm_to_type(char *nm)
114 struct obd_type *type = obd_search_type(nm);
118 if ( !request_module(nm) ) {
119 CDEBUG(D_INFO, "Loaded module '%s'\n", nm);
120 type = obd_search_type(nm);
122 CDEBUG(D_INFO, "Can't load module '%s'\n", nm);
129 /* to control /dev/obd */
130 static int obd_class_ioctl (struct inode * inode, struct file * filp,
131 unsigned int cmd, unsigned long arg)
133 /* NOTE this must be larger than any of the ioctl data structs */
135 struct obd_ioctl_data *data;
136 struct obd_device *obd = filp->private_data;
137 struct obd_conn conn;
138 int rw = OBD_BRW_READ;
142 memset(buf, 0, sizeof(buf));
144 if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS) {
145 CERROR("OBD ioctl: No device\n");
148 if (obd_ioctl_getdata(buf, buf + 800, (void *)arg)) {
149 CERROR("OBD ioctl: data error\n");
152 data = (struct obd_ioctl_data *)buf;
157 case OBD_IOC_DEVICE: {
158 CDEBUG(D_IOCTL, "\n");
159 if (data->ioc_dev >= MAX_OBD_DEVICES ||
161 CERROR("OBD ioctl: DEVICE insufficient devices\n");
164 CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
166 filp->private_data = &obd_dev[data->ioc_dev];
170 case OBD_IOC_ATTACH: {
171 struct obd_type *type;
173 /* have we attached a type to this device */
174 if (obd->obd_flags & OBD_ATTACHED) {
175 CERROR("OBD: Device %d already typed as %s.\n",
176 obd->obd_minor, MKSTR(obd->obd_type->typ_name));
180 CDEBUG(D_IOCTL, "attach %s %s\n", MKSTR(data->ioc_inlbuf1),
181 MKSTR(data->ioc_inlbuf2));
184 type = obd_nm_to_type(data->ioc_inlbuf1);
186 CERROR("OBD: unknown type dev %d\n", obd->obd_minor);
190 obd->obd_type = type;
191 obd->obd_multi_count = 0;
192 INIT_LIST_HEAD(&obd->obd_gen_clients);
193 INIT_LIST_HEAD(&obd->obd_req_list);
196 if (OBT(obd) && OBP(obd, attach))
197 err = OBP(obd, attach)(obd, sizeof(*data), data);
200 obd->obd_type = NULL;
202 obd->obd_flags |= OBD_ATTACHED;
204 CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
205 obd->obd_minor, data->ioc_inlbuf1);
206 obd->obd_proc_entry =
207 proc_lustre_register_obd_device(obd);
214 case OBD_IOC_DETACH: {
216 if (obd->obd_flags & OBD_SET_UP) {
217 CERROR("OBD device %d still set up\n", obd->obd_minor);
220 if (! (obd->obd_flags & OBD_ATTACHED) ) {
221 CERROR("OBD device %d not attached\n", obd->obd_minor);
224 if ( !list_empty(&obd->obd_gen_clients) ) {
225 CERROR("OBD device %d has connected clients\n",
229 if ( !list_empty(&obd->obd_req_list) ) {
230 CERROR("OBD device %d has hanging requests\n",
235 if (obd->obd_proc_entry)
236 proc_lustre_release_obd_device(obd);
238 obd->obd_flags &= ~OBD_ATTACHED;
239 obd->obd_type->typ_refcnt--;
240 obd->obd_type = NULL;
245 case OBD_IOC_SETUP: {
246 /* have we attached a type to this device? */
247 if (!(obd->obd_flags & OBD_ATTACHED)) {
248 CERROR("Device %d not attached\n", obd->obd_minor);
252 /* has this been done already? */
253 if ( obd->obd_flags & OBD_SET_UP ) {
254 CERROR("Device %d already setup (type %s)\n",
255 obd->obd_minor, obd->obd_type->typ_name);
259 if ( OBT(obd) && OBP(obd, setup) )
260 err = obd_setup(obd, sizeof(*data), data);
263 obd->obd_type->typ_refcnt++;
264 obd->obd_flags |= OBD_SET_UP;
269 case OBD_IOC_CLEANUP: {
270 /* have we attached a type to this device? */
271 if (!(obd->obd_flags & OBD_ATTACHED)) {
272 CERROR("Device %d not attached\n", obd->obd_minor);
276 if ( OBT(obd) && OBP(obd, cleanup) )
277 err = obd_cleanup(obd);
280 obd->obd_flags &= ~OBD_SET_UP;
281 obd->obd_type->typ_refcnt--;
286 case OBD_IOC_CONNECT: {
287 conn.oc_id = data->ioc_conn1;
290 err = obd_connect(&conn);
292 CDEBUG(D_IOCTL, "assigned connection %d\n", conn.oc_id);
293 data->ioc_conn1 = conn.oc_id;
297 err = copy_to_user((int *)arg, data, sizeof(*data));
301 case OBD_IOC_DISCONNECT: {
302 conn.oc_id = data->ioc_conn1;
305 err = obd_disconnect(&conn);
309 case OBD_IOC_DEC_USE_COUNT: {
314 case OBD_IOC_CREATE: {
315 conn.oc_id = data->ioc_conn1;
318 err = obd_create(&conn, &data->ioc_obdo1);
322 err = copy_to_user((int *)arg, data, sizeof(*data));
326 case OBD_IOC_GETATTR: {
327 conn.oc_id = data->ioc_conn1;
330 err = obd_getattr(&conn, &data->ioc_obdo1);
334 err = copy_to_user((int *)arg, data, sizeof(*data));
338 case OBD_IOC_SETATTR: {
339 conn.oc_id = data->ioc_conn1;
342 err = obd_setattr(&conn, &data->ioc_obdo1);
346 err = copy_to_user((int *)arg, data, sizeof(*data));
350 case OBD_IOC_DESTROY: {
351 conn.oc_id = data->ioc_conn1;
354 err = obd_destroy(&conn, &data->ioc_obdo1);
358 err = copy_to_user((int *)arg, data, sizeof(*data));
362 case OBD_IOC_BRW_WRITE:
364 case OBD_IOC_BRW_READ: {
365 /* FIXME: use a better ioctl data struct than obd_ioctl_data.
366 * We don't really support multiple-obdo I/Os here,
367 * for example offset and count are not per-obdo.
369 struct obd_conn conns[2];
370 struct obdo *obdos[2] = { NULL, NULL };
371 obd_count oa_bufs[2] = { 0, 0 };
372 struct page **bufs = NULL;
373 obd_size *counts = NULL;
374 obd_off *offsets = NULL;
375 obd_flag *flags = NULL;
380 pages = oa_bufs[0] = data->ioc_plen1 / PAGE_SIZE;
381 if (data->ioc_obdo2.o_id) {
383 oa_bufs[1] = data->ioc_plen2 / PAGE_SIZE;
387 CDEBUG(D_INODE, "BRW %s with %dx%d pages\n",
388 rw == OBD_BRW_READ ? "read" : "write",
390 bufs = kmalloc(pages * sizeof(*bufs), GFP_KERNEL);
391 counts = kmalloc(pages * sizeof(*counts), GFP_KERNEL);
392 offsets = kmalloc(pages * sizeof(*offsets), GFP_KERNEL);
393 flags = kmalloc(pages * sizeof(*flags), GFP_KERNEL);
394 if (!bufs || !counts || !offsets || !flags) {
395 CERROR("no memory for %d BRW per-page data\n", pages);
400 obdos[0] = &data->ioc_obdo1;
402 obdos[1] = &data->ioc_obdo2;
404 for (i = 0, pages = 0; i < num; i++) {
408 conns[i].oc_id = (&data->ioc_conn1)[i];
409 conns[i].oc_dev = obd;
411 from = (&data->ioc_pbuf1)[i];
412 off = data->ioc_offset;
414 for (j = 0; j < oa_bufs[i];
415 j++, pages++, off += PAGE_SIZE, from += PAGE_SIZE){
418 to = __get_free_pages(GFP_KERNEL, 0);
421 copy_from_user((void *)to,from,PAGE_SIZE))
424 CERROR("no memory for brw pages\n");
426 GOTO(brw_cleanup, err);
428 bufs[pages] = virt_to_page(to);
429 counts[pages] = PAGE_SIZE;
430 offsets[pages] = off;
435 err = obd_brw(rw, conns, num, obdos, oa_bufs, bufs,
436 counts, offsets, flags);
441 free_pages((unsigned long)page_address(bufs[pages]), 0);
450 conn.oc_id = data->ioc_conn1;
453 err = obd_iocontrol(cmd, &conn, sizeof(*data), data, NULL);
457 err = copy_to_user((int *)arg, data, sizeof(*data));
461 } /* obd_class_ioctl */
464 /* Driver interface done, utility functions follow */
465 int obd_register_type(struct obd_ops *ops, char *nm)
467 struct obd_type *type;
471 if (obd_init_magic != 0x11223344) {
472 CERROR("bad magic for type\n");
476 if ( obd_nm_to_type(nm) ) {
477 CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
481 OBD_ALLOC(type, sizeof(*type));
484 memset(type, 0, sizeof(*type));
485 INIT_LIST_HEAD(&type->typ_chain);
487 list_add(&type->typ_chain, obd_types.next);
493 int obd_unregister_type(char *nm)
495 struct obd_type *type = obd_nm_to_type(nm);
501 CERROR("unknown obd type\n");
505 if ( type->typ_refcnt ) {
507 CERROR("type %s has refcount (%d)\n", nm, type->typ_refcnt);
511 list_del(&type->typ_chain);
512 OBD_FREE(type, sizeof(*type));
515 } /* obd_unregister_type */
517 /* declare character device */
518 static struct file_operations obd_psdev_fops = {
519 ioctl: obd_class_ioctl, /* ioctl */
520 open: obd_class_open, /* open */
521 release: obd_class_release, /* release */
525 #define OBD_MINOR 241
526 static struct miscdevice obd_psdev = {
532 EXPORT_SYMBOL(obd_register_type);
533 EXPORT_SYMBOL(obd_unregister_type);
535 EXPORT_SYMBOL(obd_dev);
537 EXPORT_SYMBOL(gen_connect);
538 EXPORT_SYMBOL(gen_client);
539 EXPORT_SYMBOL(gen_cleanup);
540 EXPORT_SYMBOL(gen_disconnect);
541 EXPORT_SYMBOL(gen_copy_data);
542 EXPORT_SYMBOL(obdo_cachep);
544 /* EXPORT_SYMBOL(gen_multi_attach); */
545 EXPORT_SYMBOL(gen_multi_setup);
546 EXPORT_SYMBOL(gen_multi_cleanup);
547 EXPORT_SYMBOL(obd_memory);
548 EXPORT_SYMBOL(obd_fail_loc);
550 static int __init init_obdclass(void)
555 printk(KERN_INFO "OBD class driver v0.01, braam@stelias.com\n");
557 INIT_LIST_HEAD(&obd_types);
559 if ((err = misc_register(&obd_psdev))) {
560 CERROR("cannot register %d err %d\n", OBD_MINOR, err);
564 for (i = 0; i < MAX_OBD_DEVICES; i++) {
565 memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
566 obd_dev[i].obd_minor = i;
567 INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients);
568 INIT_LIST_HEAD(&obd_dev[i].obd_req_list);
569 init_waitqueue_head(&obd_dev[i].obd_req_waitq);
572 err = obd_init_obdo_cache();
576 obd_init_magic = 0x11223344;
580 static void __exit cleanup_obdclass(void)
585 misc_deregister(&obd_psdev);
586 for (i = 0; i < MAX_OBD_DEVICES; i++) {
587 struct obd_device *obd = &obd_dev[i];
588 if ( obd->obd_type &&
589 (obd->obd_flags & OBD_SET_UP) &&
590 OBT(obd) && OBP(obd, detach) ) {
591 /* XXX should this call generic detach otherwise? */
592 OBP(obd, detach)(obd);
596 obd_cleanup_obdo_cache();
598 CERROR("obd memory leaked: %ld bytes\n", obd_memory);
603 MODULE_AUTHOR("Cluster File Systems, Inc. <braam@clusterfs.com>");
604 MODULE_DESCRIPTION("Lustre Class Driver v1.0");
605 MODULE_LICENSE("GPL");
607 module_init(init_obdclass);
608 module_exit(cleanup_obdclass);