Merge tag 'block-5.9-2020-08-14' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / block / ioctl.c
index 6e827de..bdb3bbb 100644 (file)
 static int blkpg_do_ioctl(struct block_device *bdev,
                          struct blkpg_partition __user *upart, int op)
 {
-       struct block_device *bdevp;
-       struct gendisk *disk;
-       struct hd_struct *part, *lpart;
        struct blkpg_partition p;
-       struct disk_part_iter piter;
        long long start, length;
-       int partno;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
        if (copy_from_user(&p, upart, sizeof(struct blkpg_partition)))
                return -EFAULT;
-       disk = bdev->bd_disk;
        if (bdev != bdev->bd_contains)
                return -EINVAL;
-       partno = p.pno;
-       if (partno <= 0)
+
+       if (p.pno <= 0)
                return -EINVAL;
+
+       if (op == BLKPG_DEL_PARTITION)
+               return bdev_del_partition(bdev, p.pno);
+
+       start = p.start >> SECTOR_SHIFT;
+       length = p.length >> SECTOR_SHIFT;
+
+       /* check for fit in a hd_struct */
+       if (sizeof(sector_t) < sizeof(long long)) {
+               long pstart = start, plength = length;
+
+               if (pstart != start || plength != length || pstart < 0 ||
+                   plength < 0 || p.pno > 65535)
+                       return -EINVAL;
+       }
+
        switch (op) {
-               case BLKPG_ADD_PARTITION:
-                       start = p.start >> 9;
-                       length = p.length >> 9;
-                       /* check for fit in a hd_struct */
-                       if (sizeof(sector_t) == sizeof(long) &&
-                           sizeof(long long) > sizeof(long)) {
-                               long pstart = start, plength = length;
-                               if (pstart != start || plength != length
-                                   || pstart < 0 || plength < 0 || partno > 65535)
-                                       return -EINVAL;
-                       }
-                       /* check if partition is aligned to blocksize */
-                       if (p.start & (bdev_logical_block_size(bdev) - 1))
-                               return -EINVAL;
-
-                       mutex_lock(&bdev->bd_mutex);
-
-                       /* overlap? */
-                       disk_part_iter_init(&piter, disk,
-                                           DISK_PITER_INCL_EMPTY);
-                       while ((part = disk_part_iter_next(&piter))) {
-                               if (!(start + length <= part->start_sect ||
-                                     start >= part->start_sect + part->nr_sects)) {
-                                       disk_part_iter_exit(&piter);
-                                       mutex_unlock(&bdev->bd_mutex);
-                                       return -EBUSY;
-                               }
-                       }
-                       disk_part_iter_exit(&piter);
-
-                       /* all seems OK */
-                       part = add_partition(disk, partno, start, length,
-                                            ADDPART_FLAG_NONE, NULL);
-                       mutex_unlock(&bdev->bd_mutex);
-                       return PTR_ERR_OR_ZERO(part);
-               case BLKPG_DEL_PARTITION:
-                       part = disk_get_part(disk, partno);
-                       if (!part)
-                               return -ENXIO;
-
-                       bdevp = bdget(part_devt(part));
-                       disk_put_part(part);
-                       if (!bdevp)
-                               return -ENOMEM;
-
-                       mutex_lock(&bdevp->bd_mutex);
-                       if (bdevp->bd_openers) {
-                               mutex_unlock(&bdevp->bd_mutex);
-                               bdput(bdevp);
-                               return -EBUSY;
-                       }
-                       /* all seems OK */
-                       fsync_bdev(bdevp);
-                       invalidate_bdev(bdevp);
-
-                       mutex_lock_nested(&bdev->bd_mutex, 1);
-                       delete_partition(disk, partno);
-                       mutex_unlock(&bdev->bd_mutex);
-                       mutex_unlock(&bdevp->bd_mutex);
-                       bdput(bdevp);
-
-                       return 0;
-               case BLKPG_RESIZE_PARTITION:
-                       start = p.start >> 9;
-                       /* new length of partition in bytes */
-                       length = p.length >> 9;
-                       /* check for fit in a hd_struct */
-                       if (sizeof(sector_t) == sizeof(long) &&
-                           sizeof(long long) > sizeof(long)) {
-                               long pstart = start, plength = length;
-                               if (pstart != start || plength != length
-                                   || pstart < 0 || plength < 0)
-                                       return -EINVAL;
-                       }
-                       part = disk_get_part(disk, partno);
-                       if (!part)
-                               return -ENXIO;
-                       bdevp = bdget(part_devt(part));
-                       if (!bdevp) {
-                               disk_put_part(part);
-                               return -ENOMEM;
-                       }
-                       mutex_lock(&bdevp->bd_mutex);
-                       mutex_lock_nested(&bdev->bd_mutex, 1);
-                       if (start != part->start_sect) {
-                               mutex_unlock(&bdevp->bd_mutex);
-                               mutex_unlock(&bdev->bd_mutex);
-                               bdput(bdevp);
-                               disk_put_part(part);
-                               return -EINVAL;
-                       }
-                       /* overlap? */
-                       disk_part_iter_init(&piter, disk,
-                                           DISK_PITER_INCL_EMPTY);
-                       while ((lpart = disk_part_iter_next(&piter))) {
-                               if (lpart->partno != partno &&
-                                  !(start + length <= lpart->start_sect ||
-                                  start >= lpart->start_sect + lpart->nr_sects)
-                                  ) {
-                                       disk_part_iter_exit(&piter);
-                                       mutex_unlock(&bdevp->bd_mutex);
-                                       mutex_unlock(&bdev->bd_mutex);
-                                       bdput(bdevp);
-                                       disk_put_part(part);
-                                       return -EBUSY;
-                               }
-                       }
-                       disk_part_iter_exit(&piter);
-                       part_nr_sects_write(part, (sector_t)length);
-                       i_size_write(bdevp->bd_inode, p.length);
-                       mutex_unlock(&bdevp->bd_mutex);
-                       mutex_unlock(&bdev->bd_mutex);
-                       bdput(bdevp);
-                       disk_put_part(part);
-                       return 0;
-               default:
+       case BLKPG_ADD_PARTITION:
+               /* check if partition is aligned to blocksize */
+               if (p.start & (bdev_logical_block_size(bdev) - 1))
                        return -EINVAL;
+               return bdev_add_partition(bdev, p.pno, start, length);
+       case BLKPG_RESIZE_PARTITION:
+               return bdev_resize_partition(bdev, p.pno, start, length);
+       default:
+               return -EINVAL;
        }
 }
 
@@ -302,12 +204,12 @@ static int put_u64(u64 __user *argp, u64 val)
 }
 
 #ifdef CONFIG_COMPAT
-static int compat_put_long(compat_long_t *argp, long val)
+static int compat_put_long(compat_long_t __user *argp, long val)
 {
        return put_user(val, argp);
 }
 
-static int compat_put_ulong(compat_ulong_t *argp, compat_ulong_t val)
+static int compat_put_ulong(compat_ulong_t __user *argp, compat_ulong_t val)
 {
        return put_user(val, argp);
 }