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,49 +2431,45 @@ dasd_eckd_format_device(struct dasd_device *base, ...@@ -2432,49 +2431,45 @@ 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)
goto sleep;
}
retry: format_step = DASD_CQR_MAX_CCW / recs_per_track(&private->rdc_data, 0,
format_step = 255 / recs_per_track(&private->rdc_data, 0,
fdata->blksize); fdata->blksize);
do {
retry = 0;
while (fdata->start_unit <= old_stop) { while (fdata->start_unit <= old_stop) {
step = fdata->stop_unit - fdata->start_unit + 1; step = fdata->stop_unit - fdata->start_unit + 1;
if (step > format_step) if (step > format_step) {
fdata->stop_unit = fdata->start_unit + format_step - 1; fdata->stop_unit =
fdata->start_unit + format_step - 1;
}
cqr = dasd_eckd_build_format(base, fdata, enable_pav); cqr = dasd_eckd_build_format(base, fdata, enable_pav);
if (IS_ERR(cqr)) { if (IS_ERR(cqr)) {
if (PTR_ERR(cqr) == -ENOMEM) { rc = PTR_ERR(cqr);
if (rc == -ENOMEM) {
if (list_empty(&format_queue))
goto out;
/* /*
* not enough memory available * not enough memory available, start
* go to out and start requests * requests retry after first requests
* retry after first requests were finished * were finished
*/ */
fdata->stop_unit = old_stop; retry = 1;
goto sleep; break;
} else }
return PTR_ERR(cqr); goto out_err;
} }
list_add(&cqr->blocklist, &format_queue); list_add_tail(&cqr->blocklist, &format_queue);
fdata->start_unit = fdata->stop_unit + 1; fdata->start_unit = fdata->stop_unit + 1;
fdata->stop_unit = old_stop; fdata->stop_unit = old_stop;
} }
sleep: rc = dasd_sleep_on_queue(&format_queue);
sleep_rc = dasd_sleep_on_queue(&format_queue);
out_err:
list_for_each_entry_safe(cqr, n, &format_queue, blocklist) { list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
device = cqr->startdev; device = cqr->startdev;
private = (struct dasd_eckd_private *) device->private; private = (struct dasd_eckd_private *) device->private;
...@@ -2485,15 +2480,14 @@ dasd_eckd_format_device(struct dasd_device *base, ...@@ -2485,15 +2480,14 @@ dasd_eckd_format_device(struct dasd_device *base,
private->count--; private->count--;
} }
if (sleep_rc) if (rc)
return sleep_rc; goto out;
} while (retry);
/* 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