{
struct block_device *bdevp;
struct gendisk *disk;
+ struct hd_struct *part;
struct blkpg_ioctl_arg a;
struct blkpg_partition p;
+ struct disk_part_iter piter;
long long start, length;
- int part;
- int i;
+ int partno;
int err;
if (!capable(CAP_SYS_ADMIN))
disk = bdev->bd_disk;
if (bdev != bdev->bd_contains)
return -EINVAL;
- part = p.pno;
- if (part <= 0 || part >= disk->minors)
+ partno = p.pno;
+ if (partno <= 0)
return -EINVAL;
switch (a.op) {
case BLKPG_ADD_PARTITION:
mutex_lock(&bdev->bd_mutex);
/* overlap? */
- for (i = 0; i < disk->minors - 1; i++) {
- struct hd_struct *s = disk->part[i];
-
- if (!s)
- continue;
- if (!(start+length <= s->start_sect ||
- start >= s->start_sect + s->nr_sects)) {
+ 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 */
- err = add_partition(disk, part, start, length, ADDPART_FLAG_NONE);
+ err = add_partition(disk, partno, start, length,
+ ADDPART_FLAG_NONE);
mutex_unlock(&bdev->bd_mutex);
return err;
case BLKPG_DEL_PARTITION:
- if (!disk->part[part-1])
+ part = disk_get_part(disk, partno);
+ if (!part)
return -ENXIO;
- bdevp = bdget_disk(disk, part);
+
+ 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);
invalidate_bdev(bdevp);
mutex_lock_nested(&bdev->bd_mutex, 1);
- delete_partition(disk, part);
+ delete_partition(disk, partno);
mutex_unlock(&bdev->bd_mutex);
mutex_unlock(&bdevp->bd_mutex);
bdput(bdevp);
struct gendisk *disk = bdev->bd_disk;
int res;
- if (disk->minors == 1 || bdev != bdev->bd_contains)
+ if (!disk_partitionable(disk) || bdev != bdev->bd_contains)
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
struct gendisk *disk, unsigned cmd, unsigned long arg)
{
int ret;
- if (disk->fops->unlocked_ioctl)
- return disk->fops->unlocked_ioctl(file, cmd, arg);
+ fmode_t mode = 0;
+ if (file) {
+ mode = file->f_mode;
+ if (file->f_flags & O_NDELAY)
+ mode |= FMODE_NDELAY_NOW;
+ }
+
+ return __blkdev_driver_ioctl(inode->i_bdev, mode, cmd, arg);
+}
+EXPORT_SYMBOL_GPL(blkdev_driver_ioctl);
+
+int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
+{
+ struct gendisk *disk = bdev->bd_disk;
+ int ret;
- if (disk->fops->ioctl) {
+ if (disk->fops->ioctl)
+ return disk->fops->ioctl(bdev, mode, cmd, arg);
+
+ if (disk->fops->locked_ioctl) {
lock_kernel();
- ret = disk->fops->ioctl(inode, file, cmd, arg);
+ ret = disk->fops->locked_ioctl(bdev, mode, cmd, arg);
unlock_kernel();
return ret;
}
return -ENOTTY;
}
-EXPORT_SYMBOL_GPL(blkdev_driver_ioctl);
+/*
+ * For the record: _GPL here is only because somebody decided to slap it
+ * on the previous export. Sheer idiocy, since it wasn't copyrightable
+ * at all and could be open-coded without any exports by anybody who cares.
+ */
+EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl);
/*
* always keep this in sync with compat_blkdev_ioctl() and