linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: must-fix list, v5
       [not found]       ` <20030528215551.GB255@elf.ucw.cz.suse.lists.linux.kernel>
@ 2003-05-29  9:17         ` Andi Kleen
  2003-05-29  9:32           ` David S. Miller
  0 siblings, 1 reply; 34+ messages in thread
From: Andi Kleen @ 2003-05-29  9:17 UTC (permalink / raw)
  To: Pavel Machek; +Cc: akpm, davem, linux-kernel

Pavel Machek <pavel@suse.cz> writes:

> +	kiov = (sg_iovec_t *) sgp->dxferp;
> +	for (i = 0; i < sgp->iovec_count; i++) {
> +		u32 iov_base32;
> +		if (__get_user(iov_base32, &uiov->iov_base) ||
> +		    __get_user(kiov->iov_len, &uiov->iov_len))
> +			return -EFAULT;
> +		if (verify_area(VERIFY_WRITE, compat_ptr(iov_base32), kiov->iov_len))
> +			return -EFAULT;
> +		kiov->iov_base = compat_ptr(iov_base32);


This part won't work on sparc64 because it has separate address spaces
for user/kernel. I did it this way for x86-64 because I didn't realize
the sparc64 problem yet and it works fine there. For sparc64 it needs to be 
converted to compat_alloc_user_space() (see net/compat.c for an example) 
or to alloc/copy the payload again.  The first is prefered.

Pavel you would need to fix this first, otherwise Ben Collins and DaveM
will be unhappy as soon as they want to burn a CD.

> +	} else {
> +		err = verify_area(VERIFY_WRITE, compat_ptr(dxferp32), sg_io64.dxfer_len);
> +		if (err) 
> +			goto out;
> +
> +		sg_io64.dxferp = compat_ptr(dxferp32); 
> +	}

Same here.

t_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba);
> +		err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr);
> +		err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen);
> +		if (err)
> +			return -EFAULT;
> +		if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdread.cdread_buflen))
> +			return -EFAULT;
> +		cdread.cdread_bufaddr = compat_ptr(addr);

Same here.

> +		err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf);
> +		if (err)
> +			return -EFAULT;
> +		
> +
> +		if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdreadaudio.nframes*2352))
> +			return -EFAULT;

And here.

	err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer);
> +		err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
> +		if (err)
> +			return -EFAULT;
> +		if (verify_area(VERIFY_WRITE, compat_ptr(addr), cgc.buflen))
> +			return -EFAULT;
> +		cgc.buffer = compat_ptr(addr);

And here

> +	if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) {
> +		iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
> +	} else {
> +		iobuf.buffer = compat_ptr(iobuf32.buffer);
> +		if (verify_area(VERIFY_WRITE, iobuf.buffer, iobuf.length))
> +			return -EINVAL;
> +	}

And here.

> +	if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) {
> +		sioc.arg = (void*)(unsigned long)sioc32.arg;
> +        } else {
> +		sioc.arg = compat_ptr(sioc32.arg);
> +		if (verify_area(VERIFY_WRITE, sioc.arg, sioc32.length))
> +			return -EFAULT;
> +        }
> +        
> +        old_fs = get_fs(); set_fs (KERNEL_DS);
> +        err = sys_ioctl (fd, cmd, (unsigned long)&sioc);	

And here

> +
> +	if (get_user(karg.start, &uarg->start) 		||
> +	    get_user(karg.length, &uarg->length)	||
> +	    get_user(tmp, &uarg->ptr))
> +		return -EFAULT;
> +
> +	karg.ptr = compat_ptr(tmp); 
> +	if (verify_area(VERIFY_WRITE, karg.ptr, karg.length))
> +		return -EFAULT;

And here.
> +
> +	set_fs(KERNEL_DS);
> +	if (MEMREADOOB32 == cmd) 
> +		ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg);
> +	else if (MEMWRITEOOB32 == cmd)
> +		ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg);
> +	else
> +		ret = -EINVAL;
> +	set_fs(old_fs);

-Andi

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29  9:17         ` must-fix list, v5 Andi Kleen
@ 2003-05-29  9:32           ` David S. Miller
  2003-05-29  9:46             ` Pavel Machek
                               ` (3 more replies)
  0 siblings, 4 replies; 34+ messages in thread
From: David S. Miller @ 2003-05-29  9:32 UTC (permalink / raw)
  To: ak; +Cc: pavel, akpm, linux-kernel

   From: Andi Kleen <ak@suse.de>
   Date: 29 May 2003 11:17:36 +0200

   This part won't work on sparc64 because it has separate address spaces
   for user/kernel.

Yes, in fact I happen to be working in this area hold on...

I'm redoing Andi's x86_64 ioctl32 bug fixes more cleanly
for sparc64 by instead using alloc_user_space().

Sorry Andi, I just couldn't bring myself to allow those bogus
artificial limits you added just to fix these bugs... :-)

This work also pointed out many bugs in this area which should
be fixed by my stuff. (CDROMREAD* ioctls don't take struct cdrom_read
they take struct cdrom_msf which is compatible, struct
cdrom_generic_command32 was missing some members, etc. etc.)

This is a 2.4.x patch but should be easy to push over to the 2.5.x
ioctl stuff using the appropriate compat types.

--- arch/sparc64/kernel/ioctl32.c.~1~	Wed May 28 23:02:08 2003
+++ arch/sparc64/kernel/ioctl32.c	Thu May 29 02:26:02 2003
@@ -555,69 +555,38 @@ static int dev_ifconf(unsigned int fd, u
 	return err;
 }
 
-static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+static __inline__ void *alloc_user_space(long len)
 {
-	struct ifreq ifr;
-	mm_segment_t old_fs;
-	int err, len;
-	u32 data, ethcmd;
-	
-	if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
-		return -EFAULT;
-	ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
-	if (!ifr.ifr_data)
-		return -EAGAIN;
+	struct pt_regs *regs = current->thread.kregs;
+	unsigned long usp = regs->u_regs[UREG_I6];
 
-	__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+	if (!(current->thread.flags & SPARC_FLAG_32BIT))
+		usp += STACK_BIAS;
 
-	if (get_user(ethcmd, (u32 *)A(data))) {
-		err = -EFAULT;
-		goto out;
-	}
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:	len = sizeof(struct ethtool_drvinfo); break;
-	case ETHTOOL_GMSGLVL:
-	case ETHTOOL_SMSGLVL:
-	case ETHTOOL_GLINK:
-	case ETHTOOL_NWAY_RST:	len = sizeof(struct ethtool_value); break;
-	case ETHTOOL_GREGS: {
-		struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data);
-		/* darned variable size arguments */
-		if (get_user(len, (u32 *)&regaddr->len)) {
-			err = -EFAULT;
-			goto out;
-		}
-		len += sizeof(struct ethtool_regs);
-		break;
-	}
-	case ETHTOOL_GSET:
-	case ETHTOOL_SSET:	len = sizeof(struct ethtool_cmd); break;
-	default:
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	return (void *) (usp - len);
+}
 
-	if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) {
-		err = -EFAULT;
-		goto out;
-	}
+static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq *ifr;
+	struct ifreq32 *ifr32;
+	u32 data;
+	void *datap;
+	
+	ifr = alloc_user_space(sizeof(*ifr));
+	ifr32 = (struct ifreq32 *) arg;
 
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
-	set_fs (old_fs);
-	if (!err) {
-		u32 data;
+	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
+		return -EFAULT;
 
-		__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
-		len = copy_to_user((char *)A(data), ifr.ifr_data, len);
-		if (len)
-			err = -EFAULT;
-	}
+	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
+		return -EFAULT;
 
-out:
-	free_page((unsigned long)ifr.ifr_data);
-	return err;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &ifr->ifr_ifru.ifru_data))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long) ifr);
 }
 
 static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
@@ -672,17 +641,6 @@ out:
 	return err;
 }
 
-static __inline__ void *alloc_user_space(long len)
-{
-	struct pt_regs *regs = current->thread.kregs;
-	unsigned long usp = regs->u_regs[UREG_I6];
-
-	if (!(current->thread.flags & SPARC_FLAG_32BIT))
-		usp += STACK_BIAS;
-
-	return (void *) (usp - len);
-}
-
 static int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq *u_ifreq64;
@@ -1046,61 +1004,113 @@ struct fb_cmap32 {
 	__kernel_caddr_t32	transp;
 };
 
-static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int do_cmap_ptr(__u16 **ptr64, __u32 *ptr32)
 {
-	mm_segment_t old_fs = get_fs();
-	u32 red = 0, green = 0, blue = 0, transp = 0;
+	__u32 data;
+	void *datap;
+
+	if (get_user(data, ptr32))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, ptr64))
+		return -EFAULT;
+	return 0;
+}
+
+static int fb_getput_cmap(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct fb_cmap *cmap;
+	struct fb_cmap32 *cmap32;
+	int err;
+
+	cmap = alloc_user_space(sizeof(*cmap));
+	cmap32 = (struct fb_cmap32 *) arg;
+
+	if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32)))
+		return -EFAULT;
+
+	if (do_cmap_ptr(&cmap->red, &cmap32->red) ||
+	    do_cmap_ptr(&cmap->green, &cmap32->green) ||
+	    do_cmap_ptr(&cmap->blue, &cmap32->blue) ||
+	    do_cmap_ptr(&cmap->transp, &cmap32->transp))
+		return -EFAULT;
+
+	err = sys_ioctl(fd, cmd, (unsigned long) cmap);
+
+	if (!err) {
+		if (copy_in_user(&cmap32->start,
+				 &cmap->start,
+				 2 * sizeof(__u32)))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
+				  struct fb_fix_screeninfo32 *fix32)
+{
+	__u32 data;
+	int err;
+
+	err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id));
+
+	data = (__u32) (unsigned long) fix->smem_start;
+	err |= put_user(data, &fix32->smem_start);
+
+	err |= put_user(fix->smem_len, &fix32->smem_len);
+	err |= put_user(fix->type, &fix32->type);
+	err |= put_user(fix->type_aux, &fix32->type_aux);
+	err |= put_user(fix->visual, &fix32->visual);
+	err |= put_user(fix->xpanstep, &fix32->xpanstep);
+	err |= put_user(fix->ypanstep, &fix32->ypanstep);
+	err |= put_user(fix->ywrapstep, &fix32->ywrapstep);
+	err |= put_user(fix->line_length, &fix32->line_length);
+
+	data = (__u32) (unsigned long) fix->mmio_start;
+	err |= put_user(data, &fix32->mmio_start);
+
+	err |= put_user(fix->mmio_len, &fix32->mmio_len);
+	err |= put_user(fix->accel, &fix32->accel);
+	err |= copy_to_user(fix32->reserved, fix->reserved,
+			    sizeof(fix->reserved));
+
+	return err;
+}
+
+static int fb_get_fscreeninfo(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs;
 	struct fb_fix_screeninfo fix;
-	struct fb_cmap cmap;
-	void *karg;
-	int err = 0;
+	struct fb_fix_screeninfo32 *fix32;
+	int err;
+
+	fix32 = (struct fb_fix_screeninfo32 *) arg;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long) &fix);
+	set_fs(old_fs);
+
+	if (!err)
+		err = do_fscreeninfo_to_user(&fix, fix32);
+
+	return err;
+}
+
+static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	int err;
 
-	memset(&cmap, 0, sizeof(cmap));
 	switch (cmd) {
 	case FBIOGET_FSCREENINFO:
-		karg = &fix;
+		err = fb_get_fscreeninfo(fd,cmd, arg);
 		break;
+
 	case FBIOGETCMAP:
 	case FBIOPUTCMAP:
-		karg = &cmap;
-		err = __get_user(cmap.start, &((struct fb_cmap32 *)arg)->start);
-		err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len);
-		err |= __get_user(red, &((struct fb_cmap32 *)arg)->red);
-		err |= __get_user(green, &((struct fb_cmap32 *)arg)->green);
-		err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue);
-		err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp);
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
-		err = -ENOMEM;
-		cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.red)
-			goto out;
-		cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.green)
-			goto out;
-		cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.blue)
-			goto out;
-		if (transp) {
-			cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-			if (!cmap.transp)
-				goto out;
-		}
-			
-		if (cmd == FBIOGETCMAP)
-			break;
-
-		err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16));
-		err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16));
-		err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16));
-		if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16));
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
+		err = fb_getput_cmap(fd, cmd, arg);
 		break;
+
 	default:
 		do {
 			static int count;
@@ -1109,47 +1119,10 @@ static int fb_ioctl_trans(unsigned int f
 				       "cmd(%08x) arg(%08lx)\n",
 				       __FUNCTION__, fd, cmd, arg);
 		} while(0);
-		return -ENOSYS;
-	}
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)karg);
-	set_fs(old_fs);
-	if (err)
-		goto out;
-	switch (cmd) {
-	case FBIOGET_FSCREENINFO:
-		err = __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->id, (char *)fix.id, sizeof(fix.id));
-		err |= __put_user((__u32)(unsigned long)fix.smem_start, &((struct fb_fix_screeninfo32 *)arg)->smem_start);
-		err |= __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)arg)->smem_len);
-		err |= __put_user(fix.type, &((struct fb_fix_screeninfo32 *)arg)->type);
-		err |= __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)arg)->type_aux);
-		err |= __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)arg)->visual);
-		err |= __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)arg)->xpanstep);
-		err |= __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)arg)->ypanstep);
-		err |= __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)arg)->ywrapstep);
-		err |= __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)arg)->line_length);
-		err |= __put_user((__u32)(unsigned long)fix.mmio_start, &((struct fb_fix_screeninfo32 *)arg)->mmio_start);
-		err |= __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)arg)->mmio_len);
-		err |= __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)arg)->accel);
-		err |= __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->reserved, (char *)fix.reserved, sizeof(fix.reserved));
+		err = -ENOSYS;
 		break;
-	case FBIOGETCMAP:
-		err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16));
-		err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16));
-		err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16));
-		if (cmap.transp)
-			err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16));
-		break;
-	case FBIOPUTCMAP:
-		break;
-	}
-	if (err)
-		err = -EFAULT;
+	};
 
-out:	if (cmap.red) kfree(cmap.red);
-	if (cmap.green) kfree(cmap.green);
-	if (cmap.blue) kfree(cmap.blue);
-	if (cmap.transp) kfree(cmap.transp);
 	return err;
 }
 
@@ -1513,200 +1486,118 @@ typedef struct sg_iovec32 {
 	u32 iov_len;
 } sg_iovec32_t;
 
-static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
+static int sg_build_iovec(sg_io_hdr_t *sgio, void *dxferp, u16 iovec_count)
 {
-	sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32);
-	sg_iovec_t *kiov;
+	sg_iovec_t *iov = (sg_iovec_t *) (sgio + 1);
+	sg_iovec32_t *iov32 = dxferp;
 	int i;
 
-	sgp->dxferp = kmalloc(sgp->iovec_count *
-			      sizeof(sg_iovec_t), GFP_KERNEL);
-	if (!sgp->dxferp)
-		return -ENOMEM;
-	memset(sgp->dxferp, 0,
-	       sgp->iovec_count * sizeof(sg_iovec_t));
-
-	kiov = (sg_iovec_t *) sgp->dxferp;
-	for (i = 0; i < sgp->iovec_count; i++) {
-		u32 iov_base32;
-		if (__get_user(iov_base32, &uiov->iov_base) ||
-		    __get_user(kiov->iov_len, &uiov->iov_len))
-			return -EFAULT;
+	for (i = 0; i < iovec_count; i++) {
+		u32 base, len;
 
-		kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL);
-		if (!kiov->iov_base)
-			return -ENOMEM;
-		if (copy_from_user(kiov->iov_base,
-				   (void *) A(iov_base32),
-				   kiov->iov_len))
+		if (get_user(base, &iov32[i].iov_base) ||
+		    get_user(len, &iov32[i].iov_len) ||
+		    put_user((void *)(unsigned long)base, &iov[i].iov_base) ||
+		    put_user(len, &iov[i].iov_len))
 			return -EFAULT;
-
-		uiov++;
-		kiov++;
 	}
 
 	return 0;
 }
 
-static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
+static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32);
-	sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
-	int i;
+	sg_io_hdr_t *sgio;
+	sg_io_hdr32_t *sgio32;
+	u16 iovec_count;
+	u32 data;
+	void *dxferp;
+	int err;
 
-	for (i = 0; i < sgp->iovec_count; i++) {
-		u32 iov_base32;
+	sgio32 = (sg_io_hdr32_t *) arg;
+	if (get_user(iovec_count, &sgio32->iovec_count))
+		return -EFAULT;
 
-		if (__get_user(iov_base32, &uiov->iov_base))
-			return -EFAULT;
+	{
+		void *new, *top;
 
-		if (copy_to_user((void *) A(iov_base32),
-				 kiov->iov_base,
-				 kiov->iov_len))
-			return -EFAULT;
+		top = alloc_user_space(0);
+		new = alloc_user_space(sizeof(sg_io_hdr_t) +
+				       (iovec_count *
+					sizeof(sg_iovec_t)));
+		if (new > top)
+			return -EINVAL;
 
-		uiov++;
-		kiov++;
+		sgio = new;
 	}
 
-	return 0;
-}
-
-static void free_sg_iovec(sg_io_hdr_t *sgp)
-{
-	sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
-	int i;
+	/* 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;
 
-	for (i = 0; i < sgp->iovec_count; i++) {
-		if (kiov->iov_base) {
-			kfree(kiov->iov_base);
-			kiov->iov_base = NULL;
-		}
-		kiov++;
+	if (get_user(data, &sgio32->dxferp))
+		return -EFAULT;
+	dxferp = (void *) (unsigned long) data;
+	if (iovec_count) {
+		if (sg_build_iovec(sgio, dxferp, iovec_count))
+			return -EFAULT;
+	} else {
+		if (put_user(dxferp, &sgio->dxferp))
+			return -EFAULT;
 	}
-	kfree(sgp->dxferp);
-	sgp->dxferp = NULL;
-}
 
-static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	sg_io_hdr32_t *sg_io32;
-	sg_io_hdr_t sg_io64;
-	u32 dxferp32, cmdp32, sbp32;
-	mm_segment_t old_fs;
-	int err = 0;
+	{
+		unsigned char *cmdp, *sbp;
 
-	sg_io32 = (sg_io_hdr32_t *)arg;
-	err = __get_user(sg_io64.interface_id, &sg_io32->interface_id);
-	err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction);
-	err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len);
-	err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len);
-	err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count);
-	err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len);
-	err |= __get_user(sg_io64.timeout, &sg_io32->timeout);
-	err |= __get_user(sg_io64.flags, &sg_io32->flags);
-	err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id);
-
-	sg_io64.dxferp = NULL;
-	sg_io64.cmdp = NULL;
-	sg_io64.sbp = NULL;
-
-	err |= __get_user(cmdp32, &sg_io32->cmdp);
-	sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
-	if (!sg_io64.cmdp) {
-		err = -ENOMEM;
-		goto out;
-	}
-	if (copy_from_user(sg_io64.cmdp,
-			   (void *) A(cmdp32),
-			   sg_io64.cmd_len)) {
-		err = -EFAULT;
-		goto out;
-	}
-
-	err |= __get_user(sbp32, &sg_io32->sbp);
-	sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
-	if (!sg_io64.sbp) {
-		err = -ENOMEM;
-		goto out;
-	}
-	if (copy_from_user(sg_io64.sbp,
-			   (void *) A(sbp32),
-			   sg_io64.mx_sb_len)) {
-		err = -EFAULT;
-		goto out;
-	}
+		if (get_user(data, &sgio32->cmdp))
+			return -EFAULT;
+		cmdp = (unsigned char *) (unsigned long) data;
 
-	err |= __get_user(dxferp32, &sg_io32->dxferp);
-	if (sg_io64.iovec_count) {
-		int ret;
+		if (get_user(data, &sgio32->sbp))
+			return -EFAULT;
+		sbp = (unsigned char *) (unsigned long) data;
 
-		if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) {
-			err = ret;
-			goto out;
-		}
-	} else {
-		sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL);
-		if (!sg_io64.dxferp) {
-			err = -ENOMEM;
-			goto out;
-		}
-		if (copy_from_user(sg_io64.dxferp,
-				   (void *) A(dxferp32),
-				   sg_io64.dxfer_len)) {
-			err = -EFAULT;
-			goto out;
-		}
+		if (put_user(cmdp, &sgio->cmdp) ||
+		    put_user(sbp, &sgio->sbp))
+			return -EFAULT;
 	}
 
-	/* Unused internally, do not even bother to copy it over. */
-	sg_io64.usr_ptr = NULL;
+	if (copy_in_user(&sgio->timeout, &sgio32->timeout,
+			 3 * sizeof(int)))
+		return -EFAULT;
 
-	if (err)
+	if (get_user(data, &sgio32->usr_ptr))
+		return -EFAULT;
+	if (put_user((void *)(unsigned long)data, &sgio->usr_ptr))
 		return -EFAULT;
 
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64);
-	set_fs (old_fs);
+	if (copy_in_user(&sgio->status, &sgio32->status,
+			 (4 * sizeof(unsigned char)) +
+			 (2 * sizeof(unsigned (short))) +
+			 (3 * sizeof(int))))
+		return -EFAULT;
 
-	if (err < 0)
-		goto out;
+	err = sys_ioctl(fd, cmd, (unsigned long) sgio);
 
-	err = __put_user(sg_io64.pack_id, &sg_io32->pack_id);
-	err |= __put_user(sg_io64.status, &sg_io32->status);
-	err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status);
-	err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status);
-	err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr);
-	err |= __put_user(sg_io64.host_status, &sg_io32->host_status);
-	err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status);
-	err |= __put_user(sg_io64.resid, &sg_io32->resid);
-	err |= __put_user(sg_io64.duration, &sg_io32->duration);
-	err |= __put_user(sg_io64.info, &sg_io32->info);
-	err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
-	if (sg_io64.dxferp) {
-		if (sg_io64.iovec_count)
-			err |= copy_back_sg_iovec(&sg_io64, dxferp32);
-		else
-			err |= copy_to_user((void *)A(dxferp32),
-					    sg_io64.dxferp,
-					    sg_io64.dxfer_len);
-	}
-	if (err)
-		err = -EFAULT;
+	if (err >= 0) {
+		void *datap;
 
-out:
-	if (sg_io64.cmdp)
-		kfree(sg_io64.cmdp);
-	if (sg_io64.sbp)
-		kfree(sg_io64.sbp);
-	if (sg_io64.dxferp) {
-		if (sg_io64.iovec_count) {
-			free_sg_iovec(&sg_io64);
-		} else {
-			kfree(sg_io64.dxferp);
-		}
+		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;
 }
 
@@ -1757,37 +1648,65 @@ struct ppp_idle32 {
 };
 #define PPPIOCGIDLE32		_IOR('t', 63, struct ppp_idle32)
 
+static int ppp_gidle(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ppp_idle *idle;
+	struct ppp_idle32 *idle32;
+	__kernel_time_t xmit, recv;
+	int err;
+
+	idle = alloc_user_space(sizeof(*idle));
+	idle32 = (struct ppp_idle32 *) arg;
+
+	err = sys_ioctl(fd, PPPIOCGIDLE, (unsigned long) idle);
+
+	if (!err) {
+		if (get_user(xmit, &idle->xmit_idle) ||
+		    get_user(recv, &idle->recv_idle) ||
+		    put_user(xmit, &idle32->xmit_idle) ||
+		    put_user(recv, &idle32->recv_idle))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int ppp_scompress(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ppp_option_data *odata;
+	struct ppp_option_data32 *odata32;
+	__u32 data;
+	void *datap;
+
+	odata = alloc_user_space(sizeof(*odata));
+	odata32 = (struct ppp_option_data32 *) arg;
+
+	if (get_user(data, &odata32->ptr))
+		return -EFAULT;
+
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &odata->ptr))
+		return -EFAULT;
+
+	if (copy_in_user(&odata->length, &odata32->length,
+			 sizeof(__u32) + sizeof(int)))
+		return -EFAULT;
+
+	return sys_ioctl(fd, PPPIOCSCOMPRESS, (unsigned long) odata);
+}
+
 static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	mm_segment_t old_fs = get_fs();
-	struct ppp_option_data32 data32;
-	struct ppp_option_data data;
-	struct ppp_idle32 idle32;
-	struct ppp_idle idle;
-	unsigned int kcmd;
-	void *karg;
-	int err = 0;
+	int err;
 
 	switch (cmd) {
 	case PPPIOCGIDLE32:
-		kcmd = PPPIOCGIDLE;
-		karg = &idle;
+		err = ppp_gidle(fd, cmd, arg);
 		break;
+
 	case PPPIOCSCOMPRESS32:
-		if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32)))
-			return -EFAULT;
-		data.ptr = kmalloc (data32.length, GFP_KERNEL);
-		if (!data.ptr)
-			return -ENOMEM;
-		if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) {
-			kfree(data.ptr);
-			return -EFAULT;
-		}
-		data.length = data32.length;
-		data.transmit = data32.transmit;
-		kcmd = PPPIOCSCOMPRESS;
-		karg = &data;
+		err = ppp_scompress(fd, cmd, arg);
 		break;
+
 	default:
 		do {
 			static int count;
@@ -1796,26 +1715,10 @@ static int ppp_ioctl_trans(unsigned int 
 				       "cmd(%08x) arg(%08x)\n",
 				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
 		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
-	set_fs (old_fs);
-	switch (cmd) {
-	case PPPIOCGIDLE32:
-		if (err)
-			return err;
-		idle32.xmit_idle = idle.xmit_idle;
-		idle32.recv_idle = idle.recv_idle;
-		if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32)))
-			return -EFAULT;
-		break;
-	case PPPIOCSCOMPRESS32:
-		kfree(data.ptr);
-		break;
-	default:
+		err = -EINVAL;
 		break;
-	}
+	};
+
 	return err;
 }
 
@@ -1943,12 +1846,6 @@ static int mt_ioctl_trans(unsigned int f
 	return err ? -EFAULT: 0;
 }
 
-struct cdrom_read32 {
-	int			cdread_lba;
-	__kernel_caddr_t32	cdread_bufaddr;
-	int			cdread_buflen;
-};
-
 struct cdrom_read_audio32 {
 	union cdrom_addr	addr;
 	u_char			addr_format;
@@ -1962,60 +1859,94 @@ struct cdrom_generic_command32 {
 	unsigned int		buflen;
 	int			stat;
 	__kernel_caddr_t32	sense;
-	__kernel_caddr_t32	reserved[3];
+	unsigned char		data_direction;
+	int			quiet;
+	int			timeout;
+	__kernel_caddr_t32	reserved[1];
 };
 
+static int cdrom_do_read_audio(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct cdrom_read_audio *cdread_audio;
+	struct cdrom_read_audio32 *cdread_audio32;
+	__u32 data;
+	void *datap;
+
+	cdread_audio = alloc_user_space(sizeof(*cdread_audio));
+	cdread_audio32 = (struct cdrom_read_audio32 *) arg;
+
+	if (copy_in_user(&cdread_audio->addr,
+			 &cdread_audio32->addr,
+			 (sizeof(*cdread_audio32) -
+			  sizeof(__kernel_caddr_t32))))
+		return -EFAULT;
+
+	if (get_user(data, &cdread_audio32->buf))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &cdread_audio->buf))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long) cdread_audio);
+}
+
+static int __cgc_do_ptr(void **ptr64, __u32 *ptr32)
+{
+	u32 data;
+	void *datap;
+
+	if (get_user(data, ptr32))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, ptr64))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int cdrom_do_generic_command(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct cdrom_generic_command *cgc;
+	struct cdrom_generic_command32 *cgc32;
+	unsigned char dir;
+
+	cgc = alloc_user_space(sizeof(*cgc));
+	cgc32 = (struct cdrom_generic_command32 *) arg;
+
+	if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
+	    __cgc_do_ptr((void **) &cgc->buffer, &cgc32->buffer) ||
+	    copy_in_user(&cgc->buflen, &cgc32->buflen,
+			 (sizeof(unsigned int) + sizeof(int))) ||
+	    __cgc_do_ptr((void **) &cgc->sense, &cgc32->sense))
+		return -EFAULT;
+
+	if (get_user(dir, &cgc->data_direction) ||
+	    put_user(dir, &cgc32->data_direction))
+		return -EFAULT;
+
+	if (copy_in_user(&cgc->quiet, &cgc32->quiet,
+			 2 * sizeof(int)))
+		return -EFAULT;
+
+	if (__cgc_do_ptr(&cgc->reserved[0], &cgc32->reserved[0]))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long) cgc);
+}
+
 static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	mm_segment_t old_fs = get_fs();
-	struct cdrom_read cdread;
-	struct cdrom_read_audio cdreadaudio;
-	struct cdrom_generic_command cgc;
-	__kernel_caddr_t32 addr;
-	char *data = 0;
-	void *karg;
-	int err = 0;
+	int err;
 
 	switch(cmd) {
-	case CDROMREADMODE2:
-	case CDROMREADMODE1:
-	case CDROMREADRAW:
-	case CDROMREADCOOKED:
-		karg = &cdread;
-		err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba);
-		err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr);
-		err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen);
-		if (err)
-			return -EFAULT;
-		data = kmalloc(cdread.cdread_buflen, GFP_KERNEL);
-		if (!data)
-			return -ENOMEM;
-		cdread.cdread_bufaddr = data;
-		break;
 	case CDROMREADAUDIO:
-		karg = &cdreadaudio;
-		err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr));
-		err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format);
-		err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); 
-		err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf);
-		if (err)
-			return -EFAULT;
-		data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL);
-		if (!data)
-			return -ENOMEM;
-		cdreadaudio.buf = data;
+		err = cdrom_do_read_audio(fd, cmd, arg);
 		break;
+
 	case CDROM_SEND_PACKET:
-		karg = &cgc;
-		err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd));
-		err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer);
-		err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
-		if (err)
-			return -EFAULT;
-		if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL)
-			return -ENOMEM;
-		cgc.buffer = data;
+		err = cdrom_do_generic_command(fd, cmd, arg);
 		break;
+
 	default:
 		do {
 			static int count;
@@ -2024,32 +1955,11 @@ static int cdrom_ioctl_trans(unsigned in
 				       "cmd(%08x) arg(%08x)\n",
 				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
 		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)karg);
-	set_fs (old_fs);
-	if (err)
-		goto out;
-	switch (cmd) {
-	case CDROMREADMODE2:
-	case CDROMREADMODE1:
-	case CDROMREADRAW:
-	case CDROMREADCOOKED:
-		err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen);
-		break;
-	case CDROMREADAUDIO:
-		err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352);
-		break;
-	case CDROM_SEND_PACKET:
-		err = copy_to_user((char *)A(addr), data, cgc.buflen);
-		break;
-	default:
+		err = -EINVAL;
 		break;
-	}
-out:	if (data)
-		kfree(data);
-	return err ? -EFAULT : 0;
+	};
+
+	return err;
 }
 
 struct loop_info32 {
@@ -2624,52 +2534,30 @@ static struct {
 
 static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	struct atm_iobuf32 iobuf32;
-	struct atm_iobuf   iobuf = { 0, NULL };
-	mm_segment_t old_fs;
-	int err;
-
-	err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg,
-	    sizeof(struct atm_iobuf32));
-	if (err)
-		return -EFAULT;
+	struct atm_iobuf   *iobuf;
+	struct atm_iobuf32 *iobuf32;
+	u32 data;
+	void *datap;
+	int len, err;
 
-	iobuf.length = iobuf32.length;
+	iobuf = alloc_user_space(sizeof(*iobuf));
+	iobuf32 = (struct atm_iobuf32 *) arg;
 
-	if (iobuf32.buffer == (__kernel_caddr_t32) NULL || iobuf32.length == 0) {
-		iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
-	} else {
-		iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL);
-		if (iobuf.buffer == NULL) {
-			err = -ENOMEM;
-			goto out;
-		}
-
-		err = copy_from_user(iobuf.buffer, A(iobuf32.buffer), iobuf.length);
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
-	}
+	if (get_user(len, &iobuf32->length) ||
+	    get_user(data, &iobuf32->buffer))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(len, &iobuf->length) ||
+	    put_user(datap, &iobuf->buffer))
+		return -EFAULT;
 
-	old_fs = get_fs(); set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);      
-	set_fs (old_fs);
-        if(err)
-		goto out;
+	err = sys_ioctl(fd, cmd, (unsigned long)iobuf);
 
-        if(iobuf.buffer && iobuf.length > 0) {
-		err = copy_to_user(A(iobuf32.buffer), iobuf.buffer, iobuf.length);
-		if (err) {
+	if (!err) {
+		if (copy_in_user(&iobuf32->length, &iobuf->length,
+				 sizeof(int)))
 			err = -EFAULT;
-			goto out;
-		}
 	}
-	err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
-
- out:
-        if(iobuf32.buffer && iobuf32.length > 0)
-		kfree(iobuf.buffer);
 
 	return err;
 }
@@ -2677,55 +2565,29 @@ static int do_atm_iobuf(unsigned int fd,
 
 static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-        struct atmif_sioc32 sioc32;
-        struct atmif_sioc   sioc = { 0, 0, NULL };
-        mm_segment_t old_fs;
-        int err;
+        struct atmif_sioc   *sioc;
+        struct atmif_sioc32 *sioc32;
+	u32 data;
+	void *datap;
+	int err;
         
-        err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg,
-			     sizeof(struct atmif_sioc32));
-        if (err)
-                return -EFAULT;
+	sioc = alloc_user_space(sizeof(*sioc));
+	sioc32 = (struct atmif_sioc32 *) arg;
 
-        sioc.number = sioc32.number;
-        sioc.length = sioc32.length;
-        
-	if (sioc32.arg == (__kernel_caddr_t32) NULL || sioc32.length == 0) {
-		sioc.arg = (void*)(unsigned long)sioc32.arg;
-        } else {
-                sioc.arg = kmalloc(sioc.length, GFP_KERNEL);
-                if (sioc.arg == NULL) {
-                        err = -ENOMEM;
-			goto out;
-		}
-                
-                err = copy_from_user(sioc.arg, A(sioc32.arg), sioc32.length);
-                if (err) {
-                        err = -EFAULT;
-                        goto out;
-                }
-        }
-        
-        old_fs = get_fs(); set_fs (KERNEL_DS);
-        err = sys_ioctl (fd, cmd, (unsigned long)&sioc);	
-        set_fs (old_fs);
-        if(err) {
-                goto out;
+	if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) ||
+	    get_user(data, &sioc32->arg))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &sioc->arg))
+		return -EFAULT;
+
+	err = sys_ioctl(fd, cmd, (unsigned long) sioc);
+
+	if (!err) {
+		if (copy_in_user(&sioc32->length, &sioc->length,
+				 sizeof(int)))
+			err = -EFAULT;
 	}
-        
-        if(sioc.arg && sioc.length > 0) {
-                err = copy_to_user(A(sioc32.arg), sioc.arg, sioc.length);
-                if (err) {
-                        err = -EFAULT;
-                        goto out;
-                }
-        }
-        err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
-        
- out:
-        if(sioc32.arg && sioc32.length > 0)
-		kfree(sioc.arg);
-        
 	return err;
 }
 
@@ -2747,15 +2609,14 @@ static int do_atm_ioctl(unsigned int fd,
 		return do_atmif_sioc(fd, cmd32, arg);
 	}
 
-		for (i = 0; i < NR_ATM_IOCTL; i++) {
-			if (cmd32 == atm_ioctl_map[i].cmd32) {
-				cmd = atm_ioctl_map[i].cmd;
-				break;
-			}
+	for (i = 0; i < NR_ATM_IOCTL; i++) {
+		if (cmd32 == atm_ioctl_map[i].cmd32) {
+			cmd = atm_ioctl_map[i].cmd;
+			break;
 		}
-	        if (i == NR_ATM_IOCTL) {
+	}
+	if (i == NR_ATM_IOCTL)
 	        return -EINVAL;
-	        }
         
         switch (cmd) {
 	case ATM_GETNAMES:
@@ -4381,48 +4242,33 @@ struct mtd_oob_buf32 {
 
 static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	mm_segment_t 			old_fs 	= get_fs();
-	struct mtd_oob_buf32	*uarg 	= (struct mtd_oob_buf32 *)arg;
-	struct mtd_oob_buf		karg;
-	u32 tmp;
-	char *ptr;
-	int ret;
-
-	if (get_user(karg.start, &uarg->start) 		||
-	    get_user(karg.length, &uarg->length)	||
-	    get_user(tmp, &uarg->ptr))
-		return -EFAULT;
-
-	ptr = (char *)A(tmp);
-	if (0 >= karg.length) 
-		return -EINVAL;
+	struct mtd_oob_buf	*buf = alloc_user_space(sizeof(*buf));
+	struct mtd_oob_buf32	*buf32 = (struct mtd_oob_buf32 *) arg;
+	u32 data;
+	char *datap;
+	unsigned int real_cmd;
+	int err;
 
-	karg.ptr = kmalloc(karg.length, GFP_KERNEL);
-	if (NULL == karg.ptr)
-		return -ENOMEM;
+	real_cmd = (cmd == MEMREADOOB32) ?
+		MEMREADOOB : MEMWRITEOOB;
 
-	if (copy_from_user(karg.ptr, ptr, karg.length)) {
-		kfree(karg.ptr);
+	if (copy_in_user(&buf->start, &buf32->start,
+			 2 * sizeof(u32)) ||
+	    get_user(data, &buf32->ptr))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &buf->ptr))
 		return -EFAULT;
-	}
 
-	set_fs(KERNEL_DS);
-	if (MEMREADOOB32 == cmd) 
-		ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg);
-	else if (MEMWRITEOOB32 == cmd)
-		ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg);
-	else
-		ret = -EINVAL;
-	set_fs(old_fs);
+	err = sys_ioctl(fd, real_cmd, (unsigned long) buf);
 
-	if (0 == ret && cmd == MEMREADOOB32) {
-		ret = copy_to_user(ptr, karg.ptr, karg.length);
-		ret |= put_user(karg.start, &uarg->start);
-		ret |= put_user(karg.length, &uarg->length);
+	if (!err) {
+		if (copy_in_user(&buf32->start, &buf->start,
+				 2 * sizeof(u32)))
+			err = -EFAULT;
 	}
 
-	kfree(karg.ptr);
-	return ((0 == ret) ? 0 : -EFAULT);
+	return err;
 }	
 
 /* Fix sizeof(sizeof()) breakage */
@@ -4880,6 +4726,15 @@ COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS)
 COMPATIBLE_IOCTL(CDROM_LOCKDOOR)
 COMPATIBLE_IOCTL(CDROM_DEBUG)
 COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
+/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
+ * not take a struct cdrom_read, instead they take a struct cdrom_msf
+ * which is compatible.
+ */
+COMPATIBLE_IOCTL(CDROMREADMODE2)
+COMPATIBLE_IOCTL(CDROMREADMODE1)
+COMPATIBLE_IOCTL(CDROMREADRAW)
+COMPATIBLE_IOCTL(CDROMREADCOOKED)
+COMPATIBLE_IOCTL(CDROMREADALL)
 /* DVD ioctls */
 COMPATIBLE_IOCTL(DVD_READ_STRUCT)
 COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)
@@ -5333,12 +5188,7 @@ HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
-HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
 HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
 HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29  9:32           ` David S. Miller
@ 2003-05-29  9:46             ` Pavel Machek
  2003-05-29 10:01               ` David S. Miller
  2003-05-29  9:46             ` Andi Kleen
                               ` (2 subsequent siblings)
  3 siblings, 1 reply; 34+ messages in thread
From: Pavel Machek @ 2003-05-29  9:46 UTC (permalink / raw)
  To: David S. Miller; +Cc: ak, pavel, akpm, linux-kernel

Hi!

>    From: Andi Kleen <ak@suse.de>
>    Date: 29 May 2003 11:17:36 +0200
> 
>    This part won't work on sparc64 because it has separate address spaces
>    for user/kernel.
> 
> Yes, in fact I happen to be working in this area hold on...
> 
> I'm redoing Andi's x86_64 ioctl32 bug fixes more cleanly
> for sparc64 by instead using alloc_user_space().
> 
...
> 
> This is a 2.4.x patch but should be easy to push over to the 2.5.x
> ioctl stuff using the appropriate compat types.

Do you expect to work on it some more or should I start pushing it
over to the 2.5.X?
								Pavel

-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29  9:32           ` David S. Miller
  2003-05-29  9:46             ` Pavel Machek
@ 2003-05-29  9:46             ` Andi Kleen
  2003-05-29 10:01               ` David S. Miller
  2003-05-29 11:25             ` Pavel Machek
  2003-05-29 20:06             ` Pavel Machek
  3 siblings, 1 reply; 34+ messages in thread
From: Andi Kleen @ 2003-05-29  9:46 UTC (permalink / raw)
  To: David S. Miller; +Cc: ak, pavel, akpm, linux-kernel

On Thu, May 29, 2003 at 02:32:03AM -0700, David S. Miller wrote:
>    From: Andi Kleen <ak@suse.de>
>    Date: 29 May 2003 11:17:36 +0200
> 
>    This part won't work on sparc64 because it has separate address spaces
>    for user/kernel.
> 
> Yes, in fact I happen to be working in this area hold on...
> 
> I'm redoing Andi's x86_64 ioctl32 bug fixes more cleanly
> for sparc64 by instead using alloc_user_space().
> 
> Sorry Andi, I just couldn't bring myself to allow those bogus
> artificial limits you added just to fix these bugs... :-)

I also didn't like them too much and where they looked like they could
hurt I resorted to the verify_area trick instead (which didn't work 
for you...) 

I believe the remaining limits are harmless, but of course it's cleaner
to not have them.

If you use the function that extensively it would be better to allow
it to nest (e.g. add a field for the current offset in  task struct). 
Otherwise someone will get it wrong sooner or later.
(like the sock/tw_bucket ;) 

> This work also pointed out many bugs in this area which should
> be fixed by my stuff. (CDROMREAD* ioctls don't take struct cdrom_read
> they take struct cdrom_msf which is compatible, struct
> cdrom_generic_command32 was missing some members, etc. etc.)
> 
> This is a 2.4.x patch but should be easy to push over to the 2.5.x
> ioctl stuff using the appropriate compat types.

Ok thanks. I will port it to my 2.4 code.

Did you test them all?
 
-Andi

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29  9:46             ` Andi Kleen
@ 2003-05-29 10:01               ` David S. Miller
  0 siblings, 0 replies; 34+ messages in thread
From: David S. Miller @ 2003-05-29 10:01 UTC (permalink / raw)
  To: ak; +Cc: pavel, akpm, linux-kernel

   From: Andi Kleen <ak@suse.de>
   Date: Thu, 29 May 2003 11:46:48 +0200

   I believe the remaining limits are harmless, but of course it's cleaner
   to not have them.
   
The ethtool one was the worst.  It's why I didn't copy your code :-)

   If you use the function that extensively it would be better to allow
   it to nest (e.g. add a field for the current offset in  task struct). 
   Otherwise someone will get it wrong sooner or later.
   (like the sock/tw_bucket ;) 
   
This is why I kept it private to the compat layer, I see no reason
to let it slip into other code at all.

   Ok thanks. I will port it to my 2.4 code.
   
   Did you test them all?

I tested most of them, but very lightly.  I didn't test the
SG_IO stuff but that barely worked even beforehand :-)

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29  9:46             ` Pavel Machek
@ 2003-05-29 10:01               ` David S. Miller
  2003-05-29 10:03                 ` Pavel Machek
  0 siblings, 1 reply; 34+ messages in thread
From: David S. Miller @ 2003-05-29 10:01 UTC (permalink / raw)
  To: pavel; +Cc: ak, akpm, linux-kernel

   From: Pavel Machek <pavel@suse.cz>
   Date: Thu, 29 May 2003 11:46:24 +0200
   
   Do you expect to work on it some more or should I start pushing it
   over to the 2.5.X?

I don't intend to make any changes.  If we find some bugs in my
code, we'll forward the fixes to you.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29 10:01               ` David S. Miller
@ 2003-05-29 10:03                 ` Pavel Machek
  0 siblings, 0 replies; 34+ messages in thread
From: Pavel Machek @ 2003-05-29 10:03 UTC (permalink / raw)
  To: David S. Miller; +Cc: pavel, ak, akpm, linux-kernel

Hi!

>    Do you expect to work on it some more or should I start pushing it
>    over to the 2.5.X?
> 
> I don't intend to make any changes.  If we find some bugs in my
> code, we'll forward the fixes to you.

Thanx.
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29  9:32           ` David S. Miller
  2003-05-29  9:46             ` Pavel Machek
  2003-05-29  9:46             ` Andi Kleen
@ 2003-05-29 11:25             ` Pavel Machek
  2003-05-29 11:26               ` David S. Miller
  2003-05-29 20:06             ` Pavel Machek
  3 siblings, 1 reply; 34+ messages in thread
From: Pavel Machek @ 2003-05-29 11:25 UTC (permalink / raw)
  To: David S. Miller; +Cc: ak, pavel, akpm, linux-kernel

Hi!

>    This part won't work on sparc64 because it has separate address spaces
>    for user/kernel.
> 
> Yes, in fact I happen to be working in this area hold on...
> 
> I'm redoing Andi's x86_64 ioctl32 bug fixes more cleanly
> for sparc64 by instead using alloc_user_space().
> 
> Sorry Andi, I just couldn't bring myself to allow those bogus
> artificial limits you added just to fix these bugs... :-)
> 
> This work also pointed out many bugs in this area which should
> be fixed by my stuff. (CDROMREAD* ioctls don't take struct cdrom_read
> they take struct cdrom_msf which is compatible, struct
> cdrom_generic_command32 was missing some members, etc. etc.)
> 
> This is a 2.4.x patch but should be easy to push over to the 2.5.x
> ioctl stuff using the appropriate compat types.

It had to be applied by hand, otherwise okay... Mostly.

What is copy_in_user?

								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29 11:25             ` Pavel Machek
@ 2003-05-29 11:26               ` David S. Miller
  2003-05-29 11:39                 ` Arjan van de Ven
  0 siblings, 1 reply; 34+ messages in thread
From: David S. Miller @ 2003-05-29 11:26 UTC (permalink / raw)
  To: pavel; +Cc: ak, akpm, linux-kernel

   From: Pavel Machek <pavel@suse.cz>
   Date: Thu, 29 May 2003 13:25:17 +0200
   
   What is copy_in_user?

Both source and destination pointers are in userspace.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29 11:26               ` David S. Miller
@ 2003-05-29 11:39                 ` Arjan van de Ven
  2003-05-29 20:10                   ` Pavel Machek
  0 siblings, 1 reply; 34+ messages in thread
From: Arjan van de Ven @ 2003-05-29 11:39 UTC (permalink / raw)
  To: David S. Miller; +Cc: pavel, ak, akpm, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 255 bytes --]

On Thu, 2003-05-29 at 13:26, David S. Miller wrote:
>    From: Pavel Machek <pavel@suse.cz>
>    Date: Thu, 29 May 2003 13:25:17 +0200
>    
>    What is copy_in_user?
> 
> Both source and destination pointers are in userspace.

sys_memcpy() ?


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29  9:32           ` David S. Miller
                               ` (2 preceding siblings ...)
  2003-05-29 11:25             ` Pavel Machek
@ 2003-05-29 20:06             ` Pavel Machek
  2003-05-29 21:15               ` David S. Miller
  3 siblings, 1 reply; 34+ messages in thread
From: Pavel Machek @ 2003-05-29 20:06 UTC (permalink / raw)
  To: David S. Miller; +Cc: ak, pavel, akpm, linux-kernel

Hi!

>    This part won't work on sparc64 because it has separate address spaces
>    for user/kernel.
> 
> Yes, in fact I happen to be working in this area hold on...
> 
> I'm redoing Andi's x86_64 ioctl32 bug fixes more cleanly
> for sparc64 by instead using alloc_user_space().
> 
> Sorry Andi, I just couldn't bring myself to allow those bogus
> artificial limits you added just to fix these bugs... :-)
> 
> This work also pointed out many bugs in this area which should
> be fixed by my stuff. (CDROMREAD* ioctls don't take struct cdrom_read
> they take struct cdrom_msf which is compatible, struct
> cdrom_generic_command32 was missing some members, etc. etc.)
> 
> This is a 2.4.x patch but should be easy to push over to the 2.5.x
> ioctl stuff using the appropriate compat types.

It was painfull but easy to port 2.5.X. Here it is.

Andi, can you take uaccess.h part? Davem, does trivial copy_in_user I
created have expected semantics?
								Pavel

--- linux.clean/include/asm-x86_64/uaccess.h	2003-03-18 08:23:12.000000000 -0800
+++ linux/include/asm-x86_64/uaccess.h	2003-05-29 06:06:07.000000000 -0700
@@ -298,6 +298,19 @@
 	}
 }	
 
+static inline int copy_in_user(void *dst, const void *src, unsigned size) 
+{ 
+	int i, ret;
+	unsigned char c;
+	for (i=0; i<size; i++) {
+		ret = copy_from_user(&c, src, 1);
+		if (ret) return ret;
+		ret = copy_to_user(dst, &c, 1);
+		if (ret) return ret;
+	}
+	return ret;
+}	
+
 long strncpy_from_user(char *dst, const char *src, long count);
 long __strncpy_from_user(char *dst, const char *src, long count);
 long strnlen_user(const char *str, long n);
--- linux.clean/include/linux/compat_ioctl.h	2003-05-27 04:52:28.000000000 -0700
+++ linux/include/linux/compat_ioctl.h	2003-05-29 05:35:16.000000000 -0700
@@ -355,6 +355,15 @@
 COMPATIBLE_IOCTL(CDROM_LOCKDOOR)
 COMPATIBLE_IOCTL(CDROM_DEBUG)
 COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
+/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
+ * not take a struct cdrom_read, instead they take a struct cdrom_msf
+ * which is compatible.
+ */
+COMPATIBLE_IOCTL(CDROMREADMODE2)
+COMPATIBLE_IOCTL(CDROMREADMODE1)
+COMPATIBLE_IOCTL(CDROMREADRAW)
+COMPATIBLE_IOCTL(CDROMREADCOOKED)
+COMPATIBLE_IOCTL(CDROMREADALL)
 /* DVD ioctls */
 COMPATIBLE_IOCTL(DVD_READ_STRUCT)
 COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)

--- linux.clean/fs/compat_ioctl.c	2003-05-27 07:36:47.000000000 -0700
+++ linux/fs/compat_ioctl.c	2003-05-29 05:55:16.000000000 -0700
@@ -554,74 +554,27 @@
 
 static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	struct ifreq ifr;
-	mm_segment_t old_fs;
-	int err, len;
-	u32 data, ethcmd;
+	struct ifreq *ifr;
+	struct ifreq32 *ifr32;
+	u32 data;
+	void *datap;
 	
-	if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
-		return -EFAULT;
-	ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL);
-	if (!ifr.ifr_data)
-		return -EAGAIN;
-
-	__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
-
-	if (get_user(ethcmd, (u32 *)compat_ptr(data))) {
-		err = -EFAULT;
-		goto out;
-	}
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:	len = sizeof(struct ethtool_drvinfo); break;
-	case ETHTOOL_GMSGLVL:
-	case ETHTOOL_SMSGLVL:
-	case ETHTOOL_GLINK:
-	case ETHTOOL_NWAY_RST:  len = sizeof(struct ethtool_value); break;
-	case ETHTOOL_GREGS: {
-		struct ethtool_regs *regaddr = compat_ptr(data);
-		/* darned variable size arguments */
-		if (get_user(len, (u32 *)&regaddr->len)) {
-			err = -EFAULT;
-			goto out;
-		}
-		if (len > PAGE_SIZE - sizeof(struct ethtool_regs)) { 
-			err = -EINVAL;
-			goto out;
-		}			
-		len += sizeof(struct ethtool_regs);
-		break;
-	}
-	case ETHTOOL_GSET:
-	case ETHTOOL_SSET:      len = sizeof(struct ethtool_cmd); break;
-	default:
-               err = -EOPNOTSUPP;
-               goto out;
-	}
+	ifr = compat_alloc_user_space(sizeof(*ifr));
+	ifr32 = (struct ifreq32 *) arg;
 
-	if (copy_from_user(ifr.ifr_data, compat_ptr(data), len)) {
-		err = -EFAULT;
-		goto out;
-	}
+	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
+		return -EFAULT;
 
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
-	set_fs (old_fs);
-	if (!err) {
-		u32 data;
+	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
+		return -EFAULT;
 
-		__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
-		len = copy_to_user(compat_ptr(data), ifr.ifr_data, len);
-		if (len)
-			err = -EFAULT;
-	}
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &ifr->ifr_ifru.ifru_data))
+		return -EFAULT;
 
-out:
-	free_page((unsigned long)ifr.ifr_data);
-	return err;
+	return sys_ioctl(fd, cmd, (unsigned long) ifr);
 }
 
-
 static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq ifr;
@@ -894,65 +847,113 @@
 	compat_caddr_t	transp;
 };
 
-static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int do_cmap_ptr(__u16 **ptr64, __u32 *ptr32)
 {
-	mm_segment_t old_fs = get_fs();
-	u32 red = 0, green = 0, blue = 0, transp = 0;
+	__u32 data;
+	void *datap;
+
+	if (get_user(data, ptr32))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, ptr64))
+		return -EFAULT;
+	return 0;
+}
+
+static int fb_getput_cmap(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct fb_cmap *cmap;
+	struct fb_cmap32 *cmap32;
+	int err;
+
+	cmap = compat_alloc_user_space(sizeof(*cmap));
+	cmap32 = (struct fb_cmap32 *) arg;
+
+	if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32)))
+		return -EFAULT;
+
+	if (do_cmap_ptr(&cmap->red, &cmap32->red) ||
+	    do_cmap_ptr(&cmap->green, &cmap32->green) ||
+	    do_cmap_ptr(&cmap->blue, &cmap32->blue) ||
+	    do_cmap_ptr(&cmap->transp, &cmap32->transp))
+		return -EFAULT;
+
+	err = sys_ioctl(fd, cmd, (unsigned long) cmap);
+
+	if (!err) {
+		if (copy_in_user(&cmap32->start,
+				 &cmap->start,
+				 2 * sizeof(__u32)))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
+				  struct fb_fix_screeninfo32 *fix32)
+{
+	__u32 data;
+	int err;
+
+	err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id));
+
+	data = (__u32) (unsigned long) fix->smem_start;
+	err |= put_user(data, &fix32->smem_start);
+
+	err |= put_user(fix->smem_len, &fix32->smem_len);
+	err |= put_user(fix->type, &fix32->type);
+	err |= put_user(fix->type_aux, &fix32->type_aux);
+	err |= put_user(fix->visual, &fix32->visual);
+	err |= put_user(fix->xpanstep, &fix32->xpanstep);
+	err |= put_user(fix->ypanstep, &fix32->ypanstep);
+	err |= put_user(fix->ywrapstep, &fix32->ywrapstep);
+	err |= put_user(fix->line_length, &fix32->line_length);
+
+	data = (__u32) (unsigned long) fix->mmio_start;
+	err |= put_user(data, &fix32->mmio_start);
+
+	err |= put_user(fix->mmio_len, &fix32->mmio_len);
+	err |= put_user(fix->accel, &fix32->accel);
+	err |= copy_to_user(fix32->reserved, fix->reserved,
+			    sizeof(fix->reserved));
+
+	return err;
+}
+
+static int fb_get_fscreeninfo(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs;
 	struct fb_fix_screeninfo fix;
-	struct fb_cmap cmap;
-	void *karg;
-	int err = 0;
+	struct fb_fix_screeninfo32 *fix32;
+	int err;
+
+	fix32 = (struct fb_fix_screeninfo32 *) arg;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long) &fix);
+	set_fs(old_fs);
+
+	if (!err)
+		err = do_fscreeninfo_to_user(&fix, fix32);
+
+	return err;
+}
+
+static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	int err;
 
-	memset(&cmap, 0, sizeof(cmap));
 	switch (cmd) {
 	case FBIOGET_FSCREENINFO:
-		karg = &fix;
+		err = fb_get_fscreeninfo(fd,cmd, arg);
 		break;
-	case FBIOGETCMAP:
-	case FBIOPUTCMAP:
-		karg = &cmap;
-		err = __get_user(cmap.start, &((struct fb_cmap32 *)arg)->start);
-		err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len);
-		err |= __get_user(red, &((struct fb_cmap32 *)arg)->red);
-		err |= __get_user(green, &((struct fb_cmap32 *)arg)->green);
-		err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue);
-		err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp);
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
-		if (cmap.len > PAGE_SIZE/sizeof(u16)) { 
-			err = -EINVAL;
-			goto out;
-		}
-		err = -ENOMEM;
-		cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.red)
-			goto out;
-		cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.green)
-			goto out;
-		cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.blue)
-			goto out;
-		if (transp) {
-			cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-			if (!cmap.transp)
-				goto out;
-		}
-			
-		if (cmd == FBIOGETCMAP)
-			break;
 
-		err = __copy_from_user(cmap.red, compat_ptr(red), cmap.len * sizeof(__u16));
-		err |= __copy_from_user(cmap.green, compat_ptr(green), cmap.len * sizeof(__u16));
-		err |= __copy_from_user(cmap.blue, compat_ptr(blue), cmap.len * sizeof(__u16));
-		if (cmap.transp) err |= __copy_from_user(cmap.transp, compat_ptr(transp), cmap.len * sizeof(__u16));
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
+  	case FBIOGETCMAP:
+	case FBIOPUTCMAP:
+		err = fb_getput_cmap(fd, cmd, arg);
 		break;
+
 	default:
 		do {
 			static int count;
@@ -961,47 +962,10 @@
 				       "cmd(%08x) arg(%08lx)\n",
 				       __FUNCTION__, fd, cmd, arg);
 		} while(0);
-		return -ENOSYS;
-	}
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)karg);
-	set_fs(old_fs);
-	if (err)
-		goto out;
-	switch (cmd) {
-	case FBIOGET_FSCREENINFO:
-		err = __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->id, (char *)fix.id, sizeof(fix.id));
-		err |= __put_user((__u32)(unsigned long)fix.smem_start, &((struct fb_fix_screeninfo32 *)arg)->smem_start);
-		err |= __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)arg)->smem_len);
-		err |= __put_user(fix.type, &((struct fb_fix_screeninfo32 *)arg)->type);
-		err |= __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)arg)->type_aux);
-		err |= __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)arg)->visual);
-		err |= __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)arg)->xpanstep);
-		err |= __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)arg)->ypanstep);
-		err |= __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)arg)->ywrapstep);
-		err |= __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)arg)->line_length);
-		err |= __put_user((__u32)(unsigned long)fix.mmio_start, &((struct fb_fix_screeninfo32 *)arg)->mmio_start);
-		err |= __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)arg)->mmio_len);
-		err |= __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)arg)->accel);
-		err |= __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->reserved, (char *)fix.reserved, sizeof(fix.reserved));
-		break;
-	case FBIOGETCMAP:
-		err = __copy_to_user(compat_ptr(red), cmap.red, cmap.len * sizeof(__u16));
-		err |= __copy_to_user(compat_ptr(green), cmap.blue, cmap.len * sizeof(__u16));
-		err |= __copy_to_user(compat_ptr(blue), cmap.blue, cmap.len * sizeof(__u16));
-		if (cmap.transp)
-			err |= __copy_to_user(compat_ptr(transp), cmap.transp, cmap.len * sizeof(__u16));
+		err = -ENOSYS;
 		break;
-	case FBIOPUTCMAP:
-		break;
-	}
-	if (err)
-		err = -EFAULT;
+	};
 
-out:	if (cmap.red) kfree(cmap.red);
-	if (cmap.green) kfree(cmap.green);
-	if (cmap.blue) kfree(cmap.blue);
-	if (cmap.transp) kfree(cmap.transp);
 	return err;
 }
 
@@ -1056,141 +1020,118 @@
 	compat_uint_t iov_len;
 } sg_iovec32_t;
 
-#define EMU_SG_MAX 128
-
-static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
+static int sg_build_iovec(sg_io_hdr_t *sgio, void *dxferp, u16 iovec_count)
 {
-	sg_iovec32_t *uiov = compat_ptr(uptr32);
-	sg_iovec_t *kiov;
+	sg_iovec_t *iov = (sg_iovec_t *) (sgio + 1);
+	sg_iovec32_t *iov32 = dxferp;
 	int i;
 
-	if (sgp->iovec_count > EMU_SG_MAX)
-		return -EINVAL;
-	sgp->dxferp = kmalloc(sgp->iovec_count *
-			      sizeof(sg_iovec_t), GFP_KERNEL);
-	if (!sgp->dxferp)
-		return -ENOMEM;
-	memset(sgp->dxferp, 0,
-	       sgp->iovec_count * sizeof(sg_iovec_t));
-
-	kiov = (sg_iovec_t *) sgp->dxferp;
-	for (i = 0; i < sgp->iovec_count; i++) {
-		u32 iov_base32;
-		if (__get_user(iov_base32, &uiov->iov_base) ||
-		    __get_user(kiov->iov_len, &uiov->iov_len))
-			return -EFAULT;
-		if (verify_area(VERIFY_WRITE, compat_ptr(iov_base32), kiov->iov_len))
+	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((void *)(unsigned long)base, &iov[i].iov_base) ||
+		    put_user(len, &iov[i].iov_len))
 			return -EFAULT;
-		kiov->iov_base = compat_ptr(iov_base32);
-		uiov++;
-		kiov++;
 	}
 
 	return 0;
 }
 
-static void free_sg_iovec(sg_io_hdr_t *sgp)
-{
-	kfree(sgp->dxferp);
-	sgp->dxferp = NULL;
-}
-
 static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	sg_io_hdr32_t *sg_io32;
-	sg_io_hdr_t sg_io64;
-	u32 dxferp32, cmdp32, sbp32;
-	mm_segment_t old_fs;
-	int err = 0;
+	sg_io_hdr_t *sgio;
+	sg_io_hdr32_t *sgio32;
+	u16 iovec_count;
+	u32 data;
+	void *dxferp;
+	int err;
 
-	sg_io32 = (sg_io_hdr32_t *)arg;
-	err = __get_user(sg_io64.interface_id, &sg_io32->interface_id);
-	err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction);
-	err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len);
-	err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len);
-	err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count);
-	err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len);
-	err |= __get_user(sg_io64.timeout, &sg_io32->timeout);
-	err |= __get_user(sg_io64.flags, &sg_io32->flags);
-	err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id);
-
-	sg_io64.dxferp = NULL;
-	sg_io64.cmdp = NULL;
-	sg_io64.sbp = NULL;
-
-	err |= __get_user(cmdp32, &sg_io32->cmdp);
-	sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
-	if (copy_from_user(sg_io64.cmdp,
-			   compat_ptr(cmdp32),
-			   sg_io64.cmd_len)) {
-		err = -EFAULT;
-		goto out;
-	}
+	sgio32 = (sg_io_hdr32_t *) arg;
+	if (get_user(iovec_count, &sgio32->iovec_count))
+		return -EFAULT;
 
-	err |= __get_user(sbp32, &sg_io32->sbp);
-	sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
-	if (!sg_io64.sbp) {
-		err = -ENOMEM;
-		goto out;
-	}
-	if (copy_from_user(sg_io64.sbp,
-			   compat_ptr(sbp32),
-			   sg_io64.mx_sb_len)) {
-		err = -EFAULT;
-		goto out;
+	{
+		void *new, *top;
+
+		top = compat_alloc_user_space(0);
+		new = compat_alloc_user_space(sizeof(sg_io_hdr_t) +
+				       (iovec_count *
+					sizeof(sg_iovec_t)));
+		if (new > top)
+			return -EINVAL;
+
+		sgio = new;
 	}
 
-	err |= __get_user(dxferp32, &sg_io32->dxferp);
-	if (sg_io64.iovec_count) {
-		int ret;
-
-		if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) {
-			err = ret;
-			goto out;
-		}
+	/* 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 = (void *) (unsigned long) data;
+	if (iovec_count) {
+		if (sg_build_iovec(sgio, dxferp, iovec_count))
+			return -EFAULT;
 	} else {
-		err = verify_area(VERIFY_WRITE, compat_ptr(dxferp32), sg_io64.dxfer_len);
-		if (err) 
-			goto out;
+		if (put_user(dxferp, &sgio->dxferp))
+			return -EFAULT;
+	}
+
+	{
+		unsigned char *cmdp, *sbp;
+
+		if (get_user(data, &sgio32->cmdp))
+			return -EFAULT;
+		cmdp = (unsigned char *) (unsigned long) data;
 
-		sg_io64.dxferp = compat_ptr(dxferp32); 
+		if (get_user(data, &sgio32->sbp))
+			return -EFAULT;
+		sbp = (unsigned char *) (unsigned long) data;
+
+		if (put_user(cmdp, &sgio->cmdp) ||
+		    put_user(sbp, &sgio->sbp))
+			return -EFAULT;
 	}
 
-	/* Unused internally, do not even bother to copy it over. */
-	sg_io64.usr_ptr = NULL;
+	if (copy_in_user(&sgio->timeout, &sgio32->timeout,
+			 3 * sizeof(int)))
+		return -EFAULT;
 
-	if (err)
+	if (get_user(data, &sgio32->usr_ptr))
+		return -EFAULT;
+	if (put_user((void *)(unsigned long)data, &sgio->usr_ptr))
 		return -EFAULT;
 
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64);
-	set_fs (old_fs);
+	if (copy_in_user(&sgio->status, &sgio32->status,
+			 (4 * sizeof(unsigned char)) +
+			 (2 * sizeof(unsigned (short))) +
+			 (3 * sizeof(int))))
+		return -EFAULT;
 
-	if (err < 0)
-		goto out;
+	err = sys_ioctl(fd, cmd, (unsigned long) sgio);
 
-	err = __put_user(sg_io64.pack_id, &sg_io32->pack_id);
-	err |= __put_user(sg_io64.status, &sg_io32->status);
-	err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status);
-	err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status);
-	err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr);
-	err |= __put_user(sg_io64.host_status, &sg_io32->host_status);
-	err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status);
-	err |= __put_user(sg_io64.resid, &sg_io32->resid);
-	err |= __put_user(sg_io64.duration, &sg_io32->duration);
-	err |= __put_user(sg_io64.info, &sg_io32->info);
-	err |= copy_to_user(compat_ptr(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
-	if (err)
-		err = -EFAULT;
+	if (err >= 0) {
+		void *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;
+	}
 
-out:
-	if (sg_io64.cmdp)
-		kfree(sg_io64.cmdp);
-	if (sg_io64.sbp)
-		kfree(sg_io64.sbp);
-	if (sg_io64.dxferp && sg_io64.iovec_count)
-			free_sg_iovec(&sg_io64);
 	return err;
 }
 
@@ -1241,39 +1182,65 @@
 };
 #define PPPIOCGIDLE32		_IOR('t', 63, struct ppp_idle32)
 
+static int ppp_gidle(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ppp_idle *idle;
+	struct ppp_idle32 *idle32;
+	__kernel_time_t xmit, recv;
+	int err;
+
+	idle = compat_alloc_user_space(sizeof(*idle));
+	idle32 = (struct ppp_idle32 *) arg;
+
+	err = sys_ioctl(fd, PPPIOCGIDLE, (unsigned long) idle);
+
+	if (!err) {
+		if (get_user(xmit, &idle->xmit_idle) ||
+		    get_user(recv, &idle->recv_idle) ||
+		    put_user(xmit, &idle32->xmit_idle) ||
+		    put_user(recv, &idle32->recv_idle))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int ppp_scompress(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ppp_option_data *odata;
+	struct ppp_option_data32 *odata32;
+	__u32 data;
+	void *datap;
+
+	odata = compat_alloc_user_space(sizeof(*odata));
+	odata32 = (struct ppp_option_data32 *) arg;
+
+	if (get_user(data, &odata32->ptr))
+		return -EFAULT;
+
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &odata->ptr))
+		return -EFAULT;
+
+	if (copy_in_user(&odata->length, &odata32->length,
+			 sizeof(__u32) + sizeof(int)))
+		return -EFAULT;
+
+	return sys_ioctl(fd, PPPIOCSCOMPRESS, (unsigned long) odata);
+}
+
 static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	mm_segment_t old_fs = get_fs();
-	struct ppp_option_data32 data32;
-	struct ppp_option_data data;
-	struct ppp_idle32 idle32;
-	struct ppp_idle idle;
-	unsigned int kcmd;
-	void *karg;
-	int err = 0;
+	int err;
 
 	switch (cmd) {
 	case PPPIOCGIDLE32:
-		kcmd = PPPIOCGIDLE;
-		karg = &idle;
+		err = ppp_gidle(fd, cmd, arg);
 		break;
+
 	case PPPIOCSCOMPRESS32:
-		if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32)))
-			return -EFAULT;
-		if (data32.length > PAGE_SIZE) 
-			return -EINVAL;
-		data.ptr = kmalloc (data32.length, GFP_KERNEL);
-		if (!data.ptr)
-			return -ENOMEM;
-		if (copy_from_user(data.ptr, compat_ptr(data32.ptr), data32.length)) {
-			kfree(data.ptr);
-			return -EFAULT;
-		}
-		data.length = data32.length;
-		data.transmit = data32.transmit;
-		kcmd = PPPIOCSCOMPRESS;
-		karg = &data;
+		err = ppp_scompress(fd, cmd, arg);
 		break;
+
 	default:
 		do {
 			static int count;
@@ -1282,26 +1249,10 @@
 				       "cmd(%08x) arg(%08x)\n",
 				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
 		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
-	set_fs (old_fs);
-	switch (cmd) {
-	case PPPIOCGIDLE32:
-		if (err)
-			return err;
-		idle32.xmit_idle = idle.xmit_idle;
-		idle32.recv_idle = idle.recv_idle;
-		if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32)))
-			return -EFAULT;
-		break;
-	case PPPIOCSCOMPRESS32:
-		kfree(data.ptr);
-		break;
-	default:
+		err = -EINVAL;
 		break;
-	}
+	};
+
 	return err;
 }
 
@@ -1429,12 +1380,6 @@
 	return err ? -EFAULT: 0;
 }
 
-struct cdrom_read32 {
-	compat_int_t	cdread_lba;
-	compat_caddr_t	cdread_bufaddr;
-	compat_int_t	cdread_buflen;
-};
-
 struct cdrom_read_audio32 {
 	union cdrom_addr	addr;
 	u8			addr_format;
@@ -1448,60 +1393,94 @@
 	compat_uint_t	buflen;
 	compat_int_t	stat;
 	compat_caddr_t	sense;
-	compat_caddr_t	reserved[3];	/* Oops? it has data_direction, quiet and timeout fields? */
-};
+	unsigned char	data_direction;
+	compat_int_t	quiet;
+	compat_int_t	timeout;
+	compat_caddr_t	reserved[1];
+};
+  
+static int cdrom_do_read_audio(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct cdrom_read_audio *cdread_audio;
+	struct cdrom_read_audio32 *cdread_audio32;
+	__u32 data;
+	void *datap;
+
+	cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
+	cdread_audio32 = (struct cdrom_read_audio32 *) arg;
+
+	if (copy_in_user(&cdread_audio->addr,
+			 &cdread_audio32->addr,
+			 (sizeof(*cdread_audio32) -
+			  sizeof(compat_caddr_t))))
+	 	return -EFAULT;
+
+	if (get_user(data, &cdread_audio32->buf))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &cdread_audio->buf))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long) cdread_audio);
+}
+
+static int __cgc_do_ptr(void **ptr64, __u32 *ptr32)
+{
+	u32 data;
+	void *datap;
+
+	if (get_user(data, ptr32))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, ptr64))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int cdrom_do_generic_command(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct cdrom_generic_command *cgc;
+	struct cdrom_generic_command32 *cgc32;
+	unsigned char dir;
+
+	cgc = compat_alloc_user_space(sizeof(*cgc));
+	cgc32 = (struct cdrom_generic_command32 *) arg;
+
+	if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
+	    __cgc_do_ptr((void **) &cgc->buffer, &cgc32->buffer) ||
+	    copy_in_user(&cgc->buflen, &cgc32->buflen,
+			 (sizeof(unsigned int) + sizeof(int))) ||
+	    __cgc_do_ptr((void **) &cgc->sense, &cgc32->sense))
+		return -EFAULT;
+
+	if (get_user(dir, &cgc->data_direction) ||
+	    put_user(dir, &cgc32->data_direction))
+		return -EFAULT;
+
+	if (copy_in_user(&cgc->quiet, &cgc32->quiet,
+			 2 * sizeof(int)))
+		return -EFAULT;
+
+	if (__cgc_do_ptr(&cgc->reserved[0], &cgc32->reserved[0]))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long) cgc);
+}
 
 static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	mm_segment_t old_fs = get_fs();
-	struct cdrom_read cdread;
-	struct cdrom_read_audio cdreadaudio;
-	struct cdrom_generic_command cgc;
-	compat_caddr_t addr;
-	char *data = 0;
-	void *karg;
-	int err = 0;
+	int err;
 
 	switch(cmd) {
-	case CDROMREADMODE2:
-	case CDROMREADMODE1:
-	case CDROMREADRAW:
-	case CDROMREADCOOKED:
-		karg = &cdread;
-		err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba);
-		err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr);
-		err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen);
-		if (err)
-			return -EFAULT;
-		if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdread.cdread_buflen))
-			return -EFAULT;
-		cdread.cdread_bufaddr = compat_ptr(addr);
-		break;
 	case CDROMREADAUDIO:
-		karg = &cdreadaudio;
-		err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr));
-		err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format);
-		err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); 
-		err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf);
-		if (err)
-			return -EFAULT;
-		
-
-		if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdreadaudio.nframes*2352))
-			return -EFAULT;
-		cdreadaudio.buf = compat_ptr(addr);
+		err = cdrom_do_read_audio(fd, cmd, arg);
 		break;
+
 	case CDROM_SEND_PACKET:
-		karg = &cgc;
-		err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd));
-		err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer);
-		err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
-		if (err)
-			return -EFAULT;
-		if (verify_area(VERIFY_WRITE, compat_ptr(addr), cgc.buflen))
-			return -EFAULT;
-		cgc.buffer = compat_ptr(addr);
+		err = cdrom_do_generic_command(fd, cmd, arg);
 		break;
+
 	default:
 		do {
 			static int count;
@@ -1510,14 +1489,11 @@
 				       "cmd(%08x) arg(%08x)\n",
 				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
 		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)karg);
-	set_fs (old_fs);
-	if (data)
-		kfree(data);
-	return err ? -EFAULT : 0;
+		err = -EINVAL;
+		break;
+	};
+
+	return err;
 }
 
 struct loop_info32 {
@@ -1547,7 +1523,6 @@
 		err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
 		err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
 		err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
-		
 		err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset,
 					   8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
 		if (err) {
@@ -1792,68 +1767,62 @@
 
 static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	struct atm_iobuf32 iobuf32;
-	struct atm_iobuf   iobuf = { 0, NULL };
-	mm_segment_t old_fs;
-	int err;
+	struct atm_iobuf   *iobuf;
+	struct atm_iobuf32 *iobuf32;
+	u32 data;
+	void *datap;
+	int len, err;
 
-	err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg,
-	    sizeof(struct atm_iobuf32));
-	if (err)
+	iobuf = compat_alloc_user_space(sizeof(*iobuf));
+	iobuf32 = (struct atm_iobuf32 *) arg;
+
+	if (get_user(len, &iobuf32->length) ||
+	    get_user(data, &iobuf32->buffer))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(len, &iobuf->length) ||
+	    put_user(datap, &iobuf->buffer))
 		return -EFAULT;
 
-	iobuf.length = iobuf32.length;
+	err = sys_ioctl(fd, cmd, (unsigned long)iobuf);
 
-	if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) {
-		iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
-	} else {
-		iobuf.buffer = compat_ptr(iobuf32.buffer);
-		if (verify_area(VERIFY_WRITE, iobuf.buffer, iobuf.length))
-			return -EINVAL;
+	if (!err) {
+		if (copy_in_user(&iobuf32->length, &iobuf->length,
+				 sizeof(int)))
+			err = -EFAULT;
 	}
 
-	old_fs = get_fs(); set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);      
-	set_fs (old_fs);
-        if(!err)
-	err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
-
 	return err;
 }
 
-
 static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-        struct atmif_sioc32 sioc32;
-        struct atmif_sioc   sioc = { 0, 0, NULL };
-        mm_segment_t old_fs;
-        int err;
+        struct atmif_sioc   *sioc;
+	struct atmif_sioc32 *sioc32;
+	u32 data;
+	void *datap;
+	int err;
         
-        err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg,
-			     sizeof(struct atmif_sioc32));
-        if (err)
-                return -EFAULT;
+	sioc = compat_alloc_user_space(sizeof(*sioc));
+	sioc32 = (struct atmif_sioc32 *) arg;
 
-        sioc.number = sioc32.number;
-        sioc.length = sioc32.length;
-        
-	if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) {
-		sioc.arg = (void*)(unsigned long)sioc32.arg;
-        } else {
-		sioc.arg = compat_ptr(sioc32.arg);
-		if (verify_area(VERIFY_WRITE, sioc.arg, sioc32.length))
-			return -EFAULT;
-        }
-        
-        old_fs = get_fs(); set_fs (KERNEL_DS);
-        err = sys_ioctl (fd, cmd, (unsigned long)&sioc);	
-        set_fs (old_fs);
-	if (!err)
-        err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
+	if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) ||
+	    get_user(data, &sioc32->arg))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &sioc->arg))
+		return -EFAULT;
+
+	err = sys_ioctl(fd, cmd, (unsigned long) sioc);
+
+	if (!err) {
+		if (copy_in_user(&sioc32->length, &sioc->length,
+				 sizeof(int)))
+			err = -EFAULT;
+	}
 	return err;
 }
 
-
 static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
 {
         int i;
@@ -1871,15 +1840,14 @@
 		return do_atmif_sioc(fd, cmd32, arg);
 	}
 
-		for (i = 0; i < NR_ATM_IOCTL; i++) {
-			if (cmd32 == atm_ioctl_map[i].cmd32) {
-				cmd = atm_ioctl_map[i].cmd;
-				break;
-			}
+	for (i = 0; i < NR_ATM_IOCTL; i++) {
+		if (cmd32 == atm_ioctl_map[i].cmd32) {
+			cmd = atm_ioctl_map[i].cmd;
+			break;
 		}
-	        if (i == NR_ATM_IOCTL) {
+	}
+	if (i == NR_ATM_IOCTL)
 	        return -EINVAL;
-	        }
         
         switch (cmd) {
 	case ATM_GETNAMES:
@@ -2310,36 +2278,33 @@
 
 static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	mm_segment_t 			old_fs 	= get_fs();
-	struct mtd_oob_buf32	*uarg 	= (struct mtd_oob_buf32 *)arg;
-	struct mtd_oob_buf		karg;
-	u32 tmp;
-	int ret;
+	struct mtd_oob_buf	*buf = compat_alloc_user_space(sizeof(*buf));
+	struct mtd_oob_buf32	*buf32 = (struct mtd_oob_buf32 *) arg;
+	u32 data;
+	char *datap;
+	unsigned int real_cmd;
+	int err;
 
-	if (get_user(karg.start, &uarg->start) 		||
-	    get_user(karg.length, &uarg->length)	||
-	    get_user(tmp, &uarg->ptr))
-		return -EFAULT;
+	real_cmd = (cmd == MEMREADOOB32) ?
+		MEMREADOOB : MEMWRITEOOB;
 
-	karg.ptr = compat_ptr(tmp); 
-	if (verify_area(VERIFY_WRITE, karg.ptr, karg.length))
+	if (copy_in_user(&buf->start, &buf32->start,
+			 2 * sizeof(u32)) ||
+	    get_user(data, &buf32->ptr))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &buf->ptr))
 		return -EFAULT;
 
-	set_fs(KERNEL_DS);
-	if (MEMREADOOB32 == cmd) 
-		ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg);
-	else if (MEMWRITEOOB32 == cmd)
-		ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg);
-	else
-		ret = -EINVAL;
-	set_fs(old_fs);
+	err = sys_ioctl(fd, real_cmd, (unsigned long) buf);
 
-	if (0 == ret && cmd == MEMREADOOB32) {
-		ret = put_user(karg.start, &uarg->start);
-		ret |= put_user(karg.length, &uarg->length);
+	if (!err) {
+		if (copy_in_user(&buf32->start, &buf->start,
+				 2 * sizeof(u32)))
+			err = -EFAULT;
 	}
 
-	return ret;
+	return err;
 }	
 
 #undef CODE
@@ -2426,12 +2391,7 @@
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
-HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
 HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
 HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)



-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29 11:39                 ` Arjan van de Ven
@ 2003-05-29 20:10                   ` Pavel Machek
  0 siblings, 0 replies; 34+ messages in thread
From: Pavel Machek @ 2003-05-29 20:10 UTC (permalink / raw)
  To: Arjan van de Ven; +Cc: David S. Miller, ak, akpm, linux-kernel

Hi!

> >    What is copy_in_user?
> > 
> > Both source and destination pointers are in userspace.
> 
> sys_memcpy() ?

No, its for in-kernel usage. If you want to copy 10 bytes in
userspace, you can't use memcpy()... You'd have to do copy_from_user()
then copy_to_user(); and that's what copy_in_user does.

							Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-29 20:06             ` Pavel Machek
@ 2003-05-29 21:15               ` David S. Miller
  0 siblings, 0 replies; 34+ messages in thread
From: David S. Miller @ 2003-05-29 21:15 UTC (permalink / raw)
  To: pavel; +Cc: ak, akpm, linux-kernel

   From: Pavel Machek <pavel@suse.cz>
   Date: Thu, 29 May 2003 22:06:18 +0200
   
   Davem, does trivial copy_in_user I created have expected semantics?

Yes, but obviously it's not a fast one :-)

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-28 22:46             ` Andrew Morton
  2003-05-28 23:03               ` Pavel Machek
@ 2003-05-29 11:13               ` Pavel Machek
  1 sibling, 0 replies; 34+ messages in thread
From: Pavel Machek @ 2003-05-29 11:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

Hi!

> > Yes, x86-64 and sparc64 were converted.
> 
> OK, I know who to bug about those.

I'm currently porting davem's 2.4 changes forward. Did you apply the
patch (-> do you want relative patch) or not?
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-28 22:46             ` Andrew Morton
@ 2003-05-28 23:03               ` Pavel Machek
  2003-05-29 11:13               ` Pavel Machek
  1 sibling, 0 replies; 34+ messages in thread
From: Pavel Machek @ 2003-05-28 23:03 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

Hi!

> > Yes, x86-64 and sparc64 were converted.
> 
> OK, I know who to bug about those.
> 
> > It is really #included, sorry
> > about that, but I found no other solution. Patch looks like:
> 
> > +#define INCLUDES
> > +#include "compat_ioctl.c"
> 
> hm, how does the preprocessor locate this file?  Does the build system set
> up a symlink?

I used to put relative path there, now I do:

--- /usr/src/tmp/linux/arch/x86_64/ia32/Makefile        2003-05-27
13:42:40.000000000 +0200
+++ /usr/src/linux/arch/x86_64/ia32/Makefile    2003-05-27
14:58:31.000000000 +0200
@@ -14,3 +14,4 @@
                -o $@ -Wl,-T,$^

 AFLAGS_vsyscall.o = -m32
+CFLAGS_ia32_ioctl.o += -Ifs/

								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
       [not found]           ` <20030528221812.GC255@elf.ucw.cz>
@ 2003-05-28 22:46             ` Andrew Morton
  2003-05-28 23:03               ` Pavel Machek
  2003-05-29 11:13               ` Pavel Machek
  0 siblings, 2 replies; 34+ messages in thread
From: Andrew Morton @ 2003-05-28 22:46 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel

Pavel Machek <pavel@suse.cz> wrote:
>
> Yes, x86-64 and sparc64 were converted.

OK, I know who to bug about those.

> It is really #included, sorry
> about that, but I found no other solution. Patch looks like:

> +#define INCLUDES
> +#include "compat_ioctl.c"

hm, how does the preprocessor locate this file?  Does the build system set
up a symlink?


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-28 21:55       ` Pavel Machek
@ 2003-05-28 22:06         ` Andrew Morton
       [not found]           ` <20030528221812.GC255@elf.ucw.cz>
  0 siblings, 1 reply; 34+ messages in thread
From: Andrew Morton @ 2003-05-28 22:06 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel

Pavel Machek <pavel@suse.cz> wrote:
>
> Here is common part. That should enable architecture maintainers to
> pick it up when *they* need. So it is late but it should not be
> intrusive. Here it is.

 25-akpm/fs/compat_ioctl.c | 2491 ++++++++++++++++++++++++++++++++++++++++++++++

I am utterly clueless when it comes to this 32-bit compat stuff.  How does
the architecture actually use this?  #include it?

Have any architectures been converted?  Any example implementations
available?


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-28 21:48     ` Andrew Morton
@ 2003-05-28 21:55       ` Pavel Machek
  2003-05-28 22:06         ` Andrew Morton
  0 siblings, 1 reply; 34+ messages in thread
From: Pavel Machek @ 2003-05-28 21:55 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

Hi!

> > (and I have patches but Linus ignores
> > them... would it be okay to merge them
> > through you?)
> 
> This is a bit like "arch/foo/kernel/irq.c should be common code".  The
> patch exists, but is late, intrusive and only a cleanup.

Yes, excepts that this time its 2500 lines of crap^Wcode.

> However I think experience teaches us that we should push ahead with
> changes like this because not doing it creates more aggregate pain than
> doing it.
> 
> So yes, please send me your latest and we'll try to get it underway.

Here is common part. That should enable architecture maintainers to
pick it up when *they* need. So it is late but it should not be
intrusive. Here it is.
								Pavel

Index: linux/fs/compat_ioctl.c
===================================================================
--- linux.orig/fs/compat_ioctl.c	2003-05-27 13:46:05.000000000 +0200
+++ linux/fs/compat_ioctl.c	2003-05-27 16:36:47.000000000 +0200
@@ -0,0 +1,2491 @@
+/* $Id: ioc,v 1.16 2003/05/27 17:51:29 pavel Exp $
+ * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
+ *
+ * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
+ * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs 
+ * Copyright (C) 2003       Pavel Machek (pavel@suse.cz)
+ *
+ * These routines maintain argument size conversion between 32bit and 64bit
+ * ioctls.
+ */
+
+#ifdef INCLUDES
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/ioctl.h>
+#include <linux/if.h>
+#include <linux/slab.h>
+#include <linux/hdreg.h>
+#include <linux/raid/md.h>
+#include <linux/kd.h>
+#include <linux/dirent.h>
+#include <linux/route.h>
+#include <linux/in6.h>
+#include <linux/ipv6_route.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/vt.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/fd.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/if_pppox.h>
+#include <linux/mtio.h>
+#include <linux/cdrom.h>
+#include <linux/loop.h>
+#include <linux/auto_fs.h>
+#include <linux/auto_fs4.h>
+#include <linux/devfs_fs.h>
+#include <linux/tty.h>
+#include <linux/vt_kern.h>
+#include <linux/fb.h>
+#include <linux/ext2_fs.h>
+#include <linux/videodev.h>
+#include <linux/netdevice.h>
+#include <linux/raw.h>
+#include <linux/smb_fs.h>
+#include <linux/blkpg.h>
+#include <linux/blk.h>
+#include <linux/elevator.h>
+#include <linux/rtc.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/reiserfs_fs.h>
+#include <linux/if_tun.h>
+#include <linux/dirent.h>
+#include <linux/ctype.h>
+#include <linux/ioctl32.h>
+
+#include <net/sock.h>          /* siocdevprivate_ioctl */
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/rfcomm.h>
+#include <net/bluetooth/hci.h>
+
+#include <scsi/scsi.h>
+/* Ugly hack. */
+#undef __KERNEL__
+#include <scsi/scsi_ioctl.h>
+#define __KERNEL__
+#include <scsi/sg.h>
+
+#include <asm/types.h>
+#include <asm/uaccess.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/if_bonding.h>
+#include <linux/watchdog.h>
+#include <linux/dm-ioctl.h>
+
+#include <asm/module.h>
+#include <linux/soundcard.h>
+#include <linux/lp.h>
+
+#include <linux/atm.h>
+#include <linux/atmarp.h>
+#include <linux/atmclip.h>
+#include <linux/atmdev.h>
+#include <linux/atmioc.h>
+#include <linux/atmlec.h>
+#include <linux/atmmpc.h>
+#include <linux/atmsvc.h>
+#include <linux/atm_tcp.h>
+#include <linux/sonet.h>
+#include <linux/atm_suni.h>
+#include <linux/mtd/mtd.h>
+
+#include <linux/usb.h>
+#include <linux/usbdevice_fs.h>
+#include <linux/nbd.h>
+#include <linux/random.h>
+#include <linux/filter.h>
+
+#undef INCLUDES
+#endif
+
+#ifdef CODE
+
+/* Aiee. Someone does not find a difference between int and long */
+#define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
+#define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
+#define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
+#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
+
+static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	int err;
+	unsigned long val;
+	
+	set_fs (KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&val);
+	set_fs (old_fs);
+	if (!err && put_user(val, (u32 *)arg))
+		return -EFAULT;
+	return err;
+}
+ 
+static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	int err;
+	unsigned long val;
+	
+	if(get_user(val, (u32 *)arg))
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&val);
+	set_fs (old_fs);
+	if (!err && put_user(val, (u32 *)arg))
+		return -EFAULT;
+	return err;
+}
+
+static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	/* These are just misnamed, they actually get/put from/to user an int */
+	switch (cmd) {
+	case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
+	case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
+	case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
+	case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
+	}
+	return sys_ioctl(fd, cmd, arg);
+}
+ 
+struct video_tuner32 {
+	compat_int_t tuner;
+	char name[32];
+	compat_ulong_t rangelow, rangehigh;
+	u32 flags;	/* It is really u32 in videodev.h */
+	u16 mode, signal;
+};
+
+static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up)
+{
+	int i;
+
+	if(get_user(kp->tuner, &up->tuner))
+		return -EFAULT;
+	for(i = 0; i < 32; i++)
+		__get_user(kp->name[i], &up->name[i]);
+	__get_user(kp->rangelow, &up->rangelow);
+	__get_user(kp->rangehigh, &up->rangehigh);
+	__get_user(kp->flags, &up->flags);
+	__get_user(kp->mode, &up->mode);
+	__get_user(kp->signal, &up->signal);
+	return 0;
+}
+
+static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up)
+{
+	int i;
+
+	if(put_user(kp->tuner, &up->tuner))
+		return -EFAULT;
+	for(i = 0; i < 32; i++)
+		__put_user(kp->name[i], &up->name[i]);
+	__put_user(kp->rangelow, &up->rangelow);
+	__put_user(kp->rangehigh, &up->rangehigh);
+	__put_user(kp->flags, &up->flags);
+	__put_user(kp->mode, &up->mode);
+	__put_user(kp->signal, &up->signal);
+	return 0;
+}
+
+struct video_buffer32 {
+	compat_caddr_t base;
+	compat_int_t height, width, depth, bytesperline;
+};
+
+static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up)
+{
+	u32 tmp;
+
+	if(get_user(tmp, &up->base))
+		return -EFAULT;
+	kp->base = (void *) ((unsigned long)tmp);
+	__get_user(kp->height, &up->height);
+	__get_user(kp->width, &up->width);
+	__get_user(kp->depth, &up->depth);
+	__get_user(kp->bytesperline, &up->bytesperline);
+	return 0;
+}
+
+static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up)
+{
+	u32 tmp = (u32)((unsigned long)kp->base);
+
+	if(put_user(tmp, &up->base))
+		return -EFAULT;
+	__put_user(kp->height, &up->height);
+	__put_user(kp->width, &up->width);
+	__put_user(kp->depth, &up->depth);
+	__put_user(kp->bytesperline, &up->bytesperline);
+	return 0;
+}
+
+struct video_clip32 {
+	s32 x, y, width, height;	/* Its really s32 in videodev.h */
+	compat_caddr_t next;
+};
+
+struct video_window32 {
+	u32 x, y, width, height, chromakey, flags;
+	compat_caddr_t clips;
+	compat_int_t clipcount;
+};
+
+static void free_kvideo_clips(struct video_window *kp)
+{
+	struct video_clip *cp;
+
+	cp = kp->clips;
+	if(cp != NULL)
+		kfree(cp);
+}
+
+static int get_video_window32(struct video_window *kp, struct video_window32 *up)
+{
+	struct video_clip32 *ucp;
+	struct video_clip *kcp;
+	int nclips, err, i;
+	u32 tmp;
+
+	if(get_user(kp->x, &up->x))
+		return -EFAULT;
+	__get_user(kp->y, &up->y);
+	__get_user(kp->width, &up->width);
+	__get_user(kp->height, &up->height);
+	__get_user(kp->chromakey, &up->chromakey);
+	__get_user(kp->flags, &up->flags);
+	__get_user(kp->clipcount, &up->clipcount);
+	__get_user(tmp, &up->clips);
+	ucp = compat_ptr(tmp);
+	kp->clips = NULL;
+
+	nclips = kp->clipcount;
+	if(nclips == 0)
+		return 0;
+
+	if(ucp == 0)
+		return -EINVAL;
+
+	/* Peculiar interface... */
+	if(nclips < 0)
+		nclips = VIDEO_CLIPMAP_SIZE;
+
+	kcp = kmalloc(nclips * sizeof(struct video_clip), GFP_KERNEL);
+	err = -ENOMEM;
+	if(kcp == NULL)
+		goto cleanup_and_err;
+
+	kp->clips = kcp;
+	for(i = 0; i < nclips; i++) {
+		__get_user(kcp[i].x, &ucp[i].x);
+		__get_user(kcp[i].y, &ucp[i].y);
+		__get_user(kcp[i].width, &ucp[i].width);
+		__get_user(kcp[i].height, &ucp[i].height);
+		kcp[nclips].next = NULL;
+	}
+
+	return 0;
+
+cleanup_and_err:
+	free_kvideo_clips(kp);
+	return err;
+}
+
+/* You get back everything except the clips... */
+static int put_video_window32(struct video_window *kp, struct video_window32 *up)
+{
+	if(put_user(kp->x, &up->x))
+		return -EFAULT;
+	__put_user(kp->y, &up->y);
+	__put_user(kp->width, &up->width);
+	__put_user(kp->height, &up->height);
+	__put_user(kp->chromakey, &up->chromakey);
+	__put_user(kp->flags, &up->flags);
+	__put_user(kp->clipcount, &up->clipcount);
+	return 0;
+}
+
+#define VIDIOCGTUNER32		_IOWR('v',4, struct video_tuner32)
+#define VIDIOCSTUNER32		_IOW('v',5, struct video_tuner32)
+#define VIDIOCGWIN32		_IOR('v',9, struct video_window32)
+#define VIDIOCSWIN32		_IOW('v',10, struct video_window32)
+#define VIDIOCGFBUF32		_IOR('v',11, struct video_buffer32)
+#define VIDIOCSFBUF32		_IOW('v',12, struct video_buffer32)
+#define VIDIOCGFREQ32		_IOR('v',14, u32)
+#define VIDIOCSFREQ32		_IOW('v',15, u32)
+
+static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	union {
+		struct video_tuner vt;
+		struct video_buffer vb;
+		struct video_window vw;
+		unsigned long vx;
+	} karg;
+	mm_segment_t old_fs = get_fs();
+	void *up = (void *)arg;
+	int err = 0;
+
+	/* First, convert the command. */
+	switch(cmd) {
+	case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
+	case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
+	case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
+	case VIDIOCSWIN32: cmd = VIDIOCSWIN; break;
+	case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
+	case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
+	case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
+	case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
+	};
+
+	switch(cmd) {
+	case VIDIOCSTUNER:
+	case VIDIOCGTUNER:
+		err = get_video_tuner32(&karg.vt, up);
+		break;
+
+	case VIDIOCSWIN:
+		err = get_video_window32(&karg.vw, up);
+		break;
+
+	case VIDIOCSFBUF:
+		err = get_video_buffer32(&karg.vb, up);
+		break;
+
+	case VIDIOCSFREQ:
+		err = get_user(karg.vx, (u32 *)up);
+		break;
+	};
+	if(err)
+		goto out;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&karg);
+	set_fs(old_fs);
+
+	if(cmd == VIDIOCSWIN)
+		free_kvideo_clips(&karg.vw);
+
+	if(err == 0) {
+		switch(cmd) {
+		case VIDIOCGTUNER:
+			err = put_video_tuner32(&karg.vt, up);
+			break;
+
+		case VIDIOCGWIN:
+			err = put_video_window32(&karg.vw, up);
+			break;
+
+		case VIDIOCGFBUF:
+			err = put_video_buffer32(&karg.vb, up);
+			break;
+
+		case VIDIOCGFREQ:
+			err = put_user(((u32)karg.vx), (u32 *)up);
+			break;
+		};
+	}
+out:
+	return err;
+}
+
+static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct compat_timeval *up = (struct compat_timeval *)arg;
+	struct timeval ktv;
+	mm_segment_t old_fs = get_fs();
+	int err;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
+	set_fs(old_fs);
+	if(!err) {
+		err = put_user(ktv.tv_sec, &up->tv_sec);
+		err |= __put_user(ktv.tv_usec, &up->tv_usec);
+	}
+	return err;
+}
+
+struct ifmap32 {
+	compat_ulong_t mem_start;
+	compat_ulong_t mem_end;
+	unsigned short base_addr;
+	unsigned char irq;
+	unsigned char dma;
+	unsigned char port;
+};
+
+struct ifreq32 {
+#define IFHWADDRLEN     6
+#define IFNAMSIZ        16
+        union {
+                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
+        } ifr_ifrn;
+        union {
+                struct  sockaddr ifru_addr;
+                struct  sockaddr ifru_dstaddr;
+                struct  sockaddr ifru_broadaddr;
+                struct  sockaddr ifru_netmask;
+                struct  sockaddr ifru_hwaddr;
+                short   ifru_flags;
+                compat_int_t     ifru_ivalue;
+                compat_int_t     ifru_mtu;
+                struct  ifmap32 ifru_map;
+                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
+		char	ifru_newname[IFNAMSIZ];
+                compat_caddr_t ifru_data;
+	    /* XXXX? ifru_settings should be here */
+        } ifr_ifru;
+};
+
+struct ifconf32 {
+        compat_int_t	ifc_len;                        /* size of buffer       */
+        compat_caddr_t  ifcbuf;
+};
+
+#ifdef CONFIG_NET
+static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct net_device *dev;
+	struct ifreq32 ifr32;
+	int err;
+
+	if (copy_from_user(&ifr32, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+		return -EFAULT;
+
+	dev = dev_get_by_index(ifr32.ifr_ifindex);
+	if (!dev)
+		return -ENODEV;
+
+	strlcpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name));
+	dev_put(dev);
+	
+	err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
+	return (err ? -EFAULT : 0);
+}
+#endif
+
+static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifconf32 ifc32;
+	struct ifconf ifc;
+	struct ifreq32 *ifr32;
+	struct ifreq *ifr;
+	mm_segment_t old_fs;
+	unsigned int i, j;
+	int err;
+
+	if (copy_from_user(&ifc32, (struct ifconf32 *)arg, sizeof(struct ifconf32)))
+		return -EFAULT;
+
+	if(ifc32.ifcbuf == 0) {
+		ifc32.ifc_len = 0;
+		ifc.ifc_len = 0;
+		ifc.ifc_buf = NULL;
+	} else {
+		ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) *
+			sizeof (struct ifreq);
+		ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
+		if (!ifc.ifc_buf)
+			return -ENOMEM;
+	}
+	ifr = ifc.ifc_req;
+	ifr32 = compat_ptr(ifc32.ifcbuf);
+	for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) {
+		if (copy_from_user(ifr, ifr32, sizeof (struct ifreq32))) {
+			kfree (ifc.ifc_buf);
+			return -EFAULT;
+		}
+		ifr++;
+		ifr32++; 
+	}
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);	
+	set_fs (old_fs);
+	if (!err) {
+		ifr = ifc.ifc_req;
+		ifr32 = compat_ptr(ifc32.ifcbuf);
+		for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len;
+		     i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) {
+			int k = copy_to_user(ifr32, ifr, sizeof (struct ifreq32));
+			ifr32++;
+			ifr++;
+			if (k) {
+				err = -EFAULT;
+				break;
+			}
+		       
+		}
+		if (!err) {
+			if (ifc32.ifcbuf == 0) {
+				/* Translate from 64-bit structure multiple to
+				 * a 32-bit one.
+				 */
+				i = ifc.ifc_len;
+				i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32));
+				ifc32.ifc_len = i;
+			} else {
+				if (i <= ifc32.ifc_len)
+					ifc32.ifc_len = i;
+				else
+					ifc32.ifc_len = i - sizeof (struct ifreq32);
+			}
+			if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32)))
+				err = -EFAULT;
+		}
+	}
+	if(ifc.ifc_buf != NULL)
+		kfree (ifc.ifc_buf);
+	return err;
+}
+
+static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq ifr;
+	mm_segment_t old_fs;
+	int err, len;
+	u32 data, ethcmd;
+	
+	if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+		return -EFAULT;
+	ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL);
+	if (!ifr.ifr_data)
+		return -EAGAIN;
+
+	__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+
+	if (get_user(ethcmd, (u32 *)compat_ptr(data))) {
+		err = -EFAULT;
+		goto out;
+	}
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO:	len = sizeof(struct ethtool_drvinfo); break;
+	case ETHTOOL_GMSGLVL:
+	case ETHTOOL_SMSGLVL:
+	case ETHTOOL_GLINK:
+	case ETHTOOL_NWAY_RST:  len = sizeof(struct ethtool_value); break;
+	case ETHTOOL_GREGS: {
+		struct ethtool_regs *regaddr = compat_ptr(data);
+		/* darned variable size arguments */
+		if (get_user(len, (u32 *)&regaddr->len)) {
+			err = -EFAULT;
+			goto out;
+		}
+		if (len > PAGE_SIZE - sizeof(struct ethtool_regs)) { 
+			err = -EINVAL;
+			goto out;
+		}			
+		len += sizeof(struct ethtool_regs);
+		break;
+	}
+	case ETHTOOL_GSET:
+	case ETHTOOL_SSET:      len = sizeof(struct ethtool_cmd); break;
+	default:
+               err = -EOPNOTSUPP;
+               goto out;
+	}
+
+	if (copy_from_user(ifr.ifr_data, compat_ptr(data), len)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+	set_fs (old_fs);
+	if (!err) {
+		u32 data;
+
+		__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+		len = copy_to_user(compat_ptr(data), ifr.ifr_data, len);
+		if (len)
+			err = -EFAULT;
+	}
+
+out:
+	free_page((unsigned long)ifr.ifr_data);
+	return err;
+}
+
+
+static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq ifr;
+	mm_segment_t old_fs;
+	int err, len;
+	u32 data;
+	
+	if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+		return -EFAULT;
+	ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL);
+	if (!ifr.ifr_data)
+		return -EAGAIN;
+
+	switch (cmd) {
+	case SIOCBONDENSLAVE:
+	case SIOCBONDRELEASE:
+	case SIOCBONDSETHWADDR:
+	case SIOCBONDCHANGEACTIVE:
+		len = IFNAMSIZ * sizeof(char);
+		break;
+	case SIOCBONDSLAVEINFOQUERY:
+		len = sizeof(struct ifslave);
+		break;
+	case SIOCBONDINFOQUERY:
+		len = sizeof(struct ifbond);
+		break;
+	default:
+		err = -EINVAL;
+		goto out;
+	};
+
+	__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+	if (copy_from_user(ifr.ifr_data, compat_ptr(data), len)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+	set_fs (old_fs);
+	if (!err) {
+		len = copy_to_user(compat_ptr(data), ifr.ifr_data, len);
+		if (len)
+			err = -EFAULT;
+	}
+
+out:
+	free_page((unsigned long)ifr.ifr_data);
+	return err;
+}
+
+int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq *u_ifreq64;
+	struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg;
+	char tmp_buf[IFNAMSIZ];
+	void *data64;
+	u32 data32;
+
+	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
+			   IFNAMSIZ))
+		return -EFAULT;
+	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
+		return -EFAULT;
+	data64 = compat_ptr(data32);
+
+	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
+
+	/* Don't check these user accesses, just let that get trapped
+	 * in the ioctl handler instead.
+	 */
+	copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ);
+	__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data);
+
+	return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64);
+}
+
+static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq ifr;
+	mm_segment_t old_fs;
+	int err;
+	
+	switch (cmd) {
+	case SIOCSIFMAP:
+		err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name));
+		err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
+		err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
+		err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
+		err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
+		err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
+		err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
+		if (err)
+			return -EFAULT;
+		break;
+	default:
+		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+			return -EFAULT;
+		break;
+	}
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+	set_fs (old_fs);
+	if (!err) {
+		switch (cmd) {
+		case SIOCGIFFLAGS:
+		case SIOCGIFMETRIC:
+		case SIOCGIFMTU:
+		case SIOCGIFMEM:
+		case SIOCGIFHWADDR:
+		case SIOCGIFINDEX:
+		case SIOCGIFADDR:
+		case SIOCGIFBRDADDR:
+		case SIOCGIFDSTADDR:
+		case SIOCGIFNETMASK:
+		case SIOCGIFTXQLEN:
+			if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32)))
+				return -EFAULT;
+			break;
+		case SIOCGIFMAP:
+			err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name));
+			err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
+			err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
+			err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
+			err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
+			err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
+			err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
+			if (err)
+				err = -EFAULT;
+			break;
+		}
+	}
+	return err;
+}
+
+struct rtentry32 {
+        u32   		rt_pad1;
+        struct sockaddr rt_dst;         /* target address               */
+        struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
+        struct sockaddr rt_genmask;     /* target network mask (IP)     */
+        unsigned short  rt_flags;
+        short           rt_pad2;
+        u32   		rt_pad3;
+        unsigned char   rt_tos;
+        unsigned char   rt_class;
+        short           rt_pad4;
+        short           rt_metric;      /* +1 for binary compatibility! */
+        /* char * */ u32 rt_dev;        /* forcing the device at add    */
+        u32   		rt_mtu;         /* per route MTU/Window         */
+        u32   		rt_window;      /* Window clamping              */
+        unsigned short  rt_irtt;        /* Initial RTT                  */
+
+};
+
+struct in6_rtmsg32 {
+	struct in6_addr		rtmsg_dst;
+	struct in6_addr		rtmsg_src;
+	struct in6_addr		rtmsg_gateway;
+	u32			rtmsg_type;
+	u16			rtmsg_dst_len;
+	u16			rtmsg_src_len;
+	u32			rtmsg_metric;
+	u32			rtmsg_info;
+	u32			rtmsg_flags;
+	s32			rtmsg_ifindex;
+};
+
+static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+	void *r = NULL;
+	struct in6_rtmsg r6;
+	struct rtentry r4;
+	char devname[16];
+	u32 rtdev;
+	mm_segment_t old_fs = get_fs();
+	
+	struct socket *mysock = sockfd_lookup(fd, &ret);
+
+	if (mysock && mysock->sk && mysock->sk->family == AF_INET6) { /* ipv6 */
+		ret = copy_from_user (&r6.rtmsg_dst, &(((struct in6_rtmsg32 *)arg)->rtmsg_dst),
+			3 * sizeof(struct in6_addr));
+		ret |= __get_user (r6.rtmsg_type, &(((struct in6_rtmsg32 *)arg)->rtmsg_type));
+		ret |= __get_user (r6.rtmsg_dst_len, &(((struct in6_rtmsg32 *)arg)->rtmsg_dst_len));
+		ret |= __get_user (r6.rtmsg_src_len, &(((struct in6_rtmsg32 *)arg)->rtmsg_src_len));
+		ret |= __get_user (r6.rtmsg_metric, &(((struct in6_rtmsg32 *)arg)->rtmsg_metric));
+		ret |= __get_user (r6.rtmsg_info, &(((struct in6_rtmsg32 *)arg)->rtmsg_info));
+		ret |= __get_user (r6.rtmsg_flags, &(((struct in6_rtmsg32 *)arg)->rtmsg_flags));
+		ret |= __get_user (r6.rtmsg_ifindex, &(((struct in6_rtmsg32 *)arg)->rtmsg_ifindex));
+		
+		r = (void *) &r6;
+	} else { /* ipv4 */
+		ret = copy_from_user (&r4.rt_dst, &(((struct rtentry32 *)arg)->rt_dst), 3 * sizeof(struct sockaddr));
+		ret |= __get_user (r4.rt_flags, &(((struct rtentry32 *)arg)->rt_flags));
+		ret |= __get_user (r4.rt_metric, &(((struct rtentry32 *)arg)->rt_metric));
+		ret |= __get_user (r4.rt_mtu, &(((struct rtentry32 *)arg)->rt_mtu));
+		ret |= __get_user (r4.rt_window, &(((struct rtentry32 *)arg)->rt_window));
+		ret |= __get_user (r4.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt));
+		ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev));
+		if (rtdev) {
+			ret |= copy_from_user (devname, compat_ptr(rtdev), 15);
+			r4.rt_dev = devname; devname[15] = 0;
+		} else
+			r4.rt_dev = 0;
+
+		r = (void *) &r4;
+	}
+
+	if (ret)
+		return -EFAULT;
+
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl (fd, cmd, (long) r);
+	set_fs (old_fs);
+
+	if (mysock)
+		sockfd_put(mysock);
+
+	return ret;
+}
+
+struct hd_geometry32 {
+	unsigned char heads;
+	unsigned char sectors;
+	unsigned short cylinders;
+	u32 start;
+};
+                        
+static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct hd_geometry geo;
+	int err;
+	
+	set_fs (KERNEL_DS);
+	err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo);
+	set_fs (old_fs);
+	if (!err) {
+		err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4);
+		err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start));
+	}
+	return err ? -EFAULT : 0;
+}
+
+struct fb_fix_screeninfo32 {
+	char			id[16];
+        compat_caddr_t	smem_start;
+	u32			smem_len;
+	u32			type;
+	u32			type_aux;
+	u32			visual;
+	u16			xpanstep;
+	u16			ypanstep;
+	u16			ywrapstep;
+	u32			line_length;
+        compat_caddr_t	mmio_start;
+	u32			mmio_len;
+	u32			accel;
+	u16			reserved[3];
+};
+
+struct fb_cmap32 {
+	u32			start;
+	u32			len;
+	compat_caddr_t	red;
+	compat_caddr_t	green;
+	compat_caddr_t	blue;
+	compat_caddr_t	transp;
+};
+
+static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	u32 red = 0, green = 0, blue = 0, transp = 0;
+	struct fb_fix_screeninfo fix;
+	struct fb_cmap cmap;
+	void *karg;
+	int err = 0;
+
+	memset(&cmap, 0, sizeof(cmap));
+	switch (cmd) {
+	case FBIOGET_FSCREENINFO:
+		karg = &fix;
+		break;
+	case FBIOGETCMAP:
+	case FBIOPUTCMAP:
+		karg = &cmap;
+		err = __get_user(cmap.start, &((struct fb_cmap32 *)arg)->start);
+		err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len);
+		err |= __get_user(red, &((struct fb_cmap32 *)arg)->red);
+		err |= __get_user(green, &((struct fb_cmap32 *)arg)->green);
+		err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue);
+		err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp);
+		if (err) {
+			err = -EFAULT;
+			goto out;
+		}
+		if (cmap.len > PAGE_SIZE/sizeof(u16)) { 
+			err = -EINVAL;
+			goto out;
+		}
+		err = -ENOMEM;
+		cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+		if (!cmap.red)
+			goto out;
+		cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+		if (!cmap.green)
+			goto out;
+		cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+		if (!cmap.blue)
+			goto out;
+		if (transp) {
+			cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+			if (!cmap.transp)
+				goto out;
+		}
+			
+		if (cmd == FBIOGETCMAP)
+			break;
+
+		err = __copy_from_user(cmap.red, compat_ptr(red), cmap.len * sizeof(__u16));
+		err |= __copy_from_user(cmap.green, compat_ptr(green), cmap.len * sizeof(__u16));
+		err |= __copy_from_user(cmap.blue, compat_ptr(blue), cmap.len * sizeof(__u16));
+		if (cmap.transp) err |= __copy_from_user(cmap.transp, compat_ptr(transp), cmap.len * sizeof(__u16));
+		if (err) {
+			err = -EFAULT;
+			goto out;
+		}
+		break;
+	default:
+		do {
+			static int count;
+			if (++count <= 20)
+				printk("%s: Unknown fb ioctl cmd fd(%d) "
+				       "cmd(%08x) arg(%08lx)\n",
+				       __FUNCTION__, fd, cmd, arg);
+		} while(0);
+		return -ENOSYS;
+	}
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)karg);
+	set_fs(old_fs);
+	if (err)
+		goto out;
+	switch (cmd) {
+	case FBIOGET_FSCREENINFO:
+		err = __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->id, (char *)fix.id, sizeof(fix.id));
+		err |= __put_user((__u32)(unsigned long)fix.smem_start, &((struct fb_fix_screeninfo32 *)arg)->smem_start);
+		err |= __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)arg)->smem_len);
+		err |= __put_user(fix.type, &((struct fb_fix_screeninfo32 *)arg)->type);
+		err |= __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)arg)->type_aux);
+		err |= __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)arg)->visual);
+		err |= __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)arg)->xpanstep);
+		err |= __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)arg)->ypanstep);
+		err |= __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)arg)->ywrapstep);
+		err |= __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)arg)->line_length);
+		err |= __put_user((__u32)(unsigned long)fix.mmio_start, &((struct fb_fix_screeninfo32 *)arg)->mmio_start);
+		err |= __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)arg)->mmio_len);
+		err |= __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)arg)->accel);
+		err |= __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->reserved, (char *)fix.reserved, sizeof(fix.reserved));
+		break;
+	case FBIOGETCMAP:
+		err = __copy_to_user(compat_ptr(red), cmap.red, cmap.len * sizeof(__u16));
+		err |= __copy_to_user(compat_ptr(green), cmap.blue, cmap.len * sizeof(__u16));
+		err |= __copy_to_user(compat_ptr(blue), cmap.blue, cmap.len * sizeof(__u16));
+		if (cmap.transp)
+			err |= __copy_to_user(compat_ptr(transp), cmap.transp, cmap.len * sizeof(__u16));
+		break;
+	case FBIOPUTCMAP:
+		break;
+	}
+	if (err)
+		err = -EFAULT;
+
+out:	if (cmap.red) kfree(cmap.red);
+	if (cmap.green) kfree(cmap.green);
+	if (cmap.blue) kfree(cmap.blue);
+	if (cmap.transp) kfree(cmap.transp);
+	return err;
+}
+
+static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	unsigned long kval;
+	unsigned int *uvp;
+	int error;
+
+	set_fs(KERNEL_DS);
+	error = sys_ioctl(fd, cmd, (long)&kval);
+	set_fs(old_fs);
+
+	if(error == 0) {
+		uvp = (unsigned int *)arg;
+		if(put_user(kval, uvp))
+			error = -EFAULT;
+	}
+	return error;
+}
+
+
+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;
+
+#define EMU_SG_MAX 128
+
+static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
+{
+	sg_iovec32_t *uiov = compat_ptr(uptr32);
+	sg_iovec_t *kiov;
+	int i;
+
+	if (sgp->iovec_count > EMU_SG_MAX)
+		return -EINVAL;
+	sgp->dxferp = kmalloc(sgp->iovec_count *
+			      sizeof(sg_iovec_t), GFP_KERNEL);
+	if (!sgp->dxferp)
+		return -ENOMEM;
+	memset(sgp->dxferp, 0,
+	       sgp->iovec_count * sizeof(sg_iovec_t));
+
+	kiov = (sg_iovec_t *) sgp->dxferp;
+	for (i = 0; i < sgp->iovec_count; i++) {
+		u32 iov_base32;
+		if (__get_user(iov_base32, &uiov->iov_base) ||
+		    __get_user(kiov->iov_len, &uiov->iov_len))
+			return -EFAULT;
+		if (verify_area(VERIFY_WRITE, compat_ptr(iov_base32), kiov->iov_len))
+			return -EFAULT;
+		kiov->iov_base = compat_ptr(iov_base32);
+		uiov++;
+		kiov++;
+	}
+
+	return 0;
+}
+
+static void free_sg_iovec(sg_io_hdr_t *sgp)
+{
+	kfree(sgp->dxferp);
+	sgp->dxferp = NULL;
+}
+
+static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	sg_io_hdr32_t *sg_io32;
+	sg_io_hdr_t sg_io64;
+	u32 dxferp32, cmdp32, sbp32;
+	mm_segment_t old_fs;
+	int err = 0;
+
+	sg_io32 = (sg_io_hdr32_t *)arg;
+	err = __get_user(sg_io64.interface_id, &sg_io32->interface_id);
+	err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction);
+	err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len);
+	err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len);
+	err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count);
+	err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len);
+	err |= __get_user(sg_io64.timeout, &sg_io32->timeout);
+	err |= __get_user(sg_io64.flags, &sg_io32->flags);
+	err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id);
+
+	sg_io64.dxferp = NULL;
+	sg_io64.cmdp = NULL;
+	sg_io64.sbp = NULL;
+
+	err |= __get_user(cmdp32, &sg_io32->cmdp);
+	sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
+	if (copy_from_user(sg_io64.cmdp,
+			   compat_ptr(cmdp32),
+			   sg_io64.cmd_len)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	err |= __get_user(sbp32, &sg_io32->sbp);
+	sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
+	if (!sg_io64.sbp) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(sg_io64.sbp,
+			   compat_ptr(sbp32),
+			   sg_io64.mx_sb_len)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	err |= __get_user(dxferp32, &sg_io32->dxferp);
+	if (sg_io64.iovec_count) {
+		int ret;
+
+		if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) {
+			err = ret;
+			goto out;
+		}
+	} else {
+		err = verify_area(VERIFY_WRITE, compat_ptr(dxferp32), sg_io64.dxfer_len);
+		if (err) 
+			goto out;
+
+		sg_io64.dxferp = compat_ptr(dxferp32); 
+	}
+
+	/* Unused internally, do not even bother to copy it over. */
+	sg_io64.usr_ptr = NULL;
+
+	if (err)
+		return -EFAULT;
+
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64);
+	set_fs (old_fs);
+
+	if (err < 0)
+		goto out;
+
+	err = __put_user(sg_io64.pack_id, &sg_io32->pack_id);
+	err |= __put_user(sg_io64.status, &sg_io32->status);
+	err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status);
+	err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status);
+	err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr);
+	err |= __put_user(sg_io64.host_status, &sg_io32->host_status);
+	err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status);
+	err |= __put_user(sg_io64.resid, &sg_io32->resid);
+	err |= __put_user(sg_io64.duration, &sg_io32->duration);
+	err |= __put_user(sg_io64.info, &sg_io32->info);
+	err |= copy_to_user(compat_ptr(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
+	if (err)
+		err = -EFAULT;
+
+out:
+	if (sg_io64.cmdp)
+		kfree(sg_io64.cmdp);
+	if (sg_io64.sbp)
+		kfree(sg_io64.sbp);
+	if (sg_io64.dxferp && sg_io64.iovec_count)
+			free_sg_iovec(&sg_io64);
+	return err;
+}
+
+struct sock_fprog32 {
+	unsigned short	len;
+	compat_caddr_t	filter;
+};
+
+#define PPPIOCSPASS32	_IOW('t', 71, struct sock_fprog32)
+#define PPPIOCSACTIVE32	_IOW('t', 70, struct sock_fprog32)
+
+static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg;
+	struct sock_fprog *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
+	void *fptr64;
+	u32 fptr32;
+	u16 flen;
+
+	if (get_user(flen, &u_fprog32->len) ||
+	    get_user(fptr32, &u_fprog32->filter))
+		return -EFAULT;
+
+	fptr64 = compat_ptr(fptr32);
+
+	if (put_user(flen, &u_fprog64->len) ||
+	    put_user(fptr64, &u_fprog64->filter))
+		return -EFAULT;
+
+	if (cmd == PPPIOCSPASS32)
+		cmd = PPPIOCSPASS;
+	else
+		cmd = PPPIOCSACTIVE;
+
+	return sys_ioctl(fd, cmd, (unsigned long) u_fprog64);
+}
+
+struct ppp_option_data32 {
+	compat_caddr_t	ptr;
+	u32			length;
+	compat_int_t		transmit;
+};
+#define PPPIOCSCOMPRESS32	_IOW('t', 77, struct ppp_option_data32)
+
+struct ppp_idle32 {
+	compat_time_t xmit_idle;
+	compat_time_t recv_idle;
+};
+#define PPPIOCGIDLE32		_IOR('t', 63, struct ppp_idle32)
+
+static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct ppp_option_data32 data32;
+	struct ppp_option_data data;
+	struct ppp_idle32 idle32;
+	struct ppp_idle idle;
+	unsigned int kcmd;
+	void *karg;
+	int err = 0;
+
+	switch (cmd) {
+	case PPPIOCGIDLE32:
+		kcmd = PPPIOCGIDLE;
+		karg = &idle;
+		break;
+	case PPPIOCSCOMPRESS32:
+		if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32)))
+			return -EFAULT;
+		if (data32.length > PAGE_SIZE) 
+			return -EINVAL;
+		data.ptr = kmalloc (data32.length, GFP_KERNEL);
+		if (!data.ptr)
+			return -ENOMEM;
+		if (copy_from_user(data.ptr, compat_ptr(data32.ptr), data32.length)) {
+			kfree(data.ptr);
+			return -EFAULT;
+		}
+		data.length = data32.length;
+		data.transmit = data32.transmit;
+		kcmd = PPPIOCSCOMPRESS;
+		karg = &data;
+		break;
+	default:
+		do {
+			static int count;
+			if (++count <= 20)
+				printk("ppp_ioctl: Unknown cmd fd(%d) "
+				       "cmd(%08x) arg(%08x)\n",
+				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
+		return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
+	set_fs (old_fs);
+	switch (cmd) {
+	case PPPIOCGIDLE32:
+		if (err)
+			return err;
+		idle32.xmit_idle = idle.xmit_idle;
+		idle32.recv_idle = idle.recv_idle;
+		if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32)))
+			return -EFAULT;
+		break;
+	case PPPIOCSCOMPRESS32:
+		kfree(data.ptr);
+		break;
+	default:
+		break;
+	}
+	return err;
+}
+
+
+struct mtget32 {
+	compat_long_t	mt_type;
+	compat_long_t	mt_resid;
+	compat_long_t	mt_dsreg;
+	compat_long_t	mt_gstat;
+	compat_long_t	mt_erreg;
+	compat_daddr_t	mt_fileno;
+	compat_daddr_t	mt_blkno;
+};
+#define MTIOCGET32	_IOR('m', 2, struct mtget32)
+
+struct mtpos32 {
+	compat_long_t	mt_blkno;
+};
+#define MTIOCPOS32	_IOR('m', 3, struct mtpos32)
+
+struct mtconfiginfo32 {
+	compat_long_t	mt_type;
+	compat_long_t	ifc_type;
+	unsigned short	irqnr;
+	unsigned short	dmanr;
+	unsigned short	port;
+	compat_ulong_t	debug;
+	compat_uint_t	have_dens:1;
+	compat_uint_t	have_bsf:1;
+	compat_uint_t	have_fsr:1;
+	compat_uint_t	have_bsr:1;
+	compat_uint_t	have_eod:1;
+	compat_uint_t	have_seek:1;
+	compat_uint_t	have_tell:1;
+	compat_uint_t	have_ras1:1;
+	compat_uint_t	have_ras2:1;
+	compat_uint_t	have_ras3:1;
+	compat_uint_t	have_qfa:1;
+	compat_uint_t	pad1:5;
+	char	reserved[10];
+};
+#define	MTIOCGETCONFIG32	_IOR('m', 4, struct mtconfiginfo32)
+#define	MTIOCSETCONFIG32	_IOW('m', 5, struct mtconfiginfo32)
+
+static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct mtconfiginfo info;
+	struct mtget get;
+	struct mtpos pos;
+	unsigned long kcmd;
+	void *karg;
+	int err = 0;
+
+	switch(cmd) {
+	case MTIOCPOS32:
+		kcmd = MTIOCPOS;
+		karg = &pos;
+		break;
+	case MTIOCGET32:
+		kcmd = MTIOCGET;
+		karg = &get;
+		break;
+	case MTIOCGETCONFIG32:
+		kcmd = MTIOCGETCONFIG;
+		karg = &info;
+		break;
+	case MTIOCSETCONFIG32:
+		kcmd = MTIOCSETCONFIG;
+		karg = &info;
+		err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
+		err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
+		err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
+		err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
+		err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
+		err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
+		err |= __copy_from_user((char *)&info.debug + sizeof(info.debug),
+				     (char *)&((struct mtconfiginfo32 *)arg)->debug
+				     + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32));
+		if (err)
+			return -EFAULT;
+		break;
+	default:
+		do {
+			static int count;
+			if (++count <= 20)
+				printk("mt_ioctl: Unknown cmd fd(%d) "
+				       "cmd(%08x) arg(%08x)\n",
+				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
+		return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
+	set_fs (old_fs);
+	if (err)
+		return err;
+	switch (cmd) {
+	case MTIOCPOS32:
+		err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno);
+		break;
+	case MTIOCGET32:
+		err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type);
+		err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid);
+		err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg);
+		err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat);
+		err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg);
+		err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno);
+		err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno);
+		break;
+	case MTIOCGETCONFIG32:
+		err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
+		err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
+		err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
+		err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
+		err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
+		err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
+		err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug
+			    		   + sizeof(((struct mtconfiginfo32 *)arg)->debug),
+					   (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
+		break;
+	case MTIOCSETCONFIG32:
+		break;
+	}
+	return err ? -EFAULT: 0;
+}
+
+struct cdrom_read32 {
+	compat_int_t	cdread_lba;
+	compat_caddr_t	cdread_bufaddr;
+	compat_int_t	cdread_buflen;
+};
+
+struct cdrom_read_audio32 {
+	union cdrom_addr	addr;
+	u8			addr_format;
+	compat_int_t		nframes;
+	compat_caddr_t		buf;
+};
+
+struct cdrom_generic_command32 {
+	unsigned char	cmd[CDROM_PACKET_SIZE];
+	compat_caddr_t	buffer;
+	compat_uint_t	buflen;
+	compat_int_t	stat;
+	compat_caddr_t	sense;
+	compat_caddr_t	reserved[3];	/* Oops? it has data_direction, quiet and timeout fields? */
+};
+
+static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct cdrom_read cdread;
+	struct cdrom_read_audio cdreadaudio;
+	struct cdrom_generic_command cgc;
+	compat_caddr_t addr;
+	char *data = 0;
+	void *karg;
+	int err = 0;
+
+	switch(cmd) {
+	case CDROMREADMODE2:
+	case CDROMREADMODE1:
+	case CDROMREADRAW:
+	case CDROMREADCOOKED:
+		karg = &cdread;
+		err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba);
+		err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr);
+		err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen);
+		if (err)
+			return -EFAULT;
+		if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdread.cdread_buflen))
+			return -EFAULT;
+		cdread.cdread_bufaddr = compat_ptr(addr);
+		break;
+	case CDROMREADAUDIO:
+		karg = &cdreadaudio;
+		err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr));
+		err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format);
+		err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); 
+		err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf);
+		if (err)
+			return -EFAULT;
+		
+
+		if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdreadaudio.nframes*2352))
+			return -EFAULT;
+		cdreadaudio.buf = compat_ptr(addr);
+		break;
+	case CDROM_SEND_PACKET:
+		karg = &cgc;
+		err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd));
+		err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer);
+		err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
+		if (err)
+			return -EFAULT;
+		if (verify_area(VERIFY_WRITE, compat_ptr(addr), cgc.buflen))
+			return -EFAULT;
+		cgc.buffer = compat_ptr(addr);
+		break;
+	default:
+		do {
+			static int count;
+			if (++count <= 20)
+				printk("cdrom_ioctl: Unknown cmd fd(%d) "
+				       "cmd(%08x) arg(%08x)\n",
+				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
+		return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)karg);
+	set_fs (old_fs);
+	if (data)
+		kfree(data);
+	return err ? -EFAULT : 0;
+}
+
+struct loop_info32 {
+	compat_int_t	lo_number;      /* ioctl r/o */
+	compat_dev_t	lo_device;      /* ioctl r/o */
+	compat_ulong_t	lo_inode;       /* ioctl r/o */
+	compat_dev_t	lo_rdevice;     /* ioctl r/o */
+	compat_int_t	lo_offset;
+	compat_int_t	lo_encrypt_type;
+	compat_int_t	lo_encrypt_key_size;    /* ioctl w/o */
+	compat_int_t	lo_flags;       /* ioctl r/o */
+	char		lo_name[LO_NAME_SIZE];
+	unsigned char	lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+	compat_ulong_t	lo_init[2];
+	char		reserved[4];
+};
+
+static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct loop_info l;
+	int err = -EINVAL;
+
+	switch(cmd) {
+	case LOOP_SET_STATUS:
+		err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
+		err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
+		err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
+		err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
+		
+		err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset,
+					   8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
+		if (err) {
+			err = -EFAULT;
+		} else {
+			set_fs (KERNEL_DS);
+			err = sys_ioctl (fd, cmd, (unsigned long)&l);
+			set_fs (old_fs);
+		}
+		break;
+	case LOOP_GET_STATUS:
+		set_fs (KERNEL_DS);
+		err = sys_ioctl (fd, cmd, (unsigned long)&l);
+		set_fs (old_fs);
+		if (!err) {
+			err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
+			err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
+			err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
+			err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
+			err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset,
+					   (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
+			if (err)
+				err = -EFAULT;
+		}
+		break;
+	default: {
+		static int count;
+		if (++count <= 20)
+			printk("%s: Unknown loop ioctl cmd, fd(%d) "
+			       "cmd(%08x) arg(%08lx)\n",
+			       __FUNCTION__, fd, cmd, arg);
+	}
+	}
+	return err;
+}
+
+extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
+
+static int vt_check(struct file *file)
+{
+	struct tty_struct *tty;
+	struct inode *inode = file->f_dentry->d_inode;
+	
+	if (file->f_op->ioctl != tty_ioctl)
+		return -EINVAL;
+	                
+	tty = (struct tty_struct *)file->private_data;
+	if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
+		return -EINVAL;
+	                                                
+	if (tty->driver->ioctl != vt_ioctl)
+		return -EINVAL;
+	
+	/*
+	 * To have permissions to do most of the vt ioctls, we either have
+	 * to be the owner of the tty, or super-user.
+	 */
+	if (current->tty == tty || capable(CAP_SYS_ADMIN))
+		return 1;
+	return 0;                                                    
+}
+
+struct consolefontdesc32 {
+	unsigned short charcount;       /* characters in font (256 or 512) */
+	unsigned short charheight;      /* scan lines per character (1-32) */
+	compat_caddr_t chardata;	/* font data in expanded form */
+};
+
+static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file)
+{
+	struct consolefontdesc cfdarg;
+	struct console_font_op op;
+	int i, perm;
+
+	perm = vt_check(file);
+	if (perm < 0) return perm;
+	
+	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32)))
+		return -EFAULT;
+	
+	cfdarg.chardata = compat_ptr(((struct consolefontdesc32 *)&cfdarg)->chardata);
+ 	
+	switch (cmd) {
+	case PIO_FONTX:
+		if (!perm)
+			return -EPERM;
+		op.op = KD_FONT_OP_SET;
+		op.flags = 0;
+		op.width = 8;
+		op.height = cfdarg.charheight;
+		op.charcount = cfdarg.charcount;
+		op.data = cfdarg.chardata;
+		return con_font_op(fg_console, &op);
+	case GIO_FONTX:
+		if (!cfdarg.chardata)
+			return 0;
+		op.op = KD_FONT_OP_GET;
+		op.flags = 0;
+		op.width = 8;
+		op.height = cfdarg.charheight;
+		op.charcount = cfdarg.charcount;
+		op.data = cfdarg.chardata;
+		i = con_font_op(fg_console, &op);
+		if (i)
+			return i;
+		cfdarg.charheight = op.height;
+		cfdarg.charcount = op.charcount;
+		((struct consolefontdesc32 *)&cfdarg)->chardata	= (unsigned long)cfdarg.chardata;
+		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32)))
+			return -EFAULT;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct console_font_op32 {
+	compat_uint_t op;        /* operation code KD_FONT_OP_* */
+	compat_uint_t flags;     /* KD_FONT_FLAG_* */
+	compat_uint_t width, height;     /* font size */
+	compat_uint_t charcount;
+	compat_caddr_t data;    /* font data with height fixed to 32 */
+};
+                                        
+static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file)
+{
+	struct console_font_op op;
+	int perm = vt_check(file), i;
+	struct vt_struct *vt;
+	
+	if (perm < 0) return perm;
+	
+	if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32)))
+		return -EFAULT;
+	if (!perm && op.op != KD_FONT_OP_GET)
+		return -EPERM;
+	op.data = compat_ptr(((struct console_font_op32 *)&op)->data);
+	op.flags |= KD_FONT_FLAG_OLD;
+	vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data;
+	i = con_font_op(vt->vc_num, &op);
+	if (i) return i;
+	((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
+	if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32)))
+		return -EFAULT;
+	return 0;
+}
+
+struct unimapdesc32 {
+	unsigned short entry_ct;
+	compat_caddr_t entries;
+};
+
+static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc32 *user_ud, struct file *file)
+{
+	struct unimapdesc32 tmp;
+	int perm = vt_check(file);
+	
+	if (perm < 0) return perm;
+	if (copy_from_user(&tmp, user_ud, sizeof tmp))
+		return -EFAULT;
+	switch (cmd) {
+	case PIO_UNIMAP:
+		if (!perm) return -EPERM;
+		return con_set_unimap(fg_console, tmp.entry_ct, compat_ptr(tmp.entries));
+	case GIO_UNIMAP:
+		return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
+	}
+	return 0;
+}
+
+static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	__kernel_uid_t kuid;
+	int err;
+
+	cmd = SMB_IOC_GETMOUNTUID;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
+	set_fs(old_fs);
+
+	if (err >= 0)
+		err = put_user(kuid, (compat_pid_t *)arg);
+
+	return err;
+}
+
+struct atmif_sioc32 {
+        compat_int_t	number;
+        compat_int_t	length;
+        compat_caddr_t	arg;
+};
+
+struct atm_iobuf32 {
+	compat_int_t	length;
+	compat_caddr_t	buffer;
+};
+
+#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
+#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
+#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
+#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
+#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
+#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32)
+#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32)
+#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32)
+#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32)
+#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32)
+#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32)
+#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32)
+#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32)
+#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
+#define ATM_GETLOOP32	  _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
+#define ATM_SETLOOP32	  _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
+#define ATM_QUERYLOOP32	  _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
+
+static struct {
+        unsigned int cmd32;
+        unsigned int cmd;
+} atm_ioctl_map[] = {
+        { ATM_GETLINKRATE32, ATM_GETLINKRATE },
+	{ ATM_GETNAMES32,    ATM_GETNAMES },
+        { ATM_GETTYPE32,     ATM_GETTYPE },
+        { ATM_GETESI32,      ATM_GETESI },
+        { ATM_GETADDR32,     ATM_GETADDR },
+        { ATM_RSTADDR32,     ATM_RSTADDR },
+        { ATM_ADDADDR32,     ATM_ADDADDR },
+        { ATM_DELADDR32,     ATM_DELADDR },
+        { ATM_GETCIRANGE32,  ATM_GETCIRANGE },
+	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
+	{ ATM_SETESI32,      ATM_SETESI },
+	{ ATM_SETESIF32,     ATM_SETESIF },
+	{ ATM_GETSTAT32,     ATM_GETSTAT },
+	{ ATM_GETSTATZ32,    ATM_GETSTATZ },
+	{ ATM_GETLOOP32,     ATM_GETLOOP },
+	{ ATM_SETLOOP32,     ATM_SETLOOP },
+	{ ATM_QUERYLOOP32,   ATM_QUERYLOOP }
+};
+
+#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0]))
+
+
+static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct atm_iobuf32 iobuf32;
+	struct atm_iobuf   iobuf = { 0, NULL };
+	mm_segment_t old_fs;
+	int err;
+
+	err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg,
+	    sizeof(struct atm_iobuf32));
+	if (err)
+		return -EFAULT;
+
+	iobuf.length = iobuf32.length;
+
+	if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) {
+		iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
+	} else {
+		iobuf.buffer = compat_ptr(iobuf32.buffer);
+		if (verify_area(VERIFY_WRITE, iobuf.buffer, iobuf.length))
+			return -EINVAL;
+	}
+
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);      
+	set_fs (old_fs);
+        if(!err)
+	err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
+
+	return err;
+}
+
+
+static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+        struct atmif_sioc32 sioc32;
+        struct atmif_sioc   sioc = { 0, 0, NULL };
+        mm_segment_t old_fs;
+        int err;
+        
+        err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg,
+			     sizeof(struct atmif_sioc32));
+        if (err)
+                return -EFAULT;
+
+        sioc.number = sioc32.number;
+        sioc.length = sioc32.length;
+        
+	if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) {
+		sioc.arg = (void*)(unsigned long)sioc32.arg;
+        } else {
+		sioc.arg = compat_ptr(sioc32.arg);
+		if (verify_area(VERIFY_WRITE, sioc.arg, sioc32.length))
+			return -EFAULT;
+        }
+        
+        old_fs = get_fs(); set_fs (KERNEL_DS);
+        err = sys_ioctl (fd, cmd, (unsigned long)&sioc);	
+        set_fs (old_fs);
+	if (!err)
+        err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
+	return err;
+}
+
+
+static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
+{
+        int i;
+        unsigned int cmd = 0;
+        
+	switch (cmd32) {
+	case SONET_GETSTAT:
+	case SONET_GETSTATZ:
+	case SONET_GETDIAG:
+	case SONET_SETDIAG:
+	case SONET_CLRDIAG:
+	case SONET_SETFRAMING:
+	case SONET_GETFRAMING:
+	case SONET_GETFRSENSE:
+		return do_atmif_sioc(fd, cmd32, arg);
+	}
+
+		for (i = 0; i < NR_ATM_IOCTL; i++) {
+			if (cmd32 == atm_ioctl_map[i].cmd32) {
+				cmd = atm_ioctl_map[i].cmd;
+				break;
+			}
+		}
+	        if (i == NR_ATM_IOCTL) {
+	        return -EINVAL;
+	        }
+        
+        switch (cmd) {
+	case ATM_GETNAMES:
+		return do_atm_iobuf(fd, cmd, arg);
+	    
+	case ATM_GETLINKRATE:
+        case ATM_GETTYPE:
+        case ATM_GETESI:
+        case ATM_GETADDR:
+        case ATM_RSTADDR:
+        case ATM_ADDADDR:
+        case ATM_DELADDR:
+        case ATM_GETCIRANGE:
+	case ATM_SETCIRANGE:
+	case ATM_SETESI:
+	case ATM_SETESIF:
+	case ATM_GETSTAT:
+	case ATM_GETSTATZ:
+	case ATM_GETLOOP:
+	case ATM_SETLOOP:
+	case ATM_QUERYLOOP:
+                return do_atmif_sioc(fd, cmd, arg);
+        }
+
+        return -EINVAL;
+}
+
+static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	return -EINVAL;
+}
+
+static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	/* The mkswap binary hard codes it to Intel value :-((( */
+	return w_long(fd, BLKGETSIZE, arg);
+}
+
+struct blkpg_ioctl_arg32 {
+	compat_int_t op;
+	compat_int_t flags;
+	compat_int_t datalen;
+	compat_caddr_t data;
+};
+                                
+static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg)
+{
+	struct blkpg_ioctl_arg a;
+	struct blkpg_partition p;
+	int err;
+	mm_segment_t old_fs = get_fs();
+	
+	err = get_user(a.op, &arg->op);
+	err |= __get_user(a.flags, &arg->flags);
+	err |= __get_user(a.datalen, &arg->datalen);
+	err |= __get_user((long)a.data, &arg->data);
+	if (err) return err;
+	switch (a.op) {
+	case BLKPG_ADD_PARTITION:
+	case BLKPG_DEL_PARTITION:
+		if (a.datalen < sizeof(struct blkpg_partition))
+			return -EINVAL;
+                if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
+			return -EFAULT;
+		a.data = &p;
+		set_fs (KERNEL_DS);
+		err = sys_ioctl(fd, cmd, (unsigned long)&a);
+		set_fs (old_fs);
+	default:
+		return -EINVAL;
+	}                                        
+	return err;
+}
+
+static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
+}
+
+/* Fix sizeof(sizeof()) breakage */
+#define BLKBSZGET_32   _IOR(0x12,112,int)
+#define BLKBSZSET_32   _IOW(0x12,113,int)
+#define BLKGETSIZE64_32        _IOR(0x12,114,int)
+
+static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+       return sys_ioctl(fd, BLKBSZGET, arg);
+}
+
+static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+       return sys_ioctl(fd, BLKBSZSET, arg);
+}
+
+static int do_blkgetsize64(unsigned int fd, unsigned int cmd,
+                          unsigned long arg)
+{
+       return sys_ioctl(fd, BLKGETSIZE64, arg);
+}
+
+/* Bluetooth ioctls */
+#define HCIUARTSETPROTO        _IOW('U', 200, int)
+#define HCIUARTGETPROTO        _IOR('U', 201, int)
+
+#define BNEPCONNADD    _IOW('B', 200, int)
+#define BNEPCONNDEL    _IOW('B', 201, int)
+#define BNEPGETCONNLIST        _IOR('B', 210, int)
+#define BNEPGETCONNINFO        _IOR('B', 211, int)
+
+struct floppy_struct32 {
+	compat_uint_t	size;
+	compat_uint_t	sect;
+	compat_uint_t	head;
+	compat_uint_t	track;
+	compat_uint_t	stretch;
+	unsigned char	gap;
+	unsigned char	rate;
+	unsigned char	spec1;
+	unsigned char	fmt_gap;
+	const compat_caddr_t name;
+};
+
+struct floppy_drive_params32 {
+	char		cmos;
+	compat_ulong_t	max_dtr;
+	compat_ulong_t	hlt;
+	compat_ulong_t	hut;
+	compat_ulong_t	srt;
+	compat_ulong_t	spinup;
+	compat_ulong_t	spindown;
+	unsigned char	spindown_offset;
+	unsigned char	select_delay;
+	unsigned char	rps;
+	unsigned char	tracks;
+	compat_ulong_t	timeout;
+	unsigned char	interleave_sect;
+	struct floppy_max_errors max_errors;
+	char		flags;
+	char		read_track;
+	short		autodetect[8];
+	compat_int_t	checkfreq;
+	compat_int_t	native_format;
+};
+
+struct floppy_drive_struct32 {
+	signed char	flags;
+	compat_ulong_t	spinup_date;
+	compat_ulong_t	select_date;
+	compat_ulong_t	first_read_date;
+	short		probed_format;
+	short		track;
+	short		maxblock;
+	short		maxtrack;
+	compat_int_t	generation;
+	compat_int_t	keep_data;
+	compat_int_t	fd_ref;
+	compat_int_t	fd_device;
+	compat_int_t	last_checked;
+	compat_caddr_t dmabuf;
+	compat_int_t	bufblocks;
+};
+
+struct floppy_fdc_state32 {
+	compat_int_t	spec1;
+	compat_int_t	spec2;
+	compat_int_t	dtr;
+	unsigned char	version;
+	unsigned char	dor;
+	compat_ulong_t	address;
+	unsigned int	rawcmd:2;
+	unsigned int	reset:1;
+	unsigned int	need_configure:1;
+	unsigned int	perp_mode:2;
+	unsigned int	has_fifo:1;
+	unsigned int	driver_version;
+	unsigned char	track[4];
+};
+
+struct floppy_write_errors32 {
+	unsigned int	write_errors;
+	compat_ulong_t	first_error_sector;
+	compat_int_t	first_error_generation;
+	compat_ulong_t	last_error_sector;
+	compat_int_t	last_error_generation;
+	compat_uint_t	badness;
+};
+
+#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32)
+#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32)
+#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32)
+#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32)
+#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32)
+#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32)
+#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32)
+#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32)
+#define FDWERRORGET32  _IOR(2, 0x17, struct floppy_write_errors32)
+
+static struct {
+	unsigned int	cmd32;
+	unsigned int	cmd;
+} fd_ioctl_trans_table[] = {
+	{ FDSETPRM32, FDSETPRM },
+	{ FDDEFPRM32, FDDEFPRM },
+	{ FDGETPRM32, FDGETPRM },
+	{ FDSETDRVPRM32, FDSETDRVPRM },
+	{ FDGETDRVPRM32, FDGETDRVPRM },
+	{ FDGETDRVSTAT32, FDGETDRVSTAT },
+	{ FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
+	{ FDGETFDCSTAT32, FDGETFDCSTAT },
+	{ FDWERRORGET32, FDWERRORGET }
+};
+
+#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0]))
+
+static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	void *karg = NULL;
+	unsigned int kcmd = 0;
+	int i, err;
+
+	for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
+		if (cmd == fd_ioctl_trans_table[i].cmd32) {
+			kcmd = fd_ioctl_trans_table[i].cmd;
+			break;
+		}
+	if (!kcmd)
+		return -EINVAL;
+
+	switch (cmd) {
+		case FDSETPRM32:
+		case FDDEFPRM32:
+		case FDGETPRM32:
+		{
+			struct floppy_struct *f;
+
+			f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			if (cmd == FDGETPRM32)
+				break;
+			err = __get_user(f->size, &((struct floppy_struct32 *)arg)->size);
+			err |= __get_user(f->sect, &((struct floppy_struct32 *)arg)->sect);
+			err |= __get_user(f->head, &((struct floppy_struct32 *)arg)->head);
+			err |= __get_user(f->track, &((struct floppy_struct32 *)arg)->track);
+			err |= __get_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch);
+			err |= __get_user(f->gap, &((struct floppy_struct32 *)arg)->gap);
+			err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
+			err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
+			err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
+			err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
+			if (err) {
+				err = -EFAULT;
+				goto out;
+			}
+			break;
+		}
+		case FDSETDRVPRM32:
+		case FDGETDRVPRM32:
+		{
+			struct floppy_drive_params *f;
+
+			f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			if (cmd == FDGETDRVPRM32)
+				break;
+			err = __get_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos);
+			err |= __get_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr);
+			err |= __get_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt);
+			err |= __get_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut);
+			err |= __get_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt);
+			err |= __get_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup);
+			err |= __get_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown);
+			err |= __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset);
+			err |= __get_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay);
+			err |= __get_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps);
+			err |= __get_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks);
+			err |= __get_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout);
+			err |= __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect);
+			err |= __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)arg)->max_errors, sizeof(f->max_errors));
+			err |= __get_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags);
+			err |= __get_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track);
+			err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect));
+			err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq);
+			err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format);
+			if (err) {
+				err = -EFAULT;
+				goto out;
+			}
+			break;
+		}
+		case FDGETDRVSTAT32:
+		case FDPOLLDRVSTAT32:
+			karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			break;
+		case FDGETFDCSTAT32:
+			karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			break;
+		case FDWERRORGET32:
+			karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			break;
+		default:
+			return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
+	set_fs (old_fs);
+	if (err)
+		goto out;
+	switch (cmd) {
+		case FDGETPRM32:
+		{
+			struct floppy_struct *f = karg;
+
+			err = __put_user(f->size, &((struct floppy_struct32 *)arg)->size);
+			err |= __put_user(f->sect, &((struct floppy_struct32 *)arg)->sect);
+			err |= __put_user(f->head, &((struct floppy_struct32 *)arg)->head);
+			err |= __put_user(f->track, &((struct floppy_struct32 *)arg)->track);
+			err |= __put_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch);
+			err |= __put_user(f->gap, &((struct floppy_struct32 *)arg)->gap);
+			err |= __put_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
+			err |= __put_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
+			err |= __put_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
+			err |= __put_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
+			break;
+		}
+		case FDGETDRVPRM32:
+		{
+			struct floppy_drive_params *f = karg;
+
+			err = __put_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos);
+			err |= __put_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr);
+			err |= __put_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt);
+			err |= __put_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut);
+			err |= __put_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt);
+			err |= __put_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup);
+			err |= __put_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown);
+			err |= __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset);
+			err |= __put_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay);
+			err |= __put_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps);
+			err |= __put_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks);
+			err |= __put_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout);
+			err |= __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect);
+			err |= __copy_to_user(&((struct floppy_drive_params32 *)arg)->max_errors, &f->max_errors, sizeof(f->max_errors));
+			err |= __put_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags);
+			err |= __put_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track);
+			err |= __copy_to_user(((struct floppy_drive_params32 *)arg)->autodetect, f->autodetect, sizeof(f->autodetect));
+			err |= __put_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq);
+			err |= __put_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format);
+			break;
+		}
+		case FDGETDRVSTAT32:
+		case FDPOLLDRVSTAT32:
+		{
+			struct floppy_drive_struct *f = karg;
+
+			err = __put_user(f->flags, &((struct floppy_drive_struct32 *)arg)->flags);
+			err |= __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)arg)->spinup_date);
+			err |= __put_user(f->select_date, &((struct floppy_drive_struct32 *)arg)->select_date);
+			err |= __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)arg)->first_read_date);
+			err |= __put_user(f->probed_format, &((struct floppy_drive_struct32 *)arg)->probed_format);
+			err |= __put_user(f->track, &((struct floppy_drive_struct32 *)arg)->track);
+			err |= __put_user(f->maxblock, &((struct floppy_drive_struct32 *)arg)->maxblock);
+			err |= __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)arg)->maxtrack);
+			err |= __put_user(f->generation, &((struct floppy_drive_struct32 *)arg)->generation);
+			err |= __put_user(f->keep_data, &((struct floppy_drive_struct32 *)arg)->keep_data);
+			err |= __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)arg)->fd_ref);
+			err |= __put_user(f->fd_device, &((struct floppy_drive_struct32 *)arg)->fd_device);
+			err |= __put_user(f->last_checked, &((struct floppy_drive_struct32 *)arg)->last_checked);
+			err |= __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)arg)->dmabuf);
+			err |= __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)arg)->bufblocks);
+			break;
+		}
+		case FDGETFDCSTAT32:
+		{
+			struct floppy_fdc_state *f = karg;
+
+			err = __put_user(f->spec1, &((struct floppy_fdc_state32 *)arg)->spec1);
+			err |= __put_user(f->spec2, &((struct floppy_fdc_state32 *)arg)->spec2);
+			err |= __put_user(f->dtr, &((struct floppy_fdc_state32 *)arg)->dtr);
+			err |= __put_user(f->version, &((struct floppy_fdc_state32 *)arg)->version);
+			err |= __put_user(f->dor, &((struct floppy_fdc_state32 *)arg)->dor);
+			err |= __put_user(f->address, &((struct floppy_fdc_state32 *)arg)->address);
+			err |= __copy_to_user((char *)&((struct floppy_fdc_state32 *)arg)->address
+			    		   + sizeof(((struct floppy_fdc_state32 *)arg)->address),
+					   (char *)&f->address + sizeof(f->address), sizeof(int));
+			err |= __put_user(f->driver_version, &((struct floppy_fdc_state32 *)arg)->driver_version);
+			err |= __copy_to_user(((struct floppy_fdc_state32 *)arg)->track, f->track, sizeof(f->track));
+			break;
+		}
+		case FDWERRORGET32:
+		{
+			struct floppy_write_errors *f = karg;
+
+			err = __put_user(f->write_errors, &((struct floppy_write_errors32 *)arg)->write_errors);
+			err |= __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)arg)->first_error_sector);
+			err |= __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)arg)->first_error_generation);
+			err |= __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)arg)->last_error_sector);
+			err |= __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)arg)->last_error_generation);
+			err |= __put_user(f->badness, &((struct floppy_write_errors32 *)arg)->badness);
+			break;
+		}
+		default:
+			break;
+	}
+	if (err)
+		err = -EFAULT;
+
+out:	if (karg) kfree(karg);
+	return err;
+}
+
+struct mtd_oob_buf32 {
+	u_int32_t start;
+	u_int32_t length;
+	compat_caddr_t ptr;	/* unsigned char* */
+};
+
+#define MEMWRITEOOB32 	_IOWR('M',3,struct mtd_oob_buf32)
+#define MEMREADOOB32 	_IOWR('M',4,struct mtd_oob_buf32)
+
+static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t 			old_fs 	= get_fs();
+	struct mtd_oob_buf32	*uarg 	= (struct mtd_oob_buf32 *)arg;
+	struct mtd_oob_buf		karg;
+	u32 tmp;
+	int ret;
+
+	if (get_user(karg.start, &uarg->start) 		||
+	    get_user(karg.length, &uarg->length)	||
+	    get_user(tmp, &uarg->ptr))
+		return -EFAULT;
+
+	karg.ptr = compat_ptr(tmp); 
+	if (verify_area(VERIFY_WRITE, karg.ptr, karg.length))
+		return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	if (MEMREADOOB32 == cmd) 
+		ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg);
+	else if (MEMWRITEOOB32 == cmd)
+		ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg);
+	else
+		ret = -EINVAL;
+	set_fs(old_fs);
+
+	if (0 == ret && cmd == MEMREADOOB32) {
+		ret = put_user(karg.start, &uarg->start);
+		ret |= put_user(karg.length, &uarg->length);
+	}
+
+	return ret;
+}	
+
+#undef CODE
+#endif
+
+#ifdef DECLARES
+HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob)
+HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
+#ifdef CONFIG_NET
+HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
+#endif
+HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
+HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc)
+HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
+HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl)
+HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDSETHWADDR, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDSLAVEINFOQUERY, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDINFOQUERY, bond_ioctl)
+HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl)
+HANDLE_IOCTL(SIOCADDRT, routing_ioctl)
+HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
+/* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
+HANDLE_IOCTL(SIOCRTMSG, ret_einval)
+HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
+HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
+HANDLE_IOCTL(BLKRAGET, w_long)
+HANDLE_IOCTL(BLKGETSIZE, w_long)
+HANDLE_IOCTL(0x1260, broken_blkgetsize)
+HANDLE_IOCTL(BLKFRAGET, w_long)
+HANDLE_IOCTL(BLKSECTGET, w_long)
+HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans)
+HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
+HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans)
+HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans)
+HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDSETDRVPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETDRVPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans)
+HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans)
+HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans)
+HANDLE_IOCTL(SG_IO,sg_ioctl_trans)
+HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
+HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
+HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans)
+HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
+HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
+HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
+HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
+HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
+#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
+HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
+HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl)
+HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl)
+HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl)
+HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl)
+HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl)
+HANDLE_IOCTL(VIDIOCGTUNER32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCSTUNER32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCGWIN32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCSWIN32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCGFBUF32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl)
+/* One SMB ioctl needs translations. */
+#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_pid_t)
+HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
+HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETESI32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_RSTADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_ADDADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_DELADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETCIRANGE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETCIRANGE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl)
+HANDLE_IOCTL(SONET_SETDIAG, do_atm_ioctl)
+HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl)
+HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl)
+/* block stuff */
+HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget)
+HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset)
+HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64)
+
+#undef DECLARES
+#endif

-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-26  9:37   ` Pavel Machek
@ 2003-05-28 21:48     ` Andrew Morton
  2003-05-28 21:55       ` Pavel Machek
  0 siblings, 1 reply; 34+ messages in thread
From: Andrew Morton @ 2003-05-28 21:48 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel

Pavel Machek <pavel@suse.cz> wrote:
>
> Hi!
> 
> I guess "ioctl32 emulation should be shared
> accross architectures" should go on the
> list...

Noted, thanks.

> (and I have patches but Linus ignores
> them... would it be okay to merge them
> through you?)

This is a bit like "arch/foo/kernel/irq.c should be common code".  The
patch exists, but is late, intrusive and only a cleanup.

However I think experience teaches us that we should push ahead with
changes like this because not doing it creates more aggregate pain than
doing it.

So yes, please send me your latest and we'll try to get it underway.


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-21 22:23 ` Andrew Morton
  2003-05-21 22:49   ` Tom Rini
@ 2003-05-26  9:37   ` Pavel Machek
  2003-05-28 21:48     ` Andrew Morton
  1 sibling, 1 reply; 34+ messages in thread
From: Pavel Machek @ 2003-05-26  9:37 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

Hi!

I guess "ioctl32 emulation should be shared
accross architectures" should go on the
list...

(and I have patches but Linus ignores
them... would it be okay to merge them
through you?)
				Pavel
-- 
				Pavel
Written on sharp zaurus, because my Velo1 broke. If you have Velo you don't need...


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-21 22:22 Andrew Morton
                   ` (4 preceding siblings ...)
  2003-05-22  6:24 ` Jens Axboe
@ 2003-05-25 21:05 ` Daniel Jacobowitz
  5 siblings, 0 replies; 34+ messages in thread
From: Daniel Jacobowitz @ 2003-05-25 21:05 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

On Wed, May 21, 2003 at 03:22:55PM -0700, Andrew Morton wrote:
> 
> Also at ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/must-fix/
> 
> For verson 6 I shall go through the "late features" list and prioritise
> things.

Here's another one for your list: when CLONE_DETACHED threads were
removed from /proc several approaches were suggested to let procps find
out about them and none of them were implemented.  There's some real
potential for badness with these mostly-invisible processes.  Something
needs to be added so that we can display and detect them.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-22  8:31 ` Andrew Morton
@ 2003-05-22 14:23   ` Jos Hulzink
  0 siblings, 0 replies; 34+ messages in thread
From: Jos Hulzink @ 2003-05-22 14:23 UTC (permalink / raw)
  To: Andrew Morton, Grover, Andrew; +Cc: linux-kernel

On Thursday 22 May 2003 10:31, Andrew Morton wrote:
> "Grover, Andrew" <andrew.grover@intel.com> wrote:
> > > From: Andrew Morton [mailto:akpm@digeo.com]
> >
> > Hi just wanted to add some comments below:
>
> Appreciated, thanks.
>
> > >  drivers/acpi/
> > >  ~~~~~~~~~~~~~
> > >
> > >  o davej: ACPI has a number of failures right now.  There are
> >
> > ...
> >
> > Working on these (they're all in bugzilla), more help needed of course
> >
> > :)
>
> OK, well if they're safely bugzilla'd I shall remove them from here.
> Unless you think they're drop-dead stop-ship material.
>
> > > +o mochel: it seems the acpi irq routing code could use a
> > > serious rewrite.
> >
> > No the problem is the ACPI irq routing code is trying to piggyback on
> > the existing MPS-specific data structures, and it's generally a hack. So
> > yes mochel is right, but it is also purging MPS-ities from common code
> > as well. I've done some preliminary work in this area and it doesn't
> > seem to break anything (yet) but a rewrite in this area imho should not
> > be rushed out the door. And, I think the above bugs can be fixed w/o the
> > rewrite.
>
> Where do you think this work sits on the seriousness scale?  Is it
> affecting a lot of people?  Is it a large-scale restructure?

This is what bug 699 is all about I think. As far as I can see, it is a 
serious issue for people with MPS 1.4 systems: The system is unusable due to 
wrong IRQ mappings. MPS 1.4 is used in most (all ?) PPro and PII SMP systems, 
though often can be disabled. I can't say how many systems really rely on MPS 
1.4. Workaround that works for most people is booting with pci=noacpi, though 
I have reports of systems where this isn't the solution. MPS 1.1 systems 
work, though this is more a coincidence than well coded ACPI behaviour.

The amount of people that can't possibly get Linux booting with ACPI enabled 
will not be big. The amount of people that think it's annoying they have to 
disable MPS 1.4 or ACPI to get a running system might be somewhat bigger. My 
box only shuts down with ACPI, and thanks to MPS 1.4 my soundcard doesn't 
glitch when there is heavy SCSI activity. (Onboard SCSI & Soundcard share the 
interrupt when MPS 1.4 is disabled). 

Basically, what happens is that ACPI forgets to look for MPS tables when no 
MADT is found. It assumes the APIC should be set up in PIC mode, though the 
APIC has been rerouted already. As a result, the irq entries in pci_dev are 
filled with the "below 15" values, while the APIC generates "above 15" 
interrupts.

Jos

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-22  8:16 Grover, Andrew
@ 2003-05-22  8:31 ` Andrew Morton
  2003-05-22 14:23   ` Jos Hulzink
  0 siblings, 1 reply; 34+ messages in thread
From: Andrew Morton @ 2003-05-22  8:31 UTC (permalink / raw)
  To: Grover, Andrew; +Cc: linux-kernel

"Grover, Andrew" <andrew.grover@intel.com> wrote:
>
> 
> > From: Andrew Morton [mailto:akpm@digeo.com] 
> 
> Hi just wanted to add some comments below:

Appreciated, thanks.

> >  drivers/acpi/
> >  ~~~~~~~~~~~~~
> >  
> >  o davej: ACPI has a number of failures right now.  There are 
> ...
> 
> Working on these (they're all in bugzilla), more help needed of course
> :)

OK, well if they're safely bugzilla'd I shall remove them from here. 
Unless you think they're drop-dead stop-ship material.

> > +o mochel: it seems the acpi irq routing code could use a 
> > serious rewrite.
> 
> No the problem is the ACPI irq routing code is trying to piggyback on
> the existing MPS-specific data structures, and it's generally a hack. So
> yes mochel is right, but it is also purging MPS-ities from common code
> as well. I've done some preliminary work in this area and it doesn't
> seem to break anything (yet) but a rewrite in this area imho should not
> be rushed out the door. And, I think the above bugs can be fixed w/o the
> rewrite.

Where do you think this work sits on the seriousness scale?  Is it
affecting a lot of people?  Is it a large-scale restructure?

It sounds to me like it's a non-trivial piece of ACPI brain surgery and
that I should continue to track it, yes?


^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: must-fix list, v5
@ 2003-05-22  8:16 Grover, Andrew
  2003-05-22  8:31 ` Andrew Morton
  0 siblings, 1 reply; 34+ messages in thread
From: Grover, Andrew @ 2003-05-22  8:16 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel


> From: Andrew Morton [mailto:akpm@digeo.com] 

Hi just wanted to add some comments below:

>  drivers/acpi/
>  ~~~~~~~~~~~~~
>  
>  o davej: ACPI has a number of failures right now.  There are 
> a number of
> @@ -710,25 +766,32 @@
>    "network card doesn't recieve packets" booting with 
> 'acpi=off noapic' fixes
>    it.
>  
>    alan: VIA APIC stuff is one bit of this, there are also some other
>    reports that were caused by ACPI not setting level v edge 
> trigger some
>    times
>  
>  o davej: There's also another nasty 'doesnt boot' bug which 
> quite a few
>    people (myself included) are seeing on some boxes 
> (especially laptops).

Working on these (they're all in bugzilla), more help needed of course
:)

> +o mochel: it seems the acpi irq routing code could use a 
> serious rewrite.

No the problem is the ACPI irq routing code is trying to piggyback on
the existing MPS-specific data structures, and it's generally a hack. So
yes mochel is right, but it is also purging MPS-ities from common code
as well. I've done some preliminary work in this area and it doesn't
seem to break anything (yet) but a rewrite in this area imho should not
be rushed out the door. And, I think the above bugs can be fixed w/o the
rewrite.

> +o mochel: ACPI suspend doesn't work.  Important, not 
> cricital.  Pat is
> +  working it.

Go, Pat, go!

Regards -- Andy

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-21 22:22 Andrew Morton
                   ` (3 preceding siblings ...)
  2003-05-22  1:25 ` Andrew Theurer
@ 2003-05-22  6:24 ` Jens Axboe
  2003-05-25 21:05 ` Daniel Jacobowitz
  5 siblings, 0 replies; 34+ messages in thread
From: Jens Axboe @ 2003-05-22  6:24 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

On Wed, May 21 2003, Andrew Morton wrote:
> +o elevator-noop is broken.

news to me, what is broken?

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-22  1:03 ` Carl-Daniel Hailfinger
@ 2003-05-22  3:08   ` oxymoron
  0 siblings, 0 replies; 34+ messages in thread
From: oxymoron @ 2003-05-22  3:08 UTC (permalink / raw)
  To: Carl-Daniel Hailfinger; +Cc: Andrew Morton, linux-kernel, willy

On Thu, May 22, 2003 at 03:03:05AM +0200, Carl-Daniel Hailfinger wrote:
> Andrew Morton wrote:
> > Also at ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/must-fix/
> > 
> > For verson 6 I shall go through the "late features" list and prioritise
> > things.
> > 
> > Changes since v5:
> 
> > +o willy: random.c is completely lockfree, and not in a good way.  i had
> > +  some patches but nothing got seriously tested.
> 
> IIRC, Oliver Xymoron had some patches to clean up RNG support at the
> time of 2.5.39. Because things were in flux back then, he decided to
> postpone these patches until late in the 2.5 cycle.
> 
> Oliver?

Hope to respin some of the less theoretically motivated ones in the
next week, now that I've got a couple development machines. I'll look
over the locking stuff with Willy when he manages to recover his
latest from his dead laptop.

I'll probably repost the paranoid patches before long too.

--
 "Love the dolphins," she advised him. "Write by W.A.S.T.E.." 

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-21 22:22 Andrew Morton
                   ` (2 preceding siblings ...)
  2003-05-22  1:03 ` Carl-Daniel Hailfinger
@ 2003-05-22  1:25 ` Andrew Theurer
  2003-05-22  6:24 ` Jens Axboe
  2003-05-25 21:05 ` Daniel Jacobowitz
  5 siblings, 0 replies; 34+ messages in thread
From: Andrew Theurer @ 2003-05-22  1:25 UTC (permalink / raw)
  To: linux-kernel

On Wednesday 21 May 2003 17:22, Andrew Morton wrote:
> +o Overeager affinity in presence of repeated yields
> +
> +  http://www.hpl.hp.com/research/linux/kernel/o1-openmp.php
> +
> +  ingo: this is valid.  fix is in progress.

I have seen this with SpecJBB on high warehouse runs in around 2.5.66, I am 
testing now to see if it still exists in 2.5.69.  In 2.5.66 adding a bit to 
try_to_wakeup to relocate p-task_cpu to an idle cpu (if available) if the 
p->task_cpu is currently non idle helped dramatically.  This change is also 
in Andrea's 2.4 kernel tree I believe.  Basically in some situations, a quick 
push load balance before task activation.  

Also, in this particular case, this behavior may go away with the use of 
futexes in JVM, not sure yet, so I don't know if JVM and JBB are good 
justifications to make this change.  

-Andrew Theurer


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-21 22:22 Andrew Morton
  2003-05-21 22:23 ` Andrew Morton
  2003-05-21 22:41 ` Andrew Morton
@ 2003-05-22  1:03 ` Carl-Daniel Hailfinger
  2003-05-22  3:08   ` oxymoron
  2003-05-22  1:25 ` Andrew Theurer
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 34+ messages in thread
From: Carl-Daniel Hailfinger @ 2003-05-22  1:03 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, oxymoron

Andrew Morton wrote:
> Also at ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/must-fix/
> 
> For verson 6 I shall go through the "late features" list and prioritise
> things.
> 
> 
> Changes since v5:

> +o willy: random.c is completely lockfree, and not in a good way.  i had
> +  some patches but nothing got seriously tested.
> +

IIRC, Oliver Xymoron had some patches to clean up RNG support at the
time of 2.5.39. Because things were in flux back then, he decided to
postpone these patches until late in the 2.5 cycle.

Oliver?


Regards,
Carl-Daniel


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
@ 2003-05-21 23:59 Arnd Bergmann
  0 siblings, 0 replies; 34+ messages in thread
From: Arnd Bergmann @ 2003-05-21 23:59 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andrew Morton

Here is a list of things we need to do on s390 for 2.6:

arch/s390/
~~~~~~~~~

o A nastly memory management problem causes random crashes.
  These appear to be fixed/hidden by the objrmap patch, more
  investigation is needed.

drivers/s390/
~~~~~~~~~~~~~

o Early userspace and 64 bit dev_t will allow the removal of most of
  dasd_devmap.c and dasd_genhd.c.

o The 3270 console driver needs to be replaced with a working one
  (prototype is there, needs to be finished).

o Minor interface changes are pending in cio/ when the z990 machines
  are out.

There are some more things being worked on that are either post-2.6.0
or are likely to remain outside of the official kernel (i.e. not for
your list):

o Jan Glauber is working on a fix for the timer issues related
  to running on virtualized CPUs (wall-clock vs. cpu time).

o new zfcp fibre channel driver

o the qeth driver will become GPL soon

o a block device driver for ramdisks shared among virtual
  machines

o driver for crypto hardware

o 'claw' network device driver

	Arnd <><

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-21 22:49   ` Tom Rini
@ 2003-05-21 22:55     ` Andrew Morton
  0 siblings, 0 replies; 34+ messages in thread
From: Andrew Morton @ 2003-05-21 22:55 UTC (permalink / raw)
  To: Tom Rini; +Cc: linux-kernel, rmk

Tom Rini <trini@kernel.crashing.org> wrote:
>
> I talked with RMK on IRC a bit about this.  After reading
> drivers/char/rtc.c, I think this can be vastly simplied to:
> Add support for alarms to the existing generic rtc driver
> (drivers/char/genrtc.c).
> 
> Does this sound like a plan?

It certainly does, thanks.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-21 22:23 ` Andrew Morton
@ 2003-05-21 22:49   ` Tom Rini
  2003-05-21 22:55     ` Andrew Morton
  2003-05-26  9:37   ` Pavel Machek
  1 sibling, 1 reply; 34+ messages in thread
From: Tom Rini @ 2003-05-21 22:49 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, Russell King

On Wed, May 21, 2003 at 03:23:34PM -0700, Andrew Morton wrote:

> drivers/char/rtc/
> ~~~~~~~~~~~~~~~~~
> 
> o rmk: I think we need a generic RTC driver (which is backed by real RTCs).
>    Integrator-based stuff has a 32-bit 1Hz counter RTC with alarm, as has the
>   SA11xx, and probably PXA.  There's another implementation for the RiscPC
>   and ARM26 stuff.  I'd rather not see 4 implementations of the RTC userspace
>   API, but one common implementation so that stuff gets done in a consistent
>   way.
> 
>   We postponed this at the beginning of 2.4 until 2.5 happened.  We're now
>   at 2.5, and I'm about to add at least one more (the Integrator
>   implementation.) This isn't sane imo.

I talked with RMK on IRC a bit about this.  After reading
drivers/char/rtc.c, I think this can be vastly simplied to:
Add support for alarms to the existing generic rtc driver
(drivers/char/genrtc.c).

Does this sound like a plan?

-- 
Tom Rini
http://gate.crashing.org/~trini/

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-21 22:22 Andrew Morton
  2003-05-21 22:23 ` Andrew Morton
@ 2003-05-21 22:41 ` Andrew Morton
  2003-05-22  1:03 ` Carl-Daniel Hailfinger
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 34+ messages in thread
From: Andrew Morton @ 2003-05-21 22:41 UTC (permalink / raw)
  To: linux-kernel

Andrew Morton <akpm@digeo.com> wrote:
>
>  o O(1) scheduler starvation, poor behaviour seems unresolved.
>  
>    Jens: "I've been running 2.5.67-mm3 on my workstation for two days, and
>    it still doesn't feel as good as 2.4.  It's not a disaster like some
>    revisisons ago, but it still has occasional CPU "stalls" where it feels
>    like a process waits for half a second of so for CPU time.  That's is very
>    noticable."
>  
>     Also see Mike Galbraith's work.
>  
>    Conclusion: the scheduler has issues, lots of people working on it.  Rick
>    Lindsley, Andrew Theurer.

Actually this part should have been deleted.

There have been a lot of sporadic CPU scheduler problem reports and a lot
of fixes, some in just the past day or two.

So apart from David MT's discoveries we shall be wiping the slate clean and
awaiting new reports.


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: must-fix list, v5
  2003-05-21 22:22 Andrew Morton
@ 2003-05-21 22:23 ` Andrew Morton
  2003-05-21 22:49   ` Tom Rini
  2003-05-26  9:37   ` Pavel Machek
  2003-05-21 22:41 ` Andrew Morton
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 34+ messages in thread
From: Andrew Morton @ 2003-05-21 22:23 UTC (permalink / raw)
  To: linux-kernel


The full list.


Must-fix bugs
=============

drivers/char/
~~~~~~~~~~~~~

o TTY locking is broken.

  o see FIXME in do_tty_hangup().  This causes ppp BUGs in local_bh_enable()

  o Other problems: aviro, dipankar, Alan have details.

  o somebody will have to document the tty driver and ldisc API

o Lack of test cases and/or stress tests is a problem.  Contributions and
  suggestions are sought.

o Lots of drivers are using cli/sti and are broken.

o willy: random.c is completely lockfree, and not in a good way.  i had
  some patches but nothing got seriously tested.

drivers/tty
~~~~~~~~~~~

o viro: we need to fix refcounting for tty_driver (oopsable race, must fix
  anyway, hopefully about a week until it's merged) then we can do
  tty/misc/upper levels of sound and hopefully upper level of USB.

  USB is a place where we _really_ need to deal with dynamic allocation of
  device numbers and that will bite.

drivers/block/
~~~~~~~~~~~~~~

o RAID0 dies on strangely aligned BIOs

  o Need to hoist BIO-split code out of device mapper, use that.

    arjan: "if we add that function, we must be sure that it can split on
    not-a-page boundaries too otherwise it's useless for a bunch of things"

 (neilb)

 1/ RAID5 should work fine.  It accepts any sort of bio and always
    submits a 1-page bio to the underlying device, and if my
    understanding is correct, every device must be able to handle a
    single page bio, no matter what the alignment (which is why raid0
    has a problem - it doesn't). 

 2/ RAID1 works pretty well.  The only improvement needed is to define
    a merge_bvec_fn function which passes the question down to lower
    layers.  This should be easy except for the small fact that it is
    impossible :-)  There is no enforced pairing between calls to
    merge_bvec_fn and submit_bh, so it is possible that a hot spare
    with different restrictions could get swapped in between the one
    and the other and could confuse things.  I suspect that can be
    worked around somehow though...

       Someone sent me a patch that is sorely needed - it allows you
       to simply call blk_queue_stack() (or somethink like that), and it will
       get your stacked limits set appropriately.

 3/ I just realised that raid0 is easier than I had previously
    thought.  We don't need the completely functional bio splitting
    that dm has.  We only need to be able to split a bio that has just
    one page as the use of merge_bvec_fn will ensure that we never get
    a larger bio that we cannot handle.  And splitting a bio with only
    one page is a lot easier.  I now have code in my tree that
    implements this quite cleanly and will probably post a patch
    during the week.

o ideraid hasn't been ported to 2.5 at all yet.

  We need to understand whether the proposed BIO split code will suffice
  for this.

o CD burning.  There are still a few quirks to solve wrt SG_IO and ide-cd.

  Jens: The basic hang has been solved (double fault in ide-cd), there still
  seems to be some cases that don't work too well.  Don't really have a
  handle on those :/

o lmb: Last time I looked at the multipath code (2.5.50 or so) it also
  looked pretty broken; I plan to port forward the changes we did on 2.4
  before KS.

o elevator-noop is broken.

drivers/input/
~~~~~~~~~~~~~~

o rmk: unconverted keyboard/mouse drivers (there's a deadline of 2.6.0
  currently on these remaining in my/Linus' tree.)

o viro: large absence of locking.

o synaptic touchpad support

  Jens Taprogge <jens.taprogge@rwth-aachen.de> is working on this.

o andi: also the input keyboard stuff still has unusably obscure config
  options for standard PC hardware.

o viro: parport is nearly as bad as that and there the code is more hairy. 
  IMO parport is more of "figure out what API changes are needed for its
  users, get them done ASAP, then fix generic layer at leisure"

drivers/misc/
~~~~~~~~~~~~~

o rmk: UCB1[23]00 drivers, currently sitting in drivers/misc in the ARM
  tree.  (touchscreen, audio, gpio, type device.)

  These need to be moved out of drivers/misc/ and into real places

o viro: actually, misc.c has a good chance to die.  With cdev-cidr that's
  trivial.

drivers/net/
~~~~~~~~~~~~

o rmk: network drivers.  ARM people like to add tonnes of #ifdefs into
  these to customise them to their hardware platform (eg, chip access
  methods, addresses, etc.) I cope with this by not integrating them into my
  tree.  The result is that many ARM platforms can't be built from even my
  tree without extra patches.  This isn't sane, and has bred a culture of
  network drivers not being submitted.  I don't see this changing for 2.6
  though.

drivers/net/irda/
~~~~~~~~~~~~~~~~~

o dongle drivers need to be converted to sir-dev

o irport need to be converted to sir-kthread

o new drivers (irtty-sir/smsc-ircc2/donauboe) need more testing

o rmk: Refuse IrDA initialisation if sizeof(structures) is incorrect (I'm
  not sure if we still need this; I think gcc 2.95.3 on ARM shows this
  problem though.)

drivers/pci/
~~~~~~~~~~~~

o alan: Some cardbus crashes the system

  (bugzilla, please?)

o We have multiple drivers walking the pci device lists and also using
  things like pci_find_device in unsafe ways with no refcounting.  I think
  we have to make pci_find_device etc refcount somewhere and add
  pci_device_put as was done with networking.
  http://bugzilla.kernel.org/show_bug.cgi?id=709

  (gregkh will work on this)

o willy: PCI Domain support.  The 'must-fix' bit of this is getting sysfs
  to present the right interface to userspace so we can adapt pciutils & X to
  use it.

drivers/pcmcia/
~~~~~~~~~~~~~~~

o alan: Most drivers crash the system on eject randomly with timer bugs.  I
  think after RMK's stuff is in most of the pcmcia/cardbus ones go except the
  locking disaster.

  (rmk, brodo: in progress)

drivers/pld/
~~~~~~~~~~~~

o rmk: EPXA (ARM platform) PLD hotswap drivers (drivers/pld)

  (rmk: will work out what to do here.  maybe drivers/arm/)

drivers/video/
~~~~~~~~~~~~~~

o Lots of drivers don't compile, others do but don't work.

drivers/scsi/
~~~~~~~~~~~~~

o hch: large parts of the locking are hosed or not existant

  (Mike Anderson, Patrick Mansfield, Badari Pulavarty)

  o shost->my_devices isn't locked down at all

  o the host list ist locked but not refcounted, mess can happen when the
    spinlock is dropped

  o there are lots of members of struct Scsi_Host/scsi_device/scsi_cmnd
    with very unclear locking, many of them probably want to become
    atomic_t's or bitmaps (for the 1bit bitfields).

  o there's lots of volatile abuse in the scsi code that needs to be
    thought about.

  o there's some global variables incremented without any locks

o Convert am53c974, dpt_i2o, initio and pci2220i to DMA-mapping

o Make inia100, cpqfc, pci2000 and dc390t compile

o Convert

   wd33c99 based: a2091 a3000 gpv11 mvme174 sgiwd93 53c7xx based:
   amiga7xxx bvme6000 mvme16x initio am53c974 pci2000 pci2220i qla1280
   sym53c8xx dc390t

  To new error handling

  I think the sym53c8xx could probably be pulled out of the tree because
  the sym_2 replaces it.  I'm also looking at converting the qla1280.

  It also might be possible to shift the 53c7xx based drivers over to
  53c700 which does the new EH stuff, but I don't have the hardware to check
  such a shift.

  For the non-compiling stuff, I've probably missed a few that just aren't
  compilable on my platforms, so any updates would be welcome.  Also, are
  some of our non-compiling or unconverted drivers obsolete?

o rmk: I have a pending todo: I need to put the scsi error handling through
  a workout on my scsi bus from hell to make sure it does the right thing and
  doesn't get wedged.

o qlogic drivers: merge qlogicisp, feral with a view to dropping qlogicfc
  and qlogicisp

o jejb: and merge the qla2xxx too

fs/
~~~

o ext3 data=journal mode is bust.

o ext3/htree readdir can return "." and ".." in unexpected order, which
  might break buggy userspace apps.  Ted has a fix planned.


o AIO/direct-IO writes can race with truncate and wreck filesystems.

  o Easy fix is to only allow the feature for S_ISBLK files.

o hch: devfs: there's a fundamental lookup vs devfsd race that's only
  fixable by introducing a lookup vs devfs deadlock.  I can't see how this is
  fixable without getting rid of the current devfsd design.  Mandrake seems
  to have a workaround for this so this is at least not triggered so easily,
  but that's not what I'd consider a fix..

o viro: fs/char_dev.c needs removal of aeb stuff and merge of cdev-cidr. 
  In progress.

o forward-port sct's O_DIRECT fixes

o viro: there is some generic stuff for namei/namespace/super, but that's a
  slow-merge and can go in 2.6 just fine

o andi: also soft needs to be fixed - there are quite a lot of
  uninterruptible waits in sunrpc/nfs

o trond: NFS has a mmap-versus-truncate problem

kernel/sched.c/
~~~~~~~~~~~~~~~

o O(1) scheduler starvation, poor behaviour seems unresolved.

  Jens: "I've been running 2.5.67-mm3 on my workstation for two days, and
  it still doesn't feel as good as 2.4.  It's not a disaster like some
  revisisons ago, but it still has occasional CPU "stalls" where it feels
  like a process waits for half a second of so for CPU time.  That's is very
  noticable."

   Also see Mike Galbraith's work.

  Conclusion: the scheduler has issues, lots of people working on it.  Rick
  Lindsley, Andrew Theurer.

o "Persistent starvation"

  http://www.hpl.hp.com/research/linux/kernel/o1-starve.php

  ingo: "this is mostly invalid".

o Overeager affinity in presence of repeated yields

  http://www.hpl.hp.com/research/linux/kernel/o1-openmp.php

  ingo: this is valid.  fix is in progress.

o The "thud.c" test app.  This is a exploit for the interactivity
  estimator.  it's unlikely to bite in real-world cases.  Needs watching. 
  Can be ameliorated by setting nice values.

o generic interactivity problems need watching.  We've closed down a number
  of items recently without introducing new ones, so i'm confident this is
  heading in the right direction.

kernel/
~~~~~~~

o Alan: 32bit uid support is *still* broken for process accounting.

  Create a 32bit uid, turn accounting on.  Shock horror it doesn't work
  because the field is 16bit.  We need an acct structure flag day for 2.6
  IMHO

  (alan has patch)

o nasty task refcounting bug is taking ages to track down.  (bugzilla ref?)

o viro: core sysctl code is racy.  And its interaction wiuth sysfs

o gettimeofday goes backwards.  Merge up David M-T's fixes?

mm/
~~~

o Overcommit accounting gets wrong answers

  o underestimates reclaimable slab, gives bogus failures when
    dcache&icache are large.

  o gets confused by reclaimable-but-not-freed truncated ext3 pages. 
    Lame fix exists in -mm.

o Proper user level no overcommit also requires a root margin adding

o There's a vmalloc race.  David Woodhouse has a patch, but it had a
  problem.  Need to revisit it.

o GFP_DMA32 (or something like that).  Lots of ideas.  jejb, zaitcev,
  willy, arjan, wli.

o access_process_vm() doesn't flush right.  We probably need new flushing
  primitives to do this (davem?)


modules
~~~~~~~

  (Rusty)

o The .modinfo patch needs to go in.  It's trivial, but it's the major
  missing functionality vs. 2.4.  Keeps bouncing off Linus.

o __module_get(): "I know I have a refcount already and I don't care
  if they're doing rmmod --wait, gimme.".  Keeps bouncing off Linus.

o Per-cpu support inside modules (have patch, in testing).

o shemminger: The module remove rework that Rusty and Dave are working on
  needs to be fixed before 2.6.  Right now, it is impossible to write a
  protocol or network device that can be safely unloaded when it is a module.

  See:
        http://www.osdl.org/archive/shemminger/modules.html

  (This is "two stage unload")

net/
~~~~

  (davem)

o UDP apps can in theory deadlock, because the ip_append_data path can end
  up sleeping while the socket lock is held.

  It is OK to sleep with the socket held held, normally.  But in this case
  the sleep happens while waiting for socket memory/space to become
  available, if another context needs to take the socket lock to free up the
  space we could hang.

  I sent a rough patch on how to fix this to Alexey, and he is analyzing
  the situation.  I expect a final fix from him next week or so.

o Semantics for IPSEC during operations such as TCP connect suck currently.

  When we first try to connect to a destination, we may need to ask the
  IPSEC key management daemon to resolve the IPSEC routes for us.  For the
  purposes of what the kernel needs to do, you can think of it like ARP.  We
  can't send the packet out properly until we resolve the path.

  What happens now for IPSEC is basically this:

  O_NONBLOCK: returns -EAGAIN over and over until route is resolved

  !O_NONBLOCK: Sleeps until route is resolved

  These semantics are total crap.  The solution, which Alexey is working
  on, is to allow incomplete routes to exist.  These "incomplete" routes
  merely put the packet onto a "resolution queue", and once the key manager
  does it's thing we finish the output of the packet.  This is precisely how
  ARP works.

  I don't know when Alexey will be done with this.

o There are those mysterious TCP hangs of established state sockets. 
  Someone has to get a good log in order for us to effectively debug this.

net/*/netfilter/
~~~~~~~~~~~~~~~~

  (Rusty)

o Handle non-linear skbs everywhere.  This is going in via Dave now.

o Rework conntrack hashing.

o Module relationship bogosity fix (trivial, have patch).

sound/
~~~~~~

o rmk: several OSS drivers for SA11xx-based hardware in need of
  ALSA-ification and L3 bus support code for these.

o rmk: linux/sound/drivers/mpu401/mpu401.c and
  linux/sound/drivers/virmidi.c complained about 'errno' at some time in the
  past, need to confirm whether this is still a problem.

o rmk: need to complete ALSA-ification of the WaveArtist driver for both
  NetWinder and other stuff (there's some fairly fundamental differences in
  the way the mixer needs to be handled for the NetWinder.)


  (Issues with forward-porting 2.4 bugfixes.)
  (Killing off OSS is 2.7 material)


global
~~~~~~

o Lots of 2.4 fixes including some security are not in 2.5

o HZ=1000 caused lots of lost timer interrupts.  ACPI or SMM.  (andi,
  jstultz, arjan)

o There are about 60 or 70 security related checks that need doing
  (copy_user etc) from Stanford tools.  (badari is looking into this, and
  hollisb)

o A couple of hundred real looking bugzilla bugs

o viro: cdev rework.  Main group is pretty stable and I hope to feed it to
  Linus RSN.  That's cdev-cidr and ->i_cdev/->i_cindex stuff


Not-ready features and speedups
===============================


drivers/block/
~~~~~~~~~~~~~~

o Framework for selecting IO schedulers.  This is the main one really. 
  Once this is in place we can drop in new schedulers any old time, no risk.

o Anticipatory scheduler.  Working OK now, still has problems with seeky
  OLTP-style loads.

o CFQ scheduler.  Seems to work but Jens planning significant rework.

o cryptoloop: jmorris: There's no cryptoloop in the 2.4 mainline kernel,
  but I think every distro ships some version.  It would probably be useful
  to have crypto natively supported in 2.6, with backward compatibility for
  the majority of 2.4 users.

  problem: lack of a loop maintainer

o viro: paride drivers need a big cleanup

drivers/char/rtc/
~~~~~~~~~~~~~~~~~

o rmk: I think we need a generic RTC driver (which is backed by real RTCs).
   Integrator-based stuff has a 32-bit 1Hz counter RTC with alarm, as has the
  SA11xx, and probably PXA.  There's another implementation for the RiscPC
  and ARM26 stuff.  I'd rather not see 4 implementations of the RTC userspace
  API, but one common implementation so that stuff gets done in a consistent
  way.

  We postponed this at the beginning of 2.4 until 2.5 happened.  We're now
  at 2.5, and I'm about to add at least one more (the Integrator
  implementation.) This isn't sane imo.

device mapper
~~~~~~~~~~~~~

o ioctl interface cleanup patch is ready (redo the structure layouts)

o A port of the 2.4 snapshot target is in progress

o the fs interface to dm needs to be redone.  gregkh was going to work on
  this.  viro is interested in seeing work thus-far.

drivers/net/wireless/
~~~~~~~~~~~~~~~~~~~~~

  (Jean Tourrilhes <jt@bougret.hpl.hp.com>)

o get latest orinoco changes from David.

o get the latest airo.c fixes from CVS.  This will hopefully fix problems
  people have reported on the LKML.

o get HostAP driver in the kernel.  No consolidation of the 802.11
  management across driver can happen until this one is in (which is probably
  2.7.X material).  I think Jouni is mostly ready but didn't find time for
  it.

o get more wireless drivers into the kernel.  The most "integrable" drivers
  at this point seem the NWN driver, Pavel's Spectrum driver and the Atmel
  driver.

o The last two drivers mentioned above are held up by firmware issues (see
  flamewar on LKML a few days ago).  So maybe fixing those firmware issues
  should be a requirement for 2.6.X, because we can expect more wireless
  devices to need firmware upload at startup coming to market.

drivers/usb/gadget/
~~~~~~~~~~~~~~~~~~~

o rmk: SA11xx USB client/gadget code (David B has been doing some work on
  this, and keeps trying to prod me, but unfortunately I haven't had the time
  to look at his work, sorry David.)

fs/
~~~

o ext3 lock_kernel() removal: that part works OK and is mergeable.  But
  we'll also need to make lock_journal() a spinlock, and that's deep surgery.

o ext3 and ext2 block allocators have serious failure modes - interleaved
  allocations.

o 32bit quota needs a lot more testing but may work now

o Integrate Chris Mason's 2.4 reiserfs ordered data and data journaling
  patches.  They make reiserfs a lot safer.

o (Trond:) Yes: I'm still working on an atomic "open()", i.e.  one
           where we short-circuit the usual VFS path_walk() + lookup() +
           permission() + create() + ....  bullsh*t...

           I have several reasons for wanting to do this (all of
           them related to NFS of course, but much of the reasoning applies
           to *all* networked file systems).

   1) The above sequence is simply not atomic on *any* networked
      filesystem.

   2) It introduces a sh*tload of completely unnecessary RPC calls (why
      do a 'permission' RPC call when the server is in *any* case going to
      tell you whether or not this operations is allowed.  Why do a
      'lookup()' when the 'create()' call can be made to tell you whether or
      not a file already exists).

   3) It is incompatible with some operations: the current create()
      doesn't pass an 'EXCLUSIVE' flag down to the filesystems.

   4) (NFS specific?) open() has very different cache consistency
      requirements when compared to most other VFS operations.

   I'd very much like for something like Peter Braam's 'lookup with
   intent' or (better yet) for a proper dentry->open() to be integrated with
   path_walk()/open_namei().  I'm still working on the latter (Peter has
   already completed the lookup with intent stuff).

o rmk: update acorn partition parsing code - making all acorn schemes
  appear in check.c so we don't have to duplicate the scanning of multiple
  types, and adding support for eesox partitions.

o atomic i_size patches

o viro: cleaning up options-parsers in filesystems.  (patch exists, needs
  porting).

o aio: fs IO isn't async at present.  suparna has restart patches, they're
  in -mm.  Need to get Ben to review/comment.


kernel/
~~~~~~~

o rusty: Zippel's Reference count simplification.  Tricky code, but cuts
  about 120 lines from module.c.  Patch exists, needs stressing.

o rusty: /proc/kallsyms.  What most people really wanted from /proc/ksyms. 
  Patch exists.

o rusty: Fix module-failed-init races by starting module "disabled".  Patch
  exists, requires some subsystems (ie.  add_partition) to explicitly say
  "make module live now".  Without patch we are no worse off than 2.4 etc.  

o Integrate userspace irq balancing daemon.

o kexec.  Seems to work, is in -mm.

o rmk: modules / /proc/kcore / vmalloc This needs sorting and testing to
  ensure that stuff like gdb vmlinux /proc/kcore works as expected.  I
  believe this is the only show stopper preventing any ARM platform being
  built in Linus' kernel.

o kcore is a problem for ia64 (Tony Luck)

o rmk: lib/inflate.c must not use static variables (causes these to be
  referenced via GOTOFF relocations in PIC decompressor.  We have a PIC
  decompressor to avoid having to hard code a per platform zImage link
  address into the makefiles.)

o klibc merge?

mm/
~~~

o objrmap: concerns over page reclaim performance at high sharing levels,
  and interoperation with nonlinear mappings is hairy.

o Reintroduce and make /proc/sys/vm/freepages writable again so that boxes
  can be tuned for heavy interrupt load.

o oxymoron's async write-error-handling patch

net/
~~~~

  (davem)

o Real serious use of IPSEC is hampered by lack of MPLS support.  MPLS is a
  switching technology that works by switching based upon fixed length labels
  prepended to packets.  Many people use this and IPSEC to implement VPNs
  over public networks, it is also used for things like traffic engineering.

  A good reference site is:

	http://www.mplsrc.com/

  Anyways, an existing (crappy) implementation exists.  I've almost
  completed a rewrite, I should have something in the tree next week.

o Sometimes we generate IP fragments when it truly isn't necessary.

  The way IP fragmentation is specified, each fragment must be modulo 8
  bytes in length.  So suppose the device has an MTU that is not 0 modulo 8,
  ethernet even classifies in this way.  1500 == (8 * 187) + 4

  Our IP fragmenting engine can fragment on packets that are sized within
  the last modulo 8 bytes of the MTU.  This happens in obscure cases, but it
  does happen.

  I've proposed a fix to Alexey, whereby very late in the output path we
  check the packet, if we fragmented but the data length would fit into the
  MTU we unfragment the packet.

  This is low priority, because technically it creates suboptimal behavior
  rather than mis-operation.

net/*/netfilter/
~~~~~~~~~~~~~~~~

o Lots of misc. cleanups, which are happening slowly.

o davem: Netfilter needs to stop linearizing packets as much as possible.

  Zerocopy output packets are basically undone by netfilter becuase all of
  it assumed it was working with linear socket buffers.

  Rusty is fixing this piece by piece.  He is nearly done with this work. 

power management
~~~~~~~~~~~~~~~~

  (Pat) There is some preliminary work at bk://ldm.bkbits.net/linux-2.5-power,
  though I'm currently in the process of reworking it.  

  It includes: 

o New device power management core code, both for individual devices, 
  and for global state transitions. 

o A generic user interface for triggering system power state transitions.

o Arch-independent code for performing state transitions, that calls 
  platform-specific methods along the way. 

o A better suspend-to-disk mechanism than swsusp. 

  There are various other details to be worked out, which are the real fun
  part.  And of course, driver support, but that is something that can happen
  at any time.  

  (Alan)

o Frame buffer restore codepaths (that requires some deep PCI magic)

o XFree86 hooks

o AGP restoration

o DRI restoration

  (davej/Alan: not super-critical, can crash laptop on restore.  davej
  looking into it.)

o IDE suspend/resume without races (Ben is looking at this a little)

o Pat: There are already CPU device structures; MTRRs should be a
  dynamically registered interface of CPUs, which implies there needs
  to be some other glue to know that there are MTRRs that need to be
  saved/restored.

global
~~~~~~

o 64-bit dev_t.  Seems almost ready, but it's not really known how much
  work is still to do.  Patches exist in -mm but with the recent rise of the
  neo-viro I'm not sure where things are at.

o We need a kernel side API for reporting error events to userspace (could
  be async to 2.6 itself)

  (Prototype core based on netlink exists)

o Kai: Introduce a sane, easy and standard way to build external modules

o Kai: Allow separate src/objdir

o general confusion over firmware policy:

  o do we mandate that it be uploaded from userspace?

  o Is binary-blob-in-kernel-image OK?

  o Each driver (wireless, scsi, etc) seems to do it in a different,
    private manner.

  gregkh: patch exists, drivers can be ported to use new infrastructure at
  any time.

o larger cpumask_t - supporting more than BITS_PER_LONG CPUs.

  wli: patch exists.  ia32, ppc are done.  ppc64 in progress.  Needs work
  for other architectures.

drivers
~~~~~~~

o Some network drivers don't even build

o Alan: Cardbus/PCMCIA requires all Russell's stuff is merged to do
  multiheader right and so on

drivers/acpi/
~~~~~~~~~~~~~

o davej: ACPI has a number of failures right now.  There are a number of
  entries in bugzilla which could all be the same bug.  It manifests as a
  "network card doesn't recieve packets" booting with 'acpi=off noapic' fixes
  it.

  alan: VIA APIC stuff is one bit of this, there are also some other
  reports that were caused by ACPI not setting level v edge trigger some
  times

o davej: There's also another nasty 'doesnt boot' bug which quite a few
  people (myself included) are seeing on some boxes (especially laptops).

o mochel: it seems the acpi irq routing code could use a serious rewrite.

o mochel: ACPI suspend doesn't work.  Important, not cricital.  Pat is
  working it.

drivers/block/
~~~~~~~~~~~~~~

o Floppy is almost unusably buggy still

  akpm: we need more people to test & report.

drivers/char/
~~~~~~~~~~~~~

o Alan: Multiple serious bugs in the DRI drivers (most now with patches
  thankfully).  "The badness I know about is almost entirely IRQ mishandling.
   DRI failing to mask PCI irqs on exit paths."

  (might be fixed due to DRI updates?)

o Various suspect things in AGP.

drivers/ide/
~~~~~~~~~~~~

  (Alan)

o IDE requires bio walking

  "Bartlomiej has IDE multisector working" (does that mean it's fixed?)


o IDE PIO has occasional unexplained PIO disk eating reports

o IDE has multiple zillions of races/hangs in 2.5 still

o IDE scsi needs rewriting

o IDE needs significant reworking to handle Simplex right

o IDE hotplug handling for 2.5 is completely broken still

o There are lots of other IDE bugs that wont go away until the taskfile
  stuff is included, the locking bugs that allow any user to hang the IDE
  layer in 2.5, and some other updates are forward ported.  (esp.  HPT372N).

drivers/isdn/
~~~~~~~~~~~~~

  (Kai, rmk)

o isdn_tty locking is completely broken (cli() and friends)

o fix lots of remaining bugs in the isdn link layer / hisax protocol layer
  / hisax subdrivers, so that at least 99% of the users have a usable ISDN
  subsystem

o fix other drivers

o lots more cleanups, adaption to recent APIs etc

o fixup tty-based ISDN drivers which provide TIOCM* ioctls (see my recent
  3-set patch for serial stuff)

  Alternatively, we could re-introduce the fallback to driver ioctl parsing
  for these if not enough drivers get updated.

drivers/net/
~~~~~~~~~~~~

o davej: Either Wireless network drivers or PCMCIA broke somewhen.  A
  configuration that worked fine under 2.4 doesn't receive any packets.  Need
  to look into this more to make sure I don't have any misconfiguration that
  just 'happened to work' under 2.4


drivers/scsi/
~~~~~~~~~~~~~

o qlogic follies:

  - jejb: Merge the feral driver.  It covers all qlogic chips: 1020 all
    the way up to 23xxx.  mjacob is promising a "major" rewrite which
    eliminates this as a candidate for immediate inclusion.  Panics on my
    parisc hardware, works on my ia64.  BK tree is
    http://linux-scsi.bkbits.net/scsi-isp-2.5

  - qla2xxx: only for FC chips.  Has significant build issues.  hch
    promises to send me a "must fix" list for this.  I plan not to merge this
    until I at least see how Qlogic responds to the issues.  Can't currently
    build this for my only fibre card (a qla2100).  BK tree is at
    http://linux-scsi.bkbits.net/scsi-qla2xxx-2.5

  - I think the best plan currently is not to merge either of these, but
    keep shadow BK trees for them (thus holding out the possibility of
    merger) to see how they evolve.  I agree with hch that feral seems to be
    in the better shape but, barring directions to the contrary, I can't see
    why both shouldn't be included eventually.

arch/i386/
~~~~~~~~~~

o Also PC9800 merge needs finishing to the point we want for 2.6 (not all).

o ES7000 wants merging (now we are all happy with it).  That shouldn't be a
  big problem.

o davej: PAT support (for mtrr exhaustion w/ AGP)

o 2.5.x won't boot on some 440GX

  alan: Problem understood now, feasible fix in 2.4/2.4-ac.  (440GX has two
  IRQ routers, we use the $PIR table with the PIIX, but the 440GX doesnt use
  the PIIX for its IRQ routing).  Fall back to BIOS for 440GX works and Intel
  concurs.

o 2.5.x doesn't handle VIA APIC right yet.

  1. We must write the PCI_INTERRUPT_LINE

  2. We have quirk handlers that seem to trash it.

o ACPI needs the relax patches merging to work on lots of laptops

o ECC driver questions are not yet sorted (DaveJ is working on this) (Dan
  Hollis)

arch/x86_64/
~~~~~~~~~~~~

  (Andi)

o time handling is broken. Need to move up 2.4 time.c code.

o Another report of a crash at shutdown on Simics with no iommu when all
  memory was used.  Could be related to the one above.

o NMI watchdog seems to tick too fast

o not very well tested. probably more bugs lurking.

o need to coredump 64bit vsyscall code with dwarf2

o move 64bit signal trampolines into vsyscall code and add dwarf2 for it.

o describe kernel assembly with dwarf2 annotations for kgdb (currently
  waiting on some binutils changes for this) 

arch/alpha/
~~~~~~~~~~~

o rth: Ptrace writes are broken.  This means we can't (reliably) set
  breakpoints or modify variables from gdb.

arch/arm/
~~~~~~~~~

o rmk: missing raw keyboard translation tables for all ARM machines. 
  Haven't even looked into this at all.  This could be messy since there
  isn't an ARM architecture standard.  I'm presently hoping that it won't be
  an issue.  If it does, I guess we'll see drivers/char/keyboard.c explode.

arch/others/
~~~~~~~~~~~~

o SH/SH-64 need resyncing, as do some other ports.  No impact on
  mainstream platforms hopefully.

o IA64 needs merging, has impact on core code



^ permalink raw reply	[flat|nested] 34+ messages in thread

* must-fix list, v5
@ 2003-05-21 22:22 Andrew Morton
  2003-05-21 22:23 ` Andrew Morton
                   ` (5 more replies)
  0 siblings, 6 replies; 34+ messages in thread
From: Andrew Morton @ 2003-05-21 22:22 UTC (permalink / raw)
  To: linux-kernel


Also at ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/must-fix/

For verson 6 I shall go through the "late features" list and prioritise
things.


Changes since v5:

--- must-fix-4.txt	Wed May 21 15:18:28 2003
+++ must-fix-5.txt	Wed May 21 15:17:25 2003
@@ -11,20 +11,23 @@
 
   o Other problems: aviro, dipankar, Alan have details.
 
   o somebody will have to document the tty driver and ldisc API
 
 o Lack of test cases and/or stress tests is a problem.  Contributions and
   suggestions are sought.
 
 o Lots of drivers are using cli/sti and are broken.
 
+o willy: random.c is completely lockfree, and not in a good way.  i had
+  some patches but nothing got seriously tested.
+
 drivers/tty
 ~~~~~~~~~~~
 
 o viro: we need to fix refcounting for tty_driver (oopsable race, must fix
   anyway, hopefully about a week until it's merged) then we can do
   tty/misc/upper levels of sound and hopefully upper level of USB.
 
   USB is a place where we _really_ need to deal with dynamic allocation of
   device numbers and that will bite.
 
@@ -72,31 +75,37 @@
 
   We need to understand whether the proposed BIO split code will suffice
   for this.
 
 o CD burning.  There are still a few quirks to solve wrt SG_IO and ide-cd.
 
   Jens: The basic hang has been solved (double fault in ide-cd), there still
   seems to be some cases that don't work too well.  Don't really have a
   handle on those :/
 
+o lmb: Last time I looked at the multipath code (2.5.50 or so) it also
+  looked pretty broken; I plan to port forward the changes we did on 2.4
+  before KS.
+
+o elevator-noop is broken.
+
 drivers/input/
 ~~~~~~~~~~~~~~
 
 o rmk: unconverted keyboard/mouse drivers (there's a deadline of 2.6.0
   currently on these remaining in my/Linus' tree.)
 
 o viro: large absence of locking.
 
 o synaptic touchpad support
 
-  Apparently there's a userspace `tpconfig'
+  Jens Taprogge <jens.taprogge@rwth-aachen.de> is working on this.
 
 o andi: also the input keyboard stuff still has unusably obscure config
   options for standard PC hardware.
 
 o viro: parport is nearly as bad as that and there the code is more hairy. 
   IMO parport is more of "figure out what API changes are needed for its
   users, get them done ASAP, then fix generic layer at leisure"
 
 drivers/misc/
 ~~~~~~~~~~~~~
@@ -141,20 +150,24 @@
   (bugzilla, please?)
 
 o We have multiple drivers walking the pci device lists and also using
   things like pci_find_device in unsafe ways with no refcounting.  I think
   we have to make pci_find_device etc refcount somewhere and add
   pci_device_put as was done with networking.
   http://bugzilla.kernel.org/show_bug.cgi?id=709
 
   (gregkh will work on this)
 
+o willy: PCI Domain support.  The 'must-fix' bit of this is getting sysfs
+  to present the right interface to userspace so we can adapt pciutils & X to
+  use it.
+
 drivers/pcmcia/
 ~~~~~~~~~~~~~~~
 
 o alan: Most drivers crash the system on eject randomly with timer bugs.  I
   think after RMK's stuff is in most of the pcmcia/cardbus ones go except the
   locking disaster.
 
   (rmk, brodo: in progress)
 
 drivers/pld/
@@ -245,50 +258,74 @@
   In progress.
 
 o forward-port sct's O_DIRECT fixes
 
 o viro: there is some generic stuff for namei/namespace/super, but that's a
   slow-merge and can go in 2.6 just fine
 
 o andi: also soft needs to be fixed - there are quite a lot of
   uninterruptible waits in sunrpc/nfs
 
-kernel/
-~~~~~~~
+o trond: NFS has a mmap-versus-truncate problem
+
+kernel/sched.c/
+~~~~~~~~~~~~~~~
 
 o O(1) scheduler starvation, poor behaviour seems unresolved.
 
   Jens: "I've been running 2.5.67-mm3 on my workstation for two days, and
   it still doesn't feel as good as 2.4.  It's not a disaster like some
   revisisons ago, but it still has occasional CPU "stalls" where it feels
   like a process waits for half a second of so for CPU time.  That's is very
   noticable."
 
    Also see Mike Galbraith's work.
 
   Conclusion: the scheduler has issues, lots of people working on it.  Rick
   Lindsley, Andrew Theurer.
 
-o drepper: there are at least two big problems with the interaction between
-  futex and O(1).  Ingo has already patches.  But we need much more testing
-  on big boxes.  Only 4p+ machines have problems
+o "Persistent starvation"
+
+  http://www.hpl.hp.com/research/linux/kernel/o1-starve.php
+
+  ingo: "this is mostly invalid".
+
+o Overeager affinity in presence of repeated yields
+
+  http://www.hpl.hp.com/research/linux/kernel/o1-openmp.php
+
+  ingo: this is valid.  fix is in progress.
+
+o The "thud.c" test app.  This is a exploit for the interactivity
+  estimator.  it's unlikely to bite in real-world cases.  Needs watching. 
+  Can be ameliorated by setting nice values.
+
+o generic interactivity problems need watching.  We've closed down a number
+  of items recently without introducing new ones, so i'm confident this is
+  heading in the right direction.
+
+kernel/
+~~~~~~~
 
 o Alan: 32bit uid support is *still* broken for process accounting.
 
   Create a 32bit uid, turn accounting on.  Shock horror it doesn't work
   because the field is 16bit.  We need an acct structure flag day for 2.6
   IMHO
 
   (alan has patch)
 
 o nasty task refcounting bug is taking ages to track down.  (bugzilla ref?)
 
+o viro: core sysctl code is racy.  And its interaction wiuth sysfs
+
+o gettimeofday goes backwards.  Merge up David M-T's fixes?
 
 mm/
 ~~~
 
 o Overcommit accounting gets wrong answers
 
   o underestimates reclaimable slab, gives bogus failures when
     dcache&icache are large.
 
   o gets confused by reclaimable-but-not-freed truncated ext3 pages. 
@@ -419,43 +456,58 @@
 Not-ready features and speedups
 ===============================
 
 
 drivers/block/
 ~~~~~~~~~~~~~~
 
 o Framework for selecting IO schedulers.  This is the main one really. 
   Once this is in place we can drop in new schedulers any old time, no risk.
 
-o Runtime-selectable disk scheduler framework.
-
 o Anticipatory scheduler.  Working OK now, still has problems with seeky
   OLTP-style loads.
 
 o CFQ scheduler.  Seems to work but Jens planning significant rework.
 
-o The feral.com qlogic driver: needs work.
+o cryptoloop: jmorris: There's no cryptoloop in the 2.4 mainline kernel,
+  but I think every distro ships some version.  It would probably be useful
+  to have crypto natively supported in 2.6, with backward compatibility for
+  the majority of 2.4 users.
+
+  problem: lack of a loop maintainer
+
+o viro: paride drivers need a big cleanup
 
 drivers/char/rtc/
 ~~~~~~~~~~~~~~~~~
 
 o rmk: I think we need a generic RTC driver (which is backed by real RTCs).
    Integrator-based stuff has a 32-bit 1Hz counter RTC with alarm, as has the
   SA11xx, and probably PXA.  There's another implementation for the RiscPC
   and ARM26 stuff.  I'd rather not see 4 implementations of the RTC userspace
   API, but one common implementation so that stuff gets done in a consistent
   way.
 
   We postponed this at the beginning of 2.4 until 2.5 happened.  We're now
   at 2.5, and I'm about to add at least one more (the Integrator
   implementation.) This isn't sane imo.
 
+device mapper
+~~~~~~~~~~~~~
+
+o ioctl interface cleanup patch is ready (redo the structure layouts)
+
+o A port of the 2.4 snapshot target is in progress
+
+o the fs interface to dm needs to be redone.  gregkh was going to work on
+  this.  viro is interested in seeing work thus-far.
+
 drivers/net/wireless/
 ~~~~~~~~~~~~~~~~~~~~~
 
   (Jean Tourrilhes <jt@bougret.hpl.hp.com>)
 
 o get latest orinoco changes from David.
 
 o get the latest airo.c fixes from CVS.  This will hopefully fix problems
   people have reported on the LKML.
 
@@ -476,26 +528,26 @@
 drivers/usb/gadget/
 ~~~~~~~~~~~~~~~~~~~
 
 o rmk: SA11xx USB client/gadget code (David B has been doing some work on
   this, and keeps trying to prod me, but unfortunately I haven't had the time
   to look at his work, sorry David.)
 
 fs/
 ~~~
 
-o reiserfs_file_write() speedup.  There are concerns that some applications
-  do the wrong thing with large stat.st_blksize.
-
 o ext3 lock_kernel() removal: that part works OK and is mergeable.  But
   we'll also need to make lock_journal() a spinlock, and that's deep surgery.
 
+o ext3 and ext2 block allocators have serious failure modes - interleaved
+  allocations.
+
 o 32bit quota needs a lot more testing but may work now
 
 o Integrate Chris Mason's 2.4 reiserfs ordered data and data journaling
   patches.  They make reiserfs a lot safer.
 
 o (Trond:) Yes: I'm still working on an atomic "open()", i.e.  one
            where we short-circuit the usual VFS path_walk() + lookup() +
            permission() + create() + ....  bullsh*t...
 
            I have several reasons for wanting to do this (all of
@@ -519,58 +571,70 @@
 
    I'd very much like for something like Peter Braam's 'lookup with
    intent' or (better yet) for a proper dentry->open() to be integrated with
    path_walk()/open_namei().  I'm still working on the latter (Peter has
    already completed the lookup with intent stuff).
 
 o rmk: update acorn partition parsing code - making all acorn schemes
   appear in check.c so we don't have to duplicate the scanning of multiple
   types, and adding support for eesox partitions.
 
+o atomic i_size patches
+
+o viro: cleaning up options-parsers in filesystems.  (patch exists, needs
+  porting).
+
+o aio: fs IO isn't async at present.  suparna has restart patches, they're
+  in -mm.  Need to get Ben to review/comment.
+
 
 kernel/
 ~~~~~~~
 
-  (Rusty)
-
-o Zippel's Reference count simplification.  Tricky code, but cuts about 120
-  lines from module.c.  Patch exists, needs stressing.
+o rusty: Zippel's Reference count simplification.  Tricky code, but cuts
+  about 120 lines from module.c.  Patch exists, needs stressing.
 
-o /proc/kallsyms.  What most people really wanted from /proc/ksyms.  Patch
-  exists.
+o rusty: /proc/kallsyms.  What most people really wanted from /proc/ksyms. 
+  Patch exists.
 
-o Fix module-failed-init races by starting module "disabled".  Patch
+o rusty: Fix module-failed-init races by starting module "disabled".  Patch
   exists, requires some subsystems (ie.  add_partition) to explicitly say
-  "make module live now".  Without patch we are no worse off than 2.4 etc. 
+  "make module live now".  Without patch we are no worse off than 2.4 etc.  
 
 o Integrate userspace irq balancing daemon.
 
 o kexec.  Seems to work, is in -mm.
 
 o rmk: modules / /proc/kcore / vmalloc This needs sorting and testing to
   ensure that stuff like gdb vmlinux /proc/kcore works as expected.  I
   believe this is the only show stopper preventing any ARM platform being
   built in Linus' kernel.
 
+o kcore is a problem for ia64 (Tony Luck)
+
 o rmk: lib/inflate.c must not use static variables (causes these to be
   referenced via GOTOFF relocations in PIC decompressor.  We have a PIC
   decompressor to avoid having to hard code a per platform zImage link
   address into the makefiles.)
 
+o klibc merge?
+
 mm/
 ~~~
 
 o objrmap: concerns over page reclaim performance at high sharing levels,
   and interoperation with nonlinear mappings is hairy.
 
-o Readd and make /proc/sys/vm/freepages writable again so that boxes can be
-  tuned for heavy interrupt load.
+o Reintroduce and make /proc/sys/vm/freepages writable again so that boxes
+  can be tuned for heavy interrupt load.
+
+o oxymoron's async write-error-handling patch
 
 net/
 ~~~~
 
   (davem)
 
 o Real serious use of IPSEC is hampered by lack of MPLS support.  MPLS is a
   switching technology that works by switching based upon fixed length labels
   prepended to packets.  Many people use this and IPSEC to implement VPNs
   over public networks, it is also used for things like traffic engineering.
@@ -628,50 +692,38 @@
   platform-specific methods along the way. 
 
 o A better suspend-to-disk mechanism than swsusp. 
 
   There are various other details to be worked out, which are the real fun
   part.  And of course, driver support, but that is something that can happen
   at any time.  
 
   (Alan)
 
-o PCI locking
-
 o Frame buffer restore codepaths (that requires some deep PCI magic)
 
 o XFree86 hooks
 
 o AGP restoration
 
 o DRI restoration
 
-o IDE suspend/resume without races (Ben is looking at this a little)
-
-o How to deal with devices that babble (some stuff we have to global IRQ
-  off to save, and global IRQ on -after- we recover with APM)
+  (davej/Alan: not super-critical, can crash laptop on restore.  davej
+  looking into it.)
 
-o Pat's swsusp rework?
+o IDE suspend/resume without races (Ben is looking at this a little)
 
 o Pat: There are already CPU device structures; MTRRs should be a
   dynamically registered interface of CPUs, which implies there needs
   to be some other glue to know that there are MTRRs that need to be
   saved/restored.
 
-arch/i386/
-~~~~~~~~~~
-
-o Also PC9800 merge needs finishing to the point we want for 2.6 (not all).
-
-o ES7000 wants merging (now we are all happy with it).  That shouldn't be a
-  big problem.
-
 global
 ~~~~~~
 
 o 64-bit dev_t.  Seems almost ready, but it's not really known how much
   work is still to do.  Patches exist in -mm but with the recent rise of the
   neo-viro I'm not sure where things are at.
 
 o We need a kernel side API for reporting error events to userspace (could
   be async to 2.6 itself)
 
@@ -683,26 +735,30 @@
 
 o general confusion over firmware policy:
 
   o do we mandate that it be uploaded from userspace?
 
   o Is binary-blob-in-kernel-image OK?
 
   o Each driver (wireless, scsi, etc) seems to do it in a different,
     private manner.
 
+  gregkh: patch exists, drivers can be ported to use new infrastructure at
+  any time.
 
+o larger cpumask_t - supporting more than BITS_PER_LONG CPUs.
 
-
+  wli: patch exists.  ia32, ppc are done.  ppc64 in progress.  Needs work
+  for other architectures.
 
 drivers
-=======
+~~~~~~~
 
 o Some network drivers don't even build
 
 o Alan: Cardbus/PCMCIA requires all Russell's stuff is merged to do
   multiheader right and so on
 
 drivers/acpi/
 ~~~~~~~~~~~~~
 
 o davej: ACPI has a number of failures right now.  There are a number of
@@ -710,25 +766,32 @@
   "network card doesn't recieve packets" booting with 'acpi=off noapic' fixes
   it.
 
   alan: VIA APIC stuff is one bit of this, there are also some other
   reports that were caused by ACPI not setting level v edge trigger some
   times
 
 o davej: There's also another nasty 'doesnt boot' bug which quite a few
   people (myself included) are seeing on some boxes (especially laptops).
 
+o mochel: it seems the acpi irq routing code could use a serious rewrite.
+
+o mochel: ACPI suspend doesn't work.  Important, not cricital.  Pat is
+  working it.
+
 drivers/block/
 ~~~~~~~~~~~~~~
 
 o Floppy is almost unusably buggy still
 
+  akpm: we need more people to test & report.
+
 drivers/char/
 ~~~~~~~~~~~~~
 
 o Alan: Multiple serious bugs in the DRI drivers (most now with patches
   thankfully).  "The badness I know about is almost entirely IRQ mishandling.
    DRI failing to mask PCI irqs on exit paths."
 
   (might be fixed due to DRI updates?)
 
 o Various suspect things in AGP.
@@ -783,65 +846,82 @@
 
 o davej: Either Wireless network drivers or PCMCIA broke somewhen.  A
   configuration that worked fine under 2.4 doesn't receive any packets.  Need
   to look into this more to make sure I don't have any misconfiguration that
   just 'happened to work' under 2.4
 
 
 drivers/scsi/
 ~~~~~~~~~~~~~
 
-o Half of SCSI doesn't compile
+o qlogic follies:
+
+  - jejb: Merge the feral driver.  It covers all qlogic chips: 1020 all
+    the way up to 23xxx.  mjacob is promising a "major" rewrite which
+    eliminates this as a candidate for immediate inclusion.  Panics on my
+    parisc hardware, works on my ia64.  BK tree is
+    http://linux-scsi.bkbits.net/scsi-isp-2.5
+
+  - qla2xxx: only for FC chips.  Has significant build issues.  hch
+    promises to send me a "must fix" list for this.  I plan not to merge this
+    until I at least see how Qlogic responds to the issues.  Can't currently
+    build this for my only fibre card (a qla2100).  BK tree is at
+    http://linux-scsi.bkbits.net/scsi-qla2xxx-2.5
+
+  - I think the best plan currently is not to merge either of these, but
+    keep shadow BK trees for them (thus holding out the possibility of
+    merger) to see how they evolve.  I agree with hch that feral seems to be
+    in the better shape but, barring directions to the contrary, I can't see
+    why both shouldn't be included eventually.
 
 arch/i386/
 ~~~~~~~~~~
 
+o Also PC9800 merge needs finishing to the point we want for 2.6 (not all).
+
+o ES7000 wants merging (now we are all happy with it).  That shouldn't be a
+  big problem.
+
+o davej: PAT support (for mtrr exhaustion w/ AGP)
+
 o 2.5.x won't boot on some 440GX
 
   alan: Problem understood now, feasible fix in 2.4/2.4-ac.  (440GX has two
   IRQ routers, we use the $PIR table with the PIIX, but the 440GX doesnt use
   the PIIX for its IRQ routing).  Fall back to BIOS for 440GX works and Intel
   concurs.
 
 o 2.5.x doesn't handle VIA APIC right yet.
 
   1. We must write the PCI_INTERRUPT_LINE
 
   2. We have quirk handlers that seem to trash it.
 
 o ACPI needs the relax patches merging to work on lots of laptops
 
-o ECC driver questions are not yet sorted (DaveJ is working on this)
-
-o PC9800 is not fully merged - most of this I think is 2.7 stuff but a few
-  bits might be 2.6 candidate
+o ECC driver questions are not yet sorted (DaveJ is working on this) (Dan
+  Hollis)
 
 arch/x86_64/
 ~~~~~~~~~~~~
 
   (Andi)
 
 o time handling is broken. Need to move up 2.4 time.c code.
 
 o Another report of a crash at shutdown on Simics with no iommu when all
   memory was used.  Could be related to the one above.
 
 o NMI watchdog seems to tick too fast
 
-o some fixes from 2.4 still need to be merged
-
 o not very well tested. probably more bugs lurking.
 
-o 32bit vsyscalls seem to be broken
-
-o 32bit elf coredumps are broken
-
 o need to coredump 64bit vsyscall code with dwarf2
 
 o move 64bit signal trampolines into vsyscall code and add dwarf2 for it.
 
 o describe kernel assembly with dwarf2 annotations for kgdb (currently
   waiting on some binutils changes for this) 
 
 arch/alpha/
 ~~~~~~~~~~~
 
@@ -855,10 +935,12 @@
   Haven't even looked into this at all.  This could be messy since there
   isn't an ARM architecture standard.  I'm presently hoping that it won't be
   an issue.  If it does, I guess we'll see drivers/char/keyboard.c explode.
 
 arch/others/
 ~~~~~~~~~~~~
 
 o SH/SH-64 need resyncing, as do some other ports.  No impact on
   mainstream platforms hopefully.
 
+o IA64 needs merging, has impact on core code
+


^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2003-05-29 21:04 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20030521152255.4aa32fba.akpm@digeo.com.suse.lists.linux.kernel>
     [not found] ` <20030521152334.4b04c5c9.akpm@digeo.com.suse.lists.linux.kernel>
     [not found]   ` <20030526093717.GC642@zaurus.ucw.cz.suse.lists.linux.kernel>
     [not found]     ` <20030528144839.47efdc4f.akpm@digeo.com.suse.lists.linux.kernel>
     [not found]       ` <20030528215551.GB255@elf.ucw.cz.suse.lists.linux.kernel>
2003-05-29  9:17         ` must-fix list, v5 Andi Kleen
2003-05-29  9:32           ` David S. Miller
2003-05-29  9:46             ` Pavel Machek
2003-05-29 10:01               ` David S. Miller
2003-05-29 10:03                 ` Pavel Machek
2003-05-29  9:46             ` Andi Kleen
2003-05-29 10:01               ` David S. Miller
2003-05-29 11:25             ` Pavel Machek
2003-05-29 11:26               ` David S. Miller
2003-05-29 11:39                 ` Arjan van de Ven
2003-05-29 20:10                   ` Pavel Machek
2003-05-29 20:06             ` Pavel Machek
2003-05-29 21:15               ` David S. Miller
2003-05-22  8:16 Grover, Andrew
2003-05-22  8:31 ` Andrew Morton
2003-05-22 14:23   ` Jos Hulzink
  -- strict thread matches above, loose matches on Subject: below --
2003-05-21 23:59 Arnd Bergmann
2003-05-21 22:22 Andrew Morton
2003-05-21 22:23 ` Andrew Morton
2003-05-21 22:49   ` Tom Rini
2003-05-21 22:55     ` Andrew Morton
2003-05-26  9:37   ` Pavel Machek
2003-05-28 21:48     ` Andrew Morton
2003-05-28 21:55       ` Pavel Machek
2003-05-28 22:06         ` Andrew Morton
     [not found]           ` <20030528221812.GC255@elf.ucw.cz>
2003-05-28 22:46             ` Andrew Morton
2003-05-28 23:03               ` Pavel Machek
2003-05-29 11:13               ` Pavel Machek
2003-05-21 22:41 ` Andrew Morton
2003-05-22  1:03 ` Carl-Daniel Hailfinger
2003-05-22  3:08   ` oxymoron
2003-05-22  1:25 ` Andrew Theurer
2003-05-22  6:24 ` Jens Axboe
2003-05-25 21:05 ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).