s390/topology: correct topology mode proc handler
authorVasily Gorbik <gor@linux.ibm.com>
Sun, 24 Jun 2018 10:28:46 +0000 (12:28 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 6 Jul 2018 06:47:53 +0000 (08:47 +0200)
Reuse proc_douintvec_minmax to simplify topology mode proc handler.
This also enforces correct range of 0-1 on proc writes and correctly
handles numbers starting with 0 or spaces.

Before:
$ echo 01 > /proc/sys/s390/topology
$ cat /proc/sys/s390/topology
0
$ echo ' 1' > /proc/sys/s390/topology
-bash: echo: write error: Invalid argument
$ echo 2 > /proc/sys/s390/topology
-bash: echo: write error: Invalid argument
$ echo 12 > /proc/sys/s390/topology
$ cat /proc/sys/s390/topology
1

After:
$ echo 01 > /proc/sys/s390/topology
$ cat /proc/sys/s390/topology
1
$ echo ' 1' > /proc/sys/s390/topology
$ cat /proc/sys/s390/topology
1
$ echo 2 > /proc/sys/s390/topology
-bash: echo: write error: Invalid argument
$ echo 12 > /proc/sys/s390/topology
-bash: echo: write error: Invalid argument
$ echo '   0' > /proc/sys/s390/topology
$ cat /proc/sys/s390/topology
0

Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/topology.c

index 33ebb42..e8184a1 100644 (file)
@@ -579,40 +579,33 @@ early_param("topology", topology_setup);
 static int topology_ctl_handler(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       unsigned int len;
+       int enabled = topology_is_enabled();
        int new_mode;
-       char buf[2];
+       int zero = 0;
+       int one = 1;
+       int rc;
+       struct ctl_table ctl_entry = {
+               .procname       = ctl->procname,
+               .data           = &enabled,
+               .maxlen         = sizeof(int),
+               .extra1         = &zero,
+               .extra2         = &one,
+       };
+
+       rc = proc_douintvec_minmax(&ctl_entry, write, buffer, lenp, ppos);
+       if (rc < 0 || !write)
+               return rc;
 
-       if (!*lenp || *ppos) {
-               *lenp = 0;
-               return 0;
-       }
-       if (!write) {
-               memcpy(buf, topology_is_enabled() ? "1\n" : "0\n", ARRAY_SIZE(buf));
-               len = strnlen(buf, ARRAY_SIZE(buf));
-               if (len > *lenp)
-                       len = *lenp;
-               if (copy_to_user(buffer, buf, len))
-                       return -EFAULT;
-               goto out;
-       }
-       len = *lenp;
-       if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len))
-               return -EFAULT;
-       if (buf[0] != '0' && buf[0] != '1')
-               return -EINVAL;
        mutex_lock(&smp_cpu_state_mutex);
-       new_mode = topology_get_mode(buf[0] == '1');
+       new_mode = topology_get_mode(enabled);
        if (topology_mode != new_mode) {
                topology_mode = new_mode;
                topology_schedule_update();
        }
        mutex_unlock(&smp_cpu_state_mutex);
        topology_flush_work();
-out:
-       *lenp = len;
-       *ppos += len;
-       return 0;
+
+       return rc;
 }
 
 static struct ctl_table topology_ctl_table[] = {