sound/core/seq/seq_clientmgr.c | 7 ++++++- sound/core/seq/seq_ports.c | 24 ++++++++++++++++-------- sound/core/seq/seq_ports.h | 8 ++++++-- 3 files changed, 28 insertions(+), 11 deletions(-)
The current ALSA sequencer core tries to register the new kernel
sequencer port on the list at first, then fill up the port
information. This means that user-space may sneak the wrong
information before the actual data is filled, which isn't ideal.
Although the user-space should try to query the port info after the
port registration notification is sent out, it'd be still better to
have a port available with the full info from the beginning.
This patch changes the sequencer port creation and registration
procedure; now split to two steps, for creation and insertion, and the
port is registered after the information is filled.
Link: https://sashiko.dev/#/patchset/20260518194023.1667857-1-maoyixie.tju%40gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/core/seq/seq_clientmgr.c | 7 ++++++-
sound/core/seq/seq_ports.c | 24 ++++++++++++++++--------
sound/core/seq/seq_ports.h | 8 ++++++--
3 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 5719637575a9..19d6fea012f6 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1287,7 +1287,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
port_idx = -1;
if (port_idx >= SNDRV_SEQ_ADDRESS_UNKNOWN)
return -EINVAL;
- err = snd_seq_create_port(client, port_idx, &port);
+ err = snd_seq_create_port(client, &port);
if (err < 0)
return err;
@@ -1309,6 +1309,11 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
info->addr = port->addr;
snd_seq_set_port_info(port, info);
+ err = snd_seq_insert_port(client, port_idx, port);
+ if (err < 0) {
+ kfree(port);
+ return err;
+ }
if (info->capability & SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT)
client->ump_endpoint_port = port->addr.port;
snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 31ab4681c601..17daacd4476a 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -108,14 +108,13 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
}
-/* create a port, port number or a negative error code is returned
+/* create a port, 0 on success or a negative error code is returned
* the caller needs to unref the port via snd_seq_port_unlock() appropriately
*/
-int snd_seq_create_port(struct snd_seq_client *client, int port,
+int snd_seq_create_port(struct snd_seq_client *client,
struct snd_seq_client_port **port_ret)
{
- struct snd_seq_client_port *new_port, *p;
- int num;
+ struct snd_seq_client_port *new_port;
*port_ret = NULL;
@@ -141,15 +140,25 @@ int snd_seq_create_port(struct snd_seq_client *client, int port,
port_subs_info_init(&new_port->c_dest);
snd_use_lock_use(&new_port->use_lock);
+ *port_ret = new_port;
+
+ return 0;
+}
+
+/* insert the port; return the port address or a negative error code */
+int snd_seq_insert_port(struct snd_seq_client *client, int port,
+ struct snd_seq_client_port *new_port)
+{
+ struct snd_seq_client_port *p;
+ int num;
+
num = max(port, 0);
guard(mutex)(&client->ports_mutex);
guard(write_lock_irq)(&client->ports_lock);
struct list_head *insert_before = &client->ports_list_head;
list_for_each_entry(p, &client->ports_list_head, list) {
- if (p->addr.port == port) {
- kfree(new_port);
+ if (p->addr.port == port)
return -EBUSY;
- }
if (p->addr.port > num) {
insert_before = &p->list;
break;
@@ -162,7 +171,6 @@ int snd_seq_create_port(struct snd_seq_client *client, int port,
client->num_ports++;
new_port->addr.port = num; /* store the port number in the port */
sprintf(new_port->name, "port-%d", num);
- *port_ret = new_port;
return num;
}
diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h
index 40ed6cf7cb90..b689c0f4867c 100644
--- a/sound/core/seq/seq_ports.h
+++ b/sound/core/seq/seq_ports.h
@@ -98,10 +98,14 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl
DEFINE_FREE(snd_seq_port, struct snd_seq_client_port *, if (!IS_ERR_OR_NULL(_T)) snd_seq_port_unlock(_T))
-/* create a port, port number or a negative error code is returned */
-int snd_seq_create_port(struct snd_seq_client *client, int port_index,
+/* create a port, 0 on success or a negative error code is returned */
+int snd_seq_create_port(struct snd_seq_client *client,
struct snd_seq_client_port **port_ret);
+/* insert the port; return the port address or a negative error code */
+int snd_seq_insert_port(struct snd_seq_client *client, int port,
+ struct snd_seq_client_port *new_port);
+
/* delete a port */
int snd_seq_delete_port(struct snd_seq_client *client, int port);
--
2.54.0
© 2016 - 2026 Red Hat, Inc.