Whamcloud - gitweb
LU-9091 obdclass: allow bare KMGTPE param suffix
[fs/lustre-release.git] / lustre / obdclass / class_obd.c
index 5eee8ef..8543769 100644 (file)
@@ -34,9 +34,7 @@
 
 #include <linux/miscdevice.h>
 #include <linux/user_namespace.h>
-#ifdef HAVE_UIDGID_HEADER
-# include <linux/uidgid.h>
-#endif
+#include <linux/uidgid.h>
 #include <linux/atomic.h>
 #include <linux/list.h>
 
@@ -98,9 +96,6 @@ EXPORT_SYMBOL(at_early_margin);
 int at_extra = 30;
 EXPORT_SYMBOL(at_extra);
 
-atomic_long_t obd_dirty_transit_pages;
-EXPORT_SYMBOL(obd_dirty_transit_pages);
-
 #ifdef CONFIG_PROC_FS
 struct lprocfs_stats *obd_memory = NULL;
 EXPORT_SYMBOL(obd_memory);
@@ -497,23 +492,6 @@ out:
        RETURN(err);
 } /* class_handle_ioctl */
 
-/*  opening /dev/obd */
-static int obd_class_open(struct inode * inode, struct file * file)
-{
-       ENTRY;
-       try_module_get(THIS_MODULE);
-       RETURN(0);
-}
-
-/*  closing /dev/obd */
-static int obd_class_release(struct inode * inode, struct file * file)
-{
-       ENTRY;
-
-       module_put(THIS_MODULE);
-       RETURN(0);
-}
-
 /* to control /dev/obd */
 static long obd_class_ioctl(struct file *filp, unsigned int cmd,
                            unsigned long arg)
@@ -537,8 +515,6 @@ static long obd_class_ioctl(struct file *filp, unsigned int cmd,
 static struct file_operations obd_psdev_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = obd_class_ioctl,      /* unlocked_ioctl */
-       .open           = obd_class_open,       /* open */
-       .release        = obd_class_release,    /* release */
 };
 
 /* modules setup */
@@ -548,70 +524,152 @@ struct miscdevice obd_psdev = {
        .fops   = &obd_psdev_fops,
 };
 
-static int obd_init_checks(void)
+#define test_string_to_size_err(value, expect, def_unit, __rc)                \
+({                                                                            \
+       u64 __size;                                                            \
+       int __ret;                                                             \
+                                                                              \
+       BUILD_BUG_ON(sizeof(value) >= 23);                                     \
+       __ret = sysfs_memparse(value, sizeof(value) - 1, &__size, def_unit);   \
+       if (__ret != __rc)                                                     \
+               CERROR("string_helper: parsing '%s' expect rc %d != got %d\n", \
+                      value, __rc, __ret);                                    \
+       else if (!__ret && (u64)expect != __size)                              \
+               CERROR("string_helper: parsing '%s' expect %llu != got %llu\n",\
+                      value, (u64)expect, __size);                            \
+       __ret;                                                                 \
+})
+#define test_string_to_size_one(value, expect, def_unit)                      \
+       test_string_to_size_err(value, expect, def_unit, 0)
+
+static int __init obd_init_checks(void)
 {
-        __u64 u64val, div64val;
-        char buf[64];
-        int len, ret = 0;
+       __u64 u64val, div64val;
+       char buf[64];
+       int len, ret = 0;
 
        CDEBUG(D_INFO, "OBD_OBJECT_EOF = %#llx\n", (__u64)OBD_OBJECT_EOF);
 
-        u64val = OBD_OBJECT_EOF;
+       u64val = OBD_OBJECT_EOF;
        CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = %#llx\n", u64val);
-        if (u64val != OBD_OBJECT_EOF) {
+       if (u64val != OBD_OBJECT_EOF) {
                CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
-                       u64val, (int)sizeof(u64val));
-                ret = -EINVAL;
-        }
+                      u64val, (int)sizeof(u64val));
+               ret = -EINVAL;
+       }
        len = snprintf(buf, sizeof(buf), "%#llx", u64val);
-        if (len != 18) {
-               CWARN("u64 hex wrong length! strlen(%s)=%d != 18\n", buf, len);
-                ret = -EINVAL;
-        }
+       if (len != 18) {
+               CERROR("u64 hex wrong length, strlen(%s)=%d != 18\n", buf, len);
+               ret = -EINVAL;
+       }
 
-        div64val = OBD_OBJECT_EOF;
+       div64val = OBD_OBJECT_EOF;
        CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = %#llx\n", u64val);
-        if (u64val != OBD_OBJECT_EOF) {
+       if (u64val != OBD_OBJECT_EOF) {
                CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
-                       u64val, (int)sizeof(u64val));
-                ret = -EOVERFLOW;
-        }
-        if (u64val >> 8 != OBD_OBJECT_EOF >> 8) {
+                      u64val, (int)sizeof(u64val));
+               ret = -EOVERFLOW;
+       }
+       if (u64val >> 8 != OBD_OBJECT_EOF >> 8) {
                CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
-                       u64val, (int)sizeof(u64val));
-                return -EOVERFLOW;
-        }
-        if (do_div(div64val, 256) != (u64val & 255)) {
+                      u64val, (int)sizeof(u64val));
+               ret = -EOVERFLOW;
+       }
+       if (do_div(div64val, 256) != (u64val & 255)) {
                CERROR("do_div(%#llx,256) != %llu\n", u64val, u64val & 255);
-                return -EOVERFLOW;
-        }
-        if (u64val >> 8 != div64val) {
+               ret = -EOVERFLOW;
+       }
+       if (u64val >> 8 != div64val) {
                CERROR("do_div(%#llx,256) %llu != %llu\n",
-                       u64val, div64val, u64val >> 8);
-                return -EOVERFLOW;
-        }
+                      u64val, div64val, u64val >> 8);
+               ret = -EOVERFLOW;
+       }
        len = snprintf(buf, sizeof(buf), "%#llx", u64val);
-        if (len != 18) {
-               CWARN("u64 hex wrong length! strlen(%s)=%d != 18\n", buf, len);
-                ret = -EINVAL;
-        }
+       if (len != 18) {
+               CERROR("u64 hex wrong length! strlen(%s)=%d != 18\n", buf, len);
+               ret = -EINVAL;
+       }
        len = snprintf(buf, sizeof(buf), "%llu", u64val);
-        if (len != 20) {
-               CWARN("u64 wrong length! strlen(%s)=%d != 20\n", buf, len);
-                ret = -EINVAL;
-        }
+       if (len != 20) {
+               CERROR("u64 wrong length! strlen(%s)=%d != 20\n", buf, len);
+               ret = -EINVAL;
+       }
        len = snprintf(buf, sizeof(buf), "%lld", u64val);
-        if (len != 2) {
-               CWARN("s64 wrong length! strlen(%s)=%d != 2\n", buf, len);
-                ret = -EINVAL;
-        }
+       if (len != 2) {
+               CERROR("s64 wrong length! strlen(%s)=%d != 2\n", buf, len);
+               ret = -EINVAL;
+       }
        if ((u64val & ~PAGE_MASK) >= PAGE_SIZE) {
-               CWARN("mask failed: u64val %llu >= %llu\n", u64val,
-                     (__u64)PAGE_SIZE);
-                ret = -EINVAL;
-        }
+               CERROR("mask failed: u64val %llu >= %llu\n", u64val,
+                      (__u64)PAGE_SIZE);
+               ret = -EINVAL;
+       }
+       if (ret)
+               RETURN(ret);
+
+       /* invalid string */
+       if (!test_string_to_size_err("256B34", 256, "B", -EINVAL)) {
+               CERROR("string_helpers: format should be number then units\n");
+               ret = -EINVAL;
+       }
+       if (!test_string_to_size_err("132OpQ", 132, "B", -EINVAL)) {
+               CERROR("string_helpers: invalid units should be rejected\n");
+               ret = -EINVAL;
+       }
+       if (!test_string_to_size_err("1.82B", 1, "B", -EINVAL)) {
+               CERROR("string_helpers: 'B' with '.' should be invalid\n");
+               ret = -EINVAL;
+       }
+       if (test_string_to_size_one("343\n", 343, "B")) {
+               CERROR("string_helpers: should ignore newline\n");
+               ret = -EINVAL;
+       }
+       if (ret)
+               RETURN(ret);
+
+       /* memparse unit handling */
+       ret = 0;
+       ret += test_string_to_size_one("0B", 0, "B");
+       ret += test_string_to_size_one("512B", 512, "B");
+       ret += test_string_to_size_one("1.067kB", 1067, "B");
+       ret += test_string_to_size_one("1.042KiB", 1067, "B");
+       ret += test_string_to_size_one("8", 8388608, "M");
+       ret += test_string_to_size_one("65536", 65536, "B");
+       ret += test_string_to_size_one("128", 131072, "K");
+       ret += test_string_to_size_one("1M", 1048576, "B");
+       ret += test_string_to_size_one("0.5T", 549755813888ULL, "T");
+       ret += test_string_to_size_one("256.5G", 275414777856ULL, "G");
+       if (ret)
+               RETURN(ret);
+
+       /* string helper values */
+       ret += test_string_to_size_one("16", 16777216, "MiB");
+       ret += test_string_to_size_one("8.39MB", 8390000, "MiB");
+       ret += test_string_to_size_one("8.00MiB", 8388608, "MiB");
+       ret += test_string_to_size_one("256GB", 256000000000ULL, "GiB");
+       ret += test_string_to_size_one("238.731GiB", 256335459385ULL, "GiB");
+       if (ret)
+               RETURN(ret);
+
+       /* huge values */
+       ret += test_string_to_size_one("0.4TB", 400000000000ULL, "TiB");
+       ret += test_string_to_size_one("12.5TiB", 13743895347200ULL, "TiB");
+       ret += test_string_to_size_one("2PB", 2000000000000000ULL, "PiB");
+       ret += test_string_to_size_one("16PiB", 18014398509481984ULL, "PiB");
+       if (ret)
+               RETURN(ret);
+
+       /* huge values should overflow */
+       if (!test_string_to_size_err("1000EiB", 0, "EiB", -EOVERFLOW)) {
+               CERROR("string_helpers: failed to detect binary overflow\n");
+               ret = -EINVAL;
+       }
+       if (!test_string_to_size_err("1000EB", 0, "EiB", -EOVERFLOW)) {
+               CERROR("string_helpers: failed to detect decimal overflow\n");
+               ret = -EINVAL;
+       }
 
-        return ret;
+       return ret;
 }
 
 static int __init obdclass_init(void)
@@ -623,7 +681,7 @@ static int __init obdclass_init(void)
        libcfs_kkuc_init();
 
        err = obd_init_checks();
-       if (err == -EOVERFLOW)
+       if (err)
                return err;
 
 #ifdef CONFIG_PROC_FS