4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2011, 2017, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
32 #define DEBUG_SUBSYSTEM S_CLASS
34 #include <linux/miscdevice.h>
35 #include <linux/user_namespace.h>
36 #include <linux/uidgid.h>
37 #include <linux/atomic.h>
38 #include <linux/list.h>
40 #include <obd_support.h>
41 #include <obd_class.h>
42 #include <uapi/linux/lnet/lnetctl.h>
43 #include <lustre_kernelcomm.h>
44 #include <lprocfs_status.h>
45 #include <cl_object.h>
46 #ifdef HAVE_SERVER_SUPPORT
47 # include <dt_object.h>
48 # include <md_object.h>
49 #endif /* HAVE_SERVER_SUPPORT */
50 #include <uapi/linux/lustre/lustre_ioctl.h>
51 #include "llog_internal.h"
54 static __u64 obd_max_alloc;
59 static DEFINE_SPINLOCK(obd_updatemax_lock);
61 /* The following are visible and mutable through /proc/sys/lustre/. */
62 unsigned int obd_debug_peer_on_timeout;
63 EXPORT_SYMBOL(obd_debug_peer_on_timeout);
64 unsigned int obd_dump_on_timeout;
65 EXPORT_SYMBOL(obd_dump_on_timeout);
66 unsigned int obd_dump_on_eviction;
67 EXPORT_SYMBOL(obd_dump_on_eviction);
68 unsigned int obd_lbug_on_eviction;
69 EXPORT_SYMBOL(obd_lbug_on_eviction);
70 unsigned long obd_max_dirty_pages;
71 EXPORT_SYMBOL(obd_max_dirty_pages);
72 atomic_long_t obd_dirty_pages;
73 EXPORT_SYMBOL(obd_dirty_pages);
74 unsigned int obd_timeout = OBD_TIMEOUT_DEFAULT; /* seconds */
75 EXPORT_SYMBOL(obd_timeout);
76 unsigned int ldlm_timeout = LDLM_TIMEOUT_DEFAULT; /* seconds */
77 EXPORT_SYMBOL(ldlm_timeout);
78 unsigned int obd_timeout_set;
79 EXPORT_SYMBOL(obd_timeout_set);
80 unsigned int ldlm_timeout_set;
81 EXPORT_SYMBOL(ldlm_timeout_set);
82 /* bulk transfer timeout, give up after 100s by default */
83 unsigned int bulk_timeout = 100; /* seconds */
84 EXPORT_SYMBOL(bulk_timeout);
85 /* Adaptive timeout defs here instead of ptlrpc module for /proc/sys/ access */
86 unsigned int at_min = 0;
87 EXPORT_SYMBOL(at_min);
88 unsigned int at_max = 600;
89 EXPORT_SYMBOL(at_max);
90 unsigned int at_history = 600;
91 EXPORT_SYMBOL(at_history);
92 int at_early_margin = 5;
93 EXPORT_SYMBOL(at_early_margin);
95 EXPORT_SYMBOL(at_extra);
98 struct lprocfs_stats *obd_memory = NULL;
99 EXPORT_SYMBOL(obd_memory);
102 static int class_resolve_dev_name(__u32 len, const char *name)
109 CERROR("No name passed,!\n");
110 GOTO(out, rc = -EINVAL);
112 if (name[len - 1] != 0) {
113 CERROR("Name not nul terminated!\n");
114 GOTO(out, rc = -EINVAL);
117 CDEBUG(D_IOCTL, "device name %s\n", name);
118 dev = class_name2dev(name);
120 CDEBUG(D_IOCTL, "No device for name %s!\n", name);
121 GOTO(out, rc = -EINVAL);
124 CDEBUG(D_IOCTL, "device name %s, dev %d\n", name, dev);
131 #define OBD_MAX_IOCTL_BUFFER 8192
133 static int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
135 const int maxlen = 1 << 30;
136 if (data->ioc_len > maxlen) {
137 CERROR("OBD ioctl: ioc_len larger than 1<<30\n");
141 if (data->ioc_inllen1 > maxlen) {
142 CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
146 if (data->ioc_inllen2 > maxlen) {
147 CERROR("OBD ioctl: ioc_inllen2 larger than 1<<30\n");
151 if (data->ioc_inllen3 > maxlen) {
152 CERROR("OBD ioctl: ioc_inllen3 larger than 1<<30\n");
156 if (data->ioc_inllen4 > maxlen) {
157 CERROR("OBD ioctl: ioc_inllen4 larger than 1<<30\n");
161 if (data->ioc_inlbuf1 && data->ioc_inllen1 == 0) {
162 CERROR("OBD ioctl: inlbuf1 pointer but 0 length\n");
166 if (data->ioc_inlbuf2 && data->ioc_inllen2 == 0) {
167 CERROR("OBD ioctl: inlbuf2 pointer but 0 length\n");
171 if (data->ioc_inlbuf3 && data->ioc_inllen3 == 0) {
172 CERROR("OBD ioctl: inlbuf3 pointer but 0 length\n");
176 if (data->ioc_inlbuf4 && data->ioc_inllen4 == 0) {
177 CERROR("OBD ioctl: inlbuf4 pointer but 0 length\n");
181 if (data->ioc_pbuf1 && data->ioc_plen1 == 0) {
182 CERROR("OBD ioctl: pbuf1 pointer but 0 length\n");
186 if (data->ioc_pbuf2 && data->ioc_plen2 == 0) {
187 CERROR("OBD ioctl: pbuf2 pointer but 0 length\n");
191 if (!data->ioc_pbuf1 && data->ioc_plen1 != 0) {
192 CERROR("OBD ioctl: plen1 set but NULL pointer\n");
196 if (!data->ioc_pbuf2 && data->ioc_plen2 != 0) {
197 CERROR("OBD ioctl: plen2 set but NULL pointer\n");
201 if (obd_ioctl_packlen(data) > data->ioc_len) {
202 CERROR("OBD ioctl: packlen exceeds ioc_len (%d > %d)\n",
203 obd_ioctl_packlen(data), data->ioc_len);
210 /* buffer MUST be at least the size of obd_ioctl_hdr */
211 int obd_ioctl_getdata(struct obd_ioctl_data **datap, int *len, void __user *arg)
213 struct obd_ioctl_hdr hdr;
214 struct obd_ioctl_data *data;
218 if (copy_from_user(&hdr, arg, sizeof(hdr)))
221 if (hdr.ioc_version != OBD_IOCTL_VERSION) {
222 CERROR("Version mismatch kernel (%x) vs application (%x)\n",
223 OBD_IOCTL_VERSION, hdr.ioc_version);
227 if (hdr.ioc_len > OBD_MAX_IOCTL_BUFFER) {
228 CERROR("User buffer len %d exceeds %d max buffer\n",
229 hdr.ioc_len, OBD_MAX_IOCTL_BUFFER);
233 if (hdr.ioc_len < sizeof(struct obd_ioctl_data)) {
234 CERROR("User buffer too small for ioctl (%d)\n", hdr.ioc_len);
238 /* When there are lots of processes calling vmalloc on multi-core
239 * system, the high lock contention will hurt performance badly,
240 * obdfilter-survey is an example, which relies on ioctl. So we'd
241 * better avoid vmalloc on ioctl path. LU-66
243 OBD_ALLOC_LARGE(data, hdr.ioc_len);
245 CERROR("Cannot allocate control buffer of len %d\n",
251 if (copy_from_user(data, arg, hdr.ioc_len)) {
252 OBD_FREE_LARGE(data, hdr.ioc_len);
256 if (obd_ioctl_is_invalid(data)) {
257 CERROR("ioctl not correctly formatted\n");
258 OBD_FREE_LARGE(data, hdr.ioc_len);
262 if (data->ioc_inllen1) {
263 data->ioc_inlbuf1 = &data->ioc_bulk[0];
264 offset += cfs_size_round(data->ioc_inllen1);
267 if (data->ioc_inllen2) {
268 data->ioc_inlbuf2 = &data->ioc_bulk[0] + offset;
269 offset += cfs_size_round(data->ioc_inllen2);
272 if (data->ioc_inllen3) {
273 data->ioc_inlbuf3 = &data->ioc_bulk[0] + offset;
274 offset += cfs_size_round(data->ioc_inllen3);
277 if (data->ioc_inllen4)
278 data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset;
284 EXPORT_SYMBOL(obd_ioctl_getdata);
286 int class_handle_ioctl(unsigned int cmd, unsigned long arg)
288 struct obd_ioctl_data *data;
289 struct obd_device *obd = NULL;
290 int err = 0, len = 0;
293 CDEBUG(D_IOCTL, "cmd = %x\n", cmd);
294 if (obd_ioctl_getdata(&data, &len, (void __user *)arg)) {
295 CERROR("OBD ioctl: data error\n");
300 case OBD_IOC_PROCESS_CFG: {
301 struct lustre_cfg *lcfg;
303 if (!data->ioc_plen1 || !data->ioc_pbuf1) {
304 CERROR("No config buffer passed!\n");
305 GOTO(out, err = -EINVAL);
307 OBD_ALLOC(lcfg, data->ioc_plen1);
309 GOTO(out, err = -ENOMEM);
310 err = copy_from_user(lcfg, data->ioc_pbuf1,
313 err = lustre_cfg_sanity_check(lcfg, data->ioc_plen1);
315 err = class_process_config(lcfg);
317 OBD_FREE(lcfg, data->ioc_plen1);
321 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
322 case OBD_GET_VERSION: {
325 if (!data->ioc_inlbuf1) {
326 CERROR("No buffer passed in ioctl\n");
327 GOTO(out, err = -EINVAL);
330 if (strlen(LUSTRE_VERSION_STRING) + 1 > data->ioc_inllen1) {
331 CERROR("ioctl buffer too small to hold version\n");
332 GOTO(out, err = -EINVAL);
337 CWARN("%s: ioctl(OBD_GET_VERSION) is deprecated, "
338 "use llapi_get_version_string() and/or relink\n",
341 memcpy(data->ioc_bulk, LUSTRE_VERSION_STRING,
342 strlen(LUSTRE_VERSION_STRING) + 1);
344 if (copy_to_user((void __user *)arg, data, len))
349 case OBD_IOC_NAME2DEV: {
350 /* Resolve a device name. This does not change the
351 * currently selected device.
355 dev = class_resolve_dev_name(data->ioc_inllen1,
359 GOTO(out, err = -EINVAL);
361 if (copy_to_user((void __user *)arg, data, sizeof(*data)))
366 case OBD_IOC_UUID2DEV: {
367 /* Resolve a device uuid. This does not change the
368 * currently selected device.
371 struct obd_uuid uuid;
373 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
374 CERROR("No UUID passed!\n");
375 GOTO(out, err = -EINVAL);
377 if (data->ioc_inlbuf1[data->ioc_inllen1 - 1] != 0) {
378 CERROR("UUID not NUL terminated!\n");
379 GOTO(out, err = -EINVAL);
382 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
383 obd_str2uuid(&uuid, data->ioc_inlbuf1);
384 dev = class_uuid2dev(&uuid);
387 CDEBUG(D_IOCTL, "No device for UUID %s!\n",
389 GOTO(out, err = -EINVAL);
392 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
394 if (copy_to_user((void __user *)arg, data, sizeof(*data)))
399 case OBD_IOC_GETDEVICE: {
400 int index = data->ioc_count;
403 if (!data->ioc_inlbuf1) {
404 CERROR("No buffer passed in ioctl\n");
405 GOTO(out, err = -EINVAL);
407 if (data->ioc_inllen1 < 128) {
408 CERROR("ioctl buffer too small to hold version\n");
409 GOTO(out, err = -EINVAL);
412 obd = class_num2obd(index);
414 GOTO(out, err = -ENOENT);
416 if (obd->obd_stopping)
418 else if (obd->obd_inactive)
420 else if (obd->obd_set_up)
422 else if (obd->obd_attached)
427 str = (char *)data->ioc_bulk;
428 snprintf(str, len - sizeof(*data), "%3d %s %s %s %s %d",
429 (int)index, status, obd->obd_type->typ_name,
430 obd->obd_name, obd->obd_uuid.uuid,
431 atomic_read(&obd->obd_refcount));
433 if (copy_to_user((void __user *)arg, data, len))
441 if (data->ioc_dev == OBD_DEV_BY_DEVNAME) {
442 if (data->ioc_inllen4 <= 0 || data->ioc_inlbuf4 == NULL)
443 GOTO(out, err = -EINVAL);
444 if (strnlen(data->ioc_inlbuf4, MAX_OBD_NAME) >= MAX_OBD_NAME)
445 GOTO(out, err = -EINVAL);
446 obd = class_name2obd(data->ioc_inlbuf4);
447 } else if (data->ioc_dev < class_devno_max()) {
448 obd = class_num2obd(data->ioc_dev);
450 CERROR("OBD ioctl: No device\n");
451 GOTO(out, err = -EINVAL);
455 CERROR("OBD ioctl : No Device %d\n", data->ioc_dev);
456 GOTO(out, err = -EINVAL);
458 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
460 if (!obd->obd_set_up || obd->obd_stopping) {
461 CERROR("OBD ioctl: device not setup %d \n", data->ioc_dev);
462 GOTO(out, err = -EINVAL);
465 err = obd_iocontrol(cmd, obd->obd_self_export, len, data, NULL);
469 if (copy_to_user((void __user *)arg, data, len))
472 OBD_FREE_LARGE(data, len);
474 } /* class_handle_ioctl */
476 /* to control /dev/obd */
477 static long obd_class_ioctl(struct file *filp, unsigned int cmd,
483 /* Allow non-root access for some limited ioctls */
484 if (!capable(CAP_SYS_ADMIN))
485 RETURN(err = -EACCES);
487 if ((cmd & 0xffffff00) == ((int)'T') << 8) /* ignore all tty ioctls */
488 RETURN(err = -ENOTTY);
490 err = class_handle_ioctl(cmd, (unsigned long)arg);
495 /* declare character device */
496 static const struct file_operations obd_psdev_fops = {
497 .owner = THIS_MODULE,
498 .unlocked_ioctl = obd_class_ioctl, /* unlocked_ioctl */
502 static struct miscdevice obd_psdev = {
503 .minor = MISC_DYNAMIC_MINOR,
504 .name = OBD_DEV_NAME,
505 .fops = &obd_psdev_fops,
508 #define test_string_to_size_err(value, expect, def_unit, __rc) \
513 BUILD_BUG_ON(sizeof(value) >= 23); \
514 __ret = sysfs_memparse(value, sizeof(value) - 1, &__size, def_unit); \
516 CERROR("string_helper: parsing '%s' expect rc %d != got %d\n", \
517 value, __rc, __ret); \
518 else if (!__ret && (u64)expect != __size) \
519 CERROR("string_helper: parsing '%s' expect %llu != got %llu\n",\
520 value, (u64)expect, __size); \
523 #define test_string_to_size_one(value, expect, def_unit) \
524 test_string_to_size_err(value, expect, def_unit, 0)
526 static int __init obd_init_checks(void)
528 __u64 u64val, div64val;
532 CDEBUG(D_INFO, "OBD_OBJECT_EOF = %#llx\n", (__u64)OBD_OBJECT_EOF);
534 u64val = OBD_OBJECT_EOF;
535 CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = %#llx\n", u64val);
536 if (u64val != OBD_OBJECT_EOF) {
537 CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
538 u64val, (int)sizeof(u64val));
541 len = snprintf(buf, sizeof(buf), "%#llx", u64val);
543 CERROR("u64 hex wrong length, strlen(%s)=%d != 18\n", buf, len);
547 div64val = OBD_OBJECT_EOF;
548 CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = %#llx\n", u64val);
549 if (u64val != OBD_OBJECT_EOF) {
550 CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
551 u64val, (int)sizeof(u64val));
554 if (u64val >> 8 != OBD_OBJECT_EOF >> 8) {
555 CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
556 u64val, (int)sizeof(u64val));
559 if (do_div(div64val, 256) != (u64val & 255)) {
560 CERROR("do_div(%#llx,256) != %llu\n", u64val, u64val & 255);
563 if (u64val >> 8 != div64val) {
564 CERROR("do_div(%#llx,256) %llu != %llu\n",
565 u64val, div64val, u64val >> 8);
568 len = snprintf(buf, sizeof(buf), "%#llx", u64val);
570 CERROR("u64 hex wrong length! strlen(%s)=%d != 18\n", buf, len);
573 len = snprintf(buf, sizeof(buf), "%llu", u64val);
575 CERROR("u64 wrong length! strlen(%s)=%d != 20\n", buf, len);
578 len = snprintf(buf, sizeof(buf), "%lld", u64val);
580 CERROR("s64 wrong length! strlen(%s)=%d != 2\n", buf, len);
583 if ((u64val & ~PAGE_MASK) >= PAGE_SIZE) {
584 CERROR("mask failed: u64val %llu >= %llu\n", u64val,
592 if (!test_string_to_size_err("256B34", 256, "B", -EINVAL)) {
593 CERROR("string_helpers: format should be number then units\n");
596 if (!test_string_to_size_err("132OpQ", 132, "B", -EINVAL)) {
597 CERROR("string_helpers: invalid units should be rejected\n");
600 if (!test_string_to_size_err("1.82B", 1, "B", -EINVAL)) {
601 CERROR("string_helpers: 'B' with '.' should be invalid\n");
604 if (test_string_to_size_one("343\n", 343, "B")) {
605 CERROR("string_helpers: should ignore newline\n");
611 /* memparse unit handling */
613 ret += test_string_to_size_one("0B", 0, "B");
614 ret += test_string_to_size_one("512B", 512, "B");
615 ret += test_string_to_size_one("1.067kB", 1067, "B");
616 ret += test_string_to_size_one("1.042KiB", 1067, "B");
617 ret += test_string_to_size_one("8", 8388608, "M");
618 ret += test_string_to_size_one("65536", 65536, "B");
619 ret += test_string_to_size_one("128", 131072, "K");
620 ret += test_string_to_size_one("1M", 1048576, "B");
621 ret += test_string_to_size_one("0.5T", 549755813888ULL, "T");
622 ret += test_string_to_size_one("256.5G", 275414777856ULL, "G");
626 /* string helper values */
627 ret += test_string_to_size_one("16", 16777216, "MiB");
628 ret += test_string_to_size_one("8.39MB", 8390000, "MiB");
629 ret += test_string_to_size_one("8.00MiB", 8388608, "MiB");
630 ret += test_string_to_size_one("256GB", 256000000000ULL, "GiB");
631 ret += test_string_to_size_one("238.731GiB", 256335459385ULL, "GiB");
636 ret += test_string_to_size_one("0.4TB", 400000000000ULL, "TiB");
637 ret += test_string_to_size_one("12.5TiB", 13743895347200ULL, "TiB");
638 ret += test_string_to_size_one("2PB", 2000000000000000ULL, "PiB");
639 ret += test_string_to_size_one("16PiB", 18014398509481984ULL, "PiB");
643 /* huge values should overflow */
644 if (!test_string_to_size_err("1000EiB", 0, "EiB", -EOVERFLOW)) {
645 CERROR("string_helpers: failed to detect binary overflow\n");
648 if (!test_string_to_size_err("1000EB", 0, "EiB", -EOVERFLOW)) {
649 CERROR("string_helpers: failed to detect decimal overflow\n");
656 static int __init obdclass_init(void)
660 LCONSOLE_INFO("Lustre: Build Version: "LUSTRE_VERSION_STRING"\n");
664 err = obd_init_checks();
668 #ifdef CONFIG_PROC_FS
669 obd_memory = lprocfs_alloc_stats(OBD_STATS_NUM,
670 LPROCFS_STATS_FLAG_NONE |
671 LPROCFS_STATS_FLAG_IRQ_SAFE);
672 if (obd_memory == NULL) {
673 CERROR("kmalloc of 'obd_memory' failed\n");
677 lprocfs_counter_init(obd_memory, OBD_MEMORY_STAT,
678 LPROCFS_CNTR_AVGMINMAX,
681 err = obd_zombie_impexp_init();
683 goto cleanup_obd_memory;
685 err = class_handle_init();
687 goto cleanup_zombie_impexp;
689 err = misc_register(&obd_psdev);
691 CERROR("cannot register OBD miscdevice: err = %d\n", err);
692 goto cleanup_class_handle;
695 /* Default the dirty page cache cap to 1/2 of system memory.
696 * For clients with less memory, a larger fraction is needed
697 * for other purposes (mostly for BGL). */
698 if (cfs_totalram_pages() <= 512 << (20 - PAGE_SHIFT))
699 obd_max_dirty_pages = cfs_totalram_pages() / 4;
701 obd_max_dirty_pages = cfs_totalram_pages() / 2;
703 err = obd_init_caches();
705 goto cleanup_deregister;
707 err = class_procfs_init();
711 err = lu_global_init();
713 goto cleanup_class_procfs;
715 err = cl_global_init();
717 goto cleanup_lu_global;
719 err = llog_info_init();
721 goto cleanup_cl_global;
723 #ifdef HAVE_SERVER_SUPPORT
724 err = dt_global_init();
726 goto cleanup_llog_info;
728 err = lu_ucred_global_init();
730 goto cleanup_dt_global;
732 err = lustre_tgt_register_fs();
733 if (err && err != -EBUSY) {
734 /* Don't fail if server code also registers "lustre_tgt" */
735 CERROR("obdclass: register fstype 'lustre_tgt' failed: rc = %d\n",
737 goto cleanup_lu_ucred_global;
739 #endif /* HAVE_SERVER_SUPPORT */
741 /* simulate a late OOM situation now to require all
742 * alloc'ed/initialized resources to be freed
744 if (OBD_FAIL_CHECK(OBD_FAIL_OBDCLASS_MODULE_LOAD)) {
745 /* force error to ensure module will be unloaded/cleaned */
752 #ifdef HAVE_SERVER_SUPPORT
753 /* fake error but filesystem has been registered */
754 lustre_tgt_unregister_fs();
756 cleanup_lu_ucred_global:
757 lu_ucred_global_fini();
763 #endif /* HAVE_SERVER_SUPPORT */
772 cleanup_class_procfs:
773 class_procfs_clean();
776 obd_cleanup_caches();
779 misc_deregister(&obd_psdev);
781 cleanup_class_handle:
782 class_handle_cleanup();
784 cleanup_zombie_impexp:
785 obd_zombie_impexp_stop();
788 #ifdef CONFIG_PROC_FS
789 lprocfs_free_stats(&obd_memory);
795 void obd_update_maxusage(void)
799 max = obd_memory_sum();
801 spin_lock(&obd_updatemax_lock);
802 if (max > obd_max_alloc)
804 spin_unlock(&obd_updatemax_lock);
806 EXPORT_SYMBOL(obd_update_maxusage);
808 #ifdef CONFIG_PROC_FS
809 __u64 obd_memory_max(void)
813 obd_update_maxusage();
814 spin_lock(&obd_updatemax_lock);
816 spin_unlock(&obd_updatemax_lock);
820 #endif /* CONFIG_PROC_FS */
822 static void __exit obdclass_exit(void)
824 #ifdef CONFIG_PROC_FS
827 #endif /* CONFIG_PROC_FS */
830 misc_deregister(&obd_psdev);
831 #ifdef HAVE_SERVER_SUPPORT
832 lustre_tgt_unregister_fs();
833 lu_ucred_global_fini();
835 #endif /* HAVE_SERVER_SUPPORT */
840 obd_cleanup_caches();
842 class_procfs_clean();
844 class_handle_cleanup();
845 class_del_uuid(NULL); /* Delete all UUIDs. */
846 obd_zombie_impexp_stop();
848 #ifdef CONFIG_PROC_FS
849 memory_leaked = obd_memory_sum();
850 memory_max = obd_memory_max();
852 lprocfs_free_stats(&obd_memory);
853 /* the below message is checked in test-framework.sh check_mem_leak() */
854 CDEBUG((memory_leaked) ? D_ERROR : D_INFO,
855 "obd_memory max: %llu, leaked: %llu\n",
856 memory_max, memory_leaked);
857 #endif /* CONFIG_PROC_FS */
862 void obd_heat_clear(struct obd_heat_instance *instance, int count)
866 memset(instance, 0, sizeof(*instance) * count);
869 EXPORT_SYMBOL(obd_heat_clear);
872 * The file heat is calculated for every time interval period I. The access
873 * frequency during each period is counted. The file heat is only recalculated
874 * at the end of a time period. And a percentage of the former file heat is
875 * lost when recalculated. The recursion formula to calculate the heat of the
876 * file f is as follow:
878 * Hi+1(f) = (1-P)*Hi(f)+ P*Ci
880 * Where Hi is the heat value in the period between time points i*I and
881 * (i+1)*I; Ci is the access count in the period; the symbol P refers to the
882 * weight of Ci. The larger the value the value of P is, the more influence Ci
883 * has on the file heat.
885 void obd_heat_decay(struct obd_heat_instance *instance, __u64 time_second,
886 unsigned int weight, unsigned int period_second)
892 if (instance->ohi_time_second > time_second) {
893 obd_heat_clear(instance, 1);
897 if (instance->ohi_time_second == 0)
900 for (second = instance->ohi_time_second + period_second;
901 second < time_second;
902 second += period_second) {
903 instance->ohi_heat = instance->ohi_heat *
904 (256 - weight) / 256 +
905 instance->ohi_count * weight / 256;
906 instance->ohi_count = 0;
907 instance->ohi_time_second = second;
911 EXPORT_SYMBOL(obd_heat_decay);
913 __u64 obd_heat_get(struct obd_heat_instance *instance, unsigned int time_second,
914 unsigned int weight, unsigned int period_second)
918 obd_heat_decay(instance, time_second, weight, period_second);
920 if (instance->ohi_count == 0)
921 RETURN(instance->ohi_heat);
923 RETURN(instance->ohi_heat * (256 - weight) / 256 +
924 instance->ohi_count * weight / 256);
926 EXPORT_SYMBOL(obd_heat_get);
928 void obd_heat_add(struct obd_heat_instance *instance,
929 unsigned int time_second, __u64 count,
930 unsigned int weight, unsigned int period_second)
934 obd_heat_decay(instance, time_second, weight, period_second);
935 if (instance->ohi_time_second == 0) {
936 instance->ohi_time_second = time_second;
937 instance->ohi_heat = 0;
938 instance->ohi_count = count;
940 instance->ohi_count += count;
944 EXPORT_SYMBOL(obd_heat_add);
946 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
947 MODULE_DESCRIPTION("Lustre Class Driver");
948 MODULE_VERSION(LUSTRE_VERSION_STRING);
949 MODULE_LICENSE("GPL");
951 module_init(obdclass_init);
952 module_exit(obdclass_exit);