compat_ioctl: reimplement SG_IO handling
[sfrench/cifs-2.6.git] / fs / compat_ioctl.c
index 10ba2d9e20bc5e030e2174d6c5192df6ace51f60..f279e77df2561cf89fa34fad9b4f19b1c987f8ef 100644 (file)
@@ -64,151 +64,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 }
 
 #ifdef CONFIG_BLOCK
-typedef struct sg_io_hdr32 {
-       compat_int_t interface_id;      /* [i] 'S' for SCSI generic (required) */
-       compat_int_t dxfer_direction;   /* [i] data transfer direction  */
-       unsigned char cmd_len;          /* [i] SCSI command length ( <= 16 bytes) */
-       unsigned char mx_sb_len;                /* [i] max length to write to sbp */
-       unsigned short iovec_count;     /* [i] 0 implies no scatter gather */
-       compat_uint_t dxfer_len;                /* [i] byte count of data transfer */
-       compat_uint_t dxferp;           /* [i], [*io] points to data transfer memory
-                                             or scatter gather list */
-       compat_uptr_t cmdp;             /* [i], [*i] points to command to perform */
-       compat_uptr_t sbp;              /* [i], [*o] points to sense_buffer memory */
-       compat_uint_t timeout;          /* [i] MAX_UINT->no timeout (unit: millisec) */
-       compat_uint_t flags;            /* [i] 0 -> default, see SG_FLAG... */
-       compat_int_t pack_id;           /* [i->o] unused internally (normally) */
-       compat_uptr_t usr_ptr;          /* [i->o] unused internally */
-       unsigned char status;           /* [o] scsi status */
-       unsigned char masked_status;    /* [o] shifted, masked scsi status */
-       unsigned char msg_status;               /* [o] messaging level data (optional) */
-       unsigned char sb_len_wr;                /* [o] byte count actually written to sbp */
-       unsigned short host_status;     /* [o] errors from host adapter */
-       unsigned short driver_status;   /* [o] errors from software driver */
-       compat_int_t resid;             /* [o] dxfer_len - actual_transferred */
-       compat_uint_t duration;         /* [o] time taken by cmd (unit: millisec) */
-       compat_uint_t info;             /* [o] auxiliary information */
-} sg_io_hdr32_t;  /* 64 bytes long (on sparc32) */
-
-typedef struct sg_iovec32 {
-       compat_uint_t iov_base;
-       compat_uint_t iov_len;
-} sg_iovec32_t;
-
-static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iovec_count)
-{
-       sg_iovec_t __user *iov = (sg_iovec_t __user *) (sgio + 1);
-       sg_iovec32_t __user *iov32 = dxferp;
-       int i;
-
-       for (i = 0; i < iovec_count; i++) {
-               u32 base, len;
-
-               if (get_user(base, &iov32[i].iov_base) ||
-                   get_user(len, &iov32[i].iov_len) ||
-                   put_user(compat_ptr(base), &iov[i].iov_base) ||
-                   put_user(len, &iov[i].iov_len))
-                       return -EFAULT;
-       }
-
-       if (put_user(iov, &sgio->dxferp))
-               return -EFAULT;
-       return 0;
-}
-
-static int sg_ioctl_trans(struct file *file, unsigned int cmd,
-                       sg_io_hdr32_t __user *sgio32)
-{
-       sg_io_hdr_t __user *sgio;
-       u16 iovec_count;
-       u32 data;
-       void __user *dxferp;
-       int err;
-       int interface_id;
-
-       if (get_user(interface_id, &sgio32->interface_id))
-               return -EFAULT;
-       if (interface_id != 'S')
-               return do_ioctl(file, cmd, (unsigned long)sgio32);
-
-       if (get_user(iovec_count, &sgio32->iovec_count))
-               return -EFAULT;
-
-       {
-               void __user *top = compat_alloc_user_space(0);
-               void __user *new = compat_alloc_user_space(sizeof(sg_io_hdr_t) +
-                                      (iovec_count * sizeof(sg_iovec_t)));
-               if (new > top)
-                       return -EINVAL;
-
-               sgio = new;
-       }
-
-       /* Ok, now construct.  */
-       if (copy_in_user(&sgio->interface_id, &sgio32->interface_id,
-                        (2 * sizeof(int)) +
-                        (2 * sizeof(unsigned char)) +
-                        (1 * sizeof(unsigned short)) +
-                        (1 * sizeof(unsigned int))))
-               return -EFAULT;
-
-       if (get_user(data, &sgio32->dxferp))
-               return -EFAULT;
-       dxferp = compat_ptr(data);
-       if (iovec_count) {
-               if (sg_build_iovec(sgio, dxferp, iovec_count))
-                       return -EFAULT;
-       } else {
-               if (put_user(dxferp, &sgio->dxferp))
-                       return -EFAULT;
-       }
-
-       {
-               unsigned char __user *cmdp;
-               unsigned char __user *sbp;
-
-               if (get_user(data, &sgio32->cmdp))
-                       return -EFAULT;
-               cmdp = compat_ptr(data);
-
-               if (get_user(data, &sgio32->sbp))
-                       return -EFAULT;
-               sbp = compat_ptr(data);
-
-               if (put_user(cmdp, &sgio->cmdp) ||
-                   put_user(sbp, &sgio->sbp))
-                       return -EFAULT;
-       }
-
-       if (copy_in_user(&sgio->timeout, &sgio32->timeout,
-                        3 * sizeof(int)))
-               return -EFAULT;
-
-       if (get_user(data, &sgio32->usr_ptr))
-               return -EFAULT;
-       if (put_user(compat_ptr(data), &sgio->usr_ptr))
-               return -EFAULT;
-
-       err = do_ioctl(file, cmd, (unsigned long) sgio);
-
-       if (err >= 0) {
-               void __user *datap;
-
-               if (copy_in_user(&sgio32->pack_id, &sgio->pack_id,
-                                sizeof(int)) ||
-                   get_user(datap, &sgio->usr_ptr) ||
-                   put_user((u32)(unsigned long)datap,
-                            &sgio32->usr_ptr) ||
-                   copy_in_user(&sgio32->status, &sgio->status,
-                                (4 * sizeof(unsigned char)) +
-                                (2 * sizeof(unsigned short)) +
-                                (3 * sizeof(int))))
-                       err = -EFAULT;
-       }
-
-       return err;
-}
-
 struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
        char req_state;
        char orphan;
@@ -358,6 +213,7 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI)
 #endif
 #ifdef CONFIG_BLOCK
 /* SG stuff */
+COMPATIBLE_IOCTL(SG_IO)
 COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
 COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
 COMPATIBLE_IOCTL(SG_EMULATED_HOST)
@@ -435,8 +291,6 @@ static long do_ioctl_trans(unsigned int cmd,
        case PPPIOCSACTIVE32:
                return ppp_sock_fprog_ioctl_trans(file, cmd, argp);
 #ifdef CONFIG_BLOCK
-       case SG_IO:
-               return sg_ioctl_trans(file, cmd, argp);
        case SG_GET_REQUEST_TABLE:
                return sg_grt_trans(file, cmd, argp);
 #endif