[S390] dasd: revert LCU optimization
Remove the optimization that validate server is only called once per LCU. If a device is set online we only know that we already know the LCU. But if the pathgroup was lost in between we have to do a validate server again to activate some features. Since we have no indication when a pathgroup gets lost we have to do a validate server every time a device is set online. Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
e0a15d5bf4
commit
f9f8d02fae
@ -189,14 +189,12 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct alias_server *server, *newserver;
|
struct alias_server *server, *newserver;
|
||||||
struct alias_lcu *lcu, *newlcu;
|
struct alias_lcu *lcu, *newlcu;
|
||||||
int is_lcu_known;
|
|
||||||
struct dasd_uid uid;
|
struct dasd_uid uid;
|
||||||
|
|
||||||
private = (struct dasd_eckd_private *) device->private;
|
private = (struct dasd_eckd_private *) device->private;
|
||||||
|
|
||||||
device->discipline->get_uid(device, &uid);
|
device->discipline->get_uid(device, &uid);
|
||||||
spin_lock_irqsave(&aliastree.lock, flags);
|
spin_lock_irqsave(&aliastree.lock, flags);
|
||||||
is_lcu_known = 1;
|
|
||||||
server = _find_server(&uid);
|
server = _find_server(&uid);
|
||||||
if (!server) {
|
if (!server) {
|
||||||
spin_unlock_irqrestore(&aliastree.lock, flags);
|
spin_unlock_irqrestore(&aliastree.lock, flags);
|
||||||
@ -208,7 +206,6 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
|
|||||||
if (!server) {
|
if (!server) {
|
||||||
list_add(&newserver->server, &aliastree.serverlist);
|
list_add(&newserver->server, &aliastree.serverlist);
|
||||||
server = newserver;
|
server = newserver;
|
||||||
is_lcu_known = 0;
|
|
||||||
} else {
|
} else {
|
||||||
/* someone was faster */
|
/* someone was faster */
|
||||||
_free_server(newserver);
|
_free_server(newserver);
|
||||||
@ -226,12 +223,10 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
|
|||||||
if (!lcu) {
|
if (!lcu) {
|
||||||
list_add(&newlcu->lcu, &server->lculist);
|
list_add(&newlcu->lcu, &server->lculist);
|
||||||
lcu = newlcu;
|
lcu = newlcu;
|
||||||
is_lcu_known = 0;
|
|
||||||
} else {
|
} else {
|
||||||
/* someone was faster */
|
/* someone was faster */
|
||||||
_free_lcu(newlcu);
|
_free_lcu(newlcu);
|
||||||
}
|
}
|
||||||
is_lcu_known = 0;
|
|
||||||
}
|
}
|
||||||
spin_lock(&lcu->lock);
|
spin_lock(&lcu->lock);
|
||||||
list_add(&device->alias_list, &lcu->inactive_devices);
|
list_add(&device->alias_list, &lcu->inactive_devices);
|
||||||
@ -239,64 +234,7 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
|
|||||||
spin_unlock(&lcu->lock);
|
spin_unlock(&lcu->lock);
|
||||||
spin_unlock_irqrestore(&aliastree.lock, flags);
|
spin_unlock_irqrestore(&aliastree.lock, flags);
|
||||||
|
|
||||||
return is_lcu_known;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The first device to be registered on an LCU will have to do
|
|
||||||
* some additional setup steps to configure that LCU on the
|
|
||||||
* storage server. All further devices should wait with their
|
|
||||||
* initialization until the first device is done.
|
|
||||||
* To synchronize this work, the first device will call
|
|
||||||
* dasd_alias_lcu_setup_complete when it is done, and all
|
|
||||||
* other devices will wait for it with dasd_alias_wait_for_lcu_setup.
|
|
||||||
*/
|
|
||||||
void dasd_alias_lcu_setup_complete(struct dasd_device *device)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
struct alias_server *server;
|
|
||||||
struct alias_lcu *lcu;
|
|
||||||
struct dasd_uid uid;
|
|
||||||
|
|
||||||
device->discipline->get_uid(device, &uid);
|
|
||||||
lcu = NULL;
|
|
||||||
spin_lock_irqsave(&aliastree.lock, flags);
|
|
||||||
server = _find_server(&uid);
|
|
||||||
if (server)
|
|
||||||
lcu = _find_lcu(server, &uid);
|
|
||||||
spin_unlock_irqrestore(&aliastree.lock, flags);
|
|
||||||
if (!lcu) {
|
|
||||||
DBF_EVENT_DEVID(DBF_ERR, device->cdev,
|
|
||||||
"could not find lcu for %04x %02x",
|
|
||||||
uid.ssid, uid.real_unit_addr);
|
|
||||||
WARN_ON(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
complete_all(&lcu->lcu_setup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dasd_alias_wait_for_lcu_setup(struct dasd_device *device)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
struct alias_server *server;
|
|
||||||
struct alias_lcu *lcu;
|
|
||||||
struct dasd_uid uid;
|
|
||||||
|
|
||||||
device->discipline->get_uid(device, &uid);
|
|
||||||
lcu = NULL;
|
|
||||||
spin_lock_irqsave(&aliastree.lock, flags);
|
|
||||||
server = _find_server(&uid);
|
|
||||||
if (server)
|
|
||||||
lcu = _find_lcu(server, &uid);
|
|
||||||
spin_unlock_irqrestore(&aliastree.lock, flags);
|
|
||||||
if (!lcu) {
|
|
||||||
DBF_EVENT_DEVID(DBF_ERR, device->cdev,
|
|
||||||
"could not find lcu for %04x %02x",
|
|
||||||
uid.ssid, uid.real_unit_addr);
|
|
||||||
WARN_ON(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wait_for_completion(&lcu->lcu_setup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1534,6 +1534,10 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
|
|||||||
struct dasd_eckd_private *private;
|
struct dasd_eckd_private *private;
|
||||||
int enable_pav;
|
int enable_pav;
|
||||||
|
|
||||||
|
private = (struct dasd_eckd_private *) device->private;
|
||||||
|
if (private->uid.type == UA_BASE_PAV_ALIAS ||
|
||||||
|
private->uid.type == UA_HYPER_PAV_ALIAS)
|
||||||
|
return;
|
||||||
if (dasd_nopav || MACHINE_IS_VM)
|
if (dasd_nopav || MACHINE_IS_VM)
|
||||||
enable_pav = 0;
|
enable_pav = 0;
|
||||||
else
|
else
|
||||||
@ -1542,7 +1546,6 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
|
|||||||
|
|
||||||
/* may be requested feature is not available on server,
|
/* may be requested feature is not available on server,
|
||||||
* therefore just report error and go ahead */
|
* therefore just report error and go ahead */
|
||||||
private = (struct dasd_eckd_private *) device->private;
|
|
||||||
DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
|
DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
|
||||||
"returned rc=%d", private->uid.ssid, rc);
|
"returned rc=%d", private->uid.ssid, rc);
|
||||||
}
|
}
|
||||||
@ -1588,7 +1591,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
|
|||||||
struct dasd_eckd_private *private;
|
struct dasd_eckd_private *private;
|
||||||
struct dasd_block *block;
|
struct dasd_block *block;
|
||||||
struct dasd_uid temp_uid;
|
struct dasd_uid temp_uid;
|
||||||
int is_known, rc, i;
|
int rc, i;
|
||||||
int readonly;
|
int readonly;
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
|
|
||||||
@ -1651,22 +1654,12 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
|
|||||||
block->base = device;
|
block->base = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register lcu with alias handling, enable PAV if this is a new lcu */
|
/* register lcu with alias handling, enable PAV */
|
||||||
is_known = dasd_alias_make_device_known_to_lcu(device);
|
rc = dasd_alias_make_device_known_to_lcu(device);
|
||||||
if (is_known < 0) {
|
if (rc)
|
||||||
rc = is_known;
|
|
||||||
goto out_err2;
|
goto out_err2;
|
||||||
}
|
|
||||||
/*
|
|
||||||
* dasd_eckd_validate_server is done on the first device that
|
|
||||||
* is found for an LCU. All later other devices have to wait
|
|
||||||
* for it, so they will read the correct feature codes.
|
|
||||||
*/
|
|
||||||
if (!is_known) {
|
|
||||||
dasd_eckd_validate_server(device);
|
dasd_eckd_validate_server(device);
|
||||||
dasd_alias_lcu_setup_complete(device);
|
|
||||||
} else
|
|
||||||
dasd_alias_wait_for_lcu_setup(device);
|
|
||||||
|
|
||||||
/* device may report different configuration data after LCU setup */
|
/* device may report different configuration data after LCU setup */
|
||||||
rc = dasd_eckd_read_conf(device);
|
rc = dasd_eckd_read_conf(device);
|
||||||
@ -4098,7 +4091,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
|
|||||||
{
|
{
|
||||||
struct dasd_eckd_private *private;
|
struct dasd_eckd_private *private;
|
||||||
struct dasd_eckd_characteristics temp_rdc_data;
|
struct dasd_eckd_characteristics temp_rdc_data;
|
||||||
int is_known, rc;
|
int rc;
|
||||||
struct dasd_uid temp_uid;
|
struct dasd_uid temp_uid;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
@ -4121,14 +4114,10 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
|
|||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
/* register lcu with alias handling, enable PAV if this is a new lcu */
|
/* register lcu with alias handling, enable PAV if this is a new lcu */
|
||||||
is_known = dasd_alias_make_device_known_to_lcu(device);
|
rc = dasd_alias_make_device_known_to_lcu(device);
|
||||||
if (is_known < 0)
|
if (rc)
|
||||||
return is_known;
|
return rc;
|
||||||
if (!is_known) {
|
|
||||||
dasd_eckd_validate_server(device);
|
dasd_eckd_validate_server(device);
|
||||||
dasd_alias_lcu_setup_complete(device);
|
|
||||||
} else
|
|
||||||
dasd_alias_wait_for_lcu_setup(device);
|
|
||||||
|
|
||||||
/* RE-Read Configuration Data */
|
/* RE-Read Configuration Data */
|
||||||
rc = dasd_eckd_read_conf(device);
|
rc = dasd_eckd_read_conf(device);
|
||||||
|
Loading…
Reference in New Issue
Block a user