Merge branch 'bsg' of git://git.kernel.dk/data/git/linux-2.6-block
* 'bsg' of git://git.kernel.dk/data/git/linux-2.6-block: (25 commits) bsg: Kconfig updates bsg: add SCSI transport-level request support bsg: add bidi support add a struct request pointer to the request structure bsg: fix the deadlock on discarding done commands bsg: fix a blocking read bug bsg: minor bug fixes improve bsg device allocation bind bsg to all SCSI devices bsg: bind bsg to request_queue instead of gendisk bsg: add a request_queue argument to scsi_cmd_ioctl() bsg: simplify __bsg_alloc_command failpath bsg: add cheasy error checks for sysfs stuff Add queue resizing support Replace s32, u32 and u64 with __s32, __u32 and __u64 in bsg.h for userspace bsg: silence a bogus gcc warning bsg: style cleanup bsg: use u32 etc instead of uint32_t bsg: add SG_IO to SG v4 bsg: replace SG v3 with SG v4 ...
This commit is contained in:
commit
e245befce7
13 changed files with 1341 additions and 91 deletions
|
@ -51,4 +51,12 @@ config LSF
|
|||
|
||||
endif # BLOCK
|
||||
|
||||
config BLK_DEV_BSG
|
||||
bool "Block layer SG support"
|
||||
depends on SCSI && EXPERIMENTAL
|
||||
default y
|
||||
---help---
|
||||
Saying Y here will enable generic SG (SCSI generic) v4
|
||||
support for any block device.
|
||||
|
||||
source block/Kconfig.iosched
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_BSG) += bsg.o
|
||||
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
|
||||
obj-$(CONFIG_IOSCHED_AS) += as-iosched.o
|
||||
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
|
||||
|
|
1114
block/bsg.c
Normal file
1114
block/bsg.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -256,6 +256,7 @@ static void rq_init(request_queue_t *q, struct request *rq)
|
|||
rq->end_io = NULL;
|
||||
rq->end_io_data = NULL;
|
||||
rq->completion_data = NULL;
|
||||
rq->next_rq = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -41,8 +41,6 @@ const unsigned char scsi_command_size[8] =
|
|||
|
||||
EXPORT_SYMBOL(scsi_command_size);
|
||||
|
||||
#define BLK_DEFAULT_TIMEOUT (60 * HZ)
|
||||
|
||||
#include <scsi/sg.h>
|
||||
|
||||
static int sg_get_version(int __user *p)
|
||||
|
@ -114,7 +112,7 @@ static int sg_emulated_host(request_queue_t *q, int __user *p)
|
|||
#define safe_for_read(cmd) [cmd] = CMD_READ_SAFE
|
||||
#define safe_for_write(cmd) [cmd] = CMD_WRITE_SAFE
|
||||
|
||||
static int verify_command(struct file *file, unsigned char *cmd)
|
||||
int blk_verify_command(unsigned char *cmd, int has_write_perm)
|
||||
{
|
||||
static unsigned char cmd_type[256] = {
|
||||
|
||||
|
@ -193,18 +191,11 @@ static int verify_command(struct file *file, unsigned char *cmd)
|
|||
safe_for_write(GPCMD_SET_STREAMING),
|
||||
};
|
||||
unsigned char type = cmd_type[cmd[0]];
|
||||
int has_write_perm = 0;
|
||||
|
||||
/* Anybody who can open the device can do a read-safe command */
|
||||
if (type & CMD_READ_SAFE)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* file can be NULL from ioctl_by_bdev()...
|
||||
*/
|
||||
if (file)
|
||||
has_write_perm = file->f_mode & FMODE_WRITE;
|
||||
|
||||
/* Write-safe commands just require a writable open.. */
|
||||
if ((type & CMD_WRITE_SAFE) && has_write_perm)
|
||||
return 0;
|
||||
|
@ -221,25 +212,96 @@ static int verify_command(struct file *file, unsigned char *cmd)
|
|||
/* Otherwise fail it with an "Operation not permitted" */
|
||||
return -EPERM;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_verify_command);
|
||||
|
||||
int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq,
|
||||
struct sg_io_hdr *hdr, int has_write_perm)
|
||||
{
|
||||
memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
|
||||
|
||||
if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
|
||||
return -EFAULT;
|
||||
if (blk_verify_command(rq->cmd, has_write_perm))
|
||||
return -EPERM;
|
||||
|
||||
/*
|
||||
* fill in request structure
|
||||
*/
|
||||
rq->cmd_len = hdr->cmd_len;
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
|
||||
rq->timeout = (hdr->timeout * HZ) / 1000;
|
||||
if (!rq->timeout)
|
||||
rq->timeout = q->sg_timeout;
|
||||
if (!rq->timeout)
|
||||
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_fill_sghdr_rq);
|
||||
|
||||
/*
|
||||
* unmap a request that was previously mapped to this sg_io_hdr. handles
|
||||
* both sg and non-sg sg_io_hdr.
|
||||
*/
|
||||
int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr)
|
||||
{
|
||||
blk_rq_unmap_user(rq->bio);
|
||||
blk_put_request(rq);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_unmap_sghdr_rq);
|
||||
|
||||
int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
|
||||
struct bio *bio)
|
||||
{
|
||||
int r, ret = 0;
|
||||
|
||||
/*
|
||||
* fill in all the output members
|
||||
*/
|
||||
hdr->status = rq->errors & 0xff;
|
||||
hdr->masked_status = status_byte(rq->errors);
|
||||
hdr->msg_status = msg_byte(rq->errors);
|
||||
hdr->host_status = host_byte(rq->errors);
|
||||
hdr->driver_status = driver_byte(rq->errors);
|
||||
hdr->info = 0;
|
||||
if (hdr->masked_status || hdr->host_status || hdr->driver_status)
|
||||
hdr->info |= SG_INFO_CHECK;
|
||||
hdr->resid = rq->data_len;
|
||||
hdr->sb_len_wr = 0;
|
||||
|
||||
if (rq->sense_len && hdr->sbp) {
|
||||
int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
|
||||
|
||||
if (!copy_to_user(hdr->sbp, rq->sense, len))
|
||||
hdr->sb_len_wr = len;
|
||||
else
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
rq->bio = bio;
|
||||
r = blk_unmap_sghdr_rq(rq, hdr);
|
||||
if (ret)
|
||||
r = ret;
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_complete_sghdr_rq);
|
||||
|
||||
static int sg_io(struct file *file, request_queue_t *q,
|
||||
struct gendisk *bd_disk, struct sg_io_hdr *hdr)
|
||||
{
|
||||
unsigned long start_time, timeout;
|
||||
int writing = 0, ret = 0;
|
||||
unsigned long start_time;
|
||||
int writing = 0, ret = 0, has_write_perm = 0;
|
||||
struct request *rq;
|
||||
char sense[SCSI_SENSE_BUFFERSIZE];
|
||||
unsigned char cmd[BLK_MAX_CDB];
|
||||
struct bio *bio;
|
||||
|
||||
if (hdr->interface_id != 'S')
|
||||
return -EINVAL;
|
||||
if (hdr->cmd_len > BLK_MAX_CDB)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len))
|
||||
return -EFAULT;
|
||||
if (verify_command(file, cmd))
|
||||
return -EPERM;
|
||||
|
||||
if (hdr->dxfer_len > (q->max_hw_sectors << 9))
|
||||
return -EIO;
|
||||
|
@ -260,25 +322,13 @@ static int sg_io(struct file *file, request_queue_t *q,
|
|||
if (!rq)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* fill in request structure
|
||||
*/
|
||||
rq->cmd_len = hdr->cmd_len;
|
||||
memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
|
||||
memcpy(rq->cmd, cmd, hdr->cmd_len);
|
||||
if (file)
|
||||
has_write_perm = file->f_mode & FMODE_WRITE;
|
||||
|
||||
memset(sense, 0, sizeof(sense));
|
||||
rq->sense = sense;
|
||||
rq->sense_len = 0;
|
||||
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
|
||||
timeout = msecs_to_jiffies(hdr->timeout);
|
||||
rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX;
|
||||
if (!rq->timeout)
|
||||
rq->timeout = q->sg_timeout;
|
||||
if (!rq->timeout)
|
||||
rq->timeout = BLK_DEFAULT_TIMEOUT;
|
||||
if (blk_fill_sghdr_rq(q, rq, hdr, has_write_perm)) {
|
||||
blk_put_request(rq);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (hdr->iovec_count) {
|
||||
const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
|
||||
|
@ -306,6 +356,9 @@ static int sg_io(struct file *file, request_queue_t *q,
|
|||
goto out;
|
||||
|
||||
bio = rq->bio;
|
||||
memset(sense, 0, sizeof(sense));
|
||||
rq->sense = sense;
|
||||
rq->sense_len = 0;
|
||||
rq->retries = 0;
|
||||
|
||||
start_time = jiffies;
|
||||
|
@ -316,31 +369,9 @@ static int sg_io(struct file *file, request_queue_t *q,
|
|||
*/
|
||||
blk_execute_rq(q, bd_disk, rq, 0);
|
||||
|
||||
/* write to all output members */
|
||||
hdr->status = 0xff & rq->errors;
|
||||
hdr->masked_status = status_byte(rq->errors);
|
||||
hdr->msg_status = msg_byte(rq->errors);
|
||||
hdr->host_status = host_byte(rq->errors);
|
||||
hdr->driver_status = driver_byte(rq->errors);
|
||||
hdr->info = 0;
|
||||
if (hdr->masked_status || hdr->host_status || hdr->driver_status)
|
||||
hdr->info |= SG_INFO_CHECK;
|
||||
hdr->resid = rq->data_len;
|
||||
hdr->duration = ((jiffies - start_time) * 1000) / HZ;
|
||||
hdr->sb_len_wr = 0;
|
||||
|
||||
if (rq->sense_len && hdr->sbp) {
|
||||
int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
|
||||
|
||||
if (!copy_to_user(hdr->sbp, rq->sense, len))
|
||||
hdr->sb_len_wr = len;
|
||||
}
|
||||
|
||||
if (blk_rq_unmap_user(bio))
|
||||
ret = -EFAULT;
|
||||
|
||||
/* may not have succeeded, but output values written to control
|
||||
* structure (struct sg_io_hdr). */
|
||||
return blk_complete_sghdr_rq(rq, hdr, bio);
|
||||
out:
|
||||
blk_put_request(rq);
|
||||
return ret;
|
||||
|
@ -427,7 +458,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
|
|||
if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
|
||||
goto error;
|
||||
|
||||
err = verify_command(file, rq->cmd);
|
||||
err = blk_verify_command(rq->cmd, file->f_mode & FMODE_WRITE);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
|
@ -454,7 +485,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
|
|||
rq->retries = 1;
|
||||
break;
|
||||
default:
|
||||
rq->timeout = BLK_DEFAULT_TIMEOUT;
|
||||
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -501,7 +532,7 @@ static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int c
|
|||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
rq->data = NULL;
|
||||
rq->data_len = 0;
|
||||
rq->timeout = BLK_DEFAULT_TIMEOUT;
|
||||
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
|
||||
memset(rq->cmd, 0, sizeof(rq->cmd));
|
||||
rq->cmd[0] = cmd;
|
||||
rq->cmd[4] = data;
|
||||
|
@ -517,16 +548,12 @@ static inline int blk_send_start_stop(request_queue_t *q, struct gendisk *bd_dis
|
|||
return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
|
||||
}
|
||||
|
||||
int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
|
||||
int scsi_cmd_ioctl(struct file *file, struct request_queue *q,
|
||||
struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
|
||||
{
|
||||
request_queue_t *q;
|
||||
int err;
|
||||
|
||||
q = bd_disk->queue;
|
||||
if (!q)
|
||||
return -ENXIO;
|
||||
|
||||
if (blk_get_queue(q))
|
||||
if (!q || blk_get_queue(q))
|
||||
return -ENXIO;
|
||||
|
||||
switch (cmd) {
|
||||
|
|
|
@ -1709,7 +1709,7 @@ static int ub_bd_ioctl(struct inode *inode, struct file *filp,
|
|||
struct gendisk *disk = inode->i_bdev->bd_disk;
|
||||
void __user *usermem = (void __user *) arg;
|
||||
|
||||
return scsi_cmd_ioctl(filp, disk, cmd, usermem);
|
||||
return scsi_cmd_ioctl(filp, disk->queue, disk, cmd, usermem);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2695,11 +2695,12 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
|
|||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
int ret;
|
||||
struct gendisk *disk = ip->i_bdev->bd_disk;
|
||||
|
||||
/*
|
||||
* Try the generic SCSI command ioctl's first.
|
||||
*/
|
||||
ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, argp);
|
||||
ret = scsi_cmd_ioctl(file, disk->queue, disk, cmd, argp);
|
||||
if (ret != -ENOTTY)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -1258,19 +1258,25 @@ static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t
|
|||
set_bit(PC_DMA_RECOMMENDED, &pc->flags);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq)
|
||||
{
|
||||
/*
|
||||
* just support eject for now, it would not be hard to make the
|
||||
* REQ_BLOCK_PC support fully-featured
|
||||
*/
|
||||
if (rq->cmd[0] != IDEFLOPPY_START_STOP_CMD)
|
||||
return 1;
|
||||
|
||||
idefloppy_init_pc(pc);
|
||||
pc->callback = &idefloppy_rw_callback;
|
||||
memcpy(pc->c, rq->cmd, sizeof(pc->c));
|
||||
return 0;
|
||||
pc->rq = rq;
|
||||
pc->b_count = rq->data_len;
|
||||
if (rq->data_len && rq_data_dir(rq) == WRITE)
|
||||
set_bit(PC_WRITING, &pc->flags);
|
||||
pc->buffer = rq->data;
|
||||
if (rq->bio)
|
||||
set_bit(PC_DMA_RECOMMENDED, &pc->flags);
|
||||
|
||||
/*
|
||||
* possibly problematic, doesn't look like ide-floppy correctly
|
||||
* handled scattered requests if dma fails...
|
||||
*/
|
||||
pc->request_transfer = pc->buffer_size = rq->data_len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1317,10 +1323,7 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
|
|||
pc = (idefloppy_pc_t *) rq->buffer;
|
||||
} else if (blk_pc_request(rq)) {
|
||||
pc = idefloppy_next_pc_storage(drive);
|
||||
if (idefloppy_blockpc_cmd(floppy, pc, rq)) {
|
||||
idefloppy_do_end_request(drive, 0, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
idefloppy_blockpc_cmd(floppy, pc, rq);
|
||||
} else {
|
||||
blk_dump_rq_flags(rq,
|
||||
"ide-floppy: unsupported command in queue");
|
||||
|
|
|
@ -1049,9 +1049,13 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
|
|||
unsigned long flags;
|
||||
ide_driver_t *drv;
|
||||
void __user *p = (void __user *)arg;
|
||||
int err = 0, (*setfunc)(ide_drive_t *, int);
|
||||
int err, (*setfunc)(ide_drive_t *, int);
|
||||
u8 *val;
|
||||
|
||||
err = scsi_cmd_ioctl(file, bdev->bd_disk->queue, bdev->bd_disk, cmd, p);
|
||||
if (err != -ENOTTY)
|
||||
return err;
|
||||
|
||||
switch (cmd) {
|
||||
case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val;
|
||||
case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
|
||||
|
@ -1171,10 +1175,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
|
|||
return 0;
|
||||
}
|
||||
|
||||
case CDROMEJECT:
|
||||
case CDROMCLOSETRAY:
|
||||
return scsi_cmd_ioctl(file, bdev->bd_disk, cmd, p);
|
||||
|
||||
case HDIO_GET_BUSSTATE:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
|
|
|
@ -684,7 +684,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
|
|||
case SCSI_IOCTL_GET_BUS_NUMBER:
|
||||
return scsi_ioctl(sdp, cmd, p);
|
||||
default:
|
||||
error = scsi_cmd_ioctl(filp, disk, cmd, p);
|
||||
error = scsi_cmd_ioctl(filp, disk->queue, disk, cmd, p);
|
||||
if (error != -ENOTTY)
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -3549,7 +3549,8 @@ static int st_ioctl(struct inode *inode, struct file *file,
|
|||
!capable(CAP_SYS_RAWIO))
|
||||
i = -EPERM;
|
||||
else
|
||||
i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p);
|
||||
i = scsi_cmd_ioctl(file, STp->disk->queue,
|
||||
STp->disk, cmd_in, p);
|
||||
if (i != -ENOTTY)
|
||||
return i;
|
||||
break;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/bio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/bsg.h>
|
||||
|
||||
#include <asm/scatterlist.h>
|
||||
|
||||
|
@ -41,6 +42,8 @@ struct elevator_queue;
|
|||
typedef struct elevator_queue elevator_t;
|
||||
struct request_pm_state;
|
||||
struct blk_trace;
|
||||
struct request;
|
||||
struct sg_io_hdr;
|
||||
|
||||
#define BLKDEV_MIN_RQ 4
|
||||
#define BLKDEV_MAX_RQ 128 /* Default maximum */
|
||||
|
@ -314,6 +317,9 @@ struct request {
|
|||
*/
|
||||
rq_end_io_fn *end_io;
|
||||
void *end_io_data;
|
||||
|
||||
/* for bidi */
|
||||
struct request *next_rq;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -468,6 +474,10 @@ struct request_queue
|
|||
unsigned int bi_size;
|
||||
|
||||
struct mutex sysfs_lock;
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_BSG)
|
||||
struct bsg_class_device bsg_dev;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */
|
||||
|
@ -479,6 +489,7 @@ struct request_queue
|
|||
#define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */
|
||||
#define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */
|
||||
#define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */
|
||||
#define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */
|
||||
|
||||
enum {
|
||||
/*
|
||||
|
@ -543,6 +554,7 @@ enum {
|
|||
#define blk_sorted_rq(rq) ((rq)->cmd_flags & REQ_SORTED)
|
||||
#define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER)
|
||||
#define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA)
|
||||
#define blk_bidi_rq(rq) ((rq)->next_rq != NULL)
|
||||
|
||||
#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)
|
||||
|
||||
|
@ -607,6 +619,11 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn;
|
|||
#define BLK_BOUNCE_ANY ((u64)blk_max_pfn << PAGE_SHIFT)
|
||||
#define BLK_BOUNCE_ISA (ISA_DMA_THRESHOLD)
|
||||
|
||||
/*
|
||||
* default timeout for SG_IO if none specified
|
||||
*/
|
||||
#define BLK_DEFAULT_SG_TIMEOUT (60 * HZ)
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
extern int init_emergency_isa_pool(void);
|
||||
extern void blk_queue_bounce(request_queue_t *q, struct bio **bio);
|
||||
|
@ -637,7 +654,8 @@ extern void blk_requeue_request(request_queue_t *, struct request *);
|
|||
extern void blk_plug_device(request_queue_t *);
|
||||
extern int blk_remove_plug(request_queue_t *);
|
||||
extern void blk_recount_segments(request_queue_t *, struct bio *);
|
||||
extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
|
||||
extern int scsi_cmd_ioctl(struct file *, struct request_queue *,
|
||||
struct gendisk *, unsigned int, void __user *);
|
||||
extern int sg_scsi_ioctl(struct file *, struct request_queue *,
|
||||
struct gendisk *, struct scsi_ioctl_command __user *);
|
||||
|
||||
|
@ -680,6 +698,12 @@ extern int blk_execute_rq(request_queue_t *, struct gendisk *,
|
|||
struct request *, int);
|
||||
extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
|
||||
struct request *, int, rq_end_io_fn *);
|
||||
extern int blk_fill_sghdr_rq(request_queue_t *, struct request *,
|
||||
struct sg_io_hdr *, int);
|
||||
extern int blk_unmap_sghdr_rq(struct request *, struct sg_io_hdr *);
|
||||
extern int blk_complete_sghdr_rq(struct request *, struct sg_io_hdr *,
|
||||
struct bio *);
|
||||
extern int blk_verify_command(unsigned char *, int);
|
||||
|
||||
static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
|
||||
{
|
||||
|
|
70
include/linux/bsg.h
Normal file
70
include/linux/bsg.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
#ifndef BSG_H
|
||||
#define BSG_H
|
||||
|
||||
#define BSG_PROTOCOL_SCSI 0
|
||||
|
||||
#define BSG_SUB_PROTOCOL_SCSI_CMD 0
|
||||
#define BSG_SUB_PROTOCOL_SCSI_TMF 1
|
||||
#define BSG_SUB_PROTOCOL_SCSI_TRANSPORT 2
|
||||
|
||||
struct sg_io_v4 {
|
||||
__s32 guard; /* [i] 'Q' to differentiate from v3 */
|
||||
__u32 protocol; /* [i] 0 -> SCSI , .... */
|
||||
__u32 subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task
|
||||
management function, .... */
|
||||
|
||||
__u32 request_len; /* [i] in bytes */
|
||||
__u64 request; /* [i], [*i] {SCSI: cdb} */
|
||||
__u32 request_attr; /* [i] {SCSI: task attribute} */
|
||||
__u32 request_tag; /* [i] {SCSI: task tag (only if flagged)} */
|
||||
__u32 request_priority; /* [i] {SCSI: task priority} */
|
||||
__u32 max_response_len; /* [i] in bytes */
|
||||
__u64 response; /* [i], [*o] {SCSI: (auto)sense data} */
|
||||
|
||||
/* "din_" for data in (from device); "dout_" for data out (to device) */
|
||||
__u32 dout_xfer_len; /* [i] bytes to be transferred to device */
|
||||
__u32 din_xfer_len; /* [i] bytes to be transferred from device */
|
||||
__u64 dout_xferp; /* [i], [*i] */
|
||||
__u64 din_xferp; /* [i], [*o] */
|
||||
|
||||
__u32 timeout; /* [i] units: millisecond */
|
||||
__u32 flags; /* [i] bit mask */
|
||||
__u64 usr_ptr; /* [i->o] unused internally */
|
||||
__u32 spare_in; /* [i] */
|
||||
|
||||
__u32 driver_status; /* [o] 0 -> ok */
|
||||
__u32 transport_status; /* [o] 0 -> ok */
|
||||
__u32 device_status; /* [o] {SCSI: command completion status} */
|
||||
__u32 retry_delay; /* [o] {SCSI: status auxiliary information} */
|
||||
__u32 info; /* [o] additional information */
|
||||
__u32 duration; /* [o] time to complete, in milliseconds */
|
||||
__u32 response_len; /* [o] bytes of response actually written */
|
||||
__s32 din_resid; /* [o] actual_din_xfer_len - din_xfer_len */
|
||||
__u32 generated_tag; /* [o] {SCSI: task tag that transport chose} */
|
||||
__u32 spare_out; /* [o] */
|
||||
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_BSG)
|
||||
struct bsg_class_device {
|
||||
struct class_device *class_dev;
|
||||
struct device *dev;
|
||||
int minor;
|
||||
struct list_head list;
|
||||
struct request_queue *queue;
|
||||
};
|
||||
|
||||
extern int bsg_register_queue(struct request_queue *, const char *);
|
||||
extern void bsg_unregister_queue(struct request_queue *);
|
||||
#else
|
||||
struct bsg_class_device { };
|
||||
#define bsg_register_queue(disk, name) (0)
|
||||
#define bsg_unregister_queue(disk) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue