Skip to content

Commit

Permalink
[S390] dasd: revert LCU optimization
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stefan Haberland authored and Martin Schwidefsky committed Jan 18, 2012
1 parent e0a15d5 commit f9f8d02
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 89 deletions.
64 changes: 1 addition & 63 deletions drivers/s390/block/dasd_alias.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,12 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
unsigned long flags;
struct alias_server *server, *newserver;
struct alias_lcu *lcu, *newlcu;
int is_lcu_known;
struct dasd_uid uid;

private = (struct dasd_eckd_private *) device->private;

device->discipline->get_uid(device, &uid);
spin_lock_irqsave(&aliastree.lock, flags);
is_lcu_known = 1;
server = _find_server(&uid);
if (!server) {
spin_unlock_irqrestore(&aliastree.lock, flags);
Expand All @@ -208,7 +206,6 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
if (!server) {
list_add(&newserver->server, &aliastree.serverlist);
server = newserver;
is_lcu_known = 0;
} else {
/* someone was faster */
_free_server(newserver);
Expand All @@ -226,77 +223,18 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
if (!lcu) {
list_add(&newlcu->lcu, &server->lculist);
lcu = newlcu;
is_lcu_known = 0;
} else {
/* someone was faster */
_free_lcu(newlcu);
}
is_lcu_known = 0;
}
spin_lock(&lcu->lock);
list_add(&device->alias_list, &lcu->inactive_devices);
private->lcu = lcu;
spin_unlock(&lcu->lock);
spin_unlock_irqrestore(&aliastree.lock, flags);

return is_lcu_known;
}

/*
* 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);
return 0;
}

/*
Expand Down
41 changes: 15 additions & 26 deletions drivers/s390/block/dasd_eckd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,10 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
struct dasd_eckd_private *private;
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)
enable_pav = 0;
else
Expand All @@ -1542,7 +1546,6 @@ static void dasd_eckd_validate_server(struct dasd_device *device)

/* may be requested feature is not available on server,
* 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 "
"returned rc=%d", private->uid.ssid, rc);
}
Expand Down Expand Up @@ -1588,7 +1591,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
struct dasd_eckd_private *private;
struct dasd_block *block;
struct dasd_uid temp_uid;
int is_known, rc, i;
int rc, i;
int readonly;
unsigned long value;

Expand Down Expand Up @@ -1651,22 +1654,12 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
block->base = device;
}

/* register lcu with alias handling, enable PAV if this is a new lcu */
is_known = dasd_alias_make_device_known_to_lcu(device);
if (is_known < 0) {
rc = is_known;
/* register lcu with alias handling, enable PAV */
rc = dasd_alias_make_device_known_to_lcu(device);
if (rc)
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_alias_lcu_setup_complete(device);
} else
dasd_alias_wait_for_lcu_setup(device);

dasd_eckd_validate_server(device);

/* device may report different configuration data after LCU setup */
rc = dasd_eckd_read_conf(device);
Expand Down Expand Up @@ -4098,7 +4091,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
{
struct dasd_eckd_private *private;
struct dasd_eckd_characteristics temp_rdc_data;
int is_known, rc;
int rc;
struct dasd_uid temp_uid;
unsigned long flags;

Expand All @@ -4121,14 +4114,10 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
goto out_err;

/* register lcu with alias handling, enable PAV if this is a new lcu */
is_known = dasd_alias_make_device_known_to_lcu(device);
if (is_known < 0)
return is_known;
if (!is_known) {
dasd_eckd_validate_server(device);
dasd_alias_lcu_setup_complete(device);
} else
dasd_alias_wait_for_lcu_setup(device);
rc = dasd_alias_make_device_known_to_lcu(device);
if (rc)
return rc;
dasd_eckd_validate_server(device);

/* RE-Read Configuration Data */
rc = dasd_eckd_read_conf(device);
Expand Down

0 comments on commit f9f8d02

Please sign in to comment.