diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index 2d3c368bf83..0cce29f3979 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -501,6 +501,8 @@ ctl_be_block_biodone(struct bio *bio) if (beio->num_errors > 0) { if (error == EOPNOTSUPP) { ctl_set_invalid_opcode(&io->scsiio); + } else if (error == ENOSPC) { + ctl_set_space_alloc_fail(&io->scsiio); } else if (beio->bio_cmd == BIO_FLUSH) { /* XXX KDM is there is a better error here? */ ctl_set_internal_failure(&io->scsiio, @@ -711,14 +713,12 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun, char path_str[32]; ctl_scsi_path_string(io, path_str, sizeof(path_str)); - /* - * XXX KDM ZFS returns ENOSPC when the underlying - * filesystem fills up. What kind of SCSI error should we - * return for that? - */ printf("%s%s command returned errno %d\n", path_str, (beio->bio_cmd == BIO_READ) ? "READ" : "WRITE", error); - ctl_set_medium_error(&io->scsiio); + if (error == ENOSPC) { + ctl_set_space_alloc_fail(&io->scsiio); + } else + ctl_set_medium_error(&io->scsiio); ctl_complete_beio(beio); return; } @@ -804,7 +804,10 @@ ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun, * return the I/O to the user. */ if (error != 0) { - ctl_set_medium_error(&io->scsiio); + if (error == ENOSPC) { + ctl_set_space_alloc_fail(&io->scsiio); + } else + ctl_set_medium_error(&io->scsiio); ctl_complete_beio(beio); return; } diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c index d2edb2a9571..b6a8b89d133 100644 --- a/sys/cam/ctl/ctl_error.c +++ b/sys/cam/ctl/ctl_error.c @@ -805,6 +805,18 @@ ctl_set_task_aborted(struct ctl_scsiio *ctsio) ctsio->io_hdr.status = CTL_CMD_ABORTED; } +void +ctl_set_space_alloc_fail(struct ctl_scsiio *ctsio) +{ + /* "Space allocation failed write protect" */ + ctl_set_sense(ctsio, + /*current_error*/ 1, + /*sense_key*/ SSD_KEY_DATA_PROTECT, + /*asc*/ 0x27, + /*ascq*/ 0x07, + SSD_ELEM_NONE); +} + void ctl_set_success(struct ctl_scsiio *ctsio) { diff --git a/sys/cam/ctl/ctl_error.h b/sys/cam/ctl/ctl_error.h index 034d14bff99..d7d82aa392a 100644 --- a/sys/cam/ctl/ctl_error.h +++ b/sys/cam/ctl/ctl_error.h @@ -81,6 +81,7 @@ void ctl_set_reservation_conflict(struct ctl_scsiio *ctsio); void ctl_set_queue_full(struct ctl_scsiio *ctsio); void ctl_set_busy(struct ctl_scsiio *ctsio); void ctl_set_task_aborted(struct ctl_scsiio *ctsio); +void ctl_set_space_alloc_fail(struct ctl_scsiio *ctsio); void ctl_set_success(struct ctl_scsiio *ctsio); #endif /* _CTL_ERROR_H_ */ diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c index d61d4522163..959eda9125a 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -1733,7 +1733,7 @@ static struct asc_table_entry asc_table[] = { { SST(0x27, 0x06, SS_RDEF, /* XXX TBD */ "Conditional write protect") }, /* D B */ - { SST(0x27, 0x07, SS_RDEF, /* XXX TBD */ + { SST(0x27, 0x07, SS_FATAL | ENOSPC, "Space allocation failed write protect") }, /* DTLPWROMAEBKVF */ { SST(0x28, 0x00, SS_FATAL | ENXIO,