[PATCH 03/13] sg_io: use different default filters for each device class

Paolo Bonzini
2013-01-24T15:01:11Z

Store the filters in a 256-entry array, and pick an appropriate filter
for SCSI devices. Apart from SCSI disks, SG_IO is supported for CCISS,
ide-floppy and virtio-blk devices; TYPE_DISK (which is zero, i.e. the
default) is more appropriate for these devices than TYPE_ROM.

This patch already introduces some semantic change, albeit very limited;
in addition to the above change for CCISS/ide-floppy/virtio-blk, a few
commands are now forbidden for devices of type other than TYPE_ROM,
where they are reserved or vendor-specific.

Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: linux-scsi@kernel.org
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
block/scsi_ioctl.c | 14 +++++---------
drivers/scsi/scsi_scan.c | 2 ++
include/linux/blkdev.h | 2 +-
include/scsi/scsi.h | 1 +
4 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 75533bd..e68add2 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -34,8 +34,8 @@
#include <scsi/scsi_cmnd.h>

struct blk_cmd_filter {
- unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
- unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
+ u32 read_ok[BLK_SCSI_MAX_CMDS];
+ u32 write_ok[BLK_SCSI_MAX_CMDS];
};

static struct blk_cmd_filter blk_default_cmd_filter;
@@ -116,7 +116,7 @@ static int sg_emulated_host(struct request_queue *q, int __user *p)
static void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
{
#define sgio_bitmap_set(cmd, mask, rw) \
- if ((mask) != 0) __set_bit((cmd), filter->rw##_ok)
+ filter->rw##_ok[(cmd)] |= (mask);

#define D (1u << TYPE_DISK) /* Direct Access Block Device (SBC-3) */
#define T (1u << TYPE_TAPE) /* Sequential Access Device (SSC-3) */
@@ -256,16 +256,12 @@ int blk_verify_command(struct request_queue *q,
if (capable(CAP_SYS_RAWIO))
return 0;

- /* if there's no filter set, assume we're filtering everything out */
- if (!filter)
- return -EPERM;
-
/* Anybody who can open the device can do a read-safe command */
- if (test_bit(cmd[0], filter->read_ok))
+ if (filter->read_ok[cmd[0]] & (1 << q->sgio_type))
return 0;

/* Write-safe commands require a writable open */
- if (test_bit(cmd[0], filter->write_ok) && has_write_perm)
+ if (has_write_perm && filter->write_ok[cmd[0]] & (1 << q->sgio_type))
return 0;

return -EPERM;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 3e58b22..86940f3 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -782,6 +782,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
sdev->removable = (inq_result[1] & 0x80) >> 7;
}

+ sdev->request_queue->sgio_type = sdev->type;
+
switch (sdev->type) {
case TYPE_RBC:
case TYPE_TAPE:
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 0782336..b376d37 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -256,7 +256,6 @@ struct blk_queue_tag {
};

#define BLK_SCSI_MAX_CMDS (256)
-#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))

struct queue_limits {
unsigned long bounce_pfn;
@@ -403,6 +402,7 @@ struct request_queue {
*/
unsigned int sg_timeout;
unsigned int sg_reserved_size;
+ unsigned char sgio_type;
int node;
#ifdef CONFIG_BLK_DEV_IO_TRACE
struct blk_trace *blk_trace;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 66216c1..1a26291 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -325,6 +325,7 @@ static inline int scsi_status_is_good(int status)
#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */
#define TYPE_RBC 0x0e
#define TYPE_OSD 0x11
+#define TYPE_MAX 0x1f
#define TYPE_NO_LUN 0x7f

/* SCSI protocols; these are taken from SPC-3 section 7.5 */
--
1.7.1