diff options
author | Stefan Weinhuber <wein@de.ibm.com> | 2011-04-20 10:15:30 +0200 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2011-04-20 10:15:43 +0200 |
commit | 65f8da475995f667af5298c644707dbd9d646ca6 (patch) | |
tree | bca8597443060e79f09a8843903bbc55b2dece52 /drivers/s390/block/dasd_genhd.c | |
parent | 2f666bcf757cb72549f360ef6da02f03620a48b6 (diff) | |
download | lwn-65f8da475995f667af5298c644707dbd9d646ca6.tar.gz lwn-65f8da475995f667af5298c644707dbd9d646ca6.zip |
[S390] dasd: fix race between open and offline
The dasd_open function uses the private_data pointer of the gendisk to
find the dasd_block structure that matches the gendisk. When a DASD
device is set offline, we set the private_data pointer of the gendisk
to NULL and later remove the dasd_block structure, but there is still
a small race window, in which dasd_open could first read a pointer
from the private_data field and then try to use it, after the structure
has already been freed.
To close this race window, we will store a pointer to the dasd_devmap
structure of the base device in the private_data field. The devmap
entries are not deleted, and we already have proper locking and
reference counting in place, so that we can safely get from a devmap
pointer to the dasd_device and dasd_block structures of the device.
Signed-off-by: Stefan Weinhuber <wein@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd_genhd.c')
-rw-r--r-- | drivers/s390/block/dasd_genhd.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 5505bc07e1e7..19a1ff03d65e 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -73,7 +73,7 @@ int dasd_gendisk_alloc(struct dasd_block *block) if (base->features & DASD_FEATURE_READONLY || test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) set_disk_ro(gdp, 1); - gdp->private_data = block; + dasd_add_link_to_gendisk(gdp, base); gdp->queue = block->request_queue; block->gdp = gdp; set_capacity(block->gdp, 0); |