Whamcloud - gitweb
Mgs hold on the mgs_open_llog as resources on llog, and each resource will...
[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 the Lustre file system, http://www.lustre.org
9  *   Lustre is a trademark of Cluster File Systems, Inc.
10  *
11  *   You may have signed or agreed to another license before downloading
12  *   this software.  If so, you are bound by the terms and conditions
13  *   of that agreement, and the following does not apply to you.  See the
14  *   LICENSE file included with this distribution for more information.
15  *
16  *   If you did not agree to a different license, then this copy of Lustre
17  *   is open source software; you can redistribute it and/or modify it
18  *   under the terms of version 2 of the GNU General Public License as
19  *   published by the Free Software Foundation.
20  *
21  *   In either case, Lustre is distributed in the hope that it will be
22  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
23  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  *   license text for more details.
25  *
26  * These are the only exported functions, they provide some generic
27  * infrastructure for managing object devices
28  */
29
30 #define DEBUG_SUBSYSTEM S_CLASS
31 #ifndef EXPORT_SYMTAB
32 # define EXPORT_SYMTAB
33 #endif
34 #ifdef __KERNEL__
35 #include <linux/config.h> /* for CONFIG_PROC_FS */
36 #include <linux/module.h>
37 #include <linux/errno.h>
38 #include <linux/kernel.h>
39 #include <linux/major.h>
40 #include <linux/sched.h>
41 #include <linux/lp.h>
42 #include <linux/slab.h>
43 #include <linux/ioport.h>
44 #include <linux/fcntl.h>
45 #include <linux/delay.h>
46 #include <linux/skbuff.h>
47 #include <linux/proc_fs.h>
48 #include <linux/fs.h>
49 #include <linux/poll.h>
50 #include <linux/init.h>
51 #include <linux/list.h>
52 #include <linux/highmem.h>
53 #include <asm/io.h>
54 #include <asm/ioctls.h>
55 #include <asm/system.h>
56 #include <asm/poll.h>
57 #include <asm/uaccess.h>
58 #include <linux/miscdevice.h>
59 #include <linux/smp_lock.h>
60 #include <linux/seq_file.h>
61 #else
62 # include <liblustre.h>
63 #endif
64
65 #include <linux/obd_support.h>
66 #include <linux/obd_class.h>
67 #include <linux/lustre_debug.h>
68 #include <linux/lprocfs_status.h>
69 #ifdef __KERNEL__
70 #include <linux/lustre_build_version.h>
71 #include <linux/lustre_version.h>
72 #endif
73 #include <libcfs/list.h>
74 #include "llog_internal.h"
75
76 #ifndef __KERNEL__
77 /* liblustre workaround */
78 atomic_t libcfs_kmemory = {0};
79 #endif
80
81 struct obd_device obd_dev[MAX_OBD_DEVICES];
82 struct list_head obd_types;
83 spinlock_t obd_dev_lock;
84 #ifndef __KERNEL__
85 atomic_t obd_memory;
86 int obd_memmax;
87 #endif
88
89 int proc_version;
90
91 /* The following are visible and mutable through /proc/sys/lustre/. */
92 unsigned int obd_fail_loc;
93 unsigned int obd_dump_on_timeout;
94 unsigned int obd_timeout = 100; /* seconds */
95 unsigned int ldlm_timeout = 20; /* seconds */
96 unsigned int obd_health_check_timeout = 120; /* seconds */
97 char obd_lustre_upcall[128] = "DEFAULT"; /* or NONE or /full/path/to/upcall  */
98 unsigned int obd_sync_filter; /* = 0, don't sync by default */
99
100 DECLARE_WAIT_QUEUE_HEAD(obd_race_waitq);
101
102 #ifdef __KERNEL__
103 unsigned int obd_print_fail_loc(void)
104 {
105         CWARN("obd_fail_loc = %x\n", obd_fail_loc);
106         return obd_fail_loc;
107 }
108
109 void obd_set_fail_loc(unsigned int fl)
110 {
111         obd_fail_loc = fl;
112 }
113
114 /*  opening /dev/obd */
115 static int obd_class_open(struct inode * inode, struct file * file)
116 {
117         ENTRY;
118
119         PORTAL_MODULE_USE;
120         RETURN(0);
121 }
122
123 /*  closing /dev/obd */
124 static int obd_class_release(struct inode * inode, struct file * file)
125 {
126         ENTRY;
127
128         PORTAL_MODULE_UNUSE;
129         RETURN(0);
130 }
131 #endif
132
133 static inline void obd_data2conn(struct lustre_handle *conn,
134                                  struct obd_ioctl_data *data)
135 {
136         memset(conn, 0, sizeof *conn);
137         conn->cookie = data->ioc_cookie;
138 }
139
140 static inline void obd_conn2data(struct obd_ioctl_data *data,
141                                  struct lustre_handle *conn)
142 {
143         data->ioc_cookie = conn->cookie;
144 }
145
146 int class_resolve_dev_name(uint32_t len, char *name)
147 {
148         int rc;
149         int dev;
150
151         if (!len || !name) {
152                 CERROR("No name passed,!\n");
153                 GOTO(out, rc = -EINVAL);
154         }
155         if (name[len - 1] != 0) {
156                 CERROR("Name not nul terminated!\n");
157                 GOTO(out, rc = -EINVAL);
158         }
159
160         CDEBUG(D_IOCTL, "device name %s\n", name);
161         dev = class_name2dev(name);
162         if (dev == -1) {
163                 CDEBUG(D_IOCTL, "No device for name %s!\n", name);
164                 GOTO(out, rc = -EINVAL);
165         }
166
167         CDEBUG(D_IOCTL, "device name %s, dev %d\n", name, dev);
168         rc = dev;
169
170 out:
171         RETURN(rc);
172 }
173
174 int class_handle_ioctl(unsigned int cmd, unsigned long arg)
175 {
176         char *buf = NULL;
177         struct obd_ioctl_data *data;
178         struct libcfs_debug_ioctl_data *debug_data;
179         struct obd_device *obd = NULL;
180         int err = 0, len = 0;
181         ENTRY;
182
183 #ifdef __KERNEL__
184         if (current->fsuid != 0)
185                 RETURN(err = -EACCES);
186 #endif
187
188         if ((cmd & 0xffffff00) == ((int)'T') << 8) /* ignore all tty ioctls */
189                 RETURN(err = -ENOTTY);
190
191         /* only for debugging */
192         if (cmd == LIBCFS_IOC_DEBUG_MASK) {
193                 debug_data = (struct libcfs_debug_ioctl_data*)arg;
194                 libcfs_subsystem_debug = debug_data->subs;
195                 libcfs_debug = debug_data->debug;
196                 return 0;
197         }
198
199         CDEBUG(D_IOCTL, "cmd = %x, obd = %p\n", cmd, obd);
200         if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
201                 CERROR("OBD ioctl: data error\n");
202                 GOTO(out, err = -EINVAL);
203         }
204         data = (struct obd_ioctl_data *)buf;
205
206         switch (cmd) {
207         case OBD_IOC_PROCESS_CFG: {
208                 struct lustre_cfg *lcfg;
209
210                 if (!data->ioc_plen1 || !data->ioc_pbuf1) {
211                         CERROR("No config buffer passed!\n");
212                         GOTO(out, err = -EINVAL);
213                 }
214
215                 err = lustre_cfg_sanity_check(data->ioc_pbuf1,
216                                               data->ioc_plen1);
217                 if (err)
218                         GOTO(out, err);
219
220                 OBD_ALLOC(lcfg, data->ioc_plen1);
221                 err = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
222                 if (!err)
223                         err = class_process_config(lcfg);
224                 OBD_FREE(lcfg, data->ioc_plen1);
225                 GOTO(out, err);
226         }
227
228         case OBD_GET_VERSION:
229                 if (!data->ioc_inlbuf1) {
230                         CERROR("No buffer passed in ioctl\n");
231                         GOTO(out, err = -EINVAL);
232                 }
233
234                 if (strlen(BUILD_VERSION) + 1 > data->ioc_inllen1) {
235                         CERROR("ioctl buffer too small to hold version\n");
236                         GOTO(out, err = -EINVAL);
237                 }
238
239                 memcpy(data->ioc_bulk, BUILD_VERSION,
240                        strlen(BUILD_VERSION) + 1);
241
242                 err = copy_to_user((void *)arg, data, len);
243                 if (err)
244                         err = -EFAULT;
245                 GOTO(out, err);
246
247         case OBD_IOC_NAME2DEV: {
248                 /* Resolve a device name.  This does not change the
249                  * currently selected device.
250                  */
251                 int dev;
252
253                 dev = class_resolve_dev_name(data->ioc_inllen1,
254                                              data->ioc_inlbuf1);
255                 data->ioc_dev = dev;
256                 if (dev < 0)
257                         GOTO(out, err = -EINVAL);
258
259                 err = copy_to_user((void *)arg, data, sizeof(*data));
260                 if (err)
261                         err = -EFAULT;
262                 GOTO(out, err);
263         }
264
265         case OBD_IOC_UUID2DEV: {
266                 /* Resolve a device uuid.  This does not change the
267                  * currently selected device.
268                  */
269                 int dev;
270                 struct obd_uuid uuid;
271
272                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
273                         CERROR("No UUID passed!\n");
274                         GOTO(out, err = -EINVAL);
275                 }
276                 if (data->ioc_inlbuf1[data->ioc_inllen1 - 1] != 0) {
277                         CERROR("UUID not NUL terminated!\n");
278                         GOTO(out, err = -EINVAL);
279                 }
280
281                 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
282                 obd_str2uuid(&uuid, data->ioc_inlbuf1);
283                 dev = class_uuid2dev(&uuid);
284                 data->ioc_dev = dev;
285                 if (dev == -1) {
286                         CDEBUG(D_IOCTL, "No device for UUID %s!\n",
287                                data->ioc_inlbuf1);
288                         GOTO(out, err = -EINVAL);
289                 }
290
291                 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
292                        dev);
293                 err = copy_to_user((void *)arg, data, sizeof(*data));
294                 if (err)
295                         err = -EFAULT;
296                 GOTO(out, err);
297         }
298
299
300         case OBD_IOC_CLOSE_UUID: {
301                 CDEBUG(D_IOCTL, "closing all connections to uuid %s (NOOP)\n",
302                        data->ioc_inlbuf1);
303                 GOTO(out, err = 0);
304         }
305
306         }
307
308         if (data->ioc_dev >= MAX_OBD_DEVICES) {
309                 CERROR("OBD ioctl: No device\n");
310                 GOTO(out, err = -EINVAL);
311         }
312         obd = &obd_dev[data->ioc_dev];
313         if (!(obd && obd->obd_set_up) || obd->obd_stopping) {
314                 CERROR("OBD ioctl: device not setup %d \n", data->ioc_dev);
315                 GOTO(out, err = -EINVAL);
316         }
317
318         switch(cmd) {
319         case OBD_IOC_NO_TRANSNO: {
320                 if (!obd->obd_attached) {
321                         CERROR("Device %d not attached\n", obd->obd_minor);
322                         GOTO(out, err = -ENODEV);
323                 }
324                 CDEBUG(D_IOCTL,
325                        "disabling committed-transno notifications on %d\n",
326                        obd->obd_minor);
327                 obd->obd_no_transno = 1;
328                 GOTO(out, err = 0);
329         }
330
331         default: {
332                 err = obd_iocontrol(cmd, obd->obd_self_export, len, data, NULL);
333                 if (err)
334                         GOTO(out, err);
335
336                 err = copy_to_user((void *)arg, data, len);
337                 if (err)
338                         err = -EFAULT;
339                 GOTO(out, err);
340         }
341         }
342
343  out:
344         if (buf)
345                 obd_ioctl_freedata(buf, len);
346         RETURN(err);
347 } /* class_handle_ioctl */
348
349
350
351 #define OBD_MINOR 241
352 #ifdef __KERNEL__
353 /* to control /dev/obd */
354 static int obd_class_ioctl(struct inode *inode, struct file *filp,
355                            unsigned int cmd, unsigned long arg)
356 {
357         return class_handle_ioctl(cmd, arg);
358 }
359
360 /* declare character device */
361 static struct file_operations obd_psdev_fops = {
362         .owner   = THIS_MODULE,
363         .ioctl   = obd_class_ioctl,     /* ioctl */
364         .open    = obd_class_open,      /* open */
365         .release = obd_class_release,   /* release */
366 };
367
368 /* modules setup */
369 static struct miscdevice obd_psdev = {
370         .minor = OBD_MINOR,
371         .name  = "obd",
372         .fops  = &obd_psdev_fops,
373 };
374 #else
375 void *obd_psdev = NULL;
376 #endif
377
378 EXPORT_SYMBOL(obd_dev);
379 EXPORT_SYMBOL(obd_fail_loc);
380 EXPORT_SYMBOL(obd_print_fail_loc);
381 EXPORT_SYMBOL(obd_race_waitq);
382 EXPORT_SYMBOL(obd_dump_on_timeout);
383 EXPORT_SYMBOL(obd_timeout);
384 EXPORT_SYMBOL(ldlm_timeout);
385 EXPORT_SYMBOL(obd_health_check_timeout);
386 EXPORT_SYMBOL(obd_lustre_upcall);
387 EXPORT_SYMBOL(obd_sync_filter);
388 EXPORT_SYMBOL(ptlrpc_put_connection_superhack);
389 EXPORT_SYMBOL(ptlrpc_abort_inflight_superhack);
390
391 struct proc_dir_entry *proc_lustre_root;
392 EXPORT_SYMBOL(proc_lustre_root);
393
394 EXPORT_SYMBOL(class_register_type);
395 EXPORT_SYMBOL(class_unregister_type);
396 EXPORT_SYMBOL(class_get_type);
397 EXPORT_SYMBOL(class_put_type);
398 EXPORT_SYMBOL(class_name2dev);
399 EXPORT_SYMBOL(class_name2obd);
400 EXPORT_SYMBOL(class_uuid2dev);
401 EXPORT_SYMBOL(class_uuid2obd);
402 EXPORT_SYMBOL(class_find_client_obd);
403 EXPORT_SYMBOL(class_find_client_notype);
404 EXPORT_SYMBOL(class_devices_in_group);
405 EXPORT_SYMBOL(class_conn2export);
406 EXPORT_SYMBOL(class_exp2obd);
407 EXPORT_SYMBOL(class_conn2obd);
408 EXPORT_SYMBOL(class_exp2cliimp);
409 EXPORT_SYMBOL(class_conn2cliimp);
410 EXPORT_SYMBOL(class_disconnect);
411
412 /* uuid.c */
413 EXPORT_SYMBOL(class_uuid_unparse);
414 EXPORT_SYMBOL(lustre_uuid_to_peer);
415
416 EXPORT_SYMBOL(class_handle_hash);
417 EXPORT_SYMBOL(class_handle_unhash);
418 EXPORT_SYMBOL(class_handle2object);
419
420 /* config.c */
421 EXPORT_SYMBOL(class_get_profile);
422 EXPORT_SYMBOL(class_del_profile);
423 EXPORT_SYMBOL(class_process_config);
424 EXPORT_SYMBOL(class_config_parse_llog);
425 EXPORT_SYMBOL(class_config_dump_llog);
426 EXPORT_SYMBOL(class_attach);
427 EXPORT_SYMBOL(class_setup);
428 EXPORT_SYMBOL(class_cleanup);
429 EXPORT_SYMBOL(class_detach);
430 EXPORT_SYMBOL(class_manual_cleanup);
431
432 #ifdef LPROCFS
433 int obd_proc_read_version(char *page, char **start, off_t off, int count,
434                           int *eof, void *data)
435 {
436         *eof = 1;
437         return snprintf(page, count, "%s\n", BUILD_VERSION);
438 }
439
440 int obd_proc_read_kernel_version(char *page, char **start, off_t off, int count,
441                                  int *eof, void *data)
442 {
443         *eof = 1;
444         return snprintf(page, count, "%u\n", LUSTRE_KERNEL_VERSION);
445 }
446
447 int obd_proc_read_pinger(char *page, char **start, off_t off, int count,
448                          int *eof, void *data)
449 {
450         *eof = 1;
451         return snprintf(page, count, "%s\n",
452 #ifdef ENABLE_PINGER
453                         "on"
454 #else
455                         "off"
456 #endif
457                        );
458 }
459
460 static int obd_proc_read_health(char *page, char **start, off_t off,
461                                 int count, int *eof, void *data)
462 {
463         int rc = 0, i;
464         *eof = 1;
465
466         if (libcfs_catastrophe)
467                 rc += snprintf(page + rc, count - rc, "LBUG\n");
468
469         spin_lock(&obd_dev_lock);
470         for (i = 0; i < MAX_OBD_DEVICES; i++) {
471                 struct obd_device *obd;
472
473                 obd = &obd_dev[i];
474                 if (obd->obd_type == NULL)
475                         continue;
476
477                 atomic_inc(&obd->obd_refcount);
478                 spin_unlock(&obd_dev_lock);
479
480                 if (obd_health_check(obd)) {
481                         rc += snprintf(page + rc, count - rc,
482                                        "device %s reported unhealthy\n",
483                                        obd->obd_name);
484                 }
485                 class_decref(obd);
486                 spin_lock(&obd_dev_lock);
487         }
488         spin_unlock(&obd_dev_lock);
489
490         if (rc == 0)
491                 return snprintf(page, count, "healthy\n");
492
493         rc += snprintf(page + rc, count - rc, "NOT HEALTHY\n");
494         return rc;
495 }
496
497 static int obd_proc_rd_health_timeout(char *page, char **start, off_t off,
498                                       int count, int *eof, void *data)
499 {
500         *eof = 1;
501         return snprintf(page, count, "%d\n", obd_health_check_timeout);
502 }
503
504 static int obd_proc_wr_health_timeout(struct file *file, const char *buffer,
505                                       unsigned long count, void *data)
506 {
507         int val, rc;
508
509         rc = lprocfs_write_helper(buffer, count, &val);
510         if (rc)
511                 return rc;
512
513         obd_health_check_timeout = val;
514
515         return count;
516 }
517
518 /* Root for /proc/fs/lustre */
519 struct lprocfs_vars lprocfs_base[] = {
520         { "version", obd_proc_read_version, NULL, NULL },
521         { "kernel_version", obd_proc_read_kernel_version, NULL, NULL },
522         { "pinger", obd_proc_read_pinger, NULL, NULL },
523         { "health_check", obd_proc_read_health, NULL, NULL },
524         { "health_check_timeout", obd_proc_rd_health_timeout,
525           obd_proc_wr_health_timeout, NULL },        
526         { 0 }
527 };
528 #else
529 #define lprocfs_base NULL
530 #endif /* LPROCFS */
531
532 #ifdef __KERNEL__
533 static void *obd_device_list_seq_start(struct seq_file *p, loff_t*pos)
534 {
535         if (*pos >= MAX_OBD_DEVICES)
536                 return NULL;
537         return &obd_dev[*pos];
538 }
539
540 static void obd_device_list_seq_stop(struct seq_file *p, void *v)
541 {
542 }
543
544 static void *obd_device_list_seq_next(struct seq_file *p, void *v, loff_t *pos)
545 {
546         ++*pos;
547         if (*pos >= MAX_OBD_DEVICES)
548                 return NULL;
549         return &obd_dev[*pos];
550 }
551
552 static int obd_device_list_seq_show(struct seq_file *p, void *v)
553 {
554         struct obd_device *obd = (struct obd_device *)v;
555         int index = obd - &obd_dev[0];
556         char *status;
557
558         if (!obd->obd_type)
559                 return 0;
560         if (obd->obd_stopping)
561                 status = "ST";
562         else if (obd->obd_set_up)
563                 status = "UP";
564         else if (obd->obd_attached)
565                 status = "AT";
566         else
567                 status = "--";
568
569         return seq_printf(p, "%3d %s %s %s %s %d\n",
570                           (int)index, status, obd->obd_type->typ_name,
571                           obd->obd_name, obd->obd_uuid.uuid,
572                           atomic_read(&obd->obd_refcount));
573 }
574
575 struct seq_operations obd_device_list_sops = {
576         .start = obd_device_list_seq_start,
577         .stop = obd_device_list_seq_stop,
578         .next = obd_device_list_seq_next,
579         .show = obd_device_list_seq_show,
580 };
581
582 static int obd_device_list_open(struct inode *inode, struct file *file)
583 {
584         struct proc_dir_entry *dp = PDE(inode);
585         struct seq_file *seq;
586         int rc = seq_open(file, &obd_device_list_sops);
587
588         if (rc)
589                 return rc;
590
591         seq = file->private_data;
592         seq->private = dp->data;
593
594         return 0;
595 }
596
597 struct file_operations obd_device_list_fops = {
598         .owner   = THIS_MODULE,
599         .open    = obd_device_list_open,
600         .read    = seq_read,
601         .llseek  = seq_lseek,
602         .release = seq_release,
603 };
604 #endif
605
606 #define OBD_INIT_CHECK
607 #ifdef OBD_INIT_CHECK
608 int obd_init_checks(void)
609 {
610         __u64 u64val, div64val;
611         char buf[64];
612         int len, ret = 0;
613
614         CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s, LPSZ=%s, LPSSZ=%s\n",
615                LPU64, LPD64, LPX64, LPSZ, LPSSZ);
616
617         CDEBUG(D_INFO, "OBD_OBJECT_EOF = "LPX64"\n", (__u64)OBD_OBJECT_EOF);
618
619         u64val = OBD_OBJECT_EOF;
620         CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = "LPX64"\n", u64val);
621         if (u64val != OBD_OBJECT_EOF) {
622                 CERROR("__u64 "LPX64"(%d) != 0xffffffffffffffff\n",
623                        u64val, (int)sizeof(u64val));
624                 ret = -EINVAL;
625         }
626         len = snprintf(buf, sizeof(buf), LPX64, u64val);
627         if (len != 18) {
628                 CWARN("LPX64 wrong length! strlen(%s)=%d != 18\n", buf, len);
629                 ret = -EINVAL;
630         }
631
632         div64val = OBD_OBJECT_EOF;
633         CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = "LPX64"\n", u64val);
634         if (u64val != OBD_OBJECT_EOF) {
635                 CERROR("__u64 "LPX64"(%d) != 0xffffffffffffffff\n",
636                        u64val, (int)sizeof(u64val));
637                 ret = -EOVERFLOW;
638         }
639         if (u64val >> 8 != OBD_OBJECT_EOF >> 8) {
640                 CERROR("__u64 "LPX64"(%d) != 0xffffffffffffffff\n",
641                        u64val, (int)sizeof(u64val));
642                 return -EOVERFLOW;
643         }
644         if (do_div(div64val, 256) != (u64val & 255)) {
645                 CERROR("do_div("LPX64",256) != "LPU64"\n", u64val, u64val &255);
646                 return -EOVERFLOW;
647         }
648         if (u64val >> 8 != div64val) {
649                 CERROR("do_div("LPX64",256) "LPU64" != "LPU64"\n",
650                        u64val, div64val, u64val >> 8);
651                 return -EOVERFLOW;
652         }
653         len = snprintf(buf, sizeof(buf), LPX64, u64val);
654         if (len != 18) {
655                 CWARN("LPX64 wrong length! strlen(%s)=%d != 18\n", buf, len);
656                 ret = -EINVAL;
657         }
658         len = snprintf(buf, sizeof(buf), LPU64, u64val);
659         if (len != 20) {
660                 CWARN("LPU64 wrong length! strlen(%s)=%d != 20\n", buf, len);
661                 ret = -EINVAL;
662         }
663         len = snprintf(buf, sizeof(buf), LPD64, u64val);
664         if (len != 2) {
665                 CWARN("LPD64 wrong length! strlen(%s)=%d != 2\n", buf, len);
666                 ret = -EINVAL;
667         }
668         if ((u64val & ~PAGE_MASK) >= PAGE_SIZE) {
669                 CWARN("mask failed: u64val "LPU64" >= %lu\n", u64val,PAGE_SIZE);
670                 ret = -EINVAL;
671         }
672
673         return ret;
674 }
675 #else
676 #define obd_init_checks() do {} while(0)
677 #endif
678
679 #ifdef __KERNEL__
680 static int __init init_obdclass(void)
681 #else
682 int init_obdclass(void)
683 #endif
684 {
685         struct obd_device *obd;
686 #ifdef __KERNEL__
687         struct proc_dir_entry *entry;
688         int lustre_register_fs(void);
689 #endif
690         int err;
691         int i;
692
693 #ifdef __KERNEL__
694         printk(KERN_INFO "Lustre: OBD class driver Build Version: "
695                BUILD_VERSION", info@clusterfs.com\n");
696 #else
697         CDEBUG(D_INFO, "Lustre: OBD class driver Build Version: "
698                BUILD_VERSION", info@clusterfs.com\n");
699 #endif
700
701         err = obd_init_checks();
702         if (err == -EOVERFLOW)
703                 return err;
704
705         class_init_uuidlist();
706         err = class_handle_init();
707         if (err)
708                 return err;
709
710         spin_lock_init(&obd_dev_lock);
711         INIT_LIST_HEAD(&obd_types);
712
713         err = misc_register(&obd_psdev);
714         if (err) {
715                 CERROR("cannot register %d err %d\n", OBD_MINOR, err);
716                 return err;
717         }
718
719         /* This struct is already zerod for us (static global) */
720         for (i = 0, obd = obd_dev; i < MAX_OBD_DEVICES; i++, obd++)
721                 obd->obd_minor = i;
722
723         err = obd_init_caches();
724         if (err)
725                 return err;
726
727 #ifdef __KERNEL__
728         obd_sysctl_init();
729
730         proc_lustre_root = proc_mkdir("lustre", proc_root_fs);
731         if (!proc_lustre_root) {
732                 printk(KERN_ERR
733                        "LustreError: error registering /proc/fs/lustre\n");
734                 RETURN(-ENOMEM);
735         }
736         proc_version = lprocfs_add_vars(proc_lustre_root, lprocfs_base, NULL);
737         entry = create_proc_entry("devices", 0444, proc_lustre_root);
738         if (entry == NULL) {
739                 CERROR("error registering /proc/fs/lustre/devices\n");
740                 lprocfs_remove(proc_lustre_root);
741                 RETURN(-ENOMEM);
742         }
743         entry->proc_fops = &obd_device_list_fops;
744
745         lustre_register_fs();
746 #endif
747         return 0;
748 }
749
750 /* liblustre doesn't call cleanup_obdclass, apparently.  we carry on in this
751  * ifdef to the end of the file to cover module and versioning goo.*/
752 #ifdef __KERNEL__
753
754 static void cleanup_obdclass(void)
755 {
756         int i;
757         int leaked;
758         int lustre_unregister_fs(void);
759         ENTRY;
760
761         lustre_unregister_fs();
762
763         misc_deregister(&obd_psdev);
764         for (i = 0; i < MAX_OBD_DEVICES; i++) {
765                 struct obd_device *obd = &obd_dev[i];
766                 if (obd->obd_type && obd->obd_set_up &&
767                     OBT(obd) && OBP(obd, detach)) {
768                         /* XXX should this call generic detach otherwise? */
769                         OBP(obd, detach)(obd);
770                 }
771         }
772
773         obd_cleanup_caches();
774         obd_sysctl_clean();
775
776         if (proc_lustre_root) {
777                 lprocfs_remove(proc_lustre_root);
778                 proc_lustre_root = NULL;
779         }
780
781         class_handle_cleanup();
782         class_exit_uuidlist();
783
784         leaked = atomic_read(&obd_memory);
785         CDEBUG(leaked ? D_ERROR : D_INFO,
786                "obd mem max: %d leaked: %d\n", obd_memmax, leaked);
787
788         EXIT;
789 }
790
791 /* Check that we're building against the appropriate version of the Lustre
792  * kernel patch */
793 #include <linux/lustre_version.h>
794 #define LUSTRE_MIN_VERSION 37
795 #define LUSTRE_MAX_VERSION 47
796 #if (LUSTRE_KERNEL_VERSION < LUSTRE_MIN_VERSION)
797 # error Cannot continue: Your Lustre kernel patch is older than the sources
798 #elif (LUSTRE_KERNEL_VERSION > LUSTRE_MAX_VERSION)
799 # error Cannot continue: Your Lustre sources are older than the kernel patch
800 #endif
801
802 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
803 MODULE_DESCRIPTION("Lustre Class Driver Build Version: " BUILD_VERSION);
804 MODULE_LICENSE("GPL");
805
806 module_init(init_obdclass);
807 module_exit(cleanup_obdclass);
808 #endif