aboutsummaryrefslogtreecommitdiffstats
path: root/block/bsg.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-14 16:15:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-14 16:15:14 -0400
commitdddec01eb8e2b56267b37a6f9f0997a64b4e0b2a (patch)
treeb6d8bfbce9abd105384b9d116499afbe306b9c22 /block/bsg.c
parent7daf705f362e349983e92037a198b8821db198af (diff)
parent32502b8413a77b54b9e19809404109590c32dfb7 (diff)
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/linux-2.6-block: (37 commits) splice: fix generic_file_splice_read() race with page invalidation ramfs: enable splice write drivers/block/pktcdvd.c: avoid useless memset cdrom: revert commit 22a9189 (cdrom: use kmalloced buffers instead of buffers on stack) scsi: sr avoids useless buffer allocation block: blk_rq_map_kern uses the bounce buffers for stack buffers block: add blk_queue_update_dma_pad DAC960: push down BKL pktcdvd: push BKL down into driver paride: push ioctl down into driver block: use get_unaligned_* helpers block: extend queue_flag bitops block: request_module(): use format string Add bvec_merge_data to handle stacked devices and ->merge_bvec() block: integrity flags can't use bit ops on unsigned short cmdfilter: extend default read filter sg: fix odd style (extra parenthesis) introduced by cmd filter patch block: add bounce support to blk_rq_map_user_iov cfq-iosched: get rid of enable_idle being unused warning allow userspace to modify scsi command filter on per device basis ...
Diffstat (limited to 'block/bsg.c')
-rw-r--r--block/bsg.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/block/bsg.c b/block/bsg.c
index 54d617f7df3e..93e757d7174b 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -44,11 +44,12 @@ struct bsg_device {
44 char name[BUS_ID_SIZE]; 44 char name[BUS_ID_SIZE];
45 int max_queue; 45 int max_queue;
46 unsigned long flags; 46 unsigned long flags;
47 struct blk_scsi_cmd_filter *cmd_filter;
48 mode_t *f_mode;
47}; 49};
48 50
49enum { 51enum {
50 BSG_F_BLOCK = 1, 52 BSG_F_BLOCK = 1,
51 BSG_F_WRITE_PERM = 2,
52}; 53};
53 54
54#define BSG_DEFAULT_CMDS 64 55#define BSG_DEFAULT_CMDS 64
@@ -172,7 +173,7 @@ unlock:
172} 173}
173 174
174static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, 175static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
175 struct sg_io_v4 *hdr, int has_write_perm) 176 struct sg_io_v4 *hdr, struct bsg_device *bd)
176{ 177{
177 if (hdr->request_len > BLK_MAX_CDB) { 178 if (hdr->request_len > BLK_MAX_CDB) {
178 rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL); 179 rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL);
@@ -185,7 +186,8 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
185 return -EFAULT; 186 return -EFAULT;
186 187
187 if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) { 188 if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) {
188 if (blk_verify_command(rq->cmd, has_write_perm)) 189 if (blk_cmd_filter_verify_command(bd->cmd_filter, rq->cmd,
190 bd->f_mode))
189 return -EPERM; 191 return -EPERM;
190 } else if (!capable(CAP_SYS_RAWIO)) 192 } else if (!capable(CAP_SYS_RAWIO))
191 return -EPERM; 193 return -EPERM;
@@ -263,8 +265,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr)
263 rq = blk_get_request(q, rw, GFP_KERNEL); 265 rq = blk_get_request(q, rw, GFP_KERNEL);
264 if (!rq) 266 if (!rq)
265 return ERR_PTR(-ENOMEM); 267 return ERR_PTR(-ENOMEM);
266 ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, test_bit(BSG_F_WRITE_PERM, 268 ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, bd);
267 &bd->flags));
268 if (ret) 269 if (ret)
269 goto out; 270 goto out;
270 271
@@ -566,12 +567,23 @@ static inline void bsg_set_block(struct bsg_device *bd, struct file *file)
566 set_bit(BSG_F_BLOCK, &bd->flags); 567 set_bit(BSG_F_BLOCK, &bd->flags);
567} 568}
568 569
569static inline void bsg_set_write_perm(struct bsg_device *bd, struct file *file) 570static void bsg_set_cmd_filter(struct bsg_device *bd,
571 struct file *file)
570{ 572{
571 if (file->f_mode & FMODE_WRITE) 573 struct inode *inode;
572 set_bit(BSG_F_WRITE_PERM, &bd->flags); 574 struct gendisk *disk;
573 else 575
574 clear_bit(BSG_F_WRITE_PERM, &bd->flags); 576 if (!file)
577 return;
578
579 inode = file->f_dentry->d_inode;
580 if (!inode)
581 return;
582
583 disk = inode->i_bdev->bd_disk;
584
585 bd->cmd_filter = &disk->cmd_filter;
586 bd->f_mode = &file->f_mode;
575} 587}
576 588
577/* 589/*
@@ -595,6 +607,8 @@ bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
595 dprintk("%s: read %Zd bytes\n", bd->name, count); 607 dprintk("%s: read %Zd bytes\n", bd->name, count);
596 608
597 bsg_set_block(bd, file); 609 bsg_set_block(bd, file);
610 bsg_set_cmd_filter(bd, file);
611
598 bytes_read = 0; 612 bytes_read = 0;
599 ret = __bsg_read(buf, count, bd, NULL, &bytes_read); 613 ret = __bsg_read(buf, count, bd, NULL, &bytes_read);
600 *ppos = bytes_read; 614 *ppos = bytes_read;
@@ -668,7 +682,7 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
668 dprintk("%s: write %Zd bytes\n", bd->name, count); 682 dprintk("%s: write %Zd bytes\n", bd->name, count);
669 683
670 bsg_set_block(bd, file); 684 bsg_set_block(bd, file);
671 bsg_set_write_perm(bd, file); 685 bsg_set_cmd_filter(bd, file);
672 686
673 bytes_written = 0; 687 bytes_written = 0;
674 ret = __bsg_write(bd, buf, count, &bytes_written); 688 ret = __bsg_write(bd, buf, count, &bytes_written);
@@ -772,7 +786,9 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
772 } 786 }
773 787
774 bd->queue = rq; 788 bd->queue = rq;
789
775 bsg_set_block(bd, file); 790 bsg_set_block(bd, file);
791 bsg_set_cmd_filter(bd, file);
776 792
777 atomic_set(&bd->ref_count, 1); 793 atomic_set(&bd->ref_count, 1);
778 mutex_lock(&bsg_mutex); 794 mutex_lock(&bsg_mutex);