if (buffer) { if (get_user(len, (unsignedint __user *) buffer)) return -EFAULT;
if (host->hostt->info)
string = host->hostt->info(host); else
string = host->hostt->name; if (string) {
slen = strlen(string); if (len > slen)
len = slen + 1; if (copy_to_user(buffer, string, len)) return -EFAULT;
}
} return1;
}
staticint ioctl_internal_command(struct scsi_device *sdev, char *cmd, int timeout, int retries)
{ int result; struct scsi_sense_hdr sshdr; conststruct scsi_exec_args exec_args = {
.sshdr = &sshdr,
};
SCSI_LOG_IOCTL(1, sdev_printk(KERN_INFO, sdev, "Trying ioctl with scsi command %d\n", *cmd));
result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, NULL, 0, timeout,
retries, &exec_args);
SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, "Ioctl returned 0x%x\n", result));
if (result < 0) goto out; if (scsi_sense_valid(&sshdr)) { switch (sshdr.sense_key) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL)
sdev->lockable = 0; else
sdev_printk(KERN_INFO, sdev, "ioctl_internal_command: " "ILLEGAL REQUEST " "asc=0x%x ascq=0x%x\n",
sshdr.asc, sshdr.ascq); break; case NOT_READY: /* This happens if there is no disc in drive */ if (sdev->removable) break;
fallthrough; case UNIT_ATTENTION: if (sdev->removable) {
sdev->changed = 1;
result = 0; /* This is no longer considered an error */ break;
}
fallthrough; /* for non-removable media */ default:
sdev_printk(KERN_INFO, sdev, "ioctl_internal_command return code = %x\n",
result);
scsi_print_sense_hdr(sdev, NULL, &sshdr); break;
}
}
out:
SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, "IOCTL Releasing command\n")); return result;
}
/** *scsi_cmd_allowed()-Checkifthegivencommandisallowed. *@cmd:SCSIcommandtocheck *@open_for_write:isthefile/blockdeviceopenedforwriting? * *Onlyasubsetofcommandsareallowedforunprivilegedusers.Commandsused *toformatthemedia,updatethefirmware,etc.arenotpermitted. * *Return:%trueifthecmdisallowed,otherwise@false.
*/ bool scsi_cmd_allowed(unsignedchar *cmd, bool open_for_write)
{ /* root can do any command. */ if (capable(CAP_SYS_RAWIO)) returntrue;
/* Anybody who can open the device can do a read-safe command */ switch (cmd[0]) { /* Basic read-only commands */ case TEST_UNIT_READY: case REQUEST_SENSE: case READ_6: case READ_10: case READ_12: case READ_16: case READ_BUFFER: case READ_DEFECT_DATA: case READ_CAPACITY: /* also GPCMD_READ_CDVD_CAPACITY */ case READ_LONG: case INQUIRY: case MODE_SENSE: case MODE_SENSE_10: case LOG_SENSE: case START_STOP: case GPCMD_VERIFY_10: case VERIFY_16: case REPORT_LUNS: case SERVICE_ACTION_IN_16: case RECEIVE_DIAGNOSTIC: case MAINTENANCE_IN: /* also GPCMD_SEND_KEY, which is a write command */ case GPCMD_READ_BUFFER_CAPACITY: /* Audio CD commands */ case GPCMD_PLAY_CD: case GPCMD_PLAY_AUDIO_10: case GPCMD_PLAY_AUDIO_MSF: case GPCMD_PLAY_AUDIO_TI: case GPCMD_PAUSE_RESUME: /* CD/DVD data reading */ case GPCMD_READ_CD: case GPCMD_READ_CD_MSF: case GPCMD_READ_DISC_INFO: case GPCMD_READ_DVD_STRUCTURE: case GPCMD_READ_HEADER: case GPCMD_READ_TRACK_RZONE_INFO: case GPCMD_READ_SUBCHANNEL: case GPCMD_READ_TOC_PMA_ATIP: case GPCMD_REPORT_KEY: case GPCMD_SCAN: case GPCMD_GET_CONFIGURATION: case GPCMD_READ_FORMAT_CAPACITIES: case GPCMD_GET_EVENT_STATUS_NOTIFICATION: case GPCMD_GET_PERFORMANCE: case GPCMD_SEEK: case GPCMD_STOP_PLAY_SCAN: /* ZBC */ case ZBC_IN: returntrue; /* Basic writing commands */ case WRITE_6: case WRITE_10: case WRITE_VERIFY: case WRITE_12: case WRITE_VERIFY_12: case WRITE_16: case WRITE_LONG: case WRITE_LONG_2: case WRITE_SAME: case WRITE_SAME_16: case WRITE_SAME_32: case ERASE: case GPCMD_MODE_SELECT_10: case MODE_SELECT: case LOG_SELECT: case GPCMD_BLANK: case GPCMD_CLOSE_TRACK: case GPCMD_FLUSH_CACHE: case GPCMD_FORMAT_UNIT: case GPCMD_REPAIR_RZONE_TRACK: case GPCMD_RESERVE_RZONE_TRACK: case GPCMD_SEND_DVD_STRUCTURE: case GPCMD_SEND_EVENT: case GPCMD_SEND_OPC: case GPCMD_SEND_CUE_SHEET: case GPCMD_SET_SPEED: case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case GPCMD_LOAD_UNLOAD: case GPCMD_SET_STREAMING: case GPCMD_SET_READ_AHEAD: /* ZBC */ case ZBC_OUT: return open_for_write; default: returnfalse;
}
}
EXPORT_SYMBOL(scsi_cmd_allowed);
if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) goto error;
err = -EPERM; if (!scsi_cmd_allowed(scmd->cmnd, open_for_write)) goto error;
/* default. possible overridden later */
scmd->allowed = 5;
switch (opcode) { case SEND_DIAGNOSTIC: case FORMAT_UNIT:
rq->timeout = FORMAT_UNIT_TIMEOUT;
scmd->allowed = 1; break; case START_STOP:
rq->timeout = START_STOP_TIMEOUT; break; case MOVE_MEDIUM:
rq->timeout = MOVE_MEDIUM_TIMEOUT; break; case READ_ELEMENT_STATUS:
rq->timeout = READ_ELEMENT_STATUS_TIMEOUT; break; case READ_DEFECT_DATA:
rq->timeout = READ_DEFECT_DATA_TIMEOUT;
scmd->allowed = 1; break; default:
rq->timeout = BLK_DEFAULT_SG_TIMEOUT; break;
}
if (bytes) {
err = blk_rq_map_kern(rq, buffer, bytes, GFP_NOIO); if (err) goto error;
}
blk_execute_rq(rq, false);
err = scmd->result & 0xff; /* only 8 bit SCSI status */ if (err) { if (scmd->sense_len && scmd->sense_buffer) { /* limit sense len for backward compatibility */ if (copy_to_user(sic->data, scmd->sense_buffer,
min(scmd->sense_len, 16U)))
err = -EFAULT;
}
} else { if (copy_to_user(sic->data, buffer, out_len))
err = -EFAULT;
}
/* Check for deprecated ioctls ... all the ioctls which don't
* follow the new unique numbering scheme are deprecated */ switch (cmd) { case SCSI_IOCTL_SEND_COMMAND: case SCSI_IOCTL_TEST_UNIT_READY: case SCSI_IOCTL_BENCHMARK_COMMAND: case SCSI_IOCTL_SYNC: case SCSI_IOCTL_START_UNIT: case SCSI_IOCTL_STOP_UNIT:
printk(KERN_WARNING "program %s is using a deprecated SCSI " "ioctl, please convert it to SG_IO\n", current->comm); break; default: break;
}
switch (cmd) { case SG_GET_VERSION_NUM: return sg_get_version(arg); case SG_SET_TIMEOUT: return sg_set_timeout(sdev, arg); case SG_GET_TIMEOUT: return jiffies_to_clock_t(sdev->sg_timeout); case SG_GET_RESERVED_SIZE: return sg_get_reserved_size(sdev, arg); case SG_SET_RESERVED_SIZE: return sg_set_reserved_size(sdev, arg); case SG_EMULATED_HOST: return sg_emulated_host(q, arg); case SG_IO: return scsi_ioctl_sg_io(sdev, open_for_write, arg); case SCSI_IOCTL_SEND_COMMAND: return sg_scsi_ioctl(q, open_for_write, arg); case CDROM_SEND_PACKET: return scsi_cdrom_send_packet(sdev, open_for_write, arg); case CDROMCLOSETRAY: return scsi_send_start_stop(sdev, 3); case CDROMEJECT: return scsi_send_start_stop(sdev, 2); case SCSI_IOCTL_GET_IDLUN: return scsi_get_idlun(sdev, arg); case SCSI_IOCTL_GET_BUS_NUMBER: return put_user(sdev->host->host_no, (int __user *)arg); case SCSI_IOCTL_PROBE_HOST: return ioctl_probe(sdev->host, arg); case SCSI_IOCTL_DOORLOCK: return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); case SCSI_IOCTL_DOORUNLOCK: return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); case SCSI_IOCTL_TEST_UNIT_READY: return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT,
NORMAL_RETRIES, &sense_hdr); case SCSI_IOCTL_START_UNIT: return scsi_send_start_stop(sdev, 1); case SCSI_IOCTL_STOP_UNIT: return scsi_send_start_stop(sdev, 0); case SCSI_IOCTL_GET_PCI: return scsi_ioctl_get_pci(sdev, arg); case SG_SCSI_RESET: return scsi_ioctl_reset(sdev, arg);
}
#ifdef CONFIG_COMPAT if (in_compat_syscall()) { if (!sdev->host->hostt->compat_ioctl) return -EINVAL; return sdev->host->hostt->compat_ioctl(sdev, cmd, arg);
} #endif if (!sdev->host->hostt->ioctl) return -EINVAL; return sdev->host->hostt->ioctl(sdev, cmd, arg);
}
EXPORT_SYMBOL(scsi_ioctl);
/** *scsi_ioctl_block_when_processing_errors-preventcommandsfrombeingqueued *@sdev:targetscsidevice *@cmd:whichioctlisit *@ndelay:nodelay(non-blocking) * *Wecanprocessaresetevenwhenadeviceisn'tfullyoperable. * *Return:%0onsuccess,<0errorcode.
*/ int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, int cmd, bool ndelay)
{ if (cmd == SG_SCSI_RESET && ndelay) { if (scsi_host_in_recovery(sdev->host)) return -EAGAIN;
} else { if (!scsi_block_when_processing_errors(sdev)) return -ENODEV;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.