diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2008-08-16 01:10:05 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-08-27 03:50:19 -0400 |
commit | abf5439370491dd6fbb4fe1a7939680d2a9bc9d4 (patch) | |
tree | aa3630557fe4a4bc6313617f5770af30eec68515 /drivers | |
parent | 1941246dd98089dd637f44d3bd4f6cc1c61aa9e4 (diff) |
block: move cmdfilter from gendisk to request_queue
cmd_filter works only for the block layer SG_IO with SCSI block
devices. It breaks scsi/sg.c, bsg, and the block layer SG_IO with SCSI
character devices (such as st). We hit a kernel crash with them.
The problem is that cmd_filter code accesses to gendisk (having struct
blk_scsi_cmd_filter) via inode->i_bdev->bd_disk. It works for only
SCSI block device files. With character device files, inode->i_bdev
leads you to struct cdev. inode->i_bdev->bd_disk->blk_scsi_cmd_filter
isn't safe.
SCSI ULDs don't expose gendisk; they keep it private. bsg needs to be
independent on any protocols. We shouldn't change ULDs to expose their
gendisk.
This patch moves struct blk_scsi_cmd_filter from gendisk to
request_queue, a common object, which eveyone can access to.
The user interface doesn't change; users can change the filters via
/sys/block/. gendisk has a pointer to request_queue so the cmd_filter
code accesses to struct blk_scsi_cmd_filter.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/sg.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 3d36270a8b4..9d28b9f74d9 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -641,6 +641,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, | |||
641 | unsigned char cmnd[MAX_COMMAND_SIZE]; | 641 | unsigned char cmnd[MAX_COMMAND_SIZE]; |
642 | int timeout; | 642 | int timeout; |
643 | unsigned long ul_timeout; | 643 | unsigned long ul_timeout; |
644 | struct request_queue *q; | ||
644 | 645 | ||
645 | if (count < SZ_SG_IO_HDR) | 646 | if (count < SZ_SG_IO_HDR) |
646 | return -EINVAL; | 647 | return -EINVAL; |
@@ -689,7 +690,9 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, | |||
689 | sg_remove_request(sfp, srp); | 690 | sg_remove_request(sfp, srp); |
690 | return -EFAULT; | 691 | return -EFAULT; |
691 | } | 692 | } |
692 | if (read_only && !blk_verify_command(file, cmnd)) { | 693 | q = sfp->parentdp->device->request_queue; |
694 | if (read_only && blk_verify_command(&q->cmd_filter, cmnd, | ||
695 | file->f_mode & FMODE_WRITE)) { | ||
693 | sg_remove_request(sfp, srp); | 696 | sg_remove_request(sfp, srp); |
694 | return -EPERM; | 697 | return -EPERM; |
695 | } | 698 | } |
@@ -793,6 +796,7 @@ sg_ioctl(struct inode *inode, struct file *filp, | |||
793 | 796 | ||
794 | if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) | 797 | if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) |
795 | return -ENXIO; | 798 | return -ENXIO; |
799 | |||
796 | SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: %s, cmd=0x%x\n", | 800 | SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: %s, cmd=0x%x\n", |
797 | sdp->disk->disk_name, (int) cmd_in)); | 801 | sdp->disk->disk_name, (int) cmd_in)); |
798 | read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); | 802 | read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); |
@@ -1057,11 +1061,14 @@ sg_ioctl(struct inode *inode, struct file *filp, | |||
1057 | return -ENODEV; | 1061 | return -ENODEV; |
1058 | if (read_only) { | 1062 | if (read_only) { |
1059 | unsigned char opcode = WRITE_6; | 1063 | unsigned char opcode = WRITE_6; |
1064 | struct request_queue *q = sdp->device->request_queue; | ||
1060 | Scsi_Ioctl_Command __user *siocp = p; | 1065 | Scsi_Ioctl_Command __user *siocp = p; |
1061 | 1066 | ||
1062 | if (copy_from_user(&opcode, siocp->data, 1)) | 1067 | if (copy_from_user(&opcode, siocp->data, 1)) |
1063 | return -EFAULT; | 1068 | return -EFAULT; |
1064 | if (!blk_verify_command(filp, &opcode)) | 1069 | if (blk_verify_command(&q->cmd_filter, |
1070 | &opcode, | ||
1071 | filp->f_mode & FMODE_WRITE)) | ||
1065 | return -EPERM; | 1072 | return -EPERM; |
1066 | } | 1073 | } |
1067 | return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p); | 1074 | return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p); |