Skip to content

Commit ac55ad2

Browse files
hoeppnerjaxboe
authored andcommitted
s390/dasd: Fix inconsistent kobject removal
Our intention was to only remove path kobjects whenever a device is being set offline. However, one corner case was missing. If a device is disabled and enabled (using the IOCTLs BIODASDDISABLE and BIODASDENABLE respectively), the enabling process will call dasd_eckd_reload_device() which itself calls dasd_eckd_read_conf() in order to update path information. During that update, dasd_eckd_clear_conf_data() clears all old data and also removes all kobjects. This will leave us with an inconsistent state of path kobjects and a subsequent path verification leads to a failing kobject creation. Fix this by removing kobjects only in the context of offlining a device as initially intended. Fixes: 19508b2 ("s390/dasd: Display FC Endpoint Security information via sysfs") Reported-by: Stefan Haberland <[email protected]> Signed-off-by: Jan Höppner <[email protected]> Reviewed-by: Stefan Haberland <[email protected]> Reviewed-by: Cornelia Huck <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent ef49d40 commit ac55ad2

File tree

3 files changed

+17
-8
lines changed

3 files changed

+17
-8
lines changed

drivers/s390/block/dasd_devmap.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,18 +1874,26 @@ void dasd_path_create_kobjects(struct dasd_device *device)
18741874
}
18751875
EXPORT_SYMBOL(dasd_path_create_kobjects);
18761876

1877-
/*
1878-
* As we keep kobjects for the lifetime of a device, this function must not be
1879-
* called anywhere but in the context of offlining a device.
1880-
*/
1881-
void dasd_path_remove_kobj(struct dasd_device *device, int chp)
1877+
static void dasd_path_remove_kobj(struct dasd_device *device, int chp)
18821878
{
18831879
if (device->path[chp].in_sysfs) {
18841880
kobject_put(&device->path[chp].kobj);
18851881
device->path[chp].in_sysfs = false;
18861882
}
18871883
}
1888-
EXPORT_SYMBOL(dasd_path_remove_kobj);
1884+
1885+
/*
1886+
* As we keep kobjects for the lifetime of a device, this function must not be
1887+
* called anywhere but in the context of offlining a device.
1888+
*/
1889+
void dasd_path_remove_kobjects(struct dasd_device *device)
1890+
{
1891+
int i;
1892+
1893+
for (i = 0; i < 8; i++)
1894+
dasd_path_remove_kobj(device, i);
1895+
}
1896+
EXPORT_SYMBOL(dasd_path_remove_kobjects);
18891897

18901898
int dasd_add_sysfs_files(struct ccw_device *cdev)
18911899
{

drivers/s390/block/dasd_eckd.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,6 @@ static void dasd_eckd_clear_conf_data(struct dasd_device *device)
10361036
device->path[i].ssid = 0;
10371037
device->path[i].chpid = 0;
10381038
dasd_path_notoper(device, i);
1039-
dasd_path_remove_kobj(device, i);
10401039
}
10411040
}
10421041

@@ -2173,6 +2172,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
21732172
device->block = NULL;
21742173
out_err1:
21752174
dasd_eckd_clear_conf_data(device);
2175+
dasd_path_remove_kobjects(device);
21762176
kfree(device->private);
21772177
device->private = NULL;
21782178
return rc;
@@ -2191,6 +2191,7 @@ static void dasd_eckd_uncheck_device(struct dasd_device *device)
21912191
private->vdsneq = NULL;
21922192
private->gneq = NULL;
21932193
dasd_eckd_clear_conf_data(device);
2194+
dasd_path_remove_kobjects(device);
21942195
}
21952196

21962197
static struct dasd_ccw_req *

drivers/s390/block/dasd_int.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ int dasd_add_sysfs_files(struct ccw_device *);
858858
void dasd_remove_sysfs_files(struct ccw_device *);
859859
void dasd_path_create_kobj(struct dasd_device *, int);
860860
void dasd_path_create_kobjects(struct dasd_device *);
861-
void dasd_path_remove_kobj(struct dasd_device *, int);
861+
void dasd_path_remove_kobjects(struct dasd_device *);
862862

863863
struct dasd_device *dasd_device_from_cdev(struct ccw_device *);
864864
struct dasd_device *dasd_device_from_cdev_locked(struct ccw_device *);

0 commit comments

Comments
 (0)