]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - block/ioctl.c
[PATCH] introduce __blkdev_driver_ioctl()
[linux-2.6-omap-h63xx.git] / block / ioctl.c
index 342298bb6080155d768f247937e0a31fd79eff56..9a26ace6d04292b26ad4362a4956f7e3fbc01386 100644 (file)
@@ -12,11 +12,12 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
 {
        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))
@@ -28,8 +29,8 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
        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:
@@ -43,36 +44,37 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                                    || pstart < 0 || plength < 0)
                                        return -EINVAL;
                        }
-                       /* partition number in use? */
+
                        mutex_lock(&bdev->bd_mutex);
-                       if (disk->part[part - 1]) {
-                               mutex_unlock(&bdev->bd_mutex);
-                               return -EBUSY;
-                       }
-                       /* 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)) {
+                       /* 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 */
-                       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])
-                               return -ENXIO;
-                       if (disk->part[part - 1]->nr_sects == 0)
+                       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);
@@ -84,7 +86,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                        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);
@@ -100,7 +102,7 @@ static int blkdev_reread_part(struct block_device *bdev)
        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;
@@ -161,7 +163,7 @@ static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
                        bio->bi_size = len << 9;
                        len = 0;
                }
-               submit_bio(WRITE_DISCARD, bio);
+               submit_bio(DISCARD_NOBARRIER, bio);
 
                wait_for_completion(&wait);
 
@@ -281,6 +283,37 @@ int blkdev_driver_ioctl(struct inode *inode, struct file *file,
 }
 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;
+       /* you bet it'll go away by the end of patch series */
+       struct file fake_file = {};
+       struct dentry fake_dentry = {};
+       fake_file.f_mode = mode;
+       fake_file.f_path.dentry = &fake_dentry;
+       fake_dentry.d_inode = bdev->bd_inode;
+
+       if (disk->fops->unlocked_ioctl)
+               return disk->fops->unlocked_ioctl(&fake_file, cmd, arg);
+
+       if (disk->fops->ioctl) {
+               lock_kernel();
+               ret = disk->fops->ioctl(bdev->bd_inode, &fake_file, cmd, arg);
+               unlock_kernel();
+               return ret;
+       }
+
+       return -ENOTTY;
+}
+/*
+ * 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
  * compat_blkdev_locked_ioctl()