USB: UB: Let cdrecord to see a device with media absent

The command "cdrecord dev=/dev/uba x.iso" prints nasty garbage if a blank
is not in the drive. This happens because drivers have to set req->errors
separately from just returning zero uptodate with end_that_request_first,
end_that_request_last. These functions only set error in BIO, but sg_io()
ignores it.

Since we're on it, let cdrecord access a device when ->changed is set.
It's useful if someone wants to know device capabilities without burning
anything.

Signed-Off-By: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Pete Zaitcev 2006-09-07 16:54:22 -07:00 committed by Greg Kroah-Hartman
parent 14acdcd321
commit d1ad4ea331
1 changed files with 25 additions and 13 deletions

View File

@ -358,7 +358,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct ub_request *urq); struct ub_scsi_cmd *cmd, struct ub_request *urq);
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_end_rq(struct request *rq, int uptodate); static void ub_end_rq(struct request *rq, unsigned int status);
static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
struct ub_request *urq, struct ub_scsi_cmd *cmd); struct ub_request *urq, struct ub_scsi_cmd *cmd);
static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@ -639,9 +639,15 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
struct ub_request *urq; struct ub_request *urq;
int n_elem; int n_elem;
if (atomic_read(&sc->poison) || lun->changed) { if (atomic_read(&sc->poison)) {
blkdev_dequeue_request(rq); blkdev_dequeue_request(rq);
ub_end_rq(rq, 0); ub_end_rq(rq, DID_NO_CONNECT << 16);
return 0;
}
if (lun->changed && !blk_pc_request(rq)) {
blkdev_dequeue_request(rq);
ub_end_rq(rq, SAM_STAT_CHECK_CONDITION);
return 0; return 0;
} }
@ -693,7 +699,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
drop: drop:
ub_put_cmd(lun, cmd); ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0); ub_end_rq(rq, DID_ERROR << 16);
return 0; return 0;
} }
@ -761,47 +767,53 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
struct ub_lun *lun = cmd->lun; struct ub_lun *lun = cmd->lun;
struct ub_request *urq = cmd->back; struct ub_request *urq = cmd->back;
struct request *rq; struct request *rq;
int uptodate; unsigned int scsi_status;
rq = urq->rq; rq = urq->rq;
if (cmd->error == 0) { if (cmd->error == 0) {
uptodate = 1;
if (blk_pc_request(rq)) { if (blk_pc_request(rq)) {
if (cmd->act_len >= rq->data_len) if (cmd->act_len >= rq->data_len)
rq->data_len = 0; rq->data_len = 0;
else else
rq->data_len -= cmd->act_len; rq->data_len -= cmd->act_len;
} }
scsi_status = 0;
} else { } else {
uptodate = 0;
if (blk_pc_request(rq)) { if (blk_pc_request(rq)) {
/* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
rq->sense_len = UB_SENSE_SIZE; rq->sense_len = UB_SENSE_SIZE;
if (sc->top_sense[0] != 0) if (sc->top_sense[0] != 0)
rq->errors = SAM_STAT_CHECK_CONDITION; scsi_status = SAM_STAT_CHECK_CONDITION;
else else
rq->errors = DID_ERROR << 16; scsi_status = DID_ERROR << 16;
} else { } else {
if (cmd->error == -EIO) { if (cmd->error == -EIO) {
if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0) if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
return; return;
} }
scsi_status = SAM_STAT_CHECK_CONDITION;
} }
} }
urq->rq = NULL; urq->rq = NULL;
ub_put_cmd(lun, cmd); ub_put_cmd(lun, cmd);
ub_end_rq(rq, uptodate); ub_end_rq(rq, scsi_status);
blk_start_queue(lun->disk->queue); blk_start_queue(lun->disk->queue);
} }
static void ub_end_rq(struct request *rq, int uptodate) static void ub_end_rq(struct request *rq, unsigned int scsi_status)
{ {
int uptodate;
if (scsi_status == 0) {
uptodate = 1;
} else {
uptodate = 0;
rq->errors = scsi_status;
}
end_that_request_first(rq, uptodate, rq->hard_nr_sectors); end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
end_that_request_last(rq, uptodate); end_that_request_last(rq, uptodate);
} }