|
|
@@ -559,10 +559,69 @@ static void rbd_release(struct gendisk *disk, fmode_t mode)
|
|
|
put_device(&rbd_dev->dev);
|
|
|
}
|
|
|
|
|
|
+static int rbd_ioctl_set_ro(struct rbd_device *rbd_dev, unsigned long arg)
|
|
|
+{
|
|
|
+ int val;
|
|
|
+ bool ro;
|
|
|
+
|
|
|
+ if (get_user(val, (int __user *)(arg)))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ ro = val ? true : false;
|
|
|
+ /* Snapshot doesn't allow to write*/
|
|
|
+ if (rbd_dev->spec->snap_id != CEPH_NOSNAP && !ro)
|
|
|
+ return -EROFS;
|
|
|
+
|
|
|
+ if (rbd_dev->mapping.read_only != ro) {
|
|
|
+ rbd_dev->mapping.read_only = ro;
|
|
|
+ set_disk_ro(rbd_dev->disk, ro ? 1 : 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int rbd_ioctl(struct block_device *bdev, fmode_t mode,
|
|
|
+ unsigned int cmd, unsigned long arg)
|
|
|
+{
|
|
|
+ struct rbd_device *rbd_dev = bdev->bd_disk->private_data;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ spin_lock_irq(&rbd_dev->lock);
|
|
|
+ /* prevent others open this device */
|
|
|
+ if (rbd_dev->open_count > 1) {
|
|
|
+ ret = -EBUSY;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (cmd) {
|
|
|
+ case BLKROSET:
|
|
|
+ ret = rbd_ioctl_set_ro(rbd_dev, arg);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ret = -ENOTTY;
|
|
|
+ }
|
|
|
+
|
|
|
+out:
|
|
|
+ spin_unlock_irq(&rbd_dev->lock);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
+static int rbd_compat_ioctl(struct block_device *bdev, fmode_t mode,
|
|
|
+ unsigned int cmd, unsigned long arg)
|
|
|
+{
|
|
|
+ return rbd_ioctl(bdev, mode, cmd, arg);
|
|
|
+}
|
|
|
+#endif /* CONFIG_COMPAT */
|
|
|
+
|
|
|
static const struct block_device_operations rbd_bd_ops = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.open = rbd_open,
|
|
|
.release = rbd_release,
|
|
|
+ .ioctl = rbd_ioctl,
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
+ .compat_ioctl = rbd_compat_ioctl,
|
|
|
+#endif
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
@@ -3114,7 +3173,6 @@ static void rbd_request_fn(struct request_queue *q)
|
|
|
__releases(q->queue_lock) __acquires(q->queue_lock)
|
|
|
{
|
|
|
struct rbd_device *rbd_dev = q->queuedata;
|
|
|
- bool read_only = rbd_dev->mapping.read_only;
|
|
|
struct request *rq;
|
|
|
int result;
|
|
|
|
|
|
@@ -3150,7 +3208,7 @@ static void rbd_request_fn(struct request_queue *q)
|
|
|
|
|
|
if (write_request) {
|
|
|
result = -EROFS;
|
|
|
- if (read_only)
|
|
|
+ if (rbd_dev->mapping.read_only)
|
|
|
goto end_request;
|
|
|
rbd_assert(rbd_dev->spec->snap_id == CEPH_NOSNAP);
|
|
|
}
|