Merge branch 'master' into upstream
[linux-2.6.git] / block / ioctl.c
index 6e278474f9a8c1f0dcb70a560031fac870eb3220..309760b7e37f0c9a7d08ddcf047196dc1eb70875 100644 (file)
@@ -1,9 +1,11 @@
-#include <linux/sched.h>               /* for capable() */
+#include <linux/capability.h>
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
+#include <linux/hdreg.h>
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
 #include <linux/smp_lock.h>
+#include <linux/blktrace_api.h>
 #include <asm/uaccess.h>
 
 static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg)
@@ -41,9 +43,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                                        return -EINVAL;
                        }
                        /* partition number in use? */
-                       down(&bdev->bd_sem);
+                       mutex_lock(&bdev->bd_mutex);
                        if (disk->part[part - 1]) {
-                               up(&bdev->bd_sem);
+                               mutex_unlock(&bdev->bd_mutex);
                                return -EBUSY;
                        }
                        /* overlap? */
@@ -54,13 +56,13 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                                        continue;
                                if (!(start+length <= s->start_sect ||
                                      start >= s->start_sect + s->nr_sects)) {
-                                       up(&bdev->bd_sem);
+                                       mutex_unlock(&bdev->bd_mutex);
                                        return -EBUSY;
                                }
                        }
                        /* all seems OK */
                        add_partition(disk, part, start, length);
-                       up(&bdev->bd_sem);
+                       mutex_unlock(&bdev->bd_mutex);
                        return 0;
                case BLKPG_DEL_PARTITION:
                        if (!disk->part[part-1])
@@ -70,9 +72,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                        bdevp = bdget_disk(disk, part);
                        if (!bdevp)
                                return -ENOMEM;
-                       down(&bdevp->bd_sem);
+                       mutex_lock_nested(&bdevp->bd_mutex, BD_MUTEX_PARTITION);
                        if (bdevp->bd_openers) {
-                               up(&bdevp->bd_sem);
+                               mutex_unlock(&bdevp->bd_mutex);
                                bdput(bdevp);
                                return -EBUSY;
                        }
@@ -80,10 +82,10 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                        fsync_bdev(bdevp);
                        invalidate_bdev(bdevp, 0);
 
-                       down(&bdev->bd_sem);
+                       mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_WHOLE);
                        delete_partition(disk, part);
-                       up(&bdev->bd_sem);
-                       up(&bdevp->bd_sem);
+                       mutex_unlock(&bdev->bd_mutex);
+                       mutex_unlock(&bdevp->bd_mutex);
                        bdput(bdevp);
 
                        return 0;
@@ -101,10 +103,10 @@ static int blkdev_reread_part(struct block_device *bdev)
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
-       if (down_trylock(&bdev->bd_sem))
+       if (!mutex_trylock(&bdev->bd_mutex))
                return -EBUSY;
        res = rescan_partitions(disk, bdev);
-       up(&bdev->bd_sem);
+       mutex_unlock(&bdev->bd_mutex);
        return res;
 }
 
@@ -188,6 +190,11 @@ static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev,
                return put_ulong(arg, bdev->bd_inode->i_size >> 9);
        case BLKGETSIZE64:
                return put_u64(arg, bdev->bd_inode->i_size);
+       case BLKTRACESTART:
+       case BLKTRACESTOP:
+       case BLKTRACESETUP:
+       case BLKTRACETEARDOWN:
+               return blk_trace_ioctl(bdev, cmd, (char __user *) arg);
        }
        return -ENOIOCTLCMD;
 }
@@ -245,6 +252,27 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
                set_device_ro(bdev, n);
                unlock_kernel();
                return 0;
+       case HDIO_GETGEO: {
+               struct hd_geometry geo;
+
+               if (!arg)
+                       return -EINVAL;
+               if (!disk->fops->getgeo)
+                       return -ENOTTY;
+
+               /*
+                * We need to set the startsect first, the driver may
+                * want to override it.
+                */
+               geo.start = get_start_sect(bdev);
+               ret = disk->fops->getgeo(bdev, &geo);
+               if (ret)
+                       return ret;
+               if (copy_to_user((struct hd_geometry __user *)arg, &geo,
+                                       sizeof(geo)))
+                       return -EFAULT;
+               return 0;
+       }
        }
 
        lock_kernel();