dm ioctl: make bio or request based device type immutable
[firefly-linux-kernel-4.4.55.git] / drivers / md / dm-ioctl.c
index feb64d65fbfb93cc38e142edcd9b682af502ff0d..4702f380cb456f10bad1389576b75774dab93845 100644 (file)
@@ -1189,6 +1189,21 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
                goto out;
        }
 
+       /* Protect md->type against concurrent table loads. */
+       dm_lock_md_type(md);
+       if (dm_get_md_type(md) == DM_TYPE_NONE)
+               /* Initial table load: acquire type of table. */
+               dm_set_md_type(md, dm_table_get_type(t));
+       else if (dm_get_md_type(md) != dm_table_get_type(t)) {
+               DMWARN("can't change device type after initial table load.");
+               dm_table_destroy(t);
+               dm_unlock_md_type(md);
+               r = -EINVAL;
+               goto out;
+       }
+       dm_unlock_md_type(md);
+
+       /* stage inactive table */
        down_write(&_hash_lock);
        hc = dm_get_mdptr(md);
        if (!hc || hc->md != md) {
@@ -1602,6 +1617,7 @@ static long dm_compat_ctl_ioctl(struct file *file, uint command, ulong u)
 #endif
 
 static const struct file_operations _ctl_fops = {
+       .open = nonseekable_open,
        .unlocked_ioctl  = dm_ctl_ioctl,
        .compat_ioctl = dm_compat_ctl_ioctl,
        .owner   = THIS_MODULE,