1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2001 Cluster File Systems, Inc.
6 * This code is issued under the GNU General Public License.
7 * See the file COPYING in this distribution
9 * These are the only exported functions, they provide some generic
10 * infrastructure for managing object devices
12 * Object Devices Class Driver
13 * Copyright (C) 2002 Cluster File Systems, Inc.
17 #include <linux/config.h> /* for CONFIG_PROC_FS */
18 #include <linux/module.h>
19 #include <linux/errno.h>
20 #include <linux/kernel.h>
21 #include <linux/major.h>
22 #include <linux/sched.h>
24 #include <linux/slab.h>
25 #include <linux/ioport.h>
26 #include <linux/fcntl.h>
27 #include <linux/delay.h>
28 #include <linux/skbuff.h>
29 #include <linux/proc_fs.h>
31 #include <linux/poll.h>
32 #include <linux/init.h>
33 #include <linux/list.h>
35 #include <asm/system.h>
37 #include <asm/uaccess.h>
38 #include <linux/miscdevice.h>
40 #define DEBUG_SUBSYSTEM S_CLASS
42 #include <linux/obd_support.h>
43 #include <linux/obd_class.h>
44 #include <linux/smp_lock.h>
46 struct semaphore obd_conf_sem; /* serialize configuration commands */
47 struct obd_device obd_dev[MAX_OBD_DEVICES];
48 struct list_head obd_types;
49 unsigned long obd_memory = 0;
50 unsigned long obd_fail_loc = 0;
52 extern struct obd_type *class_nm_to_type(char *nm);
54 /* opening /dev/obd */
55 static int obd_class_open(struct inode * inode, struct file * file)
59 file->private_data = NULL;
64 /* closing /dev/obd */
65 static int obd_class_release(struct inode * inode, struct file * file)
69 if (file->private_data)
70 file->private_data = NULL;
77 inline void obd_data2conn(struct lustre_handle *conn, struct obd_ioctl_data *data)
79 conn->addr = data->ioc_addr;
80 conn->cookie = data->ioc_cookie;
84 inline void obd_conn2data(struct obd_ioctl_data *data, struct lustre_handle *conn)
86 data->ioc_addr = conn->addr;
87 data->ioc_cookie = conn->cookie;
91 /* to control /dev/obd */
92 static int obd_class_ioctl (struct inode * inode, struct file * filp,
93 unsigned int cmd, unsigned long arg)
97 struct obd_ioctl_data *data;
98 struct obd_device *obd = filp->private_data;
99 struct lustre_handle conn;
100 int rw = OBD_BRW_READ;
106 if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS &&
107 cmd != OBD_IOC_LIST &&
108 cmd != OBD_IOC_NAME2DEV && cmd != OBD_IOC_NEWDEV) {
109 CERROR("OBD ioctl: No device\n");
110 GOTO(out, err=-EINVAL);
112 if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
113 CERROR("OBD ioctl: data error\n");
114 GOTO(out, err=-EINVAL);
116 data = (struct obd_ioctl_data *)buf;
120 GOTO(out, err=-EINVAL);
121 case OBD_IOC_DEVICE: {
122 CDEBUG(D_IOCTL, "\n");
123 if (data->ioc_dev >= MAX_OBD_DEVICES || data->ioc_dev < 0) {
124 CERROR("OBD ioctl: DEVICE insufficient devices\n");
125 GOTO(out, err=-EINVAL);
127 CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
129 filp->private_data = &obd_dev[data->ioc_dev];
135 char *buf2 = data->ioc_bulk;
136 int remains = data->ioc_inllen1;
138 if (!data->ioc_inlbuf1) {
139 CERROR("No buffer passed!\n");
140 GOTO(out, err=-EINVAL);
144 for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
147 struct obd_device *obd = &obd_dev[i];
150 if (obd->obd_flags & OBD_SET_UP)
154 l = snprintf(buf2, remains, "%2d %s %s %s %s\n",
155 i, status, obd->obd_type->typ_name,
156 obd->obd_name, obd->obd_uuid);
160 CERROR("not enough space for device listing\n");
165 err = copy_to_user((int *)arg, data, len);
170 case OBD_IOC_NAME2DEV: {
171 /* Resolve a device name. This does not change the
172 * currently selected device.
176 if (!data->ioc_inllen1 || !data->ioc_inlbuf1 ) {
177 CERROR("No name passed,!\n");
178 GOTO(out, err=-EINVAL);
180 if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
181 CERROR("Name not nul terminated!\n");
182 GOTO(out, err=-EINVAL);
185 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
186 dev = class_name2dev(data->ioc_inlbuf1);
189 CDEBUG(D_IOCTL, "No device for name %s!\n",
191 GOTO(out, err=-EINVAL);
194 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
196 err = copy_to_user((int *)arg, data, sizeof(*data));
200 case OBD_IOC_UUID2DEV: {
201 /* Resolve a device uuid. This does not change the
202 * currently selected device.
206 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
207 CERROR("No UUID passed!\n");
208 GOTO(out, err=-EINVAL);
210 if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
211 CERROR("Name not nul terminated!\n");
212 GOTO(out, err=-EINVAL);
215 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
216 dev = class_uuid2dev(data->ioc_inlbuf1);
219 CDEBUG(D_IOCTL, "No device for name %s!\n",
221 GOTO(out, err=-EINVAL);
224 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
226 err = copy_to_user((int *)arg, data, sizeof(*data));
230 case OBD_IOC_NEWDEV: {
234 filp->private_data = NULL;
235 for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
236 struct obd_device *obd = &obd_dev[i];
237 if (!obd->obd_type) {
238 filp->private_data = obd;
247 GOTO(out, err=-EINVAL);
249 err = copy_to_user((int *)arg, data, sizeof(*data));
253 case OBD_IOC_ATTACH: {
254 struct obd_type *type;
256 /* have we attached a type to this device */
257 if (obd->obd_flags & OBD_ATTACHED) {
258 CERROR("OBD: Device %d already typed as %s.\n",
259 obd->obd_minor, MKSTR(obd->obd_type->typ_name));
260 GOTO(out, err=-EBUSY);
263 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
264 CERROR("No type passed!\n");
265 GOTO(out, err=-EINVAL);
267 if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
268 CERROR("Type not nul terminated!\n");
269 GOTO(out, err=-EINVAL);
272 CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
273 MKSTR(data->ioc_inlbuf1),
274 MKSTR(data->ioc_inlbuf2), MKSTR(data->ioc_inlbuf3));
278 type = class_nm_to_type(data->ioc_inlbuf1);
280 CERROR("OBD: unknown type dev %d\n", obd->obd_minor);
281 GOTO(out, err=-EINVAL);
284 obd->obd_type = type;
285 INIT_LIST_HEAD(&obd->obd_exports);
288 if (OBT(obd) && OBP(obd, attach))
289 err = OBP(obd,attach)(obd, sizeof(*data), data);
291 obd->obd_type = NULL;
293 obd->obd_flags |= OBD_ATTACHED;
295 CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
296 obd->obd_minor, data->ioc_inlbuf1);
297 if (data->ioc_inlbuf2) {
298 int len = strlen(data->ioc_inlbuf2) + 1;
299 OBD_ALLOC(obd->obd_name, len);
300 if (!obd->obd_name) {
301 CERROR("no memory\n");
304 memcpy(obd->obd_name, data->ioc_inlbuf2, len);
305 //obd->obd_proc_entry =
306 // proc_lustre_register_obd_device(obd);
308 CERROR("WARNING: unnamed obd device\n");
309 obd->obd_proc_entry = NULL;
312 if (data->ioc_inlbuf3) {
313 int len = strlen(data->ioc_inlbuf3);
315 CERROR("uuid should be shorter than 37 bytes\n");
317 OBD_FREE(obd->obd_name,
318 strlen(obd->obd_name) + 1);
319 GOTO(out, err=-EINVAL);
321 memcpy(obd->obd_uuid, data->ioc_inlbuf3,
322 sizeof(obd->obd_uuid));
331 case OBD_IOC_DETACH: {
333 if (obd->obd_flags & OBD_SET_UP) {
334 CERROR("OBD device %d still set up\n", obd->obd_minor);
335 GOTO(out, err=-EBUSY);
337 if (! (obd->obd_flags & OBD_ATTACHED) ) {
338 CERROR("OBD device %d not attached\n", obd->obd_minor);
339 GOTO(out, err=-ENODEV);
341 if ( !list_empty(&obd->obd_exports) ) {
342 CERROR("OBD device %d has exports\n",
344 GOTO(out, err=-EBUSY);
348 OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
349 obd->obd_name = NULL;
352 //if (obd->obd_proc_entry)
353 // proc_lustre_release_obd_device(obd);
355 obd->obd_flags &= ~OBD_ATTACHED;
356 obd->obd_type->typ_refcnt--;
357 obd->obd_type = NULL;
362 case OBD_IOC_SETUP: {
363 /* have we attached a type to this device? */
364 if (!(obd->obd_flags & OBD_ATTACHED)) {
365 CERROR("Device %d not attached\n", obd->obd_minor);
366 GOTO(out, err=-ENODEV);
369 /* has this been done already? */
370 if ( obd->obd_flags & OBD_SET_UP ) {
371 CERROR("Device %d already setup (type %s)\n",
372 obd->obd_minor, obd->obd_type->typ_name);
373 GOTO(out, err=-EBUSY);
376 if ( OBT(obd) && OBP(obd, setup) )
377 err = obd_setup(obd, sizeof(*data), data);
380 obd->obd_type->typ_refcnt++;
381 obd->obd_flags |= OBD_SET_UP;
386 case OBD_IOC_CLEANUP: {
387 /* have we attached a type to this device? */
388 if (!(obd->obd_flags & OBD_ATTACHED)) {
389 CERROR("Device %d not attached\n", obd->obd_minor);
390 GOTO(out, err=-ENODEV);
393 if ( OBT(obd) && OBP(obd, cleanup) )
394 err = obd_cleanup(obd);
397 obd->obd_flags &= ~OBD_SET_UP;
398 obd->obd_type->typ_refcnt--;
403 case OBD_IOC_CONNECT: {
404 obd_data2conn(&conn, data);
406 err = obd_connect(&conn, obd);
408 CDEBUG(D_IOCTL, "assigned export %Lx\n", conn.addr);
409 obd_conn2data(data, &conn);
413 err = copy_to_user((int *)arg, data, sizeof(*data));
417 case OBD_IOC_DISCONNECT: {
418 obd_data2conn(&conn, data);
419 err = obd_disconnect(&conn);
423 case OBD_IOC_DEC_USE_COUNT: {
428 case OBD_IOC_CREATE: {
429 obd_data2conn(&conn, data);
432 err = obd_create(&conn, &data->ioc_obdo1);
436 err = copy_to_user((int *)arg, data, sizeof(*data));
440 case OBD_IOC_GETATTR: {
442 obd_data2conn(&conn, data);
443 err = obd_getattr(&conn, &data->ioc_obdo1);
447 err = copy_to_user((int *)arg, data, sizeof(*data));
451 case OBD_IOC_SETATTR: {
452 obd_data2conn(&conn, data);
453 err = obd_setattr(&conn, &data->ioc_obdo1);
457 err = copy_to_user((int *)arg, data, sizeof(*data));
461 case OBD_IOC_DESTROY: {
462 obd_data2conn(&conn, data);
464 err = obd_destroy(&conn, &data->ioc_obdo1);
468 err = copy_to_user((int *)arg, data, sizeof(*data));
472 case OBD_IOC_BRW_WRITE:
474 case OBD_IOC_BRW_READ: {
475 /* FIXME: use a better ioctl data struct than obd_ioctl_data.
476 * We don't really support multiple-obdo I/Os here,
477 * for example offset and count are not per-obdo.
479 struct obdo *obdos[2] = { NULL, NULL };
480 obd_count oa_bufs[2] = { 0, 0 };
481 struct page **bufs = NULL;
482 obd_size *counts = NULL;
483 obd_off *offsets = NULL;
484 obd_flag *flags = NULL;
489 obd_data2conn(&conn, data);
491 pages = oa_bufs[0] = data->ioc_plen1 / PAGE_SIZE;
492 if (data->ioc_obdo2.o_id) {
494 oa_bufs[1] = data->ioc_plen2 / PAGE_SIZE;
498 CDEBUG(D_INODE, "BRW %s with %dx%d pages\n",
499 rw == OBD_BRW_READ ? "read" : "write",
501 OBD_ALLOC(bufs, pages * sizeof(*bufs));
502 OBD_ALLOC(counts, pages * sizeof(*counts));
503 OBD_ALLOC(offsets, pages * sizeof(*offsets));
504 OBD_ALLOC(flags, pages * sizeof(*flags));
505 if (!bufs || !counts || !offsets || !flags) {
506 CERROR("no memory for %d BRW per-page data\n", pages);
511 obdos[0] = &data->ioc_obdo1;
513 obdos[1] = &data->ioc_obdo2;
515 for (i = 0, pages = 0; i < num; i++) {
519 from = (&data->ioc_pbuf1)[i];
520 off = data->ioc_offset;
522 for (j = 0; j < oa_bufs[i];
523 j++, pages++, off += PAGE_SIZE, from += PAGE_SIZE){
526 to = __get_free_pages(GFP_KERNEL, 0);
529 copy_from_user((void *)to,from,PAGE_SIZE))
532 CERROR("no memory for brw pages\n");
534 GOTO(brw_cleanup, err);
536 bufs[pages] = virt_to_page(to);
537 counts[pages] = PAGE_SIZE;
538 offsets[pages] = off;
543 err = obd_brw(rw, &conn, num, obdos, oa_bufs, bufs,
544 counts, offsets, flags, NULL);
550 __free_pages(bufs[i], 0);
552 OBD_FREE(bufs, pages * sizeof(*bufs));
553 OBD_FREE(counts, pages * sizeof(*counts));
554 OBD_FREE(offsets, pages * sizeof(*offsets));
555 OBD_FREE(flags, pages * sizeof(*flags));
559 obd_data2conn(&conn, data);
561 err = obd_iocontrol(cmd, &conn, len, data, NULL);
565 err = copy_to_user((int *)arg, data, len);
574 } /* obd_class_ioctl */
578 /* declare character device */
579 static struct file_operations obd_psdev_fops = {
580 ioctl: obd_class_ioctl, /* ioctl */
581 open: obd_class_open, /* open */
582 release: obd_class_release, /* release */
586 #define OBD_MINOR 241
587 static struct miscdevice obd_psdev = {
594 EXPORT_SYMBOL(obd_dev);
595 EXPORT_SYMBOL(obdo_cachep);
596 EXPORT_SYMBOL(obd_memory);
597 EXPORT_SYMBOL(obd_fail_loc);
599 EXPORT_SYMBOL(class_register_type);
600 EXPORT_SYMBOL(class_unregister_type);
601 EXPORT_SYMBOL(class_name2dev);
602 EXPORT_SYMBOL(class_uuid2dev);
603 EXPORT_SYMBOL(class_uuid2obd);
604 EXPORT_SYMBOL(class_connect);
605 EXPORT_SYMBOL(class_conn2export);
606 EXPORT_SYMBOL(class_conn2obd);
607 EXPORT_SYMBOL(class_disconnect);
608 //EXPORT_SYMBOL(class_multi_setup);
609 //EXPORT_SYMBOL(class_multi_cleanup);
611 static int __init init_obdclass(void)
616 printk(KERN_INFO "OBD class driver v0.9, info@clusterfs.com\n");
618 sema_init(&obd_conf_sem, 1);
619 INIT_LIST_HEAD(&obd_types);
621 if ((err = misc_register(&obd_psdev))) {
622 CERROR("cannot register %d err %d\n", OBD_MINOR, err);
626 for (i = 0; i < MAX_OBD_DEVICES; i++) {
627 memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
628 obd_dev[i].obd_minor = i;
629 INIT_LIST_HEAD(&obd_dev[i].obd_exports);
632 err = obd_init_caches();
639 static void __exit cleanup_obdclass(void)
644 misc_deregister(&obd_psdev);
645 for (i = 0; i < MAX_OBD_DEVICES; i++) {
646 struct obd_device *obd = &obd_dev[i];
647 if (obd->obd_type && (obd->obd_flags & OBD_SET_UP) &&
648 OBT(obd) && OBP(obd, detach)) {
649 /* XXX should this call generic detach otherwise? */
650 OBP(obd, detach)(obd);
654 obd_cleanup_caches();
656 CERROR("obd memory leaked: %ld bytes\n", obd_memory);
660 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
661 MODULE_DESCRIPTION("Lustre Class Driver v1.0");
662 MODULE_LICENSE("GPL");
664 module_init(init_obdclass);
665 module_exit(cleanup_obdclass);