mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-13 14:04:05 +08:00
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: 4fa52aa7a8
("[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>
This commit is contained in:
parent
5029c5e4f2
commit
db46cd1e04
@ -676,18 +676,20 @@ static void dasd_profile_start(struct dasd_block *block,
|
||||
* we count each request only once.
|
||||
*/
|
||||
device = cqr->startdev;
|
||||
if (device->profile.data) {
|
||||
counter = 1; /* request is not yet queued on the start device */
|
||||
list_for_each(l, &device->ccw_queue)
|
||||
if (++counter >= 31)
|
||||
break;
|
||||
}
|
||||
if (!device->profile.data)
|
||||
return;
|
||||
|
||||
spin_lock(get_ccwdev_lock(device->cdev));
|
||||
counter = 1; /* request is not yet queued on the start device */
|
||||
list_for_each(l, &device->ccw_queue)
|
||||
if (++counter >= 31)
|
||||
break;
|
||||
spin_unlock(get_ccwdev_lock(device->cdev));
|
||||
|
||||
spin_lock(&device->profile.lock);
|
||||
if (device->profile.data) {
|
||||
device->profile.data->dasd_io_nr_req[counter]++;
|
||||
if (rq_data_dir(req) == READ)
|
||||
device->profile.data->dasd_read_nr_req[counter]++;
|
||||
}
|
||||
device->profile.data->dasd_io_nr_req[counter]++;
|
||||
if (rq_data_dir(req) == READ)
|
||||
device->profile.data->dasd_read_nr_req[counter]++;
|
||||
spin_unlock(&device->profile.lock);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user