aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuangliang Zhao <guangliang@unitedstack.com>2013-09-23 23:25:36 -0400
committerJosh Durgin <josh.durgin@inktank.com>2014-06-10 21:09:24 -0400
commit131fd9f6fc89ad2cc993f80664d18ca49d6f8483 (patch)
treea5dd9b68bb868f62229f159fd64f3c4322b21edc
parent4e217b5dc87042b0fa52b11f491c4ded1863823a (diff)
rbd: add ioctl for rbd
When running the following commands: [root@ceph0 mnt]# blockdev --setro /dev/rbd1 [root@ceph0 mnt]# blockdev --getro /dev/rbd1 0 The block setro didn't take effect, it is because the rbd doesn't support ioctl of block driver. This resolves: http://tracker.ceph.com/issues/6265 Signed-off-by: Guangliang Zhao <guangliang@unitedstack.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r--drivers/block/rbd.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 8295b3afa8e0..1c88fba98c8e 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -559,10 +559,69 @@ static void rbd_release(struct gendisk *disk, fmode_t mode)
559 put_device(&rbd_dev->dev); 559 put_device(&rbd_dev->dev);
560} 560}
561 561
562static int rbd_ioctl_set_ro(struct rbd_device *rbd_dev, unsigned long arg)
563{
564 int val;
565 bool ro;
566
567 if (get_user(val, (int __user *)(arg)))
568 return -EFAULT;
569
570 ro = val ? true : false;
571 /* Snapshot doesn't allow to write*/
572 if (rbd_dev->spec->snap_id != CEPH_NOSNAP && !ro)
573 return -EROFS;
574
575 if (rbd_dev->mapping.read_only != ro) {
576 rbd_dev->mapping.read_only = ro;
577 set_disk_ro(rbd_dev->disk, ro ? 1 : 0);
578 }
579
580 return 0;
581}
582
583static int rbd_ioctl(struct block_device *bdev, fmode_t mode,
584 unsigned int cmd, unsigned long arg)
585{
586 struct rbd_device *rbd_dev = bdev->bd_disk->private_data;
587 int ret = 0;
588
589 spin_lock_irq(&rbd_dev->lock);
590 /* prevent others open this device */
591 if (rbd_dev->open_count > 1) {
592 ret = -EBUSY;
593 goto out;
594 }
595
596 switch (cmd) {
597 case BLKROSET:
598 ret = rbd_ioctl_set_ro(rbd_dev, arg);
599 break;
600 default:
601 ret = -ENOTTY;
602 }
603
604out:
605 spin_unlock_irq(&rbd_dev->lock);
606 return ret;
607}
608
609#ifdef CONFIG_COMPAT
610static int rbd_compat_ioctl(struct block_device *bdev, fmode_t mode,
611 unsigned int cmd, unsigned long arg)
612{
613 return rbd_ioctl(bdev, mode, cmd, arg);
614}
615#endif /* CONFIG_COMPAT */
616
562static const struct block_device_operations rbd_bd_ops = { 617static const struct block_device_operations rbd_bd_ops = {
563 .owner = THIS_MODULE, 618 .owner = THIS_MODULE,
564 .open = rbd_open, 619 .open = rbd_open,
565 .release = rbd_release, 620 .release = rbd_release,
621 .ioctl = rbd_ioctl,
622#ifdef CONFIG_COMPAT
623 .compat_ioctl = rbd_compat_ioctl,
624#endif
566}; 625};
567 626
568/* 627/*
@@ -3114,7 +3173,6 @@ static void rbd_request_fn(struct request_queue *q)
3114 __releases(q->queue_lock) __acquires(q->queue_lock) 3173 __releases(q->queue_lock) __acquires(q->queue_lock)
3115{ 3174{
3116 struct rbd_device *rbd_dev = q->queuedata; 3175 struct rbd_device *rbd_dev = q->queuedata;
3117 bool read_only = rbd_dev->mapping.read_only;
3118 struct request *rq; 3176 struct request *rq;
3119 int result; 3177 int result;
3120 3178
@@ -3150,7 +3208,7 @@ static void rbd_request_fn(struct request_queue *q)
3150 3208
3151 if (write_request) { 3209 if (write_request) {
3152 result = -EROFS; 3210 result = -EROFS;
3153 if (read_only) 3211 if (rbd_dev->mapping.read_only)
3154 goto end_request; 3212 goto end_request;
3155 rbd_assert(rbd_dev->spec->snap_id == CEPH_NOSNAP); 3213 rbd_assert(rbd_dev->spec->snap_id == CEPH_NOSNAP);
3156 } 3214 }