[alsa-devel] [PATCH 00/27 v2] ALSA: seq: obsolete change of address limit
Hi,
For purpose of this patchset, please refer to my previous post: [alsa-devel] obsolete change of address limit http://mailman.alsa-project.org/pipermail/alsa-devel/2016-August/110937.html
Changes in v2: - Use '_IOC_SIZE' macro to calculate the size of argument of ioctl command. - Keep redundant longer name. - Improve comments. - Merge some patches relevant to the same features.
I give up using 'dir' field in each ioctl command to decide copying, because some ioctl commands for ALSA sequencer core includes bugs against actual implementations.
Takashi Sakamoto (27): ALSA: seq: add const qualifier to table of functions for ioctl ALSA: seq: fulfill callback entry for ioctl ALSA: seq: copy ioctl data from user space to kernel stack ALSA: seq: add documentation for snd_seq_kernel_client_ctl ALSA: seq: obsolete address mode in compatibility layer ALSA: seq: obsolete change of address limit in in-kernel path for ioctl ALSA: seq: obsolete address limit helper ALSA: seq: optimize pversion function to new design ALSA: seq: optimize client_id function to new design ALSA: seq: optimize system_info function to new design ALSA: seq: optimize running mode function to new design ALSA: seq: optimize get/set_client_info function to new design ALSA: seq: optimize create/delete_port function to new design ALSA: seq: optimize get/set_port_info function to new design ALSA: seq: optimize subscribe_port function to new design ALSA: seq: optimize create/delete_queue function to new design ALSA: seq: optimize get/set_queue_info function to new design ALSA: seq: optimize get/set_queue_info function to new design ALSA: seq: optimize get_named_queue function to new design ALSA: seq: optimize get_queue_status function to new design ALSA: seq: optimize get/set_queue_tempo function to new design ALSA: seq: optimize get/set_queue_timer function to new design ALSA: seq: optimize get/set_queue_client function to new design ALSA: seq: optimize get/set_client_pool function to new design ALSA: seq: optimize remove_events function to new design ALSA: seq: optimize get_subscription function to new design ALSA: seq: optimize query functions for subscribes, next client and port to new design
sound/core/seq/seq_clientmgr.c | 750 +++++++++++++++++++---------------------- sound/core/seq/seq_compat.c | 26 +- 2 files changed, 353 insertions(+), 423 deletions(-)
Each entry in this table is never changed in runtime. This commit moves it from .data to .rodata section.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index d6d9419..42be1e5 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2168,7 +2168,7 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
/* -------------------------------------------------------- */
-static struct seq_ioctl_table { +static const struct seq_ioctl_table { unsigned int cmd; int (*func)(struct snd_seq_client *client, void __user * arg); } ioctl_tables[] = { @@ -2207,7 +2207,7 @@ static struct seq_ioctl_table { static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, void __user *arg) { - struct seq_ioctl_table *p; + const struct seq_ioctl_table *p;
switch (cmd) { case SNDRV_SEQ_IOCTL_PVERSION:
Most of callback functions corresponding to each ioctl command are in local table, while two of them are not. This is a bit worse to handle the command in a consistent way.
This commit adds entries for these two functions in the table.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 42be1e5..78fd64e 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1129,6 +1129,16 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait) /*-----------------------------------------------------*/
+static int seq_ioctl_pversion(struct snd_seq_client *client, void __user *arg) +{ + return put_user(SNDRV_SEQ_VERSION, (int __user *)arg) ? -EFAULT : 0; +} + +static int seq_ioctl_client_id(struct snd_seq_client *client, void __user *arg) +{ + return put_user(client->number, (int __user *)arg) ? -EFAULT : 0; +} + /* SYSTEM_INFO ioctl() */ static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user *arg) { @@ -2172,6 +2182,8 @@ static const struct seq_ioctl_table { unsigned int cmd; int (*func)(struct snd_seq_client *client, void __user * arg); } ioctl_tables[] = { + { SNDRV_SEQ_IOCTL_PVERSION, seq_ioctl_pversion }, + { SNDRV_SEQ_IOCTL_CLIENT_ID, seq_ioctl_client_id }, { SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info }, { SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode }, { SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, snd_seq_ioctl_get_client_info }, @@ -2209,15 +2221,6 @@ static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, { const struct seq_ioctl_table *p;
- switch (cmd) { - case SNDRV_SEQ_IOCTL_PVERSION: - /* return sequencer version number */ - return put_user(SNDRV_SEQ_VERSION, (int __user *)arg) ? -EFAULT : 0; - case SNDRV_SEQ_IOCTL_CLIENT_ID: - /* return the id of this client */ - return put_user(client->number, (int __user *)arg) ? -EFAULT : 0; - } - if (! arg) return -EFAULT; for (p = ioctl_tables; p->cmd; p++) {
ALSA sequencer core allows kernel-mode tasks to execute operations corresponding to ioctls by user-mode tasks. This is for compatibility layers such as ABIs for 32/64 bit and I/O operations via Open Sound System.
This design requires to handle ioctl data in kernel space. For this requirement, ALSA sequencer core temporarily changes address limit for the task by get_fs()/set_fs() macro.
Although, this way get shape of code worse, because even when an pointer has '__user' qualifier, actually it refers to kernel space, depending on the task. This easily misleads readers.
This commit is a preparation for following patches to solve this issue. Data from user space is once copied to kernel stack, then operated and copied to user space, in a consistent manner. This manner forces all ioctl operations to copy the data from/to user space, even if it's read-only or write-only. Thus, it has an overhead for simpler ioctl commands.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 49 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 78fd64e..de1177f 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2180,7 +2180,7 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
static const struct seq_ioctl_table { unsigned int cmd; - int (*func)(struct snd_seq_client *client, void __user * arg); + int (*func)(struct snd_seq_client *client, void *arg); } ioctl_tables[] = { { SNDRV_SEQ_IOCTL_PVERSION, seq_ioctl_pversion }, { SNDRV_SEQ_IOCTL_CLIENT_ID, seq_ioctl_client_id }, @@ -2233,14 +2233,57 @@ static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, }
-static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long snd_seq_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { struct snd_seq_client *client = file->private_data; + const struct seq_ioctl_table *p; + /* To use kernel stack for ioctl data. */ + union ioctl_arg { + int pversion; + int client_id; + struct snd_seq_system_info system_info; + struct snd_seq_running_info running_info; + struct snd_seq_client_info client_info; + struct snd_seq_port_info port_info; + struct snd_seq_port_subscribe port_subscribe; + struct snd_seq_queue_info queue_info; + struct snd_seq_queue_status queue_status; + struct snd_seq_queue_tempo tempo; + struct snd_seq_queue_timer queue_timer; + struct snd_seq_queue_client queue_client; + struct snd_seq_client_pool client_pool; + struct snd_seq_remove_events remove_events; + struct snd_seq_query_subs query_subs; + } buf = {0}; + int err;
if (snd_BUG_ON(!client)) return -ENXIO; + + for (p = ioctl_tables; p->cmd > 0; ++p) { + if (p->cmd == cmd) + break; + } + if (p->cmd == 0) + return -ENOTTY; + + /* + * All of ioctl commands for ALSA sequencer get an argument of size + * within 13 bits. We can safely pick up the size from the command. + * On the other hand, some commands includes a bug of 'read' or 'write', + * thus we cannot utilize information from the access fields. + */ + if (copy_from_user(&buf, (const void __user *)arg, _IOC_SIZE(p->cmd))) + return -EFAULT; - return snd_seq_do_ioctl(client, cmd, (void __user *) arg); + err = p->func(client, &buf); + if (err >= 0) { + if (copy_to_user((void __user *)arg, &buf, _IOC_SIZE(p->cmd))) + return -EFAULT; + } + + return err; }
#ifdef CONFIG_COMPAT
This kernel API is used by kernel implementation. Currently, it's used for kernel clients of ALSA sequencer, while it can be used for application clients. The difference is just on address spaces of argument. In short, this kernel API can be available for application client with data in kernel space.
This commit adds a document about this.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index de1177f..586f9cd 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2469,9 +2469,17 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
-/* - * exported, called by kernel clients to perform same functions as with - * userland ioctl() +/** + * snd_seq_kernel_client_ctl - operate a command for a client with data in + * kernel space. + * @clientid: A numerical ID for a client. + * @cmd: An ioctl(2) command for ALSA sequencer operation. + * @arg: A pointer to data in kernel space. + * + * Against its name, both kernel/application client can be handled by this + * kernel API. Address space for 'arg' argument should be in kernel space. + * + * Return: 0 at success. Negative error code at failure. */ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) {
In a 32/64 bit compatibility layer of ALSA sequencer core, data for some ioctls is copied to kernel stack and passed to core operations. Then, address limit of running task is changed because core implementation expected arguments in userspace.
In this case, snd_seq_kernel_client_ctl() is available. This commit replaces with it.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_compat.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c index 6517590..d9cf163 100644 --- a/sound/core/seq/seq_compat.c +++ b/sound/core/seq/seq_compat.c @@ -42,12 +42,11 @@ struct snd_seq_port_info32 { char reserved[59]; /* for future use */ };
-static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned int cmd, - struct snd_seq_port_info32 __user *data32) +static int snd_seq_call_port_info_ioctl(int clientid, unsigned int cmd, + struct snd_seq_port_info32 __user *data32) { int err = -EFAULT; struct snd_seq_port_info *data; - mm_segment_t fs;
data = kmalloc(sizeof(*data), GFP_KERNEL); if (!data) @@ -59,9 +58,7 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned goto error; data->kernel = NULL;
- fs = snd_enter_user(); - err = snd_seq_do_ioctl(client, cmd, data); - snd_leave_user(fs); + err = snd_seq_kernel_client_ctl(clientid, cmd, data); if (err < 0) goto error;
@@ -123,17 +120,22 @@ static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned l case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION: case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT: case SNDRV_SEQ_IOCTL_RUNNING_MODE: - return snd_seq_do_ioctl(client, cmd, argp); + return snd_seq_ioctl(file, cmd, (unsigned long)argp); case SNDRV_SEQ_IOCTL_CREATE_PORT32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp); + return snd_seq_call_port_info_ioctl(client->number, + SNDRV_SEQ_IOCTL_CREATE_PORT, argp); case SNDRV_SEQ_IOCTL_DELETE_PORT32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp); + return snd_seq_call_port_info_ioctl(client->number, + SNDRV_SEQ_IOCTL_DELETE_PORT, argp); case SNDRV_SEQ_IOCTL_GET_PORT_INFO32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp); + return snd_seq_call_port_info_ioctl(client->number, + SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp); case SNDRV_SEQ_IOCTL_SET_PORT_INFO32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp); + return snd_seq_call_port_info_ioctl(client->number, + SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp); case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp); + return snd_seq_call_port_info_ioctl(client->number, + SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp); } return -ENOIOCTLCMD; }
In former commit, actual operations for each ioctl is re-designed to get data in kernel space. Therefore, no need to cast pointer in kernel space to user space.
This commit applies optimization to in-kernel path of ioctl.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 586f9cd..449eb7a 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2216,23 +2216,6 @@ static const struct seq_ioctl_table { { 0, NULL }, };
-static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, - void __user *arg) -{ - const struct seq_ioctl_table *p; - - if (! arg) - return -EFAULT; - for (p = ioctl_tables; p->cmd; p++) { - if (p->cmd == cmd) - return p->func(client, arg); - } - pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", - cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); - return -ENOTTY; -} - - static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -2484,16 +2467,23 @@ EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) { struct snd_seq_client *client; - mm_segment_t fs; - int result; + const struct seq_ioctl_table *p;
client = clientptr(clientid); if (client == NULL) return -ENXIO; - fs = snd_enter_user(); - result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg); - snd_leave_user(fs); - return result; + + for (p = ioctl_tables; p->cmd > 0; ++p) { + if (p->cmd == cmd) + break; + } + if (p->cmd == 0) { + pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", + cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); + return -ENOTTY; + } + + return p->func(client, arg); }
EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
Former commits make it useless to change address limit of running task. This commit obsoletes helper functions for it.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 15 --------------- 1 file changed, 15 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 449eb7a..a6369ca 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -87,21 +87,6 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client,
/* */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* - */ static inline unsigned short snd_seq_file_flags(struct file *file) { switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index a6369ca..439e2df6 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1114,9 +1114,12 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait) /*-----------------------------------------------------*/
-static int seq_ioctl_pversion(struct snd_seq_client *client, void __user *arg) +static int seq_ioctl_pversion(struct snd_seq_client *client, void *arg) { - return put_user(SNDRV_SEQ_VERSION, (int __user *)arg) ? -EFAULT : 0; + int *version = arg; + + *version = SNDRV_SEQ_VERSION; + return 0; }
static int seq_ioctl_client_id(struct snd_seq_client *client, void __user *arg)
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 439e2df6..9cf5a82 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1122,9 +1122,12 @@ static int seq_ioctl_pversion(struct snd_seq_client *client, void *arg) return 0; }
-static int seq_ioctl_client_id(struct snd_seq_client *client, void __user *arg) +static int seq_ioctl_client_id(struct snd_seq_client *client, void *arg) { - return put_user(client->number, (int __user *)arg) ? -EFAULT : 0; + int *number = arg; + + *number = client->number; + return 0; }
/* SYSTEM_INFO ioctl() */
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 9cf5a82..624d001 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1131,21 +1131,19 @@ static int seq_ioctl_client_id(struct snd_seq_client *client, void *arg) }
/* SYSTEM_INFO ioctl() */ -static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user *arg) +static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg) { - struct snd_seq_system_info info; + struct snd_seq_system_info *info = arg;
- memset(&info, 0, sizeof(info)); + memset(info, 0, sizeof(*info)); /* fill the info fields */ - info.queues = SNDRV_SEQ_MAX_QUEUES; - info.clients = SNDRV_SEQ_MAX_CLIENTS; - info.ports = SNDRV_SEQ_MAX_PORTS; - info.channels = 256; /* fixed limit */ - info.cur_clients = client_usage.cur; - info.cur_queues = snd_seq_queue_get_cur_queues(); + info->queues = SNDRV_SEQ_MAX_QUEUES; + info->clients = SNDRV_SEQ_MAX_CLIENTS; + info->ports = SNDRV_SEQ_MAX_PORTS; + info->channels = 256; /* fixed limit */ + info->cur_clients = client_usage.cur; + info->cur_queues = snd_seq_queue_get_cur_queues();
- if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 624d001..59de125 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1149,37 +1149,34 @@ static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg)
/* RUNNING_MODE ioctl() */ -static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void __user *arg) +static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg) { - struct snd_seq_running_info info; + struct snd_seq_running_info *info = arg; struct snd_seq_client *cptr; int err = 0;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - /* requested client number */ - cptr = snd_seq_client_use_ptr(info.client); + cptr = snd_seq_client_use_ptr(info->client); if (cptr == NULL) return -ENOENT; /* don't change !!! */
#ifdef SNDRV_BIG_ENDIAN - if (! info.big_endian) { + if (!info->big_endian) { err = -EINVAL; goto __err; } #else - if (info.big_endian) { + if (info->big_endian) { err = -EINVAL; goto __err; }
#endif - if (info.cpu_mode > sizeof(long)) { + if (info->cpu_mode > sizeof(long)) { err = -EINVAL; goto __err; } - cptr->convert32 = (info.cpu_mode < sizeof(long)); + cptr->convert32 = (info->cpu_mode < sizeof(long)); __err: snd_seq_client_unlock(cptr); return err;
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 59de125..e346786 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1210,51 +1210,43 @@ static void get_client_info(struct snd_seq_client *cptr, }
static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_client_info *client_info = arg; struct snd_seq_client *cptr; - struct snd_seq_client_info client_info; - - if (copy_from_user(&client_info, arg, sizeof(client_info))) - return -EFAULT;
/* requested client number */ - cptr = snd_seq_client_use_ptr(client_info.client); + cptr = snd_seq_client_use_ptr(client_info->client); if (cptr == NULL) return -ENOENT; /* don't change !!! */
- get_client_info(cptr, &client_info); + get_client_info(cptr, client_info); snd_seq_client_unlock(cptr);
- if (copy_to_user(arg, &client_info, sizeof(client_info))) - return -EFAULT; return 0; }
/* CLIENT_INFO ioctl() */ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_client_info client_info; - - if (copy_from_user(&client_info, arg, sizeof(client_info))) - return -EFAULT; + struct snd_seq_client_info *client_info = arg;
/* it is not allowed to set the info fields for an another client */ - if (client->number != client_info.client) + if (client->number != client_info->client) return -EPERM; /* also client type must be set now */ - if (client->type != client_info.type) + if (client->type != client_info->type) return -EINVAL;
/* fill the info fields */ - if (client_info.name[0]) - strlcpy(client->name, client_info.name, sizeof(client->name)); + if (client_info->name[0]) + strlcpy(client->name, client_info->name, sizeof(client->name));
- client->filter = client_info.filter; - client->event_lost = client_info.event_lost; - memcpy(client->event_filter, client_info.event_filter, 32); + client->filter = client_info->filter; + client->event_lost = client_info->event_lost; + memcpy(client->event_filter, client_info->event_filter, 32);
return 0; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index e346786..36ac29f 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1255,30 +1255,27 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, /* * CREATE PORT ioctl() */ -static int snd_seq_ioctl_create_port(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client_port *port; - struct snd_seq_port_info info; struct snd_seq_port_callback *callback;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - /* it is not allowed to create the port for an another client */ - if (info.addr.client != client->number) + if (info->addr.client != client->number) return -EPERM;
- port = snd_seq_create_port(client, (info.flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info.addr.port : -1); + port = snd_seq_create_port(client, (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info->addr.port : -1); if (port == NULL) return -ENOMEM;
- if (client->type == USER_CLIENT && info.kernel) { + if (client->type == USER_CLIENT && info->kernel) { snd_seq_delete_port(client, port->addr.port); return -EINVAL; } if (client->type == KERNEL_CLIENT) { - if ((callback = info.kernel) != NULL) { + callback = info->kernel; + if (callback != NULL) { if (callback->owner) port->owner = callback->owner; port->private_data = callback->private_data; @@ -1291,37 +1288,30 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, } }
- info.addr = port->addr; + info->addr = port->addr;
- snd_seq_set_port_info(port, &info); + snd_seq_set_port_info(port, info); snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
- if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; }
/* * DELETE PORT ioctl() */ -static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg) { - struct snd_seq_port_info info; + struct snd_seq_port_info *info = arg; int err;
- /* set passed parameters */ - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - /* it is not allowed to remove the port for an another client */ - if (info.addr.client != client->number) + if (info->addr.client != client->number) return -EPERM;
- err = snd_seq_delete_port(client, info.addr.port); + err = snd_seq_delete_port(client, info->addr.port); if (err >= 0) - snd_seq_system_client_ev_port_exit(client->number, info.addr.port); + snd_seq_system_client_ev_port_exit(client->number, + info->addr.port); return err; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 36ac29f..7815f88 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1319,32 +1319,27 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg) /* * GET_PORT_INFO ioctl() (on any client) */ -static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client *cptr; struct snd_seq_client_port *port; - struct snd_seq_port_info info;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - cptr = snd_seq_client_use_ptr(info.addr.client); + cptr = snd_seq_client_use_ptr(info->addr.client); if (cptr == NULL) return -ENXIO;
- port = snd_seq_port_use_ptr(cptr, info.addr.port); + port = snd_seq_port_use_ptr(cptr, info->addr.port); if (port == NULL) { snd_seq_client_unlock(cptr); return -ENOENT; /* don't change */ }
/* get port info */ - snd_seq_get_port_info(port, &info); + snd_seq_get_port_info(port, info); snd_seq_port_unlock(port); snd_seq_client_unlock(cptr);
- if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; }
@@ -1352,20 +1347,16 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, /* * SET_PORT_INFO ioctl() (only ports on this/own client) */ -static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client_port *port; - struct snd_seq_port_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT;
- if (info.addr.client != client->number) /* only set our own ports ! */ + if (info->addr.client != client->number) /* only set our own ports ! */ return -EPERM; - port = snd_seq_port_use_ptr(client, info.addr.port); + port = snd_seq_port_use_ptr(client, info->addr.port); if (port) { - snd_seq_set_port_info(port, &info); + snd_seq_set_port_info(port, info); snd_seq_port_unlock(port); } return 0;
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 62 +++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 28 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 7815f88..7b32daa 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1422,34 +1422,37 @@ int snd_seq_client_notify_subscription(int client, int port, * add to port's subscription list IOCTL interface */ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_subscribe *subs = arg; int result = -EINVAL; struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL; - struct snd_seq_port_subscribe subs;
- if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) + receiver = snd_seq_client_use_ptr(subs->dest.client); + if (receiver == NULL) goto __end; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) + sender = snd_seq_client_use_ptr(subs->sender.client); + if (sender == NULL) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) + sport = snd_seq_port_use_ptr(sender, subs->sender.port); + if (sport == NULL) goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) + dport = snd_seq_port_use_ptr(receiver, subs->dest.port); + if (dport == NULL) goto __end;
- result = check_subscription_permission(client, sport, dport, &subs); + result = check_subscription_permission(client, sport, dport, subs); if (result < 0) goto __end;
/* connect them */ - result = snd_seq_port_connect(client, sender, sport, receiver, dport, &subs); - if (! result) /* broadcast announce */ - snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, - &subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); + result = snd_seq_port_connect(client, sender, sport, receiver, dport, + subs); + if (!result) /* broadcast announce */ + snd_seq_client_notify_subscription( + SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, + subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); __end: if (sport) snd_seq_port_unlock(sport); @@ -1467,33 +1470,36 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, * remove from port's subscription list */ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_subscribe *subs = arg; int result = -ENXIO; struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL; - struct snd_seq_port_subscribe subs;
- if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) + receiver = snd_seq_client_use_ptr(subs->dest.client); + if (receiver == NULL) goto __end; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) + sender = snd_seq_client_use_ptr(subs->sender.client); + if (receiver == NULL) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) + sport = snd_seq_port_use_ptr(sender, subs->sender.port); + if (sport == NULL) goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) + dport = snd_seq_port_use_ptr(receiver, subs->dest.port); + if (dport == NULL) goto __end;
- result = check_subscription_permission(client, sport, dport, &subs); + result = check_subscription_permission(client, sport, dport, subs); if (result < 0) goto __end;
- result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, &subs); - if (! result) /* broadcast announce */ - snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, - &subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); + result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, + subs); + if (!result) /* broadcast announce */ + snd_seq_client_notify_subscription( + SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, subs, + SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); __end: if (sport) snd_seq_port_unlock(sport);
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 7b32daa..44b58dc 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1514,17 +1514,13 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
/* CREATE_QUEUE ioctl() */ -static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; int result; struct snd_seq_queue *q;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - result = snd_seq_queue_alloc(client->number, info.locked, info.flags); + result = snd_seq_queue_alloc(client->number, info->locked, info->flags); if (result < 0) return result;
@@ -1532,32 +1528,25 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, if (q == NULL) return -EINVAL;
- info.queue = q->queue; - info.locked = q->locked; - info.owner = q->owner; + info->queue = q->queue; + info->locked = q->locked; + info->owner = q->owner;
/* set queue name */ - if (! info.name[0]) - snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue); - strlcpy(q->name, info.name, sizeof(q->name)); + if (!info->name[0]) + snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue); + strlcpy(q->name, info->name, sizeof(q->name)); queuefree(q);
- if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; }
/* DELETE_QUEUE ioctl() */ -static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, void *arg) { - struct snd_seq_queue_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; + struct snd_seq_queue_info *info = arg;
- return snd_seq_queue_delete(client->number, info.queue); + return snd_seq_queue_delete(client->number, info->queue); }
/* GET_QUEUE_INFO ioctl() */
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 44b58dc..a5e1c0a 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1551,28 +1551,22 @@ static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, void *arg)
/* GET_QUEUE_INFO ioctl() */ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; struct snd_seq_queue *q;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - q = queueptr(info.queue); + q = queueptr(info->queue); if (q == NULL) return -EINVAL;
- memset(&info, 0, sizeof(info)); - info.queue = q->queue; - info.owner = q->owner; - info.locked = q->locked; - strlcpy(info.name, q->name, sizeof(info.name)); + memset(info, 0, sizeof(*info)); + info->queue = q->queue; + info->owner = q->owner; + info->locked = q->locked; + strlcpy(info->name, q->name, sizeof(info->name)); queuefree(q);
- if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index a5e1c0a..1502794 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1572,35 +1572,32 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
/* SET_QUEUE_INFO ioctl() */ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; struct snd_seq_queue *q;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (info.owner != client->number) + if (info->owner != client->number) return -EINVAL;
/* change owner/locked permission */ - if (snd_seq_queue_check_access(info.queue, client->number)) { - if (snd_seq_queue_set_owner(info.queue, client->number, info.locked) < 0) + if (snd_seq_queue_check_access(info->queue, client->number)) { + if (snd_seq_queue_set_owner(info->queue, client->number, info->locked) < 0) return -EPERM; - if (info.locked) - snd_seq_queue_use(info.queue, client->number, 1); + if (info->locked) + snd_seq_queue_use(info->queue, client->number, 1); } else { return -EPERM; }
- q = queueptr(info.queue); - if (! q) + q = queueptr(info->queue); + if (!q) return -EINVAL; if (q->owner != client->number) { queuefree(q); return -EPERM; } - strlcpy(q->name, info.name, sizeof(q->name)); + strlcpy(q->name, info->name, sizeof(q->name)); queuefree(q);
return 0;
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 1502794..3b17e72 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1604,25 +1604,20 @@ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client, }
/* GET_NAMED_QUEUE ioctl() */ -static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, void __user *arg) +static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, + void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; struct snd_seq_queue *q;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - q = snd_seq_queue_find_name(info.name); + q = snd_seq_queue_find_name(info->name); if (q == NULL) return -EINVAL; - info.queue = q->queue; - info.owner = q->owner; - info.locked = q->locked; + info->queue = q->queue; + info->owner = q->owner; + info->locked = q->locked; queuefree(q);
- if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 3b17e72..8a43272 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1623,34 +1623,29 @@ static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client,
/* GET_QUEUE_STATUS ioctl() */ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_status status; + struct snd_seq_queue_status *status = arg; struct snd_seq_queue *queue; struct snd_seq_timer *tmr;
- if (copy_from_user(&status, arg, sizeof(status))) - return -EFAULT; - - queue = queueptr(status.queue); + queue = queueptr(status->queue); if (queue == NULL) return -EINVAL; - memset(&status, 0, sizeof(status)); - status.queue = queue->queue; + memset(status, 0, sizeof(*status)); + status->queue = queue->queue; tmr = queue->timer; - status.events = queue->tickq->cells + queue->timeq->cells; + status->events = queue->tickq->cells + queue->timeq->cells;
- status.time = snd_seq_timer_get_cur_time(tmr); - status.tick = snd_seq_timer_get_cur_tick(tmr); + status->time = snd_seq_timer_get_cur_time(tmr); + status->tick = snd_seq_timer_get_cur_tick(tmr);
- status.running = tmr->running; + status->running = tmr->running;
- status.flags = queue->flags; + status->flags = queue->flags; queuefree(queue);
- if (copy_to_user(arg, &status, sizeof(status))) - return -EFAULT; return 0; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 8a43272..2f10bdd 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1652,31 +1652,26 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
/* GET_QUEUE_TEMPO ioctl() */ static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_tempo tempo; + struct snd_seq_queue_tempo *tempo = arg; struct snd_seq_queue *queue; struct snd_seq_timer *tmr;
- if (copy_from_user(&tempo, arg, sizeof(tempo))) - return -EFAULT; - - queue = queueptr(tempo.queue); + queue = queueptr(tempo->queue); if (queue == NULL) return -EINVAL; - memset(&tempo, 0, sizeof(tempo)); - tempo.queue = queue->queue; + memset(tempo, 0, sizeof(*tempo)); + tempo->queue = queue->queue; tmr = queue->timer;
- tempo.tempo = tmr->tempo; - tempo.ppq = tmr->ppq; - tempo.skew_value = tmr->skew; - tempo.skew_base = tmr->skew_base; + tempo->tempo = tmr->tempo; + tempo->ppq = tmr->ppq; + tempo->skew_value = tmr->skew; + tempo->skew_base = tmr->skew_base; queuefree(queue);
- if (copy_to_user(arg, &tempo, sizeof(tempo))) - return -EFAULT; return 0; }
@@ -1692,15 +1687,12 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) EXPORT_SYMBOL(snd_seq_set_queue_tempo);
static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_queue_tempo *tempo = arg; int result; - struct snd_seq_queue_tempo tempo; - - if (copy_from_user(&tempo, arg, sizeof(tempo))) - return -EFAULT;
- result = snd_seq_set_queue_tempo(client->number, &tempo); + result = snd_seq_set_queue_tempo(client->number, tempo); return result < 0 ? result : 0; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 44 +++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 26 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 2f10bdd..11709da 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1699,16 +1699,13 @@ static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,
/* GET_QUEUE_TIMER ioctl() */ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_timer timer; + struct snd_seq_queue_timer *timer = arg; struct snd_seq_queue *queue; struct snd_seq_timer *tmr;
- if (copy_from_user(&timer, arg, sizeof(timer))) - return -EFAULT; - - queue = queueptr(timer.queue); + queue = queueptr(timer->queue); if (queue == NULL) return -EINVAL;
@@ -1717,41 +1714,36 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, return -ERESTARTSYS; } tmr = queue->timer; - memset(&timer, 0, sizeof(timer)); - timer.queue = queue->queue; + memset(timer, 0, sizeof(*timer)); + timer->queue = queue->queue;
- timer.type = tmr->type; + timer->type = tmr->type; if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { - timer.u.alsa.id = tmr->alsa_id; - timer.u.alsa.resolution = tmr->preferred_resolution; + timer->u.alsa.id = tmr->alsa_id; + timer->u.alsa.resolution = tmr->preferred_resolution; } mutex_unlock(&queue->timer_mutex); queuefree(queue); - if (copy_to_user(arg, &timer, sizeof(timer))) - return -EFAULT; return 0; }
/* SET_QUEUE_TIMER ioctl() */ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_queue_timer *timer = arg; int result = 0; - struct snd_seq_queue_timer timer; - - if (copy_from_user(&timer, arg, sizeof(timer))) - return -EFAULT;
- if (timer.type != SNDRV_SEQ_TIMER_ALSA) + if (timer->type != SNDRV_SEQ_TIMER_ALSA) return -EINVAL;
- if (snd_seq_queue_check_access(timer.queue, client->number)) { + if (snd_seq_queue_check_access(timer->queue, client->number)) { struct snd_seq_queue *q; struct snd_seq_timer *tmr;
- q = queueptr(timer.queue); + q = queueptr(timer->queue); if (q == NULL) return -ENXIO; if (mutex_lock_interruptible(&q->timer_mutex)) { @@ -1759,13 +1751,13 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, return -ERESTARTSYS; } tmr = q->timer; - snd_seq_queue_timer_close(timer.queue); - tmr->type = timer.type; + snd_seq_queue_timer_close(timer->queue); + tmr->type = timer->type; if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { - tmr->alsa_id = timer.u.alsa.id; - tmr->preferred_resolution = timer.u.alsa.resolution; + tmr->alsa_id = timer->u.alsa.id; + tmr->preferred_resolution = timer->u.alsa.resolution; } - result = snd_seq_queue_timer_open(timer.queue); + result = snd_seq_queue_timer_open(timer->queue); mutex_unlock(&q->timer_mutex); queuefree(q); } else {
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 11709da..5f3489b 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1770,38 +1770,31 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
/* GET_QUEUE_CLIENT ioctl() */ static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_client info; + struct snd_seq_queue_client *info = arg; int used;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - used = snd_seq_queue_is_used(info.queue, client->number); + used = snd_seq_queue_is_used(info->queue, client->number); if (used < 0) return -EINVAL; - info.used = used; - info.client = client->number; + info->used = used; + info->client = client->number;
- if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; }
/* SET_QUEUE_CLIENT ioctl() */ static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_queue_client *info = arg; int err; - struct snd_seq_queue_client info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT;
- if (info.used >= 0) { - err = snd_seq_queue_use(info.queue, client->number, info.used); + if (info->used >= 0) { + err = snd_seq_queue_use(info->queue, client->number, + info->used); if (err < 0) return err; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 68 +++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 37 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 5f3489b..9998632 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1805,78 +1805,72 @@ static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client,
/* GET_CLIENT_POOL ioctl() */ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_client_pool info; + struct snd_seq_client_pool *info = arg; struct snd_seq_client *cptr;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - cptr = snd_seq_client_use_ptr(info.client); + cptr = snd_seq_client_use_ptr(info->client); if (cptr == NULL) return -ENOENT; - memset(&info, 0, sizeof(info)); - info.client = cptr->number; - info.output_pool = cptr->pool->size; - info.output_room = cptr->pool->room; - info.output_free = info.output_pool; - info.output_free = snd_seq_unused_cells(cptr->pool); + memset(info, 0, sizeof(*info)); + info->client = cptr->number; + info->output_pool = cptr->pool->size; + info->output_room = cptr->pool->room; + info->output_free = info->output_pool; + info->output_free = snd_seq_unused_cells(cptr->pool); if (cptr->type == USER_CLIENT) { - info.input_pool = cptr->data.user.fifo_pool_size; - info.input_free = info.input_pool; + info->input_pool = cptr->data.user.fifo_pool_size; + info->input_free = info->input_pool; if (cptr->data.user.fifo) - info.input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); + info->input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); } else { - info.input_pool = 0; - info.input_free = 0; + info->input_pool = 0; + info->input_free = 0; } snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; }
/* SET_CLIENT_POOL ioctl() */ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_client_pool info; + struct snd_seq_client_pool *info = arg; int rc;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (client->number != info.client) + if (client->number != info->client) return -EINVAL; /* can't change other clients */
- if (info.output_pool >= 1 && info.output_pool <= SNDRV_SEQ_MAX_EVENTS && - (! snd_seq_write_pool_allocated(client) || - info.output_pool != client->pool->size)) { + if (info->output_pool >= 1 && + info->output_pool <= SNDRV_SEQ_MAX_EVENTS && + (!snd_seq_write_pool_allocated(client) || + info->output_pool != client->pool->size)) { if (snd_seq_write_pool_allocated(client)) { /* remove all existing cells */ snd_seq_queue_client_leave_cells(client->number); snd_seq_pool_done(client->pool); } - client->pool->size = info.output_pool; + client->pool->size = info->output_pool; rc = snd_seq_pool_init(client->pool); if (rc < 0) return rc; } if (client->type == USER_CLIENT && client->data.user.fifo != NULL && - info.input_pool >= 1 && - info.input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS && - info.input_pool != client->data.user.fifo_pool_size) { + info->input_pool >= 1 && + info->input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS && + info->input_pool != client->data.user.fifo_pool_size) { /* change pool size */ - rc = snd_seq_fifo_resize(client->data.user.fifo, info.input_pool); + rc = snd_seq_fifo_resize(client->data.user.fifo, + info->input_pool); if (rc < 0) return rc; - client->data.user.fifo_pool_size = info.input_pool; + client->data.user.fifo_pool_size = info->input_pool; } - if (info.output_room >= 1 && - info.output_room <= client->pool->size) { - client->pool->room = info.output_room; + if (info->output_room >= 1 && + info->output_room <= client->pool->size) { + client->pool->room = info->output_room; }
return snd_seq_ioctl_get_client_pool(client, arg);
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 9998632..e2f332c 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1878,18 +1878,14 @@ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,
/* REMOVE_EVENTS ioctl() */ -static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, void *arg) { - struct snd_seq_remove_events info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; + struct snd_seq_remove_events *info = arg;
/* * Input mostly not implemented XXX. */ - if (info.remove_mode & SNDRV_SEQ_REMOVE_INPUT) { + if (info->remove_mode & SNDRV_SEQ_REMOVE_INPUT) { /* * No restrictions so for a user client we can clear * the whole fifo @@ -1898,8 +1894,8 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, snd_seq_fifo_clear(client->data.user.fifo); }
- if (info.remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) - snd_seq_queue_remove_cells(client->number, &info); + if (info->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) + snd_seq_queue_remove_cells(client->number, info);
return 0; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index e2f332c..c0e54b3 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1905,26 +1905,25 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, void *arg) * get subscription info */ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_subscribe *subs = arg; int result; struct snd_seq_client *sender = NULL; struct snd_seq_client_port *sport = NULL; - struct snd_seq_port_subscribe subs; struct snd_seq_subscribers *p;
- if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - result = -EINVAL; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) + sender = snd_seq_client_use_ptr(subs->sender.client); + if (sender == NULL) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) + sport = snd_seq_port_use_ptr(sender, subs->sender.port); + if (sport == NULL) goto __end; - p = snd_seq_port_get_subscription(&sport->c_src, &subs.dest); + p = snd_seq_port_get_subscription(&sport->c_src, &subs->dest); if (p) { result = 0; - subs = p->info; + *subs = p->info; } else result = -ENOENT;
@@ -1933,10 +1932,7 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, snd_seq_port_unlock(sport); if (sender) snd_seq_client_unlock(sender); - if (result >= 0) { - if (copy_to_user(arg, &subs, sizeof(subs))) - return -EFAULT; - } + return result; }
In former commit, actual operations of each ioctl command get argument in kernel space. Copying from/to user space is performed outside of the function.
This commit optimizes to the new design.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/core/seq/seq_clientmgr.c | 74 +++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 44 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index c0e54b3..04f23f1 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1940,26 +1940,24 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, /* * get subscription info - check only its presence */ -static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg) { + struct snd_seq_query_subs *subs = arg; int result = -ENXIO; struct snd_seq_client *cptr = NULL; struct snd_seq_client_port *port = NULL; - struct snd_seq_query_subs subs; struct snd_seq_port_subs_info *group; struct list_head *p; int i;
- if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - if ((cptr = snd_seq_client_use_ptr(subs.root.client)) == NULL) + cptr = snd_seq_client_use_ptr(subs->root.client); + if (cptr == NULL) goto __end; - if ((port = snd_seq_port_use_ptr(cptr, subs.root.port)) == NULL) + port = snd_seq_port_use_ptr(cptr, subs->root.port); + if (cptr == NULL) goto __end;
- switch (subs.type) { + switch (subs->type) { case SNDRV_SEQ_QUERY_SUBS_READ: group = &port->c_src; break; @@ -1972,22 +1970,22 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
down_read(&group->list_mutex); /* search for the subscriber */ - subs.num_subs = group->count; + subs->num_subs = group->count; i = 0; result = -ENOENT; list_for_each(p, &group->list_head) { - if (i++ == subs.index) { + if (i++ == subs->index) { /* found! */ struct snd_seq_subscribers *s; - if (subs.type == SNDRV_SEQ_QUERY_SUBS_READ) { + if (subs->type == SNDRV_SEQ_QUERY_SUBS_READ) { s = list_entry(p, struct snd_seq_subscribers, src_list); - subs.addr = s->info.dest; + subs->addr = s->info.dest; } else { s = list_entry(p, struct snd_seq_subscribers, dest_list); - subs.addr = s->info.sender; + subs->addr = s->info.sender; } - subs.flags = s->info.flags; - subs.queue = s->info.queue; + subs->flags = s->info.flags; + subs->queue = s->info.queue; result = 0; break; } @@ -1999,10 +1997,7 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, snd_seq_port_unlock(port); if (cptr) snd_seq_client_unlock(cptr); - if (result >= 0) { - if (copy_to_user(arg, &subs, sizeof(subs))) - return -EFAULT; - } + return result; }
@@ -2011,31 +2006,26 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, * query next client */ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_client_info *info = arg; struct snd_seq_client *cptr = NULL; - struct snd_seq_client_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT;
/* search for next client */ - info.client++; - if (info.client < 0) - info.client = 0; - for (; info.client < SNDRV_SEQ_MAX_CLIENTS; info.client++) { - cptr = snd_seq_client_use_ptr(info.client); + info->client++; + if (info->client < 0) + info->client = 0; + for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) { + cptr = snd_seq_client_use_ptr(info->client); if (cptr) break; /* found */ } if (cptr == NULL) return -ENOENT;
- get_client_info(cptr, &info); + get_client_info(cptr, info); snd_seq_client_unlock(cptr);
- if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; }
@@ -2043,34 +2033,30 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, * query next port */ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client *cptr; struct snd_seq_client_port *port = NULL; - struct snd_seq_port_info info;
- if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - cptr = snd_seq_client_use_ptr(info.addr.client); + cptr = snd_seq_client_use_ptr(info->addr.client); if (cptr == NULL) return -ENXIO;
/* search for next port */ - info.addr.port++; - port = snd_seq_port_query_nearest(cptr, &info); + info->addr.port++; + port = snd_seq_port_query_nearest(cptr, info); if (port == NULL) { snd_seq_client_unlock(cptr); return -ENOENT; }
/* get port info */ - info.addr = port->addr; - snd_seq_get_port_info(port, &info); + info->addr = port->addr; + snd_seq_get_port_info(port, info); snd_seq_port_unlock(port); snd_seq_client_unlock(cptr);
- if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; }
participants (1)
-
Takashi Sakamoto