Whamcloud - gitweb
- Make now correctly rebuilds
[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/sched.h>
23 #include <linux/lp.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>
30 #include <linux/fs.h>
31 #include <linux/poll.h>
32 #include <linux/init.h>
33 #include <linux/list.h>
34 #include <asm/io.h>
35 #include <asm/system.h>
36 #include <asm/poll.h>
37 #include <asm/uaccess.h>
38 #include <linux/miscdevice.h>
39
40 #define DEBUG_SUBSYSTEM S_CLASS
41
42 #include <linux/obd_support.h>
43 #include <linux/obd_class.h>
44 #include <linux/smp_lock.h>
45
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;
51
52 extern struct obd_type *class_nm_to_type(char *nm);
53
54 /*  opening /dev/obd */
55 static int obd_class_open(struct inode * inode, struct file * file)
56 {
57         ENTRY;
58
59         file->private_data = NULL;
60         MOD_INC_USE_COUNT;
61         RETURN(0);
62 }
63
64 /*  closing /dev/obd */
65 static int obd_class_release(struct inode * inode, struct file * file)
66 {
67         ENTRY;
68
69         if (file->private_data)
70                 file->private_data = NULL;
71
72         MOD_DEC_USE_COUNT;
73         RETURN(0);
74 }
75
76
77 inline void obd_data2conn(struct lustre_handle *conn, struct obd_ioctl_data *data)
78 {
79         conn->addr = data->ioc_addr;
80         conn->cookie = data->ioc_cookie;
81 }
82
83
84 inline void obd_conn2data(struct obd_ioctl_data *data, struct lustre_handle *conn)
85 {
86         data->ioc_addr = conn->addr;
87         data->ioc_cookie = conn->cookie;
88 }
89
90
91 /* to control /dev/obd */
92 static int obd_class_ioctl (struct inode * inode, struct file * filp,
93                             unsigned int cmd, unsigned long arg)
94 {
95         char *buf = NULL;
96         int len = 0;
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;
101         int err = 0;
102         ENTRY;
103
104         down(&obd_conf_sem); 
105
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);
111         }
112         if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
113                 CERROR("OBD ioctl: data error\n");
114                 GOTO(out, err=-EINVAL);
115         }
116         data = (struct obd_ioctl_data *)buf;
117
118         switch (cmd) {
119         case TCGETS:
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);
126                 }
127                 CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
128
129                 filp->private_data = &obd_dev[data->ioc_dev];
130                 GOTO(out, err=0);
131         }
132
133         case OBD_IOC_LIST: {
134                 int i;
135                 char *buf2 = data->ioc_bulk;
136                 int remains = data->ioc_inllen1;
137
138                 if (!data->ioc_inlbuf1) {
139                         CERROR("No buffer passed!\n");
140                         GOTO(out, err=-EINVAL);
141                 }
142
143
144                 for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
145                         int l;
146                         char *status;
147                         struct obd_device *obd = &obd_dev[i];
148                         if (!obd->obd_type) 
149                                 continue;
150                         if (obd->obd_flags & OBD_SET_UP)
151                                 status = "*";
152                         else 
153                                 status = " ";
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);
157                         buf2 +=l;
158                         remains -=l;
159                         if (remains <= 0) { 
160                                 CERROR("not enough space for device listing\n");
161                                 break;
162                         }
163                 }
164
165                 err = copy_to_user((int *)arg, data, len);
166                 GOTO(out, err);
167         }
168
169
170         case OBD_IOC_NAME2DEV: {
171                 /* Resolve a device name.  This does not change the
172                  * currently selected device.
173                  */
174                 int dev;
175
176                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1 ) {
177                         CERROR("No name passed,!\n");
178                         GOTO(out, err=-EINVAL);
179                 }
180                 if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
181                         CERROR("Name not nul terminated!\n");
182                         GOTO(out, err=-EINVAL);
183                 }
184
185                 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
186                 dev = class_name2dev(data->ioc_inlbuf1);
187                 data->ioc_dev = dev;
188                 if (dev == -1) {
189                         CDEBUG(D_IOCTL, "No device for name %s!\n",
190                                data->ioc_inlbuf1);
191                         GOTO(out, err=-EINVAL);
192                 }
193
194                 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
195                        dev);
196                 err = copy_to_user((int *)arg, data, sizeof(*data));
197                 GOTO(out, err);
198         }
199
200         case OBD_IOC_UUID2DEV: {
201                 /* Resolve a device uuid.  This does not change the
202                  * currently selected device.
203                  */
204                 int dev;
205
206                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
207                         CERROR("No UUID passed!\n");
208                         GOTO(out, err=-EINVAL);
209                 }
210                 if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
211                         CERROR("Name not nul terminated!\n");
212                         GOTO(out, err=-EINVAL);
213                 }
214
215                 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
216                 dev = class_uuid2dev(data->ioc_inlbuf1);
217                 data->ioc_dev = dev;
218                 if (dev == -1) {
219                         CDEBUG(D_IOCTL, "No device for name %s!\n",
220                                data->ioc_inlbuf1);
221                         GOTO(out, err=-EINVAL);
222                 }
223
224                 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
225                        dev);
226                 err = copy_to_user((int *)arg, data, sizeof(*data));
227                 GOTO(out, err);
228         }
229
230         case OBD_IOC_NEWDEV: {
231                 int dev = -1;
232                 int i;
233
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;
239                                 dev = i;
240                                 break;
241                         }
242                 }
243
244
245                 data->ioc_dev = dev;
246                 if (dev == -1)
247                         GOTO(out, err=-EINVAL);
248
249                 err = copy_to_user((int *)arg, data, sizeof(*data));
250                 GOTO(out, err);
251         }
252
253         case OBD_IOC_ATTACH: {
254                 struct obd_type *type;
255
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);
261                 }
262
263                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
264                         CERROR("No type passed!\n");
265                         GOTO(out, err=-EINVAL);
266                 }
267                 if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
268                         CERROR("Type not nul terminated!\n");
269                         GOTO(out, err=-EINVAL);
270                 }
271
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));
275
276                 /* find the type */
277
278                 type = class_nm_to_type(data->ioc_inlbuf1);
279                 if (!type) {
280                         CERROR("OBD: unknown type dev %d\n", obd->obd_minor);
281                         GOTO(out, err=-EINVAL);
282                 }
283
284                 obd->obd_type = type;
285                 INIT_LIST_HEAD(&obd->obd_exports);
286
287                 /* do the attach */
288                 if (OBT(obd) && OBP(obd, attach))
289                         err = OBP(obd,attach)(obd, sizeof(*data), data);
290                 if (err) {
291                         obd->obd_type = NULL;
292                 } else {
293                         obd->obd_flags |= OBD_ATTACHED;
294                         type->typ_refcnt++;
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");
302                                         LBUG();
303                                 }
304                                 memcpy(obd->obd_name, data->ioc_inlbuf2, len);
305                                 //obd->obd_proc_entry =
306                                 //        proc_lustre_register_obd_device(obd);
307                         } else { 
308                                 CERROR("WARNING: unnamed obd device\n");
309                                 obd->obd_proc_entry = NULL;
310                         }
311
312                         if (data->ioc_inlbuf3) {
313                                 int len = strlen(data->ioc_inlbuf3);
314                                 if (len > 37) { 
315                                         CERROR("uuid should be shorter than 37 bytes\n");
316                                         if (obd->obd_name)
317                                                 OBD_FREE(obd->obd_name, 
318                                                          strlen(obd->obd_name) + 1);
319                                         GOTO(out, err=-EINVAL);
320                                 }
321                                 memcpy(obd->obd_uuid, data->ioc_inlbuf3, 
322                                        sizeof(obd->obd_uuid));
323                         }
324
325                         MOD_INC_USE_COUNT;
326                 }
327
328                 GOTO(out, err);
329         }
330
331         case OBD_IOC_DETACH: {
332                 ENTRY;
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);
336                 }
337                 if (! (obd->obd_flags & OBD_ATTACHED) ) {
338                         CERROR("OBD device %d not attached\n", obd->obd_minor);
339                         GOTO(out, err=-ENODEV);
340                 }
341                 if ( !list_empty(&obd->obd_exports) ) {
342                         CERROR("OBD device %d has exports\n",
343                                obd->obd_minor);
344                         GOTO(out, err=-EBUSY);
345                 }
346
347                 if (obd->obd_name) {
348                         OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
349                         obd->obd_name = NULL;
350                 }
351
352                 //if (obd->obd_proc_entry)
353                   //      proc_lustre_release_obd_device(obd);
354
355                 obd->obd_flags &= ~OBD_ATTACHED;
356                 obd->obd_type->typ_refcnt--;
357                 obd->obd_type = NULL;
358                 MOD_DEC_USE_COUNT;
359                 GOTO(out, err=0);
360         }
361
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);
367                 }
368
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);
374                 }
375
376                 if ( OBT(obd) && OBP(obd, setup) )
377                         err = obd_setup(obd, sizeof(*data), data);
378
379                 if (!err) {
380                         obd->obd_type->typ_refcnt++;
381                         obd->obd_flags |= OBD_SET_UP;
382                 }
383
384                 GOTO(out, err);
385         }
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);
391                 }
392
393                 if ( OBT(obd) && OBP(obd, cleanup) )
394                         err = obd_cleanup(obd);
395
396                 if (!err) {
397                         obd->obd_flags &= ~OBD_SET_UP;
398                         obd->obd_type->typ_refcnt--;
399                 }
400                 GOTO(out, err);
401         }
402
403         case OBD_IOC_CONNECT: {
404                 obd_data2conn(&conn, data); 
405
406                 err = obd_connect(&conn, obd);
407
408                 CDEBUG(D_IOCTL, "assigned export %Lx\n", conn.addr);
409                 obd_conn2data(data, &conn);
410                 if (err)
411                         GOTO(out, err);
412
413                 err = copy_to_user((int *)arg, data, sizeof(*data));
414                 GOTO(out, err);
415         }
416
417         case OBD_IOC_DISCONNECT: {
418                 obd_data2conn(&conn, data);
419                 err = obd_disconnect(&conn);
420                 GOTO(out, err);
421         }
422
423         case OBD_IOC_DEC_USE_COUNT: {
424                 MOD_DEC_USE_COUNT;
425                 GOTO(out, err=0);
426         }
427
428         case OBD_IOC_CREATE: {
429                 obd_data2conn(&conn, data);
430
431
432                 err = obd_create(&conn, &data->ioc_obdo1);
433                 if (err)
434                         GOTO(out, err);
435
436                 err = copy_to_user((int *)arg, data, sizeof(*data));
437                 GOTO(out, err);
438         }
439
440         case OBD_IOC_GETATTR: {
441
442                 obd_data2conn(&conn, data);
443                 err = obd_getattr(&conn, &data->ioc_obdo1);
444                 if (err)
445                         GOTO(out, err);
446
447                 err = copy_to_user((int *)arg, data, sizeof(*data));
448                 GOTO(out, err);
449         }
450
451         case OBD_IOC_SETATTR: {
452                 obd_data2conn(&conn, data);
453                 err = obd_setattr(&conn, &data->ioc_obdo1);
454                 if (err)
455                         GOTO(out, err);
456
457                 err = copy_to_user((int *)arg, data, sizeof(*data));
458                 GOTO(out, err);
459         }
460
461         case OBD_IOC_DESTROY: {
462                 obd_data2conn(&conn, data);
463
464                 err = obd_destroy(&conn, &data->ioc_obdo1);
465                 if (err)
466                         GOTO(out, err);
467
468                 err = copy_to_user((int *)arg, data, sizeof(*data));
469                 GOTO(out, err);
470         }
471
472         case OBD_IOC_BRW_WRITE:
473                 rw = OBD_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.
478                  */
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;
485                 int             num = 1;
486                 int             pages;
487                 int             i, j;
488
489                 obd_data2conn(&conn, data);
490
491                 pages = oa_bufs[0] = data->ioc_plen1 / PAGE_SIZE;
492                 if (data->ioc_obdo2.o_id) {
493                         num = 2;
494                         oa_bufs[1] = data->ioc_plen2 / PAGE_SIZE;
495                         pages += oa_bufs[1];
496                 }
497
498                 CDEBUG(D_INODE, "BRW %s with %dx%d pages\n",
499                        rw == OBD_BRW_READ ? "read" : "write",
500                        num, oa_bufs[0]);
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);
507                         err = -ENOMEM;
508                         GOTO(brw_free, err);
509                 }
510
511                 obdos[0] = &data->ioc_obdo1;
512                 if (num > 1)
513                         obdos[1] = &data->ioc_obdo2;
514
515                 for (i = 0, pages = 0; i < num; i++) {
516                         unsigned long off;
517                         void *from;
518
519                         from = (&data->ioc_pbuf1)[i];
520                         off = data->ioc_offset;
521
522                         for (j = 0; j < oa_bufs[i];
523                              j++, pages++, off += PAGE_SIZE, from += PAGE_SIZE){
524                                 unsigned long to;
525
526                                 to = __get_free_pages(GFP_KERNEL, 0);
527                                 if (!to) {
528                                 /*      ||
529                                     copy_from_user((void *)to,from,PAGE_SIZE))
530                                         free_pages(to, 0);
531                                  */
532                                         CERROR("no memory for brw pages\n");
533                                         err = -ENOMEM;
534                                         GOTO(brw_cleanup, err);
535                                 }
536                                 bufs[pages] = virt_to_page(to);
537                                 counts[pages] = PAGE_SIZE;
538                                 offsets[pages] = off;
539                                 flags[pages] = 0;
540                         }
541                 }
542
543                 err = obd_brw(rw, &conn, num, obdos, oa_bufs, bufs,
544                               counts, offsets, flags, NULL);
545
546                 EXIT;
547         brw_cleanup:
548                 i = pages;
549                 while (i-- > 0)
550                         __free_pages(bufs[i], 0);
551         brw_free:
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));
556                 GOTO(out, err);
557         }
558         default:
559                 obd_data2conn(&conn, data);
560
561                 err = obd_iocontrol(cmd, &conn, len, data, NULL);
562                 if (err)
563                         GOTO(out, err);
564
565                 err = copy_to_user((int *)arg, data, len);
566                 GOTO(out, err);
567         }
568
569  out: 
570         if (buf) 
571                 OBD_FREE(buf, len); 
572         up(&obd_conf_sem); 
573         RETURN(err); 
574 } /* obd_class_ioctl */
575
576
577
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 */
583 };
584
585 /* modules setup */
586 #define OBD_MINOR 241
587 static struct miscdevice obd_psdev = {
588         OBD_MINOR,
589         "obd_psdev",
590         &obd_psdev_fops
591 };
592
593
594 EXPORT_SYMBOL(obd_dev);
595 EXPORT_SYMBOL(obdo_cachep);
596 EXPORT_SYMBOL(obd_memory);
597 EXPORT_SYMBOL(obd_fail_loc);
598
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);
610
611 static int __init init_obdclass(void)
612 {
613         int err;
614         int i;
615
616         printk(KERN_INFO "OBD class driver  v0.9, info@clusterfs.com\n");
617
618         sema_init(&obd_conf_sem, 1); 
619         INIT_LIST_HEAD(&obd_types);
620
621         if ((err = misc_register(&obd_psdev))) {
622                 CERROR("cannot register %d err %d\n", OBD_MINOR, err);
623                 return err;
624         }
625
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);
630         }
631
632         err = obd_init_caches();
633         if (err)
634                 return err;
635         obd_sysctl_init();
636         return 0;
637 }
638
639 static void __exit cleanup_obdclass(void)
640 {
641         int i;
642         ENTRY;
643
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);
651                 }
652         }
653
654         obd_cleanup_caches();
655         obd_sysctl_clean();
656         CERROR("obd memory leaked: %ld bytes\n", obd_memory);
657         EXIT;
658 }
659
660 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
661 MODULE_DESCRIPTION("Lustre Class Driver v1.0");
662 MODULE_LICENSE("GPL");
663
664 module_init(init_obdclass);
665 module_exit(cleanup_obdclass);