Whamcloud - gitweb
- much of the striping configuration managment and setup builds up
[fs/lustre-release.git] / lustre / obdclass / class_obd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  * 
4  * Copyright (C) 2001  Cluster File Systems, Inc.
5  *
6  * This code is issued under the GNU General Public License.
7  * See the file COPYING in this distribution
8  *
9  * These are the only exported functions, they provide some generic
10  * infrastructure for managing object devices
11  *
12  * Object Devices Class Driver
13  *              Copyright (C) 2002 Cluster File Systems, Inc.
14  */
15
16 #define EXPORT_SYMTAB
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/kmod.h>   /* for request_module() */
23 #include <linux/sched.h>
24 #include <linux/lp.h>
25 #include <linux/slab.h>
26 #include <linux/ioport.h>
27 #include <linux/fcntl.h>
28 #include <linux/delay.h>
29 #include <linux/skbuff.h>
30 #include <linux/proc_fs.h>
31 #include <linux/fs.h>
32 #include <linux/poll.h>
33 #include <linux/init.h>
34 #include <linux/list.h>
35 #include <asm/io.h>
36 #include <asm/system.h>
37 #include <asm/poll.h>
38 #include <asm/uaccess.h>
39 #include <linux/miscdevice.h>
40
41 #define DEBUG_SUBSYSTEM S_CLASS
42
43 #include <linux/obd_support.h>
44 #include <linux/obd_class.h>
45 #include <linux/smp_lock.h>
46
47 struct semaphore obd_conf_sem;   /* serialize configuration commands */ 
48 struct obd_device obd_dev[MAX_OBD_DEVICES];
49 struct list_head obd_types;
50 unsigned long obd_memory = 0;
51 unsigned long obd_fail_loc = 0;
52
53 extern struct obd_type *class_nm_to_type(char *nm);
54
55 /*  opening /dev/obd */
56 static int obd_class_open(struct inode * inode, struct file * file)
57 {
58         ENTRY;
59
60         file->private_data = NULL;
61         MOD_INC_USE_COUNT;
62         RETURN(0);
63 }
64
65 /*  closing /dev/obd */
66 static int obd_class_release(struct inode * inode, struct file * file)
67 {
68         ENTRY;
69
70         if (file->private_data)
71                 file->private_data = NULL;
72
73         MOD_DEC_USE_COUNT;
74         RETURN(0);
75 }
76
77
78 inline void obd_data2conn(struct lustre_handle *conn, struct obd_ioctl_data *data)
79 {
80         conn->addr = data->ioc_addr;
81         conn->cookie = data->ioc_cookie;
82 }
83
84
85 inline void obd_conn2data(struct obd_ioctl_data *data, struct lustre_handle *conn)
86 {
87         data->ioc_addr = conn->addr;
88         data->ioc_cookie = conn->cookie;
89 }
90
91
92 /* to control /dev/obd */
93 static int obd_class_ioctl (struct inode * inode, struct file * filp,
94                             unsigned int cmd, unsigned long arg)
95 {
96         char *buf;
97         int len;
98         struct obd_ioctl_data *data;
99         struct obd_device *obd = filp->private_data;
100         struct lustre_handle conn;
101         int rw = OBD_BRW_READ;
102         int err = 0;
103         ENTRY;
104
105         down(&obd_conf_sem); 
106
107         if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS &&
108             cmd != OBD_IOC_LIST &&
109             cmd != OBD_IOC_NAME2DEV && cmd != OBD_IOC_NEWDEV) {
110                 CERROR("OBD ioctl: No device\n");
111                 GOTO(out, err=-EINVAL);
112         }
113         if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
114                 CERROR("OBD ioctl: data error\n");
115                 GOTO(out, err=-EINVAL);
116         }
117         data = (struct obd_ioctl_data *)buf;
118
119         switch (cmd) {
120         case TCGETS:
121                 GOTO(out, err=-EINVAL);
122         case OBD_IOC_DEVICE: {
123                 CDEBUG(D_IOCTL, "\n");
124                 if (data->ioc_dev >= MAX_OBD_DEVICES || data->ioc_dev < 0) {
125                         CERROR("OBD ioctl: DEVICE insufficient devices\n");
126                         GOTO(out, err=-EINVAL);
127                 }
128                 CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
129
130                 filp->private_data = &obd_dev[data->ioc_dev];
131                 GOTO(out, err=0);
132         }
133
134         case OBD_IOC_LIST: {
135                 int i;
136                 char *buf2 = data->ioc_bulk;
137                 int remains = data->ioc_inllen1;
138
139                 if (!data->ioc_inlbuf1) {
140                         CERROR("No buffer passed!\n");
141                         GOTO(out, err=-EINVAL);
142                 }
143
144
145                 for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
146                         int l;
147                         struct obd_device *obd = &obd_dev[i];
148                         if (!obd->obd_type) 
149                                 continue;
150                         l = snprintf(buf2, remains, "%2d %s %s %s\n",
151                                      i, obd->obd_type->typ_name, 
152                                      obd->obd_name, obd->obd_uuid);
153                         buf2 +=l;
154                         remains -=l;
155                         if (remains <= 0) { 
156                                 CERROR("not enough space for device listing\n");
157                                 break;
158                         }
159                 }
160
161                 err = copy_to_user((int *)arg, data, len);
162                 GOTO(out, err);
163         }
164
165
166         case OBD_IOC_NAME2DEV: {
167                 /* Resolve a device name.  This does not change the
168                  * currently selected device.
169                  */
170                 int dev;
171
172                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1 ) {
173                         CERROR("No name passed,!\n");
174                         GOTO(out, err=-EINVAL);
175                 }
176                 if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
177                         CERROR("Name not nul terminated!\n");
178                         GOTO(out, err=-EINVAL);
179                 }
180
181                 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
182                 dev = class_name2dev(data->ioc_inlbuf1);
183                 data->ioc_dev = dev;
184                 if (dev == -1) {
185                         CDEBUG(D_IOCTL, "No device for name %s!\n",
186                                data->ioc_inlbuf1);
187                         GOTO(out, err=-EINVAL);
188                 }
189
190                 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
191                        dev);
192                 err = copy_to_user((int *)arg, data, sizeof(*data));
193                 GOTO(out, err);
194         }
195
196         case OBD_IOC_UUID2DEV: {
197                 /* Resolve a device uuid.  This does not change the
198                  * currently selected device.
199                  */
200                 int dev;
201
202                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
203                         CERROR("No UUID passed!\n");
204                         GOTO(out, err=-EINVAL);
205                 }
206                 if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
207                         CERROR("Name not nul terminated!\n");
208                         GOTO(out, err=-EINVAL);
209                 }
210
211                 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
212                 dev = class_uuid2dev(data->ioc_inlbuf1);
213                 data->ioc_dev = dev;
214                 if (dev == -1) {
215                         CDEBUG(D_IOCTL, "No device for name %s!\n",
216                                data->ioc_inlbuf1);
217                         GOTO(out, err=-EINVAL);
218                 }
219
220                 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
221                        dev);
222                 err = copy_to_user((int *)arg, data, sizeof(*data));
223                 GOTO(out, err);
224         }
225
226         case OBD_IOC_NEWDEV: {
227                 int dev = -1;
228                 int i;
229
230                 filp->private_data = NULL;
231                 for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
232                         struct obd_device *obd = &obd_dev[i];
233                         if (!obd->obd_type) {
234                                 filp->private_data = obd;
235                                 dev = i;
236                                 break;
237                         }
238                 }
239
240
241                 data->ioc_dev = dev;
242                 if (dev == -1)
243                         GOTO(out, err=-EINVAL);
244
245                 err = copy_to_user((int *)arg, data, sizeof(*data));
246                 GOTO(out, err);
247         }
248
249         case OBD_IOC_ATTACH: {
250                 struct obd_type *type;
251
252                 /* have we attached a type to this device */
253                 if (obd->obd_flags & OBD_ATTACHED) {
254                         CERROR("OBD: Device %d already typed as %s.\n",
255                                obd->obd_minor, MKSTR(obd->obd_type->typ_name));
256                         GOTO(out, err=-EBUSY);
257                 }
258
259                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
260                         CERROR("No type passed!\n");
261                         GOTO(out, err=-EINVAL);
262                 }
263                 if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
264                         CERROR("Type not nul terminated!\n");
265                         GOTO(out, err=-EINVAL);
266                 }
267
268                 CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n", 
269                        MKSTR(data->ioc_inlbuf1),
270                        MKSTR(data->ioc_inlbuf2), MKSTR(data->ioc_inlbuf3));
271
272                 /* find the type */
273
274                 type = class_nm_to_type(data->ioc_inlbuf1);
275                 if (!type) {
276                         CERROR("OBD: unknown type dev %d\n", obd->obd_minor);
277                         GOTO(out, err=-EINVAL);
278                 }
279
280                 obd->obd_type = type;
281                 INIT_LIST_HEAD(&obd->obd_exports);
282
283                 /* do the attach */
284                 if (OBT(obd) && OBP(obd, attach))
285                         err = OBP(obd,attach)(obd, sizeof(*data), data);
286                 if (err) {
287                         obd->obd_type = NULL;
288                 } else {
289                         obd->obd_flags |= OBD_ATTACHED;
290                         type->typ_refcnt++;
291                         CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
292                                obd->obd_minor, data->ioc_inlbuf1);
293                         if (data->ioc_inlbuf2) {
294                                 int len = strlen(data->ioc_inlbuf2) + 1;
295                                 OBD_ALLOC(obd->obd_name, len + 1);
296                                 if (!obd->obd_name) {
297                                         CERROR("no memory\n");
298                                         LBUG();
299                                 }
300                                 memcpy(obd->obd_name, data->ioc_inlbuf2, len + 1);
301                                 obd->obd_proc_entry =
302                                         proc_lustre_register_obd_device(obd);
303                         } else { 
304                                 CERROR("WARNING: unnamed obd device\n");
305                                 obd->obd_proc_entry = NULL;
306                         }
307
308                         if (data->ioc_inlbuf3) {
309                                 int len = strlen(data->ioc_inlbuf3);
310                                 if (len > 37) { 
311                                         CERROR("uuid should be shorter than 37 bytes\n");
312                                         if (obd->obd_name)
313                                                 OBD_FREE(obd->obd_name, 
314                                                          strlen(obd->obd_name) + 1);
315                                         GOTO(out, err=-EINVAL);
316                                 }
317                                 memcpy(obd->obd_uuid, data->ioc_inlbuf3, 
318                                        sizeof(obd->obd_uuid));
319                         }
320
321                         MOD_INC_USE_COUNT;
322                 }
323
324                 GOTO(out, err);
325         }
326
327         case OBD_IOC_DETACH: {
328                 ENTRY;
329                 if (obd->obd_flags & OBD_SET_UP) {
330                         CERROR("OBD device %d still set up\n", obd->obd_minor);
331                         GOTO(out, err=-EBUSY);
332                 }
333                 if (! (obd->obd_flags & OBD_ATTACHED) ) {
334                         CERROR("OBD device %d not attached\n", obd->obd_minor);
335                         GOTO(out, err=-ENODEV);
336                 }
337                 if ( !list_empty(&obd->obd_exports) ) {
338                         CERROR("OBD device %d has exports\n",
339                                obd->obd_minor);
340                         GOTO(out, err=-EBUSY);
341                 }
342
343                 if (obd->obd_name) {
344                         OBD_FREE(obd->obd_name, strlen(obd->obd_name)+ 1);
345                         obd->obd_name = NULL;
346                 }
347
348                 if (obd->obd_proc_entry)
349                         proc_lustre_release_obd_device(obd);
350
351                 obd->obd_flags &= ~OBD_ATTACHED;
352                 obd->obd_type->typ_refcnt--;
353                 obd->obd_type = NULL;
354                 MOD_DEC_USE_COUNT;
355                 GOTO(out, err=0);
356         }
357
358         case OBD_IOC_SETUP: {
359                 /* have we attached a type to this device? */
360                 if (!(obd->obd_flags & OBD_ATTACHED)) {
361                         CERROR("Device %d not attached\n", obd->obd_minor);
362                         GOTO(out, err=-ENODEV);
363                 }
364
365                 /* has this been done already? */
366                 if ( obd->obd_flags & OBD_SET_UP ) {
367                         CERROR("Device %d already setup (type %s)\n",
368                                obd->obd_minor, obd->obd_type->typ_name);
369                         GOTO(out, err=-EBUSY);
370                 }
371
372                 if ( OBT(obd) && OBP(obd, setup) )
373                         err = obd_setup(obd, sizeof(*data), data);
374
375                 if (!err) {
376                         obd->obd_type->typ_refcnt++;
377                         obd->obd_flags |= OBD_SET_UP;
378                 }
379
380                 GOTO(out, err);
381         }
382         case OBD_IOC_CLEANUP: {
383                 /* have we attached a type to this device? */
384                 if (!(obd->obd_flags & OBD_ATTACHED)) {
385                         CERROR("Device %d not attached\n", obd->obd_minor);
386                         GOTO(out, err=-ENODEV);
387                 }
388
389                 if ( OBT(obd) && OBP(obd, cleanup) )
390                         err = obd_cleanup(obd);
391
392                 if (!err) {
393                         obd->obd_flags &= ~OBD_SET_UP;
394                         obd->obd_type->typ_refcnt--;
395                 }
396                 GOTO(out, err);
397         }
398
399         case OBD_IOC_CONNECT: {
400                 obd_data2conn(&conn, data); 
401
402                 err = obd_connect(&conn, obd);
403
404                 CDEBUG(D_IOCTL, "assigned export %Lx\n", conn.addr);
405                 obd_conn2data(data, &conn);
406                 if (err)
407                         GOTO(out, err);
408
409                 err = copy_to_user((int *)arg, data, sizeof(*data));
410                 GOTO(out, err);
411         }
412
413         case OBD_IOC_DISCONNECT: {
414                 obd_data2conn(&conn, data);
415                 err = obd_disconnect(&conn);
416                 GOTO(out, err);
417         }
418
419         case OBD_IOC_DEC_USE_COUNT: {
420                 MOD_DEC_USE_COUNT;
421                 GOTO(out, err=0);
422         }
423
424         case OBD_IOC_CREATE: {
425                 obd_data2conn(&conn, data);
426
427                 err = obd_create(&conn, &data->ioc_obdo1);
428                 if (err)
429                         GOTO(out, err);
430
431                 err = copy_to_user((int *)arg, data, sizeof(*data));
432                 GOTO(out, err);
433         }
434
435         case OBD_IOC_GETATTR: {
436
437                 obd_data2conn(&conn, data);
438                 err = obd_getattr(&conn, &data->ioc_obdo1);
439                 if (err)
440                         GOTO(out, err);
441
442                 err = copy_to_user((int *)arg, data, sizeof(*data));
443                 GOTO(out, err);
444         }
445
446         case OBD_IOC_SETATTR: {
447                 obd_data2conn(&conn, data);
448                 err = obd_setattr(&conn, &data->ioc_obdo1);
449                 if (err)
450                         GOTO(out, err);
451
452                 err = copy_to_user((int *)arg, data, sizeof(*data));
453                 GOTO(out, err);
454         }
455
456         case OBD_IOC_DESTROY: {
457                 obd_data2conn(&conn, data);
458
459                 err = obd_destroy(&conn, &data->ioc_obdo1);
460                 if (err)
461                         GOTO(out, err);
462
463                 err = copy_to_user((int *)arg, data, sizeof(*data));
464                 GOTO(out, err);
465         }
466
467         case OBD_IOC_BRW_WRITE:
468                 rw = OBD_BRW_WRITE;
469         case OBD_IOC_BRW_READ: {
470                 /* FIXME: use a better ioctl data struct than obd_ioctl_data.
471                  *        We don't really support multiple-obdo I/Os here,
472                  *        for example offset and count are not per-obdo.
473                  */
474                 struct obdo     *obdos[2] = { NULL, NULL };
475                 obd_count       oa_bufs[2] = { 0, 0 };
476                 struct page     **bufs = NULL;
477                 obd_size        *counts = NULL;
478                 obd_off         *offsets = NULL;
479                 obd_flag        *flags = NULL;
480                 int             num = 1;
481                 int             pages;
482                 int             i, j;
483
484                 obd_data2conn(&conn, data);
485
486                 pages = oa_bufs[0] = data->ioc_plen1 / PAGE_SIZE;
487                 if (data->ioc_obdo2.o_id) {
488                         num = 2;
489                         oa_bufs[1] = data->ioc_plen2 / PAGE_SIZE;
490                         pages += oa_bufs[1];
491                 }
492
493                 CDEBUG(D_INODE, "BRW %s with %dx%d pages\n",
494                        rw == OBD_BRW_READ ? "read" : "write",
495                        num, oa_bufs[0]);
496                 OBD_ALLOC(bufs, pages * sizeof(*bufs));
497                 OBD_ALLOC(counts, pages * sizeof(*counts));
498                 OBD_ALLOC(offsets, pages * sizeof(*offsets));
499                 OBD_ALLOC(flags, pages * sizeof(*flags));
500                 if (!bufs || !counts || !offsets || !flags) {
501                         CERROR("no memory for %d BRW per-page data\n", pages);
502                         err = -ENOMEM;
503                         GOTO(brw_free, err);
504                 }
505
506                 obdos[0] = &data->ioc_obdo1;
507                 if (num > 1)
508                         obdos[1] = &data->ioc_obdo2;
509
510                 for (i = 0, pages = 0; i < num; i++) {
511                         unsigned long off;
512                         void *from;
513
514                         from = (&data->ioc_pbuf1)[i];
515                         off = data->ioc_offset;
516
517                         for (j = 0; j < oa_bufs[i];
518                              j++, pages++, off += PAGE_SIZE, from += PAGE_SIZE){
519                                 unsigned long to;
520
521                                 to = __get_free_pages(GFP_KERNEL, 0);
522                                 if (!to) {
523                                 /*      ||
524                                     copy_from_user((void *)to,from,PAGE_SIZE))
525                                         free_pages(to, 0);
526                                  */
527                                         CERROR("no memory for brw pages\n");
528                                         err = -ENOMEM;
529                                         GOTO(brw_cleanup, err);
530                                 }
531                                 bufs[pages] = virt_to_page(to);
532                                 counts[pages] = PAGE_SIZE;
533                                 offsets[pages] = off;
534                                 flags[pages] = 0;
535                         }
536                 }
537
538                 err = obd_brw(rw, &conn, num, obdos, oa_bufs, bufs,
539                               counts, offsets, flags, NULL);
540
541                 EXIT;
542         brw_cleanup:
543                 i = pages;
544                 while (i-- > 0)
545                         __free_pages(bufs[i], 0);
546         brw_free:
547                 OBD_FREE(bufs, pages * sizeof(*bufs));
548                 OBD_FREE(counts, pages * sizeof(*counts));
549                 OBD_FREE(offsets, pages * sizeof(*offsets));
550                 OBD_FREE(flags, pages * sizeof(*flags));
551                 GOTO(out, err);
552         }
553         default:
554                 obd_data2conn(&conn, data);
555
556                 err = obd_iocontrol(cmd, &conn, len, data, NULL);
557                 if (err)
558                         GOTO(out, err);
559
560                 err = copy_to_user((int *)arg, data, len);
561                 GOTO(out, err);
562         }
563
564  out: 
565         OBD_FREE(buf, len); 
566         up(&obd_conf_sem); 
567         RETURN(err); 
568 } /* obd_class_ioctl */
569
570
571
572 /* declare character device */
573 static struct file_operations obd_psdev_fops = {
574         ioctl: obd_class_ioctl,       /* ioctl */
575         open: obd_class_open,        /* open */
576         release: obd_class_release,     /* release */
577 };
578
579 /* modules setup */
580 #define OBD_MINOR 241
581 static struct miscdevice obd_psdev = {
582         OBD_MINOR,
583         "obd_psdev",
584         &obd_psdev_fops
585 };
586
587
588 EXPORT_SYMBOL(obd_dev);
589 EXPORT_SYMBOL(obdo_cachep);
590 EXPORT_SYMBOL(obd_memory);
591 EXPORT_SYMBOL(obd_fail_loc);
592
593 EXPORT_SYMBOL(class_register_type);
594 EXPORT_SYMBOL(class_unregister_type);
595 EXPORT_SYMBOL(class_name2dev);
596 EXPORT_SYMBOL(class_uuid2dev);
597 EXPORT_SYMBOL(class_uuid2obd);
598 EXPORT_SYMBOL(class_connect);
599 EXPORT_SYMBOL(class_conn2export);
600 EXPORT_SYMBOL(class_conn2obd);
601 EXPORT_SYMBOL(class_disconnect);
602 //EXPORT_SYMBOL(class_multi_setup);
603 //EXPORT_SYMBOL(class_multi_cleanup);
604
605 static int __init init_obdclass(void)
606 {
607         int err;
608         int i;
609
610         printk(KERN_INFO "OBD class driver  v0.9, info@clusterfs.com\n");
611
612         sema_init(&obd_conf_sem, 1); 
613         INIT_LIST_HEAD(&obd_types);
614
615         if ((err = misc_register(&obd_psdev))) {
616                 CERROR("cannot register %d err %d\n", OBD_MINOR, err);
617                 return err;
618         }
619
620         for (i = 0; i < MAX_OBD_DEVICES; i++) {
621                 memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
622                 obd_dev[i].obd_minor = i;
623                 INIT_LIST_HEAD(&obd_dev[i].obd_exports);
624         }
625
626         err = obd_init_caches();
627         if (err)
628                 return err;
629         obd_sysctl_init();
630         return 0;
631 }
632
633 static void __exit cleanup_obdclass(void)
634 {
635         int i;
636         ENTRY;
637
638         misc_deregister(&obd_psdev);
639         for (i = 0; i < MAX_OBD_DEVICES; i++) {
640                 struct obd_device *obd = &obd_dev[i];
641                 if (obd->obd_type && (obd->obd_flags & OBD_SET_UP) &&
642                     OBT(obd) && OBP(obd, detach)) {
643                         /* XXX should this call generic detach otherwise? */
644                         OBP(obd, detach)(obd);
645                 }
646         }
647
648         obd_cleanup_caches();
649         obd_sysctl_clean();
650         CERROR("obd memory leaked: %ld bytes\n", obd_memory);
651         EXIT;
652 }
653
654 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
655 MODULE_DESCRIPTION("Lustre Class Driver v1.0");
656 MODULE_LICENSE("GPL");
657
658 module_init(init_obdclass);
659 module_exit(cleanup_obdclass);