[SCSI] block: fix the partial mappings with struct rq_map_data
[safe/jmp/linux-2.6] / block / compat_ioctl.c
index 5b3db06..f87615d 100644 (file)
@@ -177,7 +177,7 @@ struct compat_blkpg_ioctl_arg {
        compat_caddr_t data;
 };
 
-static int compat_blkpg_ioctl(struct inode *inode, struct file *file,
+static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
                unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
 {
        struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
@@ -196,7 +196,7 @@ static int compat_blkpg_ioctl(struct inode *inode, struct file *file,
        if (err)
                return err;
 
-       return blkdev_ioctl(inode, file, cmd, (unsigned long)a);
+       return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
 }
 
 #define BLKBSZGET_32           _IOR(0x12, 112, int)
@@ -582,8 +582,6 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
 static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
                        unsigned cmd, unsigned long arg)
 {
-       int ret;
-
        switch (cmd) {
        case HDIO_GET_UNMASKINTR:
        case HDIO_GET_MULTCOUNT:
@@ -679,6 +677,29 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
        case DVD_WRITE_STRUCT:
        case DVD_AUTH:
                arg = (unsigned long)compat_ptr(arg);
+       /* These intepret arg as an unsigned long, not as a pointer,
+        * so we must not do compat_ptr() conversion. */
+       case HDIO_SET_MULTCOUNT:
+       case HDIO_SET_UNMASKINTR:
+       case HDIO_SET_KEEPSETTINGS:
+       case HDIO_SET_32BIT:
+       case HDIO_SET_NOWERR:
+       case HDIO_SET_DMA:
+       case HDIO_SET_PIO_MODE:
+       case HDIO_SET_NICE:
+       case HDIO_SET_WCACHE:
+       case HDIO_SET_ACOUSTIC:
+       case HDIO_SET_BUSSTATE:
+       case HDIO_SET_ADDRESS:
+       case CDROMEJECT_SW:
+       case CDROM_SET_OPTIONS:
+       case CDROM_CLEAR_OPTIONS:
+       case CDROM_SELECT_SPEED:
+       case CDROM_SELECT_DISC:
+       case CDROM_MEDIA_CHANGED:
+       case CDROM_DRIVE_STATUS:
+       case CDROM_LOCKDOOR:
+       case CDROM_DEBUG:
                break;
        default:
                /* unknown ioctl number */
@@ -701,8 +722,14 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        struct backing_dev_info *bdi;
        loff_t size;
 
+       /*
+        * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
+        * to updated it before every ioctl.
+        */
        if (file->f_flags & O_NDELAY)
-               mode |= FMODE_NDELAY_NOW;
+               mode |= FMODE_NDELAY;
+       else
+               mode &= ~FMODE_NDELAY;
 
        switch (cmd) {
        case HDIO_GETGEO:
@@ -715,13 +742,13 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
         * but we call blkdev_ioctl, which gets the lock for us
         */
        case BLKRRPART:
-               return blkdev_ioctl(inode, file, cmd,
+               return blkdev_ioctl(bdev, mode, cmd,
                                (unsigned long)compat_ptr(arg));
        case BLKBSZSET_32:
-               return blkdev_ioctl(inode, file, BLKBSZSET,
+               return blkdev_ioctl(bdev, mode, BLKBSZSET,
                                (unsigned long)compat_ptr(arg));
        case BLKPG:
-               return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg));
+               return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
        case BLKRAGET:
        case BLKFRAGET:
                if (!arg)
@@ -747,9 +774,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                bdi = blk_get_backing_dev_info(bdev);
                if (bdi == NULL)
                        return -ENOTTY;
-               lock_kernel();
                bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
-               unlock_kernel();
                return 0;
        case BLKGETSIZE:
                size = bdev->bd_inode->i_size;