Whamcloud - gitweb
merge b_devel into HEAD, which will become 0.7.3
[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  * Object Devices Class Driver
5  *
6  *  Copyright (C) 2001-2003 Cluster File Systems, Inc.
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  * These are the only exported functions, they provide some generic
24  * infrastructure for managing object devices
25  */
26
27 #define DEBUG_SUBSYSTEM S_CLASS
28 #define EXPORT_SYMTAB
29 #ifdef __KERNEL__
30 #include <linux/config.h> /* for CONFIG_PROC_FS */
31 #include <linux/module.h>
32 #include <linux/errno.h>
33 #include <linux/kernel.h>
34 #include <linux/major.h>
35 #include <linux/sched.h>
36 #include <linux/lp.h>
37 #include <linux/slab.h>
38 #include <linux/ioport.h>
39 #include <linux/fcntl.h>
40 #include <linux/delay.h>
41 #include <linux/skbuff.h>
42 #include <linux/proc_fs.h>
43 #include <linux/fs.h>
44 #include <linux/poll.h>
45 #include <linux/init.h>
46 #include <linux/list.h>
47 #include <linux/highmem.h>
48 #include <asm/io.h>
49 #include <asm/ioctls.h>
50 #include <asm/system.h>
51 #include <asm/poll.h>
52 #include <asm/uaccess.h>
53 #include <linux/miscdevice.h>
54 #include <linux/smp_lock.h>
55 #else
56 # include <liblustre.h>
57 #endif
58
59 #include <linux/obd_support.h>
60 #include <linux/obd_class.h>
61 #include <linux/lustre_debug.h>
62 #include <linux/lprocfs_status.h>
63 #include <portals/lib-types.h> /* for PTL_MD_MAX_IOV */
64 #include <linux/lustre_build_version.h>
65 #include <portals/list.h>
66
67 struct semaphore obd_conf_sem;   /* serialize configuration commands */
68 struct obd_device obd_dev[MAX_OBD_DEVICES];
69 struct list_head obd_types;
70 atomic_t obd_memory;
71 int obd_memmax;
72
73 /* Root for /proc/lustre */
74 struct proc_dir_entry *proc_lustre_root = NULL;
75 int obd_proc_read_version(char *page, char **start, off_t off, int count, int *eof, void *data);
76 struct lprocfs_vars lprocfs_version[] = {{"version", obd_proc_read_version, NULL, NULL },{NULL,NULL,NULL,NULL}};
77 int proc_version;
78
79 /* The following are visible and mutable through /proc/sys/lustre/. */
80 unsigned long obd_fail_loc;
81 unsigned long obd_timeout = 100;
82 unsigned long obd_bulk_timeout = 1;
83 char obd_lustre_upcall[128] = "/usr/lib/lustre/lustre_upcall";
84 unsigned long obd_sync_filter; /* = 0, don't sync by default */
85
86 #ifdef __KERNEL__
87 /*  opening /dev/obd */
88 static int obd_class_open(struct inode * inode, struct file * file)
89 {
90         struct obd_class_user_state *ocus;
91         ENTRY;
92
93         OBD_ALLOC(ocus, sizeof(*ocus));
94         if (ocus == NULL)
95                 return (-ENOMEM);
96
97         INIT_LIST_HEAD(&ocus->ocus_conns);
98         file->private_data = ocus;
99
100         PORTAL_MODULE_USE;
101         RETURN(0);
102 }
103
104 /*  closing /dev/obd */
105 static int obd_class_release(struct inode * inode, struct file * file)
106 {
107         struct obd_class_user_state *ocus = file->private_data;
108         struct obd_class_user_conn  *c;
109         ENTRY;
110
111         while (!list_empty (&ocus->ocus_conns)) {
112                 c = list_entry (ocus->ocus_conns.next,
113                                 struct obd_class_user_conn, ocuc_chain);
114                 list_del (&c->ocuc_chain);
115
116                 CDEBUG (D_IOCTL, "Auto-disconnect %p\n", &c->ocuc_conn);
117
118                 down (&obd_conf_sem);
119                 obd_disconnect (&c->ocuc_conn, 0);
120                 up (&obd_conf_sem);
121
122                 OBD_FREE (c, sizeof (*c));
123         }
124
125         OBD_FREE (ocus, sizeof (*ocus));
126
127         PORTAL_MODULE_UNUSE;
128         RETURN(0);
129 }
130 #endif
131
132 static int
133 obd_class_add_user_conn (struct obd_class_user_state *ocus,
134                          struct lustre_handle *conn)
135 {
136         struct obd_class_user_conn *c;
137
138         /* NB holding obd_conf_sem */
139
140         OBD_ALLOC (c, sizeof (*c));
141         if (ocus == NULL)
142                 return (-ENOMEM);
143
144         c->ocuc_conn = *conn;
145         list_add (&c->ocuc_chain, &ocus->ocus_conns);
146         return (0);
147 }
148
149 static void
150 obd_class_remove_user_conn (struct obd_class_user_state *ocus,
151                             struct lustre_handle *conn)
152 {
153         struct list_head *e;
154         struct obd_class_user_conn *c;
155
156         /* NB holding obd_conf_sem or last reference */
157
158         list_for_each (e, &ocus->ocus_conns) {
159                 c = list_entry (e, struct obd_class_user_conn, ocuc_chain);
160                 if (conn->cookie == c->ocuc_conn.cookie) {
161                         list_del (&c->ocuc_chain);
162                         OBD_FREE (c, sizeof (*c));
163                         return;
164                 }
165         }
166 }
167
168 static inline void obd_data2conn(struct lustre_handle *conn,
169                                  struct obd_ioctl_data *data)
170 {
171         memset(conn, 0, sizeof *conn);
172         conn->cookie = data->ioc_cookie;
173 }
174
175 static inline void obd_conn2data(struct obd_ioctl_data *data,
176                                  struct lustre_handle *conn)
177 {
178         data->ioc_cookie = conn->cookie;
179 }
180
181 static void dump_exports(struct obd_device *obd)
182 {
183         struct obd_export *exp, *n;
184
185         list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) {
186                 CERROR("%s: %p %s %d %d %p\n",
187                        obd->obd_name, exp, exp->exp_client_uuid.uuid,
188                        atomic_read(&exp->exp_refcount),
189                        exp->exp_failed, exp->exp_outstanding_reply );
190         }
191 }
192
193 int class_handle_ioctl(struct obd_class_user_state *ocus, unsigned int cmd,
194                        unsigned long arg)
195 {
196         char *buf = NULL;
197         struct obd_ioctl_data *data;
198         struct portals_debug_ioctl_data *debug_data;
199         struct obd_device *obd = ocus->ocus_current_obd;
200         struct lustre_handle conn;
201         int err = 0, len = 0, serialised = 0;
202         ENTRY;
203
204         if ((cmd & 0xffffff00) == ((int)'T') << 8) /* ignore all tty ioctls */
205                 RETURN(err = -ENOTTY);
206
207         /* only for debugging */
208         if (cmd == PTL_IOC_DEBUG_MASK) {
209                 debug_data = (struct portals_debug_ioctl_data*)arg;
210                 portal_subsystem_debug = debug_data->subs;
211                 portal_debug = debug_data->debug;
212                 return 0;
213         }
214
215         switch (cmd) {
216         case OBD_IOC_BRW_WRITE:
217         case OBD_IOC_BRW_READ:
218         case OBD_IOC_GETATTR:
219         case ECHO_IOC_ENQUEUE:
220         case ECHO_IOC_CANCEL:
221                 break;
222         default:
223                 down(&obd_conf_sem);
224                 serialised = 1;
225                 break;
226         }
227
228         CDEBUG(D_IOCTL, "cmd = %x, obd = %p\n", cmd, obd);
229         if (!obd && cmd != OBD_IOC_DEVICE &&
230             cmd != OBD_IOC_LIST && cmd != OBD_GET_VERSION &&
231             cmd != OBD_IOC_NAME2DEV && cmd != OBD_IOC_UUID2DEV &&
232             cmd != OBD_IOC_NEWDEV && cmd != OBD_IOC_ADD_UUID &&
233             cmd != OBD_IOC_DEL_UUID && cmd != OBD_IOC_CLOSE_UUID) {
234                 CERROR("OBD ioctl: No device\n");
235                 GOTO(out, err = -EINVAL);
236         }
237         if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
238                 CERROR("OBD ioctl: data error\n");
239                 GOTO(out, err = -EINVAL);
240         }
241         data = (struct obd_ioctl_data *)buf;
242
243         switch (cmd) {
244         case OBD_IOC_DEVICE: {
245                 CDEBUG(D_IOCTL, "\n");
246                 if (data->ioc_dev >= MAX_OBD_DEVICES || data->ioc_dev < 0) {
247                         CERROR("OBD ioctl: DEVICE invalid device %d\n",
248                                data->ioc_dev);
249                         GOTO(out, err = -EINVAL);
250                 }
251                 CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
252
253                 ocus->ocus_current_obd = &obd_dev[data->ioc_dev];
254                 GOTO(out, err = 0);
255         }
256
257         case OBD_IOC_LIST: {
258                 int i;
259                 char *buf2 = data->ioc_bulk;
260                 int remains = data->ioc_inllen1;
261
262                 if (!data->ioc_inlbuf1) {
263                         CERROR("No buffer passed!\n");
264                         GOTO(out, err = -EINVAL);
265                 }
266
267
268                 for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
269                         int l;
270                         char *status;
271                         struct obd_device *obd = &obd_dev[i];
272
273                         if (!obd->obd_type)
274                                 continue;
275                         if (obd->obd_stopping)
276                                 status = "ST";
277                         else if (obd->obd_set_up)
278                                 status = "UP";
279                         else if (obd->obd_attached)
280                                 status = "AT";
281                         else
282                                 status = "-";
283                         l = snprintf(buf2, remains, "%2d %s %s %s %s %d\n",
284                                      i, status, obd->obd_type->typ_name,
285                                      obd->obd_name, obd->obd_uuid.uuid,
286                                      obd->obd_type->typ_refcnt);
287                         buf2 +=l;
288                         remains -=l;
289                         if (remains <= 0) {
290                                 CERROR("not enough space for device listing\n");
291                                 break;
292                         }
293                 }
294
295                 err = copy_to_user((void *)arg, data, len);
296                 if (err)
297                         err = -EFAULT;
298                 GOTO(out, err);
299         }
300
301         case OBD_GET_VERSION:
302                 if (!data->ioc_inlbuf1) {
303                         CERROR("No buffer passed in ioctl\n");
304                         GOTO(out, err = -EINVAL);
305                 }
306
307                 if (strlen(BUILD_VERSION) + 1 > data->ioc_inllen1) {
308                         CERROR("ioctl buffer too small to hold version\n");
309                         GOTO(out, err = -EINVAL);
310                 }
311
312                 memcpy(data->ioc_bulk, BUILD_VERSION,
313                        strlen(BUILD_VERSION) + 1);
314
315                 err = copy_to_user((void *)arg, data, len);
316                 if (err)
317                         err = -EFAULT;
318                 GOTO(out, err);
319
320         case OBD_IOC_NAME2DEV: {
321                 /* Resolve a device name.  This does not change the
322                  * currently selected device.
323                  */
324                 int dev;
325
326                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1 ) {
327                         CERROR("No name passed,!\n");
328                         GOTO(out, err = -EINVAL);
329                 }
330                 if (data->ioc_inlbuf1[data->ioc_inllen1 - 1] != 0) {
331                         CERROR("Name not nul terminated!\n");
332                         GOTO(out, err = -EINVAL);
333                 }
334
335                 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
336                 dev = class_name2dev(data->ioc_inlbuf1);
337                 data->ioc_dev = dev;
338                 if (dev == -1) {
339                         CDEBUG(D_IOCTL, "No device for name %s!\n",
340                                data->ioc_inlbuf1);
341                         GOTO(out, err = -EINVAL);
342                 }
343
344                 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
345                        dev);
346                 err = copy_to_user((void *)arg, data, sizeof(*data));
347                 if (err)
348                         err = -EFAULT;
349                 GOTO(out, err);
350         }
351
352         case OBD_IOC_UUID2DEV: {
353                 /* Resolve a device uuid.  This does not change the
354                  * currently selected device.
355                  */
356                 int dev;
357                 struct obd_uuid uuid;
358
359                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
360                         CERROR("No UUID passed!\n");
361                         GOTO(out, err = -EINVAL);
362                 }
363                 if (data->ioc_inlbuf1[data->ioc_inllen1 - 1] != 0) {
364                         CERROR("UUID not NUL terminated!\n");
365                         GOTO(out, err = -EINVAL);
366                 }
367
368                 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
369                 obd_str2uuid(&uuid, data->ioc_inlbuf1);
370                 dev = class_uuid2dev(&uuid);
371                 data->ioc_dev = dev;
372                 if (dev == -1) {
373                         CDEBUG(D_IOCTL, "No device for UUID %s!\n",
374                                data->ioc_inlbuf1);
375                         GOTO(out, err = -EINVAL);
376                 }
377
378                 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
379                        dev);
380                 err = copy_to_user((void *)arg, data, sizeof(*data));
381                 if (err)
382                         err = -EFAULT;
383                 GOTO(out, err);
384         }
385
386
387
388         case OBD_IOC_NEWDEV: {
389                 int dev = -1;
390                 int i;
391
392                 ocus->ocus_current_obd = NULL;
393                 for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
394                         struct obd_device *obd = &obd_dev[i];
395                         if (!obd->obd_type) {
396                                 ocus->ocus_current_obd = obd;
397                                 dev = i;
398                                 break;
399                         }
400                 }
401
402
403                 data->ioc_dev = dev;
404                 if (dev == -1)
405                         GOTO(out, err = -EINVAL);
406
407                 err = copy_to_user((void *)arg, data, sizeof(*data));
408                 if (err)
409                         err = -EFAULT;
410                 GOTO(out, err);
411         }
412
413         case OBD_IOC_ATTACH: {
414                 struct obd_type *type;
415                 int minor, len;
416
417                 /* have we attached a type to this device */
418                 if (obd->obd_attached|| obd->obd_type) {
419                         CERROR("OBD: Device %d already typed as %s.\n",
420                                obd->obd_minor, MKSTR(obd->obd_type->typ_name));
421                         GOTO(out, err = -EBUSY);
422                 }
423
424                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
425                         CERROR("No type passed!\n");
426                         GOTO(out, err = -EINVAL);
427                 }
428                 if (data->ioc_inlbuf1[data->ioc_inllen1 - 1] != 0) {
429                         CERROR("Type not nul terminated!\n");
430                         GOTO(out, err = -EINVAL);
431                 }
432                 if (!data->ioc_inllen2 || !data->ioc_inlbuf2) {
433                         CERROR("No name passed!\n");
434                         GOTO(out, err = -EINVAL);
435                 }
436                 if (data->ioc_inlbuf2[data->ioc_inllen2 - 1] != 0) {
437                         CERROR("Name not nul terminated!\n");
438                         GOTO(out, err = -EINVAL);
439                 }
440                 if (!data->ioc_inllen3 || !data->ioc_inlbuf3) {
441                         CERROR("No UUID passed!\n");
442                         GOTO(out, err = -EINVAL);
443                 }
444                 if (data->ioc_inlbuf3[data->ioc_inllen3 - 1] != 0) {
445                         CERROR("UUID not nul terminated!\n");
446                         GOTO(out, err = -EINVAL);
447                 }
448
449                 CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
450                        MKSTR(data->ioc_inlbuf1),
451                        MKSTR(data->ioc_inlbuf2), MKSTR(data->ioc_inlbuf3));
452
453                 /* find the type */
454                 type = class_get_type(data->ioc_inlbuf1);
455                 if (!type) {
456                         CERROR("OBD: unknown type dev %d\n", obd->obd_minor);
457                         GOTO(out, err = -EINVAL);
458                 }
459
460                 minor = obd->obd_minor;
461                 memset(obd, 0, sizeof(*obd));
462                 obd->obd_minor = minor;
463                 obd->obd_type = type;
464                 INIT_LIST_HEAD(&obd->obd_exports);
465                 obd->obd_num_exports = 0;
466                 INIT_LIST_HEAD(&obd->obd_imports);
467                 spin_lock_init(&obd->obd_dev_lock);
468                 init_waitqueue_head(&obd->obd_refcount_waitq);
469
470                 /* XXX belong ins setup not attach  */
471                 /* recovery data */
472                 spin_lock_init(&obd->obd_processing_task_lock);
473                 init_waitqueue_head(&obd->obd_next_transno_waitq);
474                 INIT_LIST_HEAD(&obd->obd_recovery_queue);
475                 INIT_LIST_HEAD(&obd->obd_delayed_reply_queue);
476
477                 init_waitqueue_head(&obd->obd_commit_waitq);
478
479                 len = strlen(data->ioc_inlbuf2) + 1;
480                 OBD_ALLOC(obd->obd_name, len);
481                 if (!obd->obd_name) {
482                         class_put_type(obd->obd_type);
483                         obd->obd_type = NULL;
484                         GOTO(out, err = -ENOMEM);
485                 }
486                 memcpy(obd->obd_name, data->ioc_inlbuf2, len);
487
488                 len = strlen(data->ioc_inlbuf3);
489                 if (len >= sizeof(obd->obd_uuid)) {
490                         CERROR("uuid must be < "LPSZ" bytes long\n",
491                                sizeof(obd->obd_uuid));
492                         if (obd->obd_name)
493                                 OBD_FREE(obd->obd_name,
494                                          strlen(obd->obd_name) + 1);
495                         class_put_type(obd->obd_type);
496                         obd->obd_type = NULL;
497                         GOTO(out, err = -EINVAL);
498                 }
499                 memcpy(obd->obd_uuid.uuid, data->ioc_inlbuf3, len);
500
501                 /* do the attach */
502                 if (OBP(obd, attach))
503                         err = OBP(obd,attach)(obd, sizeof(*data), data);
504                 if (err) {
505                         if(data->ioc_inlbuf2)
506                                 OBD_FREE(obd->obd_name,
507                                          strlen(obd->obd_name) + 1);
508                         class_put_type(obd->obd_type);
509                         obd->obd_type = NULL;
510                 } else {
511                         obd->obd_attached = 1;
512
513                         type->typ_refcnt++;
514                         CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
515                                obd->obd_minor, data->ioc_inlbuf1);
516                 }
517
518                 GOTO(out, err);
519         }
520
521         case OBD_IOC_DETACH: {
522                 ENTRY;
523                 if (obd->obd_set_up) {
524                         CERROR("OBD device %d still set up\n", obd->obd_minor);
525                         GOTO(out, err = -EBUSY);
526                 }
527                 if (!obd->obd_attached) {
528                         CERROR("OBD device %d not attached\n", obd->obd_minor);
529                         GOTO(out, err = -ENODEV);
530                 }
531                 if (OBP(obd, detach))
532                         err = OBP(obd,detach)(obd);
533
534                 if (obd->obd_name) {
535                         OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
536                         obd->obd_name = NULL;
537                 }
538
539                 obd->obd_attached = 0;
540                 obd->obd_type->typ_refcnt--;
541                 class_put_type(obd->obd_type);
542                 obd->obd_type = NULL;
543                 memset(obd, 0, sizeof(*obd));
544                 GOTO(out, err = 0);
545         }
546
547         case OBD_IOC_SETUP: {
548                 /* have we attached a type to this device? */
549                 if (!obd->obd_attached) {
550                         CERROR("Device %d not attached\n", obd->obd_minor);
551                         GOTO(out, err = -ENODEV);
552                 }
553
554                 /* has this been done already? */
555                 if (obd->obd_set_up) {
556                         CERROR("Device %d already setup (type %s)\n",
557                                obd->obd_minor, obd->obd_type->typ_name);
558                         GOTO(out, err = -EBUSY);
559                 }
560
561                 atomic_set(&obd->obd_refcount, 0);
562
563                 if (OBT(obd) && OBP(obd, setup))
564                         err = obd_setup(obd, sizeof(*data), data);
565
566                 if (!err) {
567                         obd->obd_type->typ_refcnt++;
568                         obd->obd_set_up = 1;
569                         atomic_inc(&obd->obd_refcount);
570                 }
571
572                 GOTO(out, err);
573         }
574         case OBD_IOC_CLEANUP: {
575                 int flags = 0;
576                 char *flag;
577
578                 if (!obd->obd_set_up) {
579                         CERROR("Device %d not setup\n", obd->obd_minor);
580                         GOTO(out, err = -ENODEV);
581                 }
582
583                 if (data->ioc_inlbuf1) {
584                         for (flag = data->ioc_inlbuf1; *flag != 0; flag++)
585                                 switch (*flag) {
586                                 case 'F':
587                                         flags |= OBD_OPT_FORCE;
588                                         break;
589                                 case 'A':
590                                         flags |= OBD_OPT_FAILOVER;
591                                         break;
592                                 default:
593                                         CERROR("unrecognised flag '%c'\n",
594                                                *flag);
595                                 }
596                 }
597
598                 if (atomic_read(&obd->obd_refcount) == 1 ||
599                     flags & OBD_OPT_FORCE) {
600                         /* this will stop new connections, and need to
601                            do it before class_disconnect_exports() */
602                         obd->obd_stopping = 1;
603                 }
604
605                 if (atomic_read(&obd->obd_refcount) > 1) {
606                         struct l_wait_info lwi = LWI_TIMEOUT_INTR(60 * HZ, NULL,
607                                                                   NULL, NULL);
608                         int rc;
609
610                         if (!(flags & OBD_OPT_FORCE)) {
611                                 CERROR("OBD device %d (%p) has refcount %d\n",
612                                        obd->obd_minor, obd,
613                                        atomic_read(&obd->obd_refcount));
614                                 dump_exports(obd);
615                                 GOTO(out, err = -EBUSY);
616                         }
617                         class_disconnect_exports(obd, flags);
618                         CDEBUG(D_IOCTL,
619                                "%s: waiting for obd refs to go away: %d\n",
620                                obd->obd_name, atomic_read(&obd->obd_refcount));
621
622                         rc = l_wait_event(obd->obd_refcount_waitq,
623                                      atomic_read(&obd->obd_refcount) < 2, &lwi);
624                         if (rc == 0) {
625                                 LASSERT(atomic_read(&obd->obd_refcount) == 1);
626                         } else {
627                                 CERROR("wait cancelled cleaning anyway. "
628                                        "refcount: %d\n",
629                                        atomic_read(&obd->obd_refcount));
630                                 dump_exports(obd);
631                         }
632                         CDEBUG(D_IOCTL, "%s: awake, now finishing cleanup\n",
633                                obd->obd_name);
634                 }
635
636                 if (OBT(obd) && OBP(obd, cleanup))
637                         err = obd_cleanup(obd, flags);
638
639                 if (!err) {
640                         obd->obd_set_up = obd->obd_stopping = 0;
641                         obd->obd_type->typ_refcnt--;
642                         atomic_dec(&obd->obd_refcount);
643                         /* XXX this should be an LASSERT */
644                         if (atomic_read(&obd->obd_refcount) > 0) 
645                                 CERROR("%s still has refcount %d after "
646                                        "cleanup.\n", obd->obd_name,
647                                        atomic_read(&obd->obd_refcount));
648                 }
649
650                 GOTO(out, err);
651         }
652
653         case OBD_IOC_CONNECT: {
654                 struct obd_uuid cluuid = { "OBD_CLASS_UUID" };
655                 obd_data2conn(&conn, data);
656
657                 err = obd_connect(&conn, obd, &cluuid);
658
659                 CDEBUG(D_IOCTL, "assigned export "LPX64"\n", conn.cookie);
660                 obd_conn2data(data, &conn);
661                 if (err)
662                         GOTO(out, err);
663
664                 err = obd_class_add_user_conn (ocus, &conn);
665                 if (err != 0) {
666                         obd_disconnect (&conn, 0);
667                         GOTO (out, err);
668                 }
669
670                 err = copy_to_user((void *)arg, data, sizeof(*data));
671                 if (err != 0) {
672                         obd_class_remove_user_conn (ocus, &conn);
673                         obd_disconnect (&conn, 0);
674                         GOTO (out, err = -EFAULT);
675                 }
676                 GOTO(out, err);
677         }
678
679         case OBD_IOC_DISCONNECT: {
680                 obd_data2conn(&conn, data);
681                 obd_class_remove_user_conn (ocus, &conn);
682                 err = obd_disconnect(&conn, 0);
683                 GOTO(out, err);
684         }
685
686         case OBD_IOC_NO_TRANSNO: {
687                 if (!obd->obd_attached) {
688                         CERROR("Device %d not attached\n", obd->obd_minor);
689                         GOTO(out, err = -ENODEV);
690                 }
691                 CDEBUG(D_IOCTL,
692                        "disabling committed-transno notifications on %d\n",
693                        obd->obd_minor);
694                 obd->obd_no_transno = 1;
695                 GOTO(out, err = 0);
696         }
697
698         case OBD_IOC_CLOSE_UUID: {
699                 struct lustre_peer peer;
700                 CDEBUG(D_IOCTL, "closing all connections to uuid %s\n",
701                        data->ioc_inlbuf1);
702                 lustre_uuid_to_peer(data->ioc_inlbuf1, &peer);
703                 GOTO(out, err = 0);
704         }
705         case OBD_IOC_ADD_UUID: {
706                 CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid "LPX64
707                        ", nal %d\n", data->ioc_inlbuf1, data->ioc_nid,
708                        data->ioc_nal);
709
710                 err = class_add_uuid(data->ioc_inlbuf1, data->ioc_nid,
711                                      data->ioc_nal);
712                 GOTO(out, err);
713         }
714         case OBD_IOC_DEL_UUID: {
715                 CDEBUG(D_IOCTL, "removing mappings for uuid %s\n",
716                        data->ioc_inlbuf1 == NULL ? "<all uuids>" :
717                        data->ioc_inlbuf1);
718
719                 err = class_del_uuid(data->ioc_inlbuf1);
720                 GOTO(out, err);
721         }
722         default: { 
723                 // obd_data2conn(&conn, data);
724                 struct obd_class_user_conn *oconn = list_entry(ocus->ocus_conns.next, struct obd_class_user_conn, ocuc_chain);
725                 err = obd_iocontrol(cmd, &oconn->ocuc_conn, len, data, NULL);
726                 if (err)
727                         GOTO(out, err);
728
729                 err = copy_to_user((void *)arg, data, len);
730                 if (err)
731                         err = -EFAULT;
732                 GOTO(out, err);
733         }
734         }
735
736  out:
737         if (buf)
738                 obd_ioctl_freedata(buf, len);
739         if (serialised)
740                 up(&obd_conf_sem);
741         RETURN(err);
742 } /* class_handle_ioctl */
743
744
745
746 #define OBD_MINOR 241
747 #ifdef __KERNEL__
748 /* to control /dev/obd */
749 static int obd_class_ioctl(struct inode *inode, struct file *filp,
750                            unsigned int cmd, unsigned long arg)
751 {
752         return class_handle_ioctl(filp->private_data, cmd, arg);
753 }
754
755 /* declare character device */
756 static struct file_operations obd_psdev_fops = {
757         ioctl:   obd_class_ioctl,       /* ioctl */
758         open:    obd_class_open,        /* open */
759         release: obd_class_release,     /* release */
760 };
761
762 /* modules setup */
763 static struct miscdevice obd_psdev = {
764         OBD_MINOR,
765         "obd_psdev",
766         &obd_psdev_fops
767 };
768 #else
769 void *obd_psdev = NULL;
770 #endif
771
772 EXPORT_SYMBOL(obd_dev);
773 EXPORT_SYMBOL(obdo_cachep);
774 EXPORT_SYMBOL(obd_memory);
775 EXPORT_SYMBOL(obd_memmax);
776 EXPORT_SYMBOL(obd_fail_loc);
777 EXPORT_SYMBOL(obd_timeout);
778 EXPORT_SYMBOL(obd_lustre_upcall);
779 EXPORT_SYMBOL(obd_sync_filter);
780 EXPORT_SYMBOL(ptlrpc_put_connection_superhack);
781 EXPORT_SYMBOL(ptlrpc_abort_inflight_superhack);
782 EXPORT_SYMBOL(proc_lustre_root);
783
784 EXPORT_SYMBOL(lctl_fake_uuid);
785
786 EXPORT_SYMBOL(class_register_type);
787 EXPORT_SYMBOL(class_unregister_type);
788 EXPORT_SYMBOL(class_get_type);
789 EXPORT_SYMBOL(class_put_type);
790 EXPORT_SYMBOL(class_name2dev);
791 EXPORT_SYMBOL(class_name2obd);
792 EXPORT_SYMBOL(class_uuid2dev);
793 EXPORT_SYMBOL(class_uuid2obd);
794 EXPORT_SYMBOL(class_export_get);
795 EXPORT_SYMBOL(class_export_put);
796 EXPORT_SYMBOL(class_new_export);
797 EXPORT_SYMBOL(class_unlink_export);
798 EXPORT_SYMBOL(class_import_get);
799 EXPORT_SYMBOL(class_import_put);
800 EXPORT_SYMBOL(class_new_import);
801 EXPORT_SYMBOL(class_destroy_import);
802 EXPORT_SYMBOL(class_connect);
803 EXPORT_SYMBOL(class_conn2export);
804 EXPORT_SYMBOL(class_conn2obd);
805 EXPORT_SYMBOL(class_conn2cliimp);
806 EXPORT_SYMBOL(class_conn2ldlmimp);
807 EXPORT_SYMBOL(class_disconnect);
808 EXPORT_SYMBOL(class_disconnect_exports);
809
810 /* uuid.c */
811 EXPORT_SYMBOL(class_uuid_unparse);
812 EXPORT_SYMBOL(lustre_uuid_to_peer);
813 EXPORT_SYMBOL(client_tgtuuid2obd);
814
815 EXPORT_SYMBOL(class_handle_hash);
816 EXPORT_SYMBOL(class_handle_unhash);
817 EXPORT_SYMBOL(class_handle2object);
818
819 #ifdef __KERNEL__
820 static int __init init_obdclass(void)
821 #else
822 int init_obdclass(void)
823 #endif
824 {
825         struct obd_device *obd;
826         int err;
827         int i;
828
829         printk(KERN_INFO "OBD class driver Build Version: " BUILD_VERSION
830                       ", info@clusterfs.com\n");
831
832         class_init_uuidlist();
833         err = class_handle_init();
834         if (err)
835                 return err;
836
837         sema_init(&obd_conf_sem, 1);
838         INIT_LIST_HEAD(&obd_types);
839
840         err = misc_register(&obd_psdev);
841         if (err) {
842                 CERROR("cannot register %d err %d\n", OBD_MINOR, err);
843                 return err;
844         }
845
846         /* This struct is already zerod for us (static global) */
847         for (i = 0, obd = obd_dev; i < MAX_OBD_DEVICES; i++, obd++)
848                 obd->obd_minor = i;
849
850         err = obd_init_caches();
851         if (err)
852                 return err;
853
854 #ifdef __KERNEL__
855         obd_sysctl_init();
856 #endif
857
858 #ifdef LPROCFS
859         proc_lustre_root = proc_mkdir("lustre", proc_root_fs);
860         if (!proc_lustre_root)
861                 printk(KERN_ERR "error registering /proc/fs/lustre\n");
862         proc_version = lprocfs_add_vars(proc_lustre_root,lprocfs_version,NULL);
863 #else
864         proc_lustre_root = NULL;
865         proc_version = -1;
866 #endif
867         return 0;
868 }
869
870 #ifdef LPROCFS
871 int obd_proc_read_version(char *page, char **start, off_t off, int count, int *eof, void *data) {
872         *eof = 1;
873         return snprintf(page, count, "%s\n", BUILD_VERSION);
874 }
875 #else
876 int obd_proc_read_version(char *page, char **start, off_t off, int count, int *eof, void *data) { return 0; }
877 #endif
878
879 #ifdef __KERNEL__
880 static void /*__exit*/ cleanup_obdclass(void)
881 #else
882 static void cleanup_obdclass(void)
883 #endif
884 {
885         int i;
886         ENTRY;
887
888         misc_deregister(&obd_psdev);
889         for (i = 0; i < MAX_OBD_DEVICES; i++) {
890                 struct obd_device *obd = &obd_dev[i];
891                 if (obd->obd_type && obd->obd_set_up &&
892                     OBT(obd) && OBP(obd, detach)) {
893                         /* XXX should this call generic detach otherwise? */
894                         OBP(obd, detach)(obd);
895                 }
896         }
897
898         obd_cleanup_caches();
899 #ifdef __KERNEL__
900         obd_sysctl_clean();
901 #endif
902         if (proc_lustre_root) {
903                 lprocfs_remove(proc_lustre_root);
904                 proc_lustre_root = NULL;
905         }
906
907         class_handle_cleanup();
908         class_exit_uuidlist();
909
910         CERROR("obd mem max: %d leaked: %d\n", obd_memmax,
911                atomic_read(&obd_memory));
912         EXIT;
913 }
914
915 /* Check that we're building against the appropriate version of the Lustre
916  * kernel patch */
917 #ifdef __KERNEL__
918 #include <linux/lustre_version.h>
919 #define LUSTRE_MIN_VERSION 21
920 #define LUSTRE_MAX_VERSION 21
921 #if (LUSTRE_KERNEL_VERSION < LUSTRE_MIN_VERSION)
922 # error Cannot continue: Your Lustre kernel patch is older than the sources
923 #elif (LUSTRE_KERNEL_VERSION > LUSTRE_MAX_VERSION)
924 # error Cannot continue: Your Lustre sources are older than the kernel patch
925 #endif
926  #else
927 # warning "Lib Lustre - no versioning information"
928 #endif
929
930 #ifdef __KERNEL__
931 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
932 MODULE_DESCRIPTION("Lustre Class Driver Build Version: " BUILD_VERSION);
933 MODULE_LICENSE("GPL");
934
935 module_init(init_obdclass);
936 module_exit(cleanup_obdclass);
937 #endif