aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-08-16 01:10:05 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-08-27 03:50:19 -0400
commitabf5439370491dd6fbb4fe1a7939680d2a9bc9d4 (patch)
treeaa3630557fe4a4bc6313617f5770af30eec68515 /drivers
parent1941246dd98089dd637f44d3bd4f6cc1c61aa9e4 (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.c11
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);