Skip to content

Commit

Permalink
s390/dasd: improve speed of dasdfmt
Browse files Browse the repository at this point in the history
Reorganize format IO requests and enable usage of PAV.

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 Apr 17, 2013
1 parent e5dcf00 commit d42e171
Show file tree
Hide file tree
Showing 4 changed files with 351 additions and 143 deletions.
109 changes: 99 additions & 10 deletions drivers/s390/block/dasd.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ static struct dentry *dasd_debugfs_setup(const char *name,
static int dasd_state_known_to_basic(struct dasd_device *device)
{
struct dasd_block *block = device->block;
int rc;
int rc = 0;

/* Allocate and register gendisk structure. */
if (block) {
Expand All @@ -273,7 +273,8 @@ static int dasd_state_known_to_basic(struct dasd_device *device)
DBF_DEV_EVENT(DBF_EMERG, device, "%s", "debug area created");

device->state = DASD_STATE_BASIC;
return 0;

return rc;
}

/*
Expand All @@ -282,6 +283,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device)
static int dasd_state_basic_to_known(struct dasd_device *device)
{
int rc;

if (device->block) {
dasd_profile_exit(&device->block->profile);
if (device->block->debugfs_dentry)
Expand Down Expand Up @@ -332,20 +334,27 @@ static int dasd_state_basic_to_ready(struct dasd_device *device)
if (block->base->discipline->do_analysis != NULL)
rc = block->base->discipline->do_analysis(block);
if (rc) {
if (rc != -EAGAIN)
if (rc != -EAGAIN) {
device->state = DASD_STATE_UNFMT;
goto out;
}
return rc;
}
dasd_setup_queue(block);
set_capacity(block->gdp,
block->blocks << block->s2b_shift);
device->state = DASD_STATE_READY;
rc = dasd_scan_partitions(block);
if (rc)
if (rc) {
device->state = DASD_STATE_BASIC;
return rc;
}
} else {
device->state = DASD_STATE_READY;
}
out:
if (device->discipline->basic_to_ready)
rc = device->discipline->basic_to_ready(device);
return rc;
}

Expand All @@ -368,6 +377,11 @@ static int dasd_state_ready_to_basic(struct dasd_device *device)
{
int rc;

if (device->discipline->ready_to_basic) {
rc = device->discipline->ready_to_basic(device);
if (rc)
return rc;
}
device->state = DASD_STATE_BASIC;
if (device->block) {
struct dasd_block *block = device->block;
Expand Down Expand Up @@ -402,16 +416,10 @@ static int dasd_state_unfmt_to_basic(struct dasd_device *device)
static int
dasd_state_ready_to_online(struct dasd_device * device)
{
int rc;
struct gendisk *disk;
struct disk_part_iter piter;
struct hd_struct *part;

if (device->discipline->ready_to_online) {
rc = device->discipline->ready_to_online(device);
if (rc)
return rc;
}
device->state = DASD_STATE_ONLINE;
if (device->block) {
dasd_schedule_block_bh(device->block);
Expand Down Expand Up @@ -444,6 +452,7 @@ static int dasd_state_online_to_ready(struct dasd_device *device)
if (rc)
return rc;
}

device->state = DASD_STATE_READY;
if (device->block && !(device->features & DASD_FEATURE_USERAW)) {
disk = device->block->bdev->bd_disk;
Expand Down Expand Up @@ -2223,6 +2232,77 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
return rc;
}

static inline int _wait_for_wakeup_queue(struct list_head *ccw_queue)
{
struct dasd_ccw_req *cqr;

list_for_each_entry(cqr, ccw_queue, blocklist) {
if (cqr->callback_data != DASD_SLEEPON_END_TAG)
return 0;
}

return 1;
}

static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible)
{
struct dasd_device *device;
int rc;
struct dasd_ccw_req *cqr, *n;

retry:
list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
device = cqr->startdev;
if (cqr->status != DASD_CQR_FILLED) /*could be failed*/
continue;

if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags) &&
!test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
cqr->status = DASD_CQR_FAILED;
cqr->intrc = -EPERM;
continue;
}
/*Non-temporary stop condition will trigger fail fast*/
if (device->stopped & ~DASD_STOPPED_PENDING &&
test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
!dasd_eer_enabled(device)) {
cqr->status = DASD_CQR_FAILED;
cqr->intrc = -EAGAIN;
continue;
}

/*Don't try to start requests if device is stopped*/
if (interruptible) {
rc = wait_event_interruptible(
generic_waitq, !device->stopped);
if (rc == -ERESTARTSYS) {
cqr->status = DASD_CQR_FAILED;
cqr->intrc = rc;
continue;
}
} else
wait_event(generic_waitq, !(device->stopped));

if (!cqr->callback)
cqr->callback = dasd_wakeup_cb;
cqr->callback_data = DASD_SLEEPON_START_TAG;
dasd_add_request_tail(cqr);
}

wait_event(generic_waitq, _wait_for_wakeup_queue(ccw_queue));

rc = 0;
list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
if (__dasd_sleep_on_erp(cqr))
rc = 1;
}
if (rc)
goto retry;


return 0;
}

/*
* Queue a request to the tail of the device ccw_queue and wait for
* it's completion.
Expand All @@ -2232,6 +2312,15 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr)
return _dasd_sleep_on(cqr, 0);
}

/*
* Start requests from a ccw_queue and wait for their completion.
*/
int dasd_sleep_on_queue(struct list_head *ccw_queue)
{
return _dasd_sleep_on_queue(ccw_queue, 0);
}
EXPORT_SYMBOL(dasd_sleep_on_queue);

/*
* Queue a request to the tail of the device ccw_queue and wait
* interruptible for it's completion.
Expand Down
Loading

0 comments on commit d42e171

Please sign in to comment.