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: <stable@vger.kernel.org> Fixes: 4fa52aa ("[S390] dasd: add enhanced DASD statistics interface") Reviewed-by: Stefan Haberland <sth@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com> Signed-off-by: Stefan Haberland <sth@linux.ibm.com> Link: https://lore.kernel.org/r/20231025132437.1223363-3-sth@linux.ibm.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 5029c5e commit db46cd1

1 file changed

Lines changed: 13 additions & 11 deletions

File tree

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)