in block/dasd_eckd.c [2954:3076]
static int dasd_eckd_format_process_data(struct dasd_device *base,
struct format_data_t *fdata,
int enable_pav, int tpm,
struct eckd_count *fmt_buffer, int rpt,
struct irb *irb)
{
struct dasd_eckd_private *private = base->private;
struct dasd_ccw_req *cqr, *n;
struct list_head format_queue;
struct dasd_device *device;
char *sense = NULL;
int old_start, old_stop, format_step;
int step, retry;
int rc;
rc = dasd_eckd_format_sanity_checks(base, fdata);
if (rc)
return rc;
INIT_LIST_HEAD(&format_queue);
old_start = fdata->start_unit;
old_stop = fdata->stop_unit;
if (!tpm && fmt_buffer != NULL) {
/* Command Mode / Format Check */
format_step = 1;
} else if (tpm && fmt_buffer != NULL) {
/* Transport Mode / Format Check */
format_step = DASD_CQR_MAX_CCW / rpt;
} else {
/* Normal Formatting */
format_step = DASD_CQR_MAX_CCW /
recs_per_track(&private->rdc_data, 0, 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;
}
cqr = dasd_eckd_format_build_ccw_req(base, fdata,
enable_pav, tpm,
fmt_buffer, rpt);
if (IS_ERR(cqr)) {
rc = PTR_ERR(cqr);
if (rc == -ENOMEM) {
if (list_empty(&format_queue))
goto out;
/*
* 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);
if (fmt_buffer) {
step = fdata->stop_unit - fdata->start_unit + 1;
fmt_buffer += rpt * step;
}
fdata->start_unit = fdata->stop_unit + 1;
fdata->stop_unit = old_stop;
}
rc = dasd_sleep_on_queue(&format_queue);
out_err:
list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
device = cqr->startdev;
private = device->private;
if (cqr->status == DASD_CQR_FAILED) {
/*
* Only get sense data if called by format
* check
*/
if (fmt_buffer && irb) {
sense = dasd_get_sense(&cqr->irb);
memcpy(irb, &cqr->irb, sizeof(*irb));
}
rc = -EIO;
}
list_del_init(&cqr->blocklist);
dasd_ffree_request(cqr, device);
private->count--;
}
if (rc && rc != -EIO)
goto out;
if (rc == -EIO) {
/*
* In case fewer than the expected records are on the
* track, we will most likely get a 'No Record Found'
* error (in command mode) or a 'File Protected' error
* (in transport mode). Those particular cases shouldn't
* pass the -EIO to the IOCTL, therefore reset the rc
* and continue.
*/
if (sense &&
(sense[1] & SNS1_NO_REC_FOUND ||
sense[1] & SNS1_FILE_PROTECTED))
retry = 1;
else
goto out;
}
} while (retry);
out:
fdata->start_unit = old_start;
fdata->stop_unit = old_stop;
return rc;
}