mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-29 11:42:36 +00:00
Input: serio_raw - use guard notation for locks and other resources
Use guard notation when acquiring mutexes and spinlocks, and when pausing and resuming serio port. Such guard notation makes the code more compact and error handling more robust by ensuring that locks are released in all code paths when control leaves critical section. Link: https://lore.kernel.org/r/20240905041732.2034348-21-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
924c5eeb17
commit
5b53a9d40c
@ -75,41 +75,31 @@ static int serio_raw_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct serio_raw *serio_raw;
|
||||
struct serio_raw_client *client;
|
||||
int retval;
|
||||
|
||||
retval = mutex_lock_interruptible(&serio_raw_mutex);
|
||||
if (retval)
|
||||
return retval;
|
||||
scoped_guard(mutex_intr, &serio_raw_mutex) {
|
||||
serio_raw = serio_raw_locate(iminor(inode));
|
||||
if (!serio_raw)
|
||||
return -ENODEV;
|
||||
|
||||
serio_raw = serio_raw_locate(iminor(inode));
|
||||
if (!serio_raw) {
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
if (serio_raw->dead)
|
||||
return -ENODEV;
|
||||
|
||||
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
|
||||
client->serio_raw = serio_raw;
|
||||
file->private_data = client;
|
||||
|
||||
kref_get(&serio_raw->kref);
|
||||
|
||||
scoped_guard(serio_pause_rx, serio_raw->serio)
|
||||
list_add_tail(&client->node, &serio_raw->client_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (serio_raw->dead) {
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
||||
if (!client) {
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
client->serio_raw = serio_raw;
|
||||
file->private_data = client;
|
||||
|
||||
kref_get(&serio_raw->kref);
|
||||
|
||||
serio_pause_rx(serio_raw->serio);
|
||||
list_add_tail(&client->node, &serio_raw->client_list);
|
||||
serio_continue_rx(serio_raw->serio);
|
||||
|
||||
out:
|
||||
mutex_unlock(&serio_raw_mutex);
|
||||
return retval;
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
static void serio_raw_free(struct kref *kref)
|
||||
@ -126,9 +116,8 @@ static int serio_raw_release(struct inode *inode, struct file *file)
|
||||
struct serio_raw_client *client = file->private_data;
|
||||
struct serio_raw *serio_raw = client->serio_raw;
|
||||
|
||||
serio_pause_rx(serio_raw->serio);
|
||||
list_del(&client->node);
|
||||
serio_continue_rx(serio_raw->serio);
|
||||
scoped_guard(serio_pause_rx, serio_raw->serio)
|
||||
list_del(&client->node);
|
||||
|
||||
kfree(client);
|
||||
|
||||
@ -139,19 +128,15 @@ static int serio_raw_release(struct inode *inode, struct file *file)
|
||||
|
||||
static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
|
||||
{
|
||||
bool empty;
|
||||
guard(serio_pause_rx)(serio_raw->serio);
|
||||
|
||||
serio_pause_rx(serio_raw->serio);
|
||||
if (serio_raw->head == serio_raw->tail)
|
||||
return false; /* queue is empty */
|
||||
|
||||
empty = serio_raw->head == serio_raw->tail;
|
||||
if (!empty) {
|
||||
*c = serio_raw->queue[serio_raw->tail];
|
||||
serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
|
||||
}
|
||||
*c = serio_raw->queue[serio_raw->tail];
|
||||
serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
|
||||
|
||||
serio_continue_rx(serio_raw->serio);
|
||||
|
||||
return !empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
static ssize_t serio_raw_read(struct file *file, char __user *buffer,
|
||||
@ -200,40 +185,32 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
|
||||
{
|
||||
struct serio_raw_client *client = file->private_data;
|
||||
struct serio_raw *serio_raw = client->serio_raw;
|
||||
int retval = 0;
|
||||
int written;
|
||||
unsigned char c;
|
||||
|
||||
retval = mutex_lock_interruptible(&serio_raw_mutex);
|
||||
if (retval)
|
||||
return retval;
|
||||
scoped_guard(mutex_intr, &serio_raw_mutex) {
|
||||
if (serio_raw->dead)
|
||||
return -ENODEV;
|
||||
|
||||
if (serio_raw->dead) {
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if (count > 32)
|
||||
count = 32;
|
||||
|
||||
if (count > 32)
|
||||
count = 32;
|
||||
while (count--) {
|
||||
if (get_user(c, buffer++))
|
||||
return -EFAULT;
|
||||
|
||||
while (count--) {
|
||||
if (get_user(c, buffer++)) {
|
||||
retval = -EFAULT;
|
||||
goto out;
|
||||
if (serio_write(serio_raw->serio, c)) {
|
||||
/* Either signal error or partial write */
|
||||
return written ?: -EIO;
|
||||
}
|
||||
|
||||
written++;
|
||||
}
|
||||
|
||||
if (serio_write(serio_raw->serio, c)) {
|
||||
/* Either signal error or partial write */
|
||||
if (retval == 0)
|
||||
retval = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval++;
|
||||
return written;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&serio_raw_mutex);
|
||||
return retval;
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
static __poll_t serio_raw_poll(struct file *file, poll_table *wait)
|
||||
@ -379,10 +356,10 @@ static void serio_raw_hangup(struct serio_raw *serio_raw)
|
||||
{
|
||||
struct serio_raw_client *client;
|
||||
|
||||
serio_pause_rx(serio_raw->serio);
|
||||
list_for_each_entry(client, &serio_raw->client_list, node)
|
||||
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
|
||||
serio_continue_rx(serio_raw->serio);
|
||||
scoped_guard(serio_pause_rx, serio_raw->serio) {
|
||||
list_for_each_entry(client, &serio_raw->client_list, node)
|
||||
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
|
||||
}
|
||||
|
||||
wake_up_interruptible(&serio_raw->wait);
|
||||
}
|
||||
@ -394,10 +371,10 @@ static void serio_raw_disconnect(struct serio *serio)
|
||||
|
||||
misc_deregister(&serio_raw->dev);
|
||||
|
||||
mutex_lock(&serio_raw_mutex);
|
||||
serio_raw->dead = true;
|
||||
list_del_init(&serio_raw->node);
|
||||
mutex_unlock(&serio_raw_mutex);
|
||||
scoped_guard(mutex, &serio_raw_mutex) {
|
||||
serio_raw->dead = true;
|
||||
list_del_init(&serio_raw->node);
|
||||
}
|
||||
|
||||
serio_raw_hangup(serio_raw);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user