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>
This commit is contained in:
committed by
Jens Axboe
parent
1941246dd9
commit
abf5439370
@@ -641,6 +641,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
|
||||
unsigned char cmnd[MAX_COMMAND_SIZE];
|
||||
int timeout;
|
||||
unsigned long ul_timeout;
|
||||
struct request_queue *q;
|
||||
|
||||
if (count < SZ_SG_IO_HDR)
|
||||
return -EINVAL;
|
||||
@@ -689,7 +690,9 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
|
||||
sg_remove_request(sfp, srp);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (read_only && !blk_verify_command(file, cmnd)) {
|
||||
q = sfp->parentdp->device->request_queue;
|
||||
if (read_only && blk_verify_command(&q->cmd_filter, cmnd,
|
||||
file->f_mode & FMODE_WRITE)) {
|
||||
sg_remove_request(sfp, srp);
|
||||
return -EPERM;
|
||||
}
|
||||
@@ -793,6 +796,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
|
||||
|
||||
if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
|
||||
return -ENXIO;
|
||||
|
||||
SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: %s, cmd=0x%x\n",
|
||||
sdp->disk->disk_name, (int) cmd_in));
|
||||
read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
|
||||
@@ -1057,11 +1061,14 @@ sg_ioctl(struct inode *inode, struct file *filp,
|
||||
return -ENODEV;
|
||||
if (read_only) {
|
||||
unsigned char opcode = WRITE_6;
|
||||
struct request_queue *q = sdp->device->request_queue;
|
||||
Scsi_Ioctl_Command __user *siocp = p;
|
||||
|
||||
if (copy_from_user(&opcode, siocp->data, 1))
|
||||
return -EFAULT;
|
||||
if (!blk_verify_command(filp, &opcode))
|
||||
if (blk_verify_command(&q->cmd_filter,
|
||||
&opcode,
|
||||
filp->f_mode & FMODE_WRITE))
|
||||
return -EPERM;
|
||||
}
|
||||
return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
|
||||
|
Reference in New Issue
Block a user