]> www.infradead.org Git - users/hch/block.git/commitdiff
md: implement ->set_read_only to hook into BLKROSET processing
authorChristoph Hellwig <hch@lst.de>
Thu, 29 Oct 2020 12:29:07 +0000 (13:29 +0100)
committerChristoph Hellwig <hch@lst.de>
Sat, 14 Nov 2020 17:26:30 +0000 (18:26 +0100)
Implement the ->set_read_only method instead of parsing the actual
ioctl command.

Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/md/md.c

index 32e375d50fee170684d3503db9cf2dbcb535822d..fa31b71a72a35dc76c061db38b5c3b1889ea5336 100644 (file)
@@ -7477,7 +7477,6 @@ static inline bool md_ioctl_valid(unsigned int cmd)
 {
        switch (cmd) {
        case ADD_NEW_DISK:
-       case BLKROSET:
        case GET_ARRAY_INFO:
        case GET_BITMAP_FILE:
        case GET_DISK_INFO:
@@ -7504,7 +7503,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
        int err = 0;
        void __user *argp = (void __user *)arg;
        struct mddev *mddev = NULL;
-       int ro;
        bool did_set_md_closing = false;
 
        if (!md_ioctl_valid(cmd))
@@ -7684,35 +7682,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
                        goto unlock;
                }
                break;
-
-       case BLKROSET:
-               if (get_user(ro, (int __user *)(arg))) {
-                       err = -EFAULT;
-                       goto unlock;
-               }
-               err = -EINVAL;
-
-               /* if the bdev is going readonly the value of mddev->ro
-                * does not matter, no writes are coming
-                */
-               if (ro)
-                       goto unlock;
-
-               /* are we are already prepared for writes? */
-               if (mddev->ro != 1)
-                       goto unlock;
-
-               /* transitioning to readauto need only happen for
-                * arrays that call md_write_start
-                */
-               if (mddev->pers) {
-                       err = restart_array(mddev);
-                       if (err == 0) {
-                               mddev->ro = 2;
-                               set_disk_ro(mddev->gendisk, 0);
-                       }
-               }
-               goto unlock;
        }
 
        /*
@@ -7806,6 +7775,36 @@ static int md_compat_ioctl(struct block_device *bdev, fmode_t mode,
 }
 #endif /* CONFIG_COMPAT */
 
+static int md_set_read_only(struct block_device *bdev, bool ro)
+{
+       struct mddev *mddev = bdev->bd_disk->private_data;
+       int err;
+
+       err = mddev_lock(mddev);
+       if (err)
+               return err;
+
+       if (!mddev->raid_disks && !mddev->external) {
+               err = -ENODEV;
+               goto out_unlock;
+       }
+
+       /*
+        * Transitioning to read-auto need only happen for arrays that call
+        * md_write_start and which are not ready for writes yet.
+        */
+       if (!ro && mddev->ro == 1 && mddev->pers) {
+               err = restart_array(mddev);
+               if (err)
+                       goto out_unlock;
+               mddev->ro = 2;
+       }
+
+out_unlock:
+       mddev_unlock(mddev);
+       return err;
+}
+
 static int md_open(struct block_device *bdev, fmode_t mode)
 {
        /*
@@ -7883,6 +7882,7 @@ const struct block_device_operations md_fops =
 #endif
        .getgeo         = md_getgeo,
        .check_events   = md_check_events,
+       .set_read_only  = md_set_read_only,
 };
 
 static int md_thread(void *arg)