Skip to content

Commit 5b53a9d

Browse files
committed
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/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 924c5ee commit 5b53a9d

File tree

1 file changed

+49
-72
lines changed

1 file changed

+49
-72
lines changed

drivers/input/serio/serio_raw.c

Lines changed: 49 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -75,41 +75,31 @@ static int serio_raw_open(struct inode *inode, struct file *file)
7575
{
7676
struct serio_raw *serio_raw;
7777
struct serio_raw_client *client;
78-
int retval;
7978

80-
retval = mutex_lock_interruptible(&serio_raw_mutex);
81-
if (retval)
82-
return retval;
79+
scoped_guard(mutex_intr, &serio_raw_mutex) {
80+
serio_raw = serio_raw_locate(iminor(inode));
81+
if (!serio_raw)
82+
return -ENODEV;
8383

84-
serio_raw = serio_raw_locate(iminor(inode));
85-
if (!serio_raw) {
86-
retval = -ENODEV;
87-
goto out;
88-
}
84+
if (serio_raw->dead)
85+
return -ENODEV;
8986

90-
if (serio_raw->dead) {
91-
retval = -ENODEV;
92-
goto out;
93-
}
87+
client = kzalloc(sizeof(*client), GFP_KERNEL);
88+
if (!client)
89+
return -ENOMEM;
9490

95-
client = kzalloc(sizeof(*client), GFP_KERNEL);
96-
if (!client) {
97-
retval = -ENOMEM;
98-
goto out;
99-
}
91+
client->serio_raw = serio_raw;
92+
file->private_data = client;
10093

101-
client->serio_raw = serio_raw;
102-
file->private_data = client;
94+
kref_get(&serio_raw->kref);
10395

104-
kref_get(&serio_raw->kref);
96+
scoped_guard(serio_pause_rx, serio_raw->serio)
97+
list_add_tail(&client->node, &serio_raw->client_list);
10598

106-
serio_pause_rx(serio_raw->serio);
107-
list_add_tail(&client->node, &serio_raw->client_list);
108-
serio_continue_rx(serio_raw->serio);
99+
return 0;
100+
}
109101

110-
out:
111-
mutex_unlock(&serio_raw_mutex);
112-
return retval;
102+
return -EINTR;
113103
}
114104

115105
static void serio_raw_free(struct kref *kref)
@@ -126,9 +116,8 @@ static int serio_raw_release(struct inode *inode, struct file *file)
126116
struct serio_raw_client *client = file->private_data;
127117
struct serio_raw *serio_raw = client->serio_raw;
128118

129-
serio_pause_rx(serio_raw->serio);
130-
list_del(&client->node);
131-
serio_continue_rx(serio_raw->serio);
119+
scoped_guard(serio_pause_rx, serio_raw->serio)
120+
list_del(&client->node);
132121

133122
kfree(client);
134123

@@ -139,19 +128,15 @@ static int serio_raw_release(struct inode *inode, struct file *file)
139128

140129
static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
141130
{
142-
bool empty;
131+
guard(serio_pause_rx)(serio_raw->serio);
143132

144-
serio_pause_rx(serio_raw->serio);
145-
146-
empty = serio_raw->head == serio_raw->tail;
147-
if (!empty) {
148-
*c = serio_raw->queue[serio_raw->tail];
149-
serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
150-
}
133+
if (serio_raw->head == serio_raw->tail)
134+
return false; /* queue is empty */
151135

152-
serio_continue_rx(serio_raw->serio);
136+
*c = serio_raw->queue[serio_raw->tail];
137+
serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
153138

154-
return !empty;
139+
return true;
155140
}
156141

157142
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,
200185
{
201186
struct serio_raw_client *client = file->private_data;
202187
struct serio_raw *serio_raw = client->serio_raw;
203-
int retval = 0;
188+
int written;
204189
unsigned char c;
205190

206-
retval = mutex_lock_interruptible(&serio_raw_mutex);
207-
if (retval)
208-
return retval;
191+
scoped_guard(mutex_intr, &serio_raw_mutex) {
192+
if (serio_raw->dead)
193+
return -ENODEV;
209194

210-
if (serio_raw->dead) {
211-
retval = -ENODEV;
212-
goto out;
213-
}
195+
if (count > 32)
196+
count = 32;
214197

215-
if (count > 32)
216-
count = 32;
198+
while (count--) {
199+
if (get_user(c, buffer++))
200+
return -EFAULT;
217201

218-
while (count--) {
219-
if (get_user(c, buffer++)) {
220-
retval = -EFAULT;
221-
goto out;
222-
}
202+
if (serio_write(serio_raw->serio, c)) {
203+
/* Either signal error or partial write */
204+
return written ?: -EIO;
205+
}
223206

224-
if (serio_write(serio_raw->serio, c)) {
225-
/* Either signal error or partial write */
226-
if (retval == 0)
227-
retval = -EIO;
228-
goto out;
207+
written++;
229208
}
230209

231-
retval++;
210+
return written;
232211
}
233212

234-
out:
235-
mutex_unlock(&serio_raw_mutex);
236-
return retval;
213+
return -EINTR;
237214
}
238215

239216
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)
379356
{
380357
struct serio_raw_client *client;
381358

382-
serio_pause_rx(serio_raw->serio);
383-
list_for_each_entry(client, &serio_raw->client_list, node)
384-
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
385-
serio_continue_rx(serio_raw->serio);
359+
scoped_guard(serio_pause_rx, serio_raw->serio) {
360+
list_for_each_entry(client, &serio_raw->client_list, node)
361+
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
362+
}
386363

387364
wake_up_interruptible(&serio_raw->wait);
388365
}
@@ -394,10 +371,10 @@ static void serio_raw_disconnect(struct serio *serio)
394371

395372
misc_deregister(&serio_raw->dev);
396373

397-
mutex_lock(&serio_raw_mutex);
398-
serio_raw->dead = true;
399-
list_del_init(&serio_raw->node);
400-
mutex_unlock(&serio_raw_mutex);
374+
scoped_guard(mutex, &serio_raw_mutex) {
375+
serio_raw->dead = true;
376+
list_del_init(&serio_raw->node);
377+
}
401378

402379
serio_raw_hangup(serio_raw);
403380

0 commit comments

Comments
 (0)