Skip to content

Commit db46cd1

Browse files
hoeppnerjaxboe
authored andcommitted
s390/dasd: protect device queue against concurrent access
In dasd_profile_start() the amount of requests on the device queue are counted. The access to the device queue is unprotected against concurrent access. With a lot of parallel I/O, especially with alias devices enabled, the device queue can change while dasd_profile_start() is accessing the queue. In the worst case this leads to a kernel panic due to incorrect pointer accesses. Fix this by taking the device lock before accessing the queue and counting the requests. Additionally the check for a valid profile data pointer can be done earlier to avoid unnecessary locking in a hot path. Cc: <[email protected]> Fixes: 4fa52aa ("[S390] dasd: add enhanced DASD statistics interface") Reviewed-by: Stefan Haberland <[email protected]> Signed-off-by: Jan Höppner <[email protected]> Signed-off-by: Stefan Haberland <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 5029c5e commit db46cd1

File tree

1 file changed

+13
-11
lines changed

1 file changed

+13
-11
lines changed

drivers/s390/block/dasd.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -676,18 +676,20 @@ static void dasd_profile_start(struct dasd_block *block,
676676
* we count each request only once.
677677
*/
678678
device = cqr->startdev;
679-
if (device->profile.data) {
680-
counter = 1; /* request is not yet queued on the start device */
681-
list_for_each(l, &device->ccw_queue)
682-
if (++counter >= 31)
683-
break;
684-
}
679+
if (!device->profile.data)
680+
return;
681+
682+
spin_lock(get_ccwdev_lock(device->cdev));
683+
counter = 1; /* request is not yet queued on the start device */
684+
list_for_each(l, &device->ccw_queue)
685+
if (++counter >= 31)
686+
break;
687+
spin_unlock(get_ccwdev_lock(device->cdev));
688+
685689
spin_lock(&device->profile.lock);
686-
if (device->profile.data) {
687-
device->profile.data->dasd_io_nr_req[counter]++;
688-
if (rq_data_dir(req) == READ)
689-
device->profile.data->dasd_read_nr_req[counter]++;
690-
}
690+
device->profile.data->dasd_io_nr_req[counter]++;
691+
if (rq_data_dir(req) == READ)
692+
device->profile.data->dasd_read_nr_req[counter]++;
691693
spin_unlock(&device->profile.lock);
692694
}
693695

0 commit comments

Comments
 (0)