Whamcloud - gitweb
LU-14428 libcfs: discard cfs_trace_copyin_string()
[fs/lustre-release.git] / libcfs / libcfs / module.c
index 81c1f6f..d7c1bcf 100644 (file)
@@ -54,6 +54,7 @@
 #include <libcfs/libcfs.h>
 #include <libcfs/libcfs_crypto.h>
 #include <lnet/lib-lnet.h>
+#include <libcfs/crypto/llcrypt.h>
 #include "tracefile.h"
 
 static struct dentry *lnet_debugfs_root;
@@ -72,13 +73,14 @@ static inline size_t libcfs_ioctl_packlen(struct libcfs_ioctl_data *data)
 
 static bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data)
 {
-       if (data->ioc_hdr.ioc_len > BIT(30))
+       const int maxlen = 1 << 30;
+       if (data->ioc_hdr.ioc_len > maxlen)
                return true;
 
-       if (data->ioc_inllen1 > BIT(30))
+       if (data->ioc_inllen1 > maxlen)
                return true;
 
-       if (data->ioc_inllen2 > BIT(30))
+       if (data->ioc_inllen2 > maxlen)
                return true;
 
        if (data->ioc_inlbuf1 && !data->ioc_inllen1)
@@ -285,17 +287,16 @@ static int __proc_dobitmasks(void *data, int write,
                             loff_t pos, void __user *buffer, int nob)
 {
        const int     tmpstrlen = 512;
-       char         *tmpstr;
+       char         *tmpstr = NULL;
        int           rc;
        unsigned int *mask = data;
        int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
        int           is_printk = (mask == &libcfs_printk) ? 1 : 0;
 
-       rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
-       if (rc < 0)
-               return rc;
-
        if (!write) {
+               rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
+               if (rc < 0)
+                       return rc;
                libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
                rc = strlen(tmpstr);
 
@@ -306,13 +307,11 @@ static int __proc_dobitmasks(void *data, int write,
                                                      tmpstr + pos, "\n");
                }
        } else {
-               rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
-               if (rc < 0) {
-                       kfree(tmpstr);
-                       return rc;
-               }
+               tmpstr = memdup_user_nul(buffer, nob);
+               if (!tmpstr)
+                       return -ENOMEM;
 
-               rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
+               rc = libcfs_debug_str2mask(mask, strim(tmpstr), is_subsys);
                /* Always print LBUG/LASSERT to console, so keep this mask */
                if (is_printk)
                        *mask |= D_EMERG;
@@ -386,12 +385,151 @@ static int proc_fail_loc(struct ctl_table *table, int write,
        int rc;
        long old_fail_loc = cfs_fail_loc;
 
-       rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
-       if (old_fail_loc != cfs_fail_loc)
+       if (!*lenp || *ppos) {
+               *lenp = 0;
+               return 0;
+       }
+
+       if (write) {
+               char *kbuf = memdup_user_nul(buffer, *lenp);
+
+               if (IS_ERR(kbuf))
+                       return PTR_ERR(kbuf);
+               rc = kstrtoul(kbuf, 0, &cfs_fail_loc);
+               kfree(kbuf);
+               *ppos += *lenp;
+       } else {
+               char kbuf[64/3+3];
+
+               rc = scnprintf(kbuf, sizeof(kbuf), "%lu\n", cfs_fail_loc);
+               if (copy_to_user(buffer, kbuf, rc))
+                       rc = -EFAULT;
+               else {
+                       *lenp = rc;
+                       *ppos += rc;
+               }
+       }
+
+       if (old_fail_loc != cfs_fail_loc) {
+               cfs_race_state = 1;
                wake_up(&cfs_race_waitq);
+       }
+       return rc;
+}
+
+int debugfs_doint(struct ctl_table *table, int write,
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int rc;
+
+       if (!*lenp || *ppos) {
+               *lenp = 0;
+               return 0;
+       }
+
+       if (write) {
+               char *kbuf = memdup_user_nul(buffer, *lenp);
+               int val;
+
+               if (IS_ERR(kbuf))
+                       return PTR_ERR(kbuf);
+
+               rc = kstrtoint(kbuf, 0, &val);
+               kfree(kbuf);
+               if (!rc) {
+                       if (table->extra1 && val < *(int *)table->extra1)
+                               val = *(int *)table->extra1;
+                       if (table->extra2 && val > *(int *)table->extra2)
+                               val = *(int *)table->extra2;
+                       *(int *)table->data = val;
+               }
+               *ppos += *lenp;
+       } else {
+               char kbuf[64/3+3];
+
+               rc = scnprintf(kbuf, sizeof(kbuf), "%u\n", *(int *)table->data);
+               if (copy_to_user(buffer, kbuf, rc))
+                       rc = -EFAULT;
+               else {
+                       *lenp = rc;
+                       *ppos += rc;
+               }
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL(debugfs_doint);
+
+static int debugfs_dou64(struct ctl_table *table, int write,
+                        void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int rc;
+
+       if (!*lenp || *ppos) {
+               *lenp = 0;
+               return 0;
+       }
+
+       if (write) {
+               char *kbuf = memdup_user_nul(buffer, *lenp);
+               unsigned long long val;
+
+               if (IS_ERR(kbuf))
+                       return PTR_ERR(kbuf);
+
+               rc = kstrtoull(kbuf, 0, &val);
+               kfree(kbuf);
+               if (!rc)
+                       *(u64 *)table->data = val;
+               *ppos += *lenp;
+       } else {
+               char kbuf[64/3+3];
+
+               rc = scnprintf(kbuf, sizeof(kbuf), "%llu\n",
+                              (unsigned long long)*(u64 *)table->data);
+               if (copy_to_user(buffer, kbuf, rc))
+                       rc = -EFAULT;
+               else {
+                       *lenp = rc;
+                       *ppos += rc;
+               }
+       }
+
        return rc;
 }
 
+static int debugfs_dostring(struct ctl_table *table, int write,
+                           void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int len = *lenp;
+       char *kbuf = table->data;
+
+       if (!len || *ppos) {
+               *lenp = 0;
+               return 0;
+       }
+       if (len > table->maxlen)
+               len = table->maxlen;
+       if (write) {
+               if (copy_from_user(kbuf, buffer, len))
+                       return -EFAULT;
+               memset(kbuf+len, 0, table->maxlen - len);
+               *ppos = *lenp;
+       } else {
+               len = strnlen(kbuf, len);
+               if (copy_to_user(buffer, kbuf, len))
+                       return -EFAULT;
+               if (len < *lenp) {
+                       if (copy_to_user(buffer+len, "\n", 1))
+                               return -EFAULT;
+                       len += 1;
+               }
+               *ppos += len;
+               *lenp -= len;
+       }
+       return len;
+}
+
 static int __proc_cpt_table(void *data, int write,
                            loff_t pos, void __user *buffer, int nob)
 {
@@ -402,8 +540,6 @@ static int __proc_cpt_table(void *data, int write,
        if (write)
                return -EPERM;
 
-       LASSERT(cfs_cpt_tab);
-
        while (1) {
                LIBCFS_ALLOC(buf, len);
                if (buf == NULL)
@@ -450,8 +586,6 @@ static int __proc_cpt_distance(void *data, int write,
        if (write)
                return -EPERM;
 
-       LASSERT(cfs_cpt_tab);
-
        while (1) {
                LIBCFS_ALLOC(buf, len);
                if (buf == NULL)
@@ -527,21 +661,21 @@ static struct ctl_table lnet_table[] = {
                .data           = lnet_debug_log_upcall,
                .maxlen         = sizeof(lnet_debug_log_upcall),
                .mode           = 0644,
-               .proc_handler   = &proc_dostring,
+               .proc_handler   = &debugfs_dostring,
        },
        {
                .procname       = "lnet_memused",
-               .data           = (int *)&libcfs_kmemory.counter,
-               .maxlen         = sizeof(int),
+               .data           = (u64 *)&libcfs_kmem.counter,
+               .maxlen         = sizeof(u64),
                .mode           = 0444,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &debugfs_dou64,
        },
        {
                .procname       = "catastrophe",
                .data           = &libcfs_catastrophe,
                .maxlen         = sizeof(int),
                .mode           = 0444,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &debugfs_doint,
        },
        {
                .procname       = "dump_kernel",
@@ -560,7 +694,7 @@ static struct ctl_table lnet_table[] = {
                .data           = &libcfs_watchdog_ratelimit,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
+               .proc_handler   = &debugfs_doint,
                .extra1         = &min_watchdog_ratelimit,
                .extra2         = &max_watchdog_ratelimit,
        },
@@ -583,14 +717,14 @@ static struct ctl_table lnet_table[] = {
                .data           = &cfs_fail_val,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec
+               .proc_handler   = &debugfs_doint
        },
        {
                .procname       = "fail_err",
                .data           = &cfs_fail_err,
                .maxlen         = sizeof(cfs_fail_err),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &debugfs_doint,
        },
        {
        }
@@ -721,12 +855,16 @@ static int __init libcfs_init(void)
 
        cfs_arch_init();
 
+       init_libcfs_vfree_atomic();
+
        rc = libcfs_debug_init(5 * 1024 * 1024);
        if (rc < 0) {
                pr_err("LustreError: libcfs_debug_init: rc = %d\n", rc);
                return (rc);
        }
 
+       cfs_debug_init();
+
        rc = cfs_cpu_init();
        if (rc != 0)
                goto cleanup_debug;
@@ -761,6 +899,12 @@ static int __init libcfs_init(void)
        if (!IS_ERR_OR_NULL(lnet_debugfs_root))
                lnet_insert_debugfs_links(lnet_debugfs_symlinks);
 
+       rc = llcrypt_init();
+       if (rc) {
+               CERROR("llcrypt_init: error %d\n", rc);
+               goto cleanup_wi;
+       }
+
        CDEBUG (D_OTHER, "portals setup OK\n");
        return 0;
 cleanup_wi:
@@ -782,8 +926,10 @@ static void __exit libcfs_exit(void)
        debugfs_remove_recursive(lnet_debugfs_root);
        lnet_debugfs_root = NULL;
 
-       CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
-              atomic_read(&libcfs_kmemory));
+       CDEBUG(D_MALLOC, "before Portals cleanup: kmem %lld\n",
+              libcfs_kmem_read());
+
+       llcrypt_exit();
 
        if (cfs_rehash_wq) {
                destroy_workqueue(cfs_rehash_wq);
@@ -798,13 +944,15 @@ static void __exit libcfs_exit(void)
        cfs_cpu_fini();
 
        /* the below message is checked in test-framework.sh check_mem_leak() */
-       if (atomic_read(&libcfs_kmemory) != 0)
-               CERROR("Portals memory leaked: %d bytes\n",
-                      atomic_read(&libcfs_kmemory));
+       if (libcfs_kmem_read() != 0)
+               CERROR("Portals memory leaked: %lld bytes\n",
+                      libcfs_kmem_read());
 
        rc = libcfs_debug_cleanup();
        if (rc)
                pr_err("LustreError: libcfs_debug_cleanup: rc = %d\n", rc);
+
+       exit_libcfs_vfree_atomic();
 }
 
 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");