* sys32_ioctl -> compat_ioctl -- generic
@ 2003-03-03 23:21 Pavel Machek
2003-03-04 23:28 ` Stephen Rothwell
2003-03-04 23:36 ` Stephen Rothwell
0 siblings, 2 replies; 7+ messages in thread
From: Pavel Machek @ 2003-03-03 23:21 UTC (permalink / raw)
To: torvalds, kernel list
Hi!
This is generic part of sys32_ioctl -> compat_ioctl. Please apply,
Pavel
--- clean/include/linux/ioctl32.h 2003-03-03 23:39:15.000000000 +0100
+++ linux/include/linux/ioctl32.h 2003-02-20 10:48:21.000000000 +0100
@@ -19,5 +19,10 @@
extern int unregister_ioctl32_conversion(unsigned int cmd);
+struct ioctl_trans {
+ unsigned long cmd;
+ int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
+ struct ioctl_trans *next;
+};
#endif
--- clean/kernel/compat.c 2003-03-03 23:39:39.000000000 +0100
+++ linux/kernel/compat.c 2003-02-20 10:48:21.000000000 +0100
@@ -18,6 +18,12 @@
#include <linux/signal.h>
#include <linux/sched.h> /* for MAX_SCHEDULE_TIMEOUT */
#include <linux/futex.h> /* for FUTEX_WAIT */
+#include <linux/ioctl32.h>
+#include <linux/init.h>
+#include <linux/sockios.h> /* for SIOCDEVPRIVATE */
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ctype.h>
#include <asm/uaccess.h>
@@ -226,3 +232,219 @@
}
return do_futex((unsigned long)uaddr, op, val, timeout);
}
+
+/* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64 */
+
+#define IOCTL_HASHSIZE 256
+struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
+
+extern struct ioctl_trans ioctl_start[], ioctl_end[];
+
+static inline unsigned long ioctl32_hash(unsigned long cmd)
+{
+ return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE;
+}
+
+static void ioctl32_insert_translation(struct ioctl_trans *trans)
+{
+ unsigned long hash;
+ struct ioctl_trans *t;
+
+ hash = ioctl32_hash (trans->cmd);
+ if (!ioctl32_hash_table[hash])
+ ioctl32_hash_table[hash] = trans;
+ else {
+ t = ioctl32_hash_table[hash];
+ while (t->next)
+ t = t->next;
+ trans->next = 0;
+ t->next = trans;
+ }
+}
+
+static int __init init_sys32_ioctl(void)
+{
+ int i;
+
+ for (i = 0; &ioctl_start[i] < &ioctl_end[0]; i++) {
+ if (ioctl_start[i].next != 0) {
+ printk("ioctl translation %d bad\n",i);
+ return -1;
+ }
+
+ ioctl32_insert_translation(&ioctl_start[i]);
+ }
+ return 0;
+}
+
+__initcall(init_sys32_ioctl);
+
+static struct ioctl_trans *ioctl_free_list;
+
+/* Never free them really. This avoids SMP races. With a Read-Copy-Update
+ enabled kernel we could just use the RCU infrastructure for this. */
+static void free_ioctl(struct ioctl_trans *t)
+{
+ t->cmd = 0;
+ mb();
+ t->next = ioctl_free_list;
+ ioctl_free_list = t;
+}
+
+int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *))
+{
+ struct ioctl_trans *t;
+ unsigned long hash = ioctl32_hash(cmd);
+
+ lock_kernel();
+ for (t = (struct ioctl_trans *)ioctl32_hash_table[hash];
+ t;
+ t = t->next) {
+ if (t->cmd == cmd) {
+ printk("Trying to register duplicated ioctl32 handler %x\n", cmd);
+ unlock_kernel();
+ return -EINVAL;
+ }
+ }
+
+ if (ioctl_free_list) {
+ t = ioctl_free_list;
+ ioctl_free_list = t->next;
+ } else {
+ t = kmalloc(sizeof(struct ioctl_trans), GFP_KERNEL);
+ if (!t) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+ }
+
+ t->next = NULL;
+ t->cmd = cmd;
+ t->handler = handler;
+ ioctl32_insert_translation(t);
+
+ unlock_kernel();
+ return 0;
+}
+
+static inline int builtin_ioctl(struct ioctl_trans *t)
+{
+ return t >= (struct ioctl_trans *)ioctl_start &&
+ t < (struct ioctl_trans *)ioctl_end;
+}
+
+/* Problem:
+ This function cannot unregister duplicate ioctls, because they are not
+ unique.
+ When they happen we need to extend the prototype to pass the handler too. */
+
+int unregister_ioctl32_conversion(unsigned int cmd)
+{
+ unsigned long hash = ioctl32_hash(cmd);
+ struct ioctl_trans *t, *t1;
+
+ lock_kernel();
+
+ t = (struct ioctl_trans *)ioctl32_hash_table[hash];
+ if (!t) {
+ unlock_kernel();
+ return -EINVAL;
+ }
+
+ if (t->cmd == cmd) {
+ if (builtin_ioctl(t)) {
+ printk("%p tried to unregister builtin ioctl %x\n",
+ __builtin_return_address(0), cmd);
+ } else {
+ ioctl32_hash_table[hash] = t->next;
+ free_ioctl(t);
+ unlock_kernel();
+ return 0;
+ }
+ }
+ while (t->next) {
+ t1 = (struct ioctl_trans *)(long)t->next;
+ if (t1->cmd == cmd) {
+ if (builtin_ioctl(t1)) {
+ printk("%p tried to unregister builtin ioctl %x\n",
+ __builtin_return_address(0), cmd);
+ goto out;
+ } else {
+ t->next = t1->next;
+ free_ioctl(t1);
+ unlock_kernel();
+ return 0;
+ }
+ }
+ t = t1;
+ }
+ printk(KERN_ERR "Trying to free unknown 32bit ioctl handler %x\n", cmd);
+ out:
+ unlock_kernel();
+ return -EINVAL;
+}
+
+EXPORT_SYMBOL(register_ioctl32_conversion);
+EXPORT_SYMBOL(unregister_ioctl32_conversion);
+
+asmlinkage long compat_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct file * filp;
+ int error = -EBADF;
+ int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
+ struct ioctl_trans *t;
+
+ filp = fget(fd);
+ if(!filp)
+ goto out2;
+
+ if (!filp->f_op || !filp->f_op->ioctl) {
+ error = sys_ioctl (fd, cmd, arg);
+ goto out;
+ }
+
+ t = (struct ioctl_trans *)ioctl32_hash_table [ioctl32_hash (cmd)];
+
+ while (t && t->cmd != cmd)
+ t = (struct ioctl_trans *)t->next;
+ if (t) {
+ handler = t->handler;
+ error = handler(fd, cmd, arg, filp);
+ } else if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
+ error = siocdevprivate_ioctl(fd, cmd, arg);
+ } else {
+ static int count;
+ if (++count <= 50) {
+ char buf[10];
+ char *path = (char *)__get_free_page(GFP_KERNEL), *fn = "?";
+
+ /* find the name of the device. */
+ if (path) {
+ struct file *f = fget(fd);
+ if (f) {
+ fn = d_path(f->f_dentry, f->f_vfsmnt,
+ path, PAGE_SIZE);
+ fput(f);
+ }
+ }
+
+ sprintf(buf,"'%c'", (cmd>>24) & 0x3f);
+ if (!isprint(buf[1]))
+ sprintf(buf, "%02x", buf[1]);
+ printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
+ "cmd(%08x){%s} arg(%08x) on %s\n",
+ current->comm, current->pid,
+ (int)fd, (unsigned int)cmd, buf, (unsigned int)arg,
+ fn);
+ if (path)
+ free_page((unsigned long)path);
+ }
+ error = -EINVAL;
+ }
+out:
+ fput(filp);
+out2:
+ return error;
+}
+
+
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: sys32_ioctl -> compat_ioctl -- generic
2003-03-03 23:21 sys32_ioctl -> compat_ioctl -- generic Pavel Machek
@ 2003-03-04 23:28 ` Stephen Rothwell
2003-03-05 21:43 ` Pavel Machek
2003-03-04 23:36 ` Stephen Rothwell
1 sibling, 1 reply; 7+ messages in thread
From: Stephen Rothwell @ 2003-03-04 23:28 UTC (permalink / raw)
To: Pavel Machek; +Cc: torvalds, linux-kernel
Hi Pavel,
On Tue, 4 Mar 2003 00:21:22 +0100 Pavel Machek <pavel@ucw.cz> wrote:
>
> This is generic part of sys32_ioctl -> compat_ioctl. Please apply,
Thanks for this - you saved me a headache :-)
Some comments:
> --- clean/kernel/compat.c 2003-03-03 23:39:39.000000000 +0100
> +++ linux/kernel/compat.c 2003-02-20 10:48:21.000000000 +0100
All this really belongs in fs/compat.c ...
One thing that Linus (and I) wanted from the compatability layer is
to try to keep all 32 bit assumptions out of the generic code - I
understand that this my not be possible, but we would like to try.
So maybe you could start by changing ioctl32 to compat_ioctl everywhere -
I know that this is just cosmetic, but it gives the better impression of
what the code is about ...
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: sys32_ioctl -> compat_ioctl -- generic
2003-03-04 23:28 ` Stephen Rothwell
@ 2003-03-05 21:43 ` Pavel Machek
0 siblings, 0 replies; 7+ messages in thread
From: Pavel Machek @ 2003-03-05 21:43 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: Pavel Machek, torvalds, linux-kernel
Hi!
> > This is generic part of sys32_ioctl -> compat_ioctl. Please apply,
>
> Thanks for this - you saved me a headache :-)
Well, I fear total sum of headache stayed constant ;-).
Anyway, producing these patches seems "easy" compared to actually
merging them. You seem to have some experience with this, would you be
willing to help?
> Some comments:
>
> > --- clean/kernel/compat.c 2003-03-03 23:39:39.000000000 +0100
> > +++ linux/kernel/compat.c 2003-02-20 10:48:21.000000000 +0100
>
> All this really belongs in fs/compat.c ...
>
> One thing that Linus (and I) wanted from the compatability layer is
> to try to keep all 32 bit assumptions out of the generic code - I
> understand that this my not be possible, but we would like to try.
>
> So maybe you could start by changing ioctl32 to compat_ioctl everywhere -
> I know that this is just cosmetic, but it gives the better impression of
> what the code is about ...
I thought about that, but I fear resulting diff would be too big (and
would bitrot extremely quickly). I thought I'd try to merge simple (&
small) stuff first, to see how bit it will be.....
Pavel
--
Horseback riding is like software...
...vgf orggre jura vgf serr.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: sys32_ioctl -> compat_ioctl -- generic
2003-03-03 23:21 sys32_ioctl -> compat_ioctl -- generic Pavel Machek
2003-03-04 23:28 ` Stephen Rothwell
@ 2003-03-04 23:36 ` Stephen Rothwell
2003-03-06 23:37 ` Pavel Machek
1 sibling, 1 reply; 7+ messages in thread
From: Stephen Rothwell @ 2003-03-04 23:36 UTC (permalink / raw)
To: Pavel Machek; +Cc: torvalds, linux-kernel
On Tue, 4 Mar 2003 00:21:22 +0100 Pavel Machek <pavel@ucw.cz> wrote:
>
> +asmlinkage long compat_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
For consistancy, this should be called compat_sys_ioctl.
> +{
> + struct file * filp;
> + filp = fget(fd);
> + /* find the name of the device. */
> + if (path) {
> + struct file *f = fget(fd);
Is it really necessary to do another fget(fd) ?
Also, if you are adding this much code, you should add a copyright notice
to the top of the file ...
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: sys32_ioctl -> compat_ioctl -- generic
2003-03-04 23:36 ` Stephen Rothwell
@ 2003-03-06 23:37 ` Pavel Machek
2003-03-09 22:44 ` Stephen Rothwell
2003-03-10 11:28 ` Andi Kleen
0 siblings, 2 replies; 7+ messages in thread
From: Pavel Machek @ 2003-03-06 23:37 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: torvalds, linux-kernel, ak
Hi!
> > +asmlinkage long compat_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
>
> For consistancy, this should be called compat_sys_ioctl.
Done. (And moved whole stuff to fs/compat.c).
> > +{
> > + struct file * filp;
>
> > + filp = fget(fd);
>
> > + /* find the name of the device. */
> > + if (path) {
> > + struct file *f = fget(fd);
>
> Is it really necessary to do another fget(fd) ?
This is andi's code, but it seems unneeded, fixed.
> Also, if you are adding this much code, you should add a copyright notice
> to the top of the file ...
I actually need to copy copyrights from ia32_ioctl, where I took
this. Done.
Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: sys32_ioctl -> compat_ioctl -- generic
2003-03-06 23:37 ` Pavel Machek
@ 2003-03-09 22:44 ` Stephen Rothwell
2003-03-10 11:28 ` Andi Kleen
1 sibling, 0 replies; 7+ messages in thread
From: Stephen Rothwell @ 2003-03-09 22:44 UTC (permalink / raw)
To: Pavel Machek; +Cc: torvalds, linux-kernel, ak
Hi Pavel,
Sorry I haven't responded earlier. I am willing to help in
any way I can, so let me know.
On Fri, 7 Mar 2003 00:37:21 +0100 Pavel Machek <pavel@ucw.cz> wrote:
>
> Hi!
>
> > For consistancy, this should be called compat_sys_ioctl.
>
> Done. (And moved whole stuff to fs/compat.c).
Great.
> This is andi's code, but it seems unneeded, fixed.
I assume Andi will scream if there is something subtle there :-)
> > Also, if you are adding this much code, you should add a copyright notice
> > to the top of the file ...
>
> I actually need to copy copyrights from ia32_ioctl, where I took
> this. Done.
OK, I will have a deeper look soon.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: sys32_ioctl -> compat_ioctl -- generic
2003-03-06 23:37 ` Pavel Machek
2003-03-09 22:44 ` Stephen Rothwell
@ 2003-03-10 11:28 ` Andi Kleen
1 sibling, 0 replies; 7+ messages in thread
From: Andi Kleen @ 2003-03-10 11:28 UTC (permalink / raw)
To: Pavel Machek; +Cc: Stephen Rothwell, torvalds, linux-kernel, ak
> > > +{
> > > + struct file * filp;
> >
> > > + filp = fget(fd);
> >
> > > + /* find the name of the device. */
> > > + if (path) {
> > > + struct file *f = fget(fd);
> >
> > Is it really necessary to do another fget(fd) ?
>
> This is andi's code, but it seems unneeded, fixed.
Yes, it's redundant.
-Andi
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2003-03-10 11:17 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-03-03 23:21 sys32_ioctl -> compat_ioctl -- generic Pavel Machek
2003-03-04 23:28 ` Stephen Rothwell
2003-03-05 21:43 ` Pavel Machek
2003-03-04 23:36 ` Stephen Rothwell
2003-03-06 23:37 ` Pavel Machek
2003-03-09 22:44 ` Stephen Rothwell
2003-03-10 11:28 ` Andi Kleen
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).