Commit 46d1c03c authored by Jan Höppner's avatar Jan Höppner Committed by Martin Schwidefsky

s390/dasd: Improve dasd format code

- Make sure a calling function can rely on data in fdata by resetting to
  its initial values
- Move special treatment for track 0 and 1 to dasd_eckd_build_format
- Replace dangerous backward goto with a loop logic
- Add define for number that specifies the maximum amount of CCWs per
  request and is used for format_step calculation
- Remove unused variable
Signed-off-by: default avatarJan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent f369b98e
...@@ -2349,14 +2349,14 @@ dasd_eckd_build_format(struct dasd_device *base, ...@@ -2349,14 +2349,14 @@ dasd_eckd_build_format(struct dasd_device *base,
* when formatting CDL * when formatting CDL
*/ */
if ((intensity & 0x08) && if ((intensity & 0x08) &&
fdata->start_unit == 0) { address.cyl == 0 && address.head == 0) {
if (i < 3) { if (i < 3) {
ect->kl = 4; ect->kl = 4;
ect->dl = sizes_trk0[i] - 4; ect->dl = sizes_trk0[i] - 4;
} }
} }
if ((intensity & 0x08) && if ((intensity & 0x08) &&
fdata->start_unit == 1) { address.cyl == 0 && address.head == 1) {
ect->kl = 44; ect->kl = 44;
ect->dl = LABEL_SIZE - 44; ect->dl = LABEL_SIZE - 44;
} }
...@@ -2392,14 +2392,13 @@ dasd_eckd_format_device(struct dasd_device *base, ...@@ -2392,14 +2392,13 @@ dasd_eckd_format_device(struct dasd_device *base,
int enable_pav) int enable_pav)
{ {
struct dasd_ccw_req *cqr, *n; struct dasd_ccw_req *cqr, *n;
struct dasd_block *block;
struct dasd_eckd_private *private; struct dasd_eckd_private *private;
struct list_head format_queue; struct list_head format_queue;
struct dasd_device *device; struct dasd_device *device;
int old_stop, format_step; int old_start, old_stop, format_step;
int step, rc = 0, sleep_rc; int step, retry;
int rc = 0;
block = base->block;
private = (struct dasd_eckd_private *) base->private; private = (struct dasd_eckd_private *) base->private;
/* Sanity checks. */ /* Sanity checks. */
...@@ -2432,68 +2431,63 @@ dasd_eckd_format_device(struct dasd_device *base, ...@@ -2432,68 +2431,63 @@ dasd_eckd_format_device(struct dasd_device *base,
INIT_LIST_HEAD(&format_queue); INIT_LIST_HEAD(&format_queue);
old_start = fdata->start_unit;
old_stop = fdata->stop_unit; old_stop = fdata->stop_unit;
while (fdata->start_unit <= 1) {
fdata->stop_unit = fdata->start_unit;
cqr = dasd_eckd_build_format(base, fdata, enable_pav);
list_add(&cqr->blocklist, &format_queue);
fdata->stop_unit = old_stop;
fdata->start_unit++;
if (fdata->start_unit > fdata->stop_unit) format_step = DASD_CQR_MAX_CCW / recs_per_track(&private->rdc_data, 0,
goto sleep; fdata->blksize);
} do {
retry = 0;
while (fdata->start_unit <= old_stop) {
step = fdata->stop_unit - fdata->start_unit + 1;
if (step > format_step) {
fdata->stop_unit =
fdata->start_unit + format_step - 1;
}
retry: cqr = dasd_eckd_build_format(base, fdata, enable_pav);
format_step = 255 / recs_per_track(&private->rdc_data, 0, if (IS_ERR(cqr)) {
fdata->blksize); rc = PTR_ERR(cqr);
while (fdata->start_unit <= old_stop) { if (rc == -ENOMEM) {
step = fdata->stop_unit - fdata->start_unit + 1; if (list_empty(&format_queue))
if (step > format_step) goto out;
fdata->stop_unit = fdata->start_unit + format_step - 1; /*
* not enough memory available, start
* requests retry after first requests
* were finished
*/
retry = 1;
break;
}
goto out_err;
}
list_add_tail(&cqr->blocklist, &format_queue);
cqr = dasd_eckd_build_format(base, fdata, enable_pav); fdata->start_unit = fdata->stop_unit + 1;
if (IS_ERR(cqr)) { fdata->stop_unit = old_stop;
if (PTR_ERR(cqr) == -ENOMEM) {
/*
* not enough memory available
* go to out and start requests
* retry after first requests were finished
*/
fdata->stop_unit = old_stop;
goto sleep;
} else
return PTR_ERR(cqr);
} }
list_add(&cqr->blocklist, &format_queue);
fdata->start_unit = fdata->stop_unit + 1; rc = dasd_sleep_on_queue(&format_queue);
fdata->stop_unit = old_stop;
}
sleep: out_err:
sleep_rc = dasd_sleep_on_queue(&format_queue); list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
device = cqr->startdev;
private = (struct dasd_eckd_private *) device->private;
if (cqr->status == DASD_CQR_FAILED)
rc = -EIO;
list_del_init(&cqr->blocklist);
dasd_sfree_request(cqr, device);
private->count--;
}
list_for_each_entry_safe(cqr, n, &format_queue, blocklist) { if (rc)
device = cqr->startdev; goto out;
private = (struct dasd_eckd_private *) device->private;
if (cqr->status == DASD_CQR_FAILED)
rc = -EIO;
list_del_init(&cqr->blocklist);
dasd_sfree_request(cqr, device);
private->count--;
}
if (sleep_rc) } while (retry);
return sleep_rc;
/* out:
* in case of ENOMEM we need to retry after fdata->start_unit = old_start;
* first requests are finished fdata->stop_unit = old_stop;
*/
if (fdata->start_unit <= fdata->stop_unit)
goto retry;
return rc; return rc;
} }
......
...@@ -240,6 +240,13 @@ struct dasd_ccw_req { ...@@ -240,6 +240,13 @@ struct dasd_ccw_req {
/* Signature for error recovery functions. */ /* Signature for error recovery functions. */
typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
/*
* A single CQR can only contain a maximum of 255 CCWs. It is limited by
* the locate record and locate record extended count value which can only hold
* 1 Byte max.
*/
#define DASD_CQR_MAX_CCW 255
/* /*
* Unique identifier for dasd device. * Unique identifier for dasd device.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment