Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+54 -77
+54 -77
drivers/input/serio/serio_raw.c
··· 75 75 { 76 76 struct serio_raw *serio_raw; 77 77 struct serio_raw_client *client; 78 - int retval; 79 78 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; 83 83 84 - serio_raw = serio_raw_locate(iminor(inode)); 85 - if (!serio_raw) { 86 - retval = -ENODEV; 87 - goto out; 84 + if (serio_raw->dead) 85 + return -ENODEV; 86 + 87 + client = kzalloc(sizeof(*client), GFP_KERNEL); 88 + if (!client) 89 + return -ENOMEM; 90 + 91 + client->serio_raw = serio_raw; 92 + file->private_data = client; 93 + 94 + kref_get(&serio_raw->kref); 95 + 96 + scoped_guard(serio_pause_rx, serio_raw->serio) 97 + list_add_tail(&client->node, &serio_raw->client_list); 98 + 99 + return 0; 88 100 } 89 101 90 - if (serio_raw->dead) { 91 - retval = -ENODEV; 92 - goto out; 93 - } 94 - 95 - client = kzalloc(sizeof(*client), GFP_KERNEL); 96 - if (!client) { 97 - retval = -ENOMEM; 98 - goto out; 99 - } 100 - 101 - client->serio_raw = serio_raw; 102 - file->private_data = client; 103 - 104 - kref_get(&serio_raw->kref); 105 - 106 - serio_pause_rx(serio_raw->serio); 107 - list_add_tail(&client->node, &serio_raw->client_list); 108 - serio_continue_rx(serio_raw->serio); 109 - 110 - out: 111 - mutex_unlock(&serio_raw_mutex); 112 - return retval; 102 + return -EINTR; 113 103 } 114 104 115 105 static void serio_raw_free(struct kref *kref) ··· 116 126 struct serio_raw_client *client = file->private_data; 117 127 struct serio_raw *serio_raw = client->serio_raw; 118 128 119 - serio_pause_rx(serio_raw->serio); 120 - list_del(&client->node); 121 - serio_continue_rx(serio_raw->serio); 129 + scoped_guard(serio_pause_rx, serio_raw->serio) 130 + list_del(&client->node); 122 131 123 132 kfree(client); 124 133 ··· 128 139 129 140 static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) 130 141 { 131 - bool empty; 142 + guard(serio_pause_rx)(serio_raw->serio); 132 143 133 - serio_pause_rx(serio_raw->serio); 144 + if (serio_raw->head == serio_raw->tail) 145 + return false; /* queue is empty */ 134 146 135 - empty = serio_raw->head == serio_raw->tail; 136 - if (!empty) { 137 - *c = serio_raw->queue[serio_raw->tail]; 138 - serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; 139 - } 147 + *c = serio_raw->queue[serio_raw->tail]; 148 + serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; 140 149 141 - serio_continue_rx(serio_raw->serio); 142 - 143 - return !empty; 150 + return true; 144 151 } 145 152 146 153 static ssize_t serio_raw_read(struct file *file, char __user *buffer, ··· 185 200 { 186 201 struct serio_raw_client *client = file->private_data; 187 202 struct serio_raw *serio_raw = client->serio_raw; 188 - int retval = 0; 203 + int written; 189 204 unsigned char c; 190 205 191 - retval = mutex_lock_interruptible(&serio_raw_mutex); 192 - if (retval) 193 - return retval; 206 + scoped_guard(mutex_intr, &serio_raw_mutex) { 207 + if (serio_raw->dead) 208 + return -ENODEV; 194 209 195 - if (serio_raw->dead) { 196 - retval = -ENODEV; 197 - goto out; 198 - } 210 + if (count > 32) 211 + count = 32; 199 212 200 - if (count > 32) 201 - count = 32; 213 + while (count--) { 214 + if (get_user(c, buffer++)) 215 + return -EFAULT; 202 216 203 - while (count--) { 204 - if (get_user(c, buffer++)) { 205 - retval = -EFAULT; 206 - goto out; 217 + if (serio_write(serio_raw->serio, c)) { 218 + /* Either signal error or partial write */ 219 + return written ?: -EIO; 220 + } 221 + 222 + written++; 207 223 } 208 224 209 - if (serio_write(serio_raw->serio, c)) { 210 - /* Either signal error or partial write */ 211 - if (retval == 0) 212 - retval = -EIO; 213 - goto out; 214 - } 215 - 216 - retval++; 225 + return written; 217 226 } 218 227 219 - out: 220 - mutex_unlock(&serio_raw_mutex); 221 - return retval; 228 + return -EINTR; 222 229 } 223 230 224 231 static __poll_t serio_raw_poll(struct file *file, poll_table *wait) ··· 356 379 { 357 380 struct serio_raw_client *client; 358 381 359 - 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 - serio_continue_rx(serio_raw->serio); 382 + scoped_guard(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 + } 363 386 364 387 wake_up_interruptible(&serio_raw->wait); 365 388 } ··· 371 394 372 395 misc_deregister(&serio_raw->dev); 373 396 374 - mutex_lock(&serio_raw_mutex); 375 - serio_raw->dead = true; 376 - list_del_init(&serio_raw->node); 377 - mutex_unlock(&serio_raw_mutex); 397 + scoped_guard(mutex, &serio_raw_mutex) { 398 + serio_raw->dead = true; 399 + list_del_init(&serio_raw->node); 400 + } 378 401 379 402 serio_raw_hangup(serio_raw); 380 403