Commit 90df68e7 authored by Linus Torvalds's avatar Linus Torvalds

Block layer ioctl cleanups.

Rename old "block_ioctl()" function: it's "scsi_cmd_ioctl()", as that
is what the function does. Rename the whole file "scsi_ioctl.c"
parent 6e8b5dcf
......@@ -9,9 +9,9 @@
#
export-objs := elevator.o ll_rw_blk.o loop.o genhd.o acsi.o \
block_ioctl.o deadline-iosched.o
scsi_ioctl.o deadline-iosched.o
obj-y := elevator.o ll_rw_blk.o blkpg.o genhd.o block_ioctl.o deadline-iosched.o
obj-y := elevator.o ll_rw_blk.o blkpg.o genhd.o scsi_ioctl.o deadline-iosched.o
obj-$(CONFIG_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
......
......@@ -305,6 +305,6 @@ int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return 0;
default:
return -EINVAL;
return -ENOTTY;
}
}
......@@ -27,8 +27,12 @@
#include <linux/module.h>
#include <linux/blk.h>
#include <linux/completion.h>
#include <linux/cdrom.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
#include <asm/uaccess.h>
int blk_do_rq(request_queue_t *q, struct request *rq)
{
......@@ -50,7 +54,114 @@ int blk_do_rq(request_queue_t *q, struct request *rq)
return err;
}
int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
#include <scsi/sg.h>
static int sg_get_version(int *p)
{
static int sg_version_num = 30527;
return put_user(sg_version_num, p);
}
static int scsi_get_idlun(request_queue_t *q, int *p)
{
return put_user(0, p);
}
static int scsi_get_bus(request_queue_t *q, int *p)
{
return put_user(0, p);
}
static int sg_get_timeout(request_queue_t *q)
{
return HZ;
}
static int sg_set_timeout(request_queue_t *q, int *p)
{
int timeout;
int error = get_user(timeout, p);
return error;
}
static int reserved_size = 0;
static int sg_get_reserved_size(request_queue_t *q, int *p)
{
return put_user(reserved_size, p);
}
static int sg_set_reserved_size(request_queue_t *q, int *p)
{
int size;
int error = get_user(size, p);
if (!error)
reserved_size = size;
return error;
}
static int sg_emulated_host(request_queue_t *q, int *p)
{
return put_user(1, p);
}
static int sg_io(request_queue_t *q, struct sg_io_hdr *uptr)
{
int i, err;
struct sg_io_hdr hdr;
struct request *rq;
void *buffer;
if (!access_ok(VERIFY_WRITE, uptr, sizeof(*uptr)))
return -EFAULT;
if (copy_from_user(&hdr, uptr, sizeof(*uptr)))
return -EFAULT;
if ( hdr.cmd_len > sizeof(rq->cmd) )
return -EINVAL;
buffer = NULL;
if (hdr.dxfer_len) {
unsigned int bytes = (hdr.dxfer_len + 511) & ~511;
switch (hdr.dxfer_direction) {
default:
return -EINVAL;
case SG_DXFER_TO_DEV:
case SG_DXFER_FROM_DEV:
case SG_DXFER_TO_FROM_DEV:
break;
}
buffer = kmalloc(bytes, GFP_USER);
if (!buffer)
return -ENOMEM;
if (hdr.dxfer_direction == SG_DXFER_TO_DEV ||
hdr.dxfer_direction == SG_DXFER_TO_FROM_DEV)
copy_from_user(buffer, hdr.dxferp, hdr.dxfer_len);
}
rq = blk_get_request(q, WRITE, __GFP_WAIT);
rq->timeout = 60*HZ;
rq->data = buffer;
rq->data_len = hdr.dxfer_len;
rq->flags = REQ_BLOCK_PC;
memset(rq->cmd, 0, sizeof(rq->cmd));
copy_from_user(rq->cmd, hdr.cmdp, hdr.cmd_len);
err = blk_do_rq(q, rq);
blk_put_request(rq);
copy_to_user(uptr, &hdr, sizeof(*uptr));
if (buffer) {
if (hdr.dxfer_direction == SG_DXFER_FROM_DEV ||
hdr.dxfer_direction == SG_DXFER_TO_FROM_DEV)
copy_to_user(hdr.dxferp, buffer, hdr.dxfer_len);
kfree(buffer);
}
return err;
}
int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
{
request_queue_t *q;
struct request *rq;
......@@ -61,11 +172,32 @@ int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return -ENXIO;
switch (cmd) {
case SG_GET_VERSION_NUM:
return sg_get_version((int *) arg);
case SCSI_IOCTL_GET_IDLUN:
return scsi_get_idlun(q, (int *) arg);
case SCSI_IOCTL_GET_BUS_NUMBER:
return scsi_get_bus(q, (int *) arg);
case SG_SET_TIMEOUT:
return sg_set_timeout(q, (int *) arg);
case SG_GET_TIMEOUT:
return sg_get_timeout(q);
case SG_GET_RESERVED_SIZE:
return sg_get_reserved_size(q, (int *) arg);
case SG_SET_RESERVED_SIZE:
return sg_set_reserved_size(q, (int *) arg);
case SG_EMULATED_HOST:
return sg_emulated_host(q, (int *) arg);
case SG_IO:
return sg_io(q, (struct sg_io_hdr *) arg);
case CDROMCLOSETRAY:
close = 1;
case CDROMEJECT:
rq = blk_get_request(q, WRITE, __GFP_WAIT);
rq->flags = REQ_BLOCK_PC;
rq->data = NULL;
rq->data_len = 0;
rq->timeout = 60*HZ;
memset(rq->cmd, 0, sizeof(rq->cmd));
rq->cmd[0] = GPCMD_START_STOP_UNIT;
rq->cmd[4] = 0x02 + (close != 0);
......@@ -80,4 +212,4 @@ int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return err;
}
EXPORT_SYMBOL(block_ioctl);
EXPORT_SYMBOL(scsi_cmd_ioctl);
......@@ -2639,7 +2639,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case CDROMEJECT:
case CDROMCLOSETRAY:
return block_ioctl(inode->i_bdev, cmd, arg);
return scsi_cmd_ioctl(inode->i_bdev, cmd, arg);
case HDIO_GET_BUSSTATE:
if (!capable(CAP_SYS_ADMIN))
......
......@@ -825,44 +825,9 @@ static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
int ret = -EINVAL;
switch (cmd) {
/*
* deprecated, use the /proc/iosched interface instead
*/
case BLKELVGET:
case BLKELVSET:
ret = -ENOTTY;
break;
case BLKRAGET:
case BLKROGET:
case BLKBSZGET:
case BLKSSZGET:
case BLKFRAGET:
case BLKSECTGET:
case BLKRASET:
case BLKFRASET:
case BLKBSZSET:
case BLKPG:
ret = blk_ioctl(bdev, cmd, arg);
break;
case BLKRRPART:
ret = blkdev_reread_part(bdev);
break;
default:
if (bdev->bd_op->ioctl)
ret =bdev->bd_op->ioctl(inode, file, cmd, arg);
if (ret == -EINVAL) {
switch (cmd) {
case BLKGETSIZE:
case BLKGETSIZE64:
case BLKFLSBUF:
case BLKROSET:
ret = blk_ioctl(bdev,cmd,arg);
break;
}
}
}
int ret = blk_ioctl(bdev, cmd, arg);
if (ret == -ENOTTY && bdev->bd_op->ioctl)
ret = bdev->bd_op->ioctl(inode, file, cmd, arg);
return ret;
}
......
......@@ -60,6 +60,12 @@ struct request {
int tag;
void *special;
char *buffer;
/* For packet commands */
unsigned int data_len;
void *data, *sense;
unsigned int timeout;
struct completion *waiting;
struct bio *bio, *biotail;
request_queue_t *q;
......@@ -85,6 +91,8 @@ enum rq_flag_bits {
__REQ_BLOCK_PC, /* queued down pc from block layer */
__REQ_SENSE, /* sense retrival */
__REQ_FAILED, /* set if the request failed */
__REQ_QUIET, /* don't worry about errors */
__REQ_SPECIAL, /* driver suplied command */
__REQ_DRIVE_CMD,
__REQ_DRIVE_TASK,
......@@ -103,6 +111,8 @@ enum rq_flag_bits {
#define REQ_PC (1 << __REQ_PC)
#define REQ_BLOCK_PC (1 << __REQ_BLOCK_PC)
#define REQ_SENSE (1 << __REQ_SENSE)
#define REQ_FAILED (1 << __REQ_FAILED)
#define REQ_QUIET (1 << __REQ_QUIET)
#define REQ_SPECIAL (1 << __REQ_SPECIAL)
#define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD)
#define REQ_DRIVE_TASK (1 << __REQ_DRIVE_TASK)
......@@ -301,7 +311,7 @@ extern int blk_remove_plug(request_queue_t *);
extern void blk_recount_segments(request_queue_t *, struct bio *);
extern inline int blk_phys_contig_segment(request_queue_t *q, struct bio *, struct bio *);
extern inline int blk_hw_contig_segment(request_queue_t *q, struct bio *, struct bio *);
extern int block_ioctl(struct block_device *, unsigned int, unsigned long);
extern int scsi_cmd_ioctl(struct block_device *, unsigned int, unsigned long);
extern void blk_start_queue(request_queue_t *q);
extern void blk_stop_queue(request_queue_t *q);
extern void __blk_stop_queue(request_queue_t *q);
......
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