ALSA: hda - Add 3stack-automute model to AD1882 codec
[pandora-kernel.git] / block / ioctl.c
index ba15b2d..4476e0e 100644 (file)
@@ -13,7 +13,7 @@ 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 hd_struct *part, *lpart;
        struct blkpg_ioctl_arg a;
        struct blkpg_partition p;
        struct disk_part_iter piter;
@@ -36,8 +36,8 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                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) && 
+                       /* 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
@@ -91,6 +91,59 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                        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:
                        return -EINVAL;