linux-2-6-30-support-for-head-20090407
[openafs.git] / src / afs / LINUX / osi_ioctl.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Linux module support routines.
12  *
13  */
14 #include <afsconfig.h>
15 #include "afs/param.h"
16
17 RCSID
18     ("$Header$");
19
20 #include <linux/module.h> /* early to avoid printf->printk mapping */
21 #include "afs/sysincludes.h"
22 #include "afsincludes.h"
23 #include "h/unistd.h"           /* For syscall numbers. */
24 #include "h/mm.h"
25
26 #ifdef AFS_AMD64_LINUX20_ENV
27 #include <asm/ia32_unistd.h>
28 #endif
29 #ifdef AFS_SPARC64_LINUX20_ENV
30 #include <linux/ioctl32.h>
31 #endif
32
33 #include <linux/proc_fs.h>
34 #include <linux/slab.h>
35 #include <linux/init.h>
36 #include <linux/sched.h>
37 #include <linux/kernel.h>
38
39 extern struct proc_dir_entry *openafs_procfs;
40 #if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
41 static int ioctl32_done;
42 #endif
43
44 extern asmlinkage long
45 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
46
47 static int
48 afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
49           unsigned long arg)
50 {
51
52     struct afsprocdata sysargs;
53 #ifdef NEED_IOCTL32
54     struct afsprocdata32 sysargs32;
55 #endif
56
57     if (cmd != VIOC_SYSCALL && cmd != VIOC_SYSCALL32) return -EINVAL;
58
59 #ifdef NEED_IOCTL32
60 #ifdef AFS_LINUX26_ENV 
61 #ifdef AFS_S390X_LINUX26_ENV
62     if (test_thread_flag(TIF_31BIT))
63 #elif AFS_AMD64_LINUX20_ENV
64     if (test_thread_flag(TIF_IA32))
65 #else
66     if (test_thread_flag(TIF_32BIT))
67 #endif /* AFS_S390X_LINUX26_ENV */
68 #else
69 #ifdef AFS_SPARC64_LINUX24_ENV
70     if (current->thread.flags & SPARC_FLAG_32BIT)
71 #elif defined(AFS_SPARC64_LINUX20_ENV)
72     if (current->tss.flags & SPARC_FLAG_32BIT)
73 #elif defined(AFS_AMD64_LINUX20_ENV)
74     if (current->thread.flags & THREAD_IA32)
75 #elif defined(AFS_PPC64_LINUX20_ENV)
76     if (current->thread.flags & PPC_FLAG_32BIT)
77 #elif defined(AFS_S390X_LINUX20_ENV)
78     if (current->thread.flags & S390_FLAG_31BIT)
79 #else
80 #error Not done for this linux type
81 #endif /* AFS_LINUX26_ENV */
82 #endif /* NEED_IOCTL32 */
83     {
84         if (copy_from_user(&sysargs32, (void *)arg,
85                            sizeof(struct afsprocdata32)))
86             return -EFAULT;
87
88         return afs_syscall((unsigned long)sysargs32.syscall,
89                            (unsigned long)sysargs32.param1,
90                            (unsigned long)sysargs32.param2,
91                            (unsigned long)sysargs32.param3,
92                            (unsigned long)sysargs32.param4);
93     } else
94 #endif
95     {
96         if (copy_from_user(&sysargs, (void *)arg, sizeof(struct afsprocdata)))
97             return -EFAULT;
98
99         return afs_syscall(sysargs.syscall, sysargs.param1,
100                            sysargs.param2, sysargs.param3, sysargs.param4);
101     }
102 }
103
104 #if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
105 static long afs_unlocked_ioctl(struct file *file, unsigned int cmd,
106                                unsigned long arg) {
107     return afs_ioctl(FILE_INODE(file), file, cmd, arg);
108 }
109 #endif
110
111 static struct file_operations afs_syscall_fops = {
112 #ifdef HAVE_UNLOCKED_IOCTL
113     .unlocked_ioctl = afs_unlocked_ioctl,
114 #else
115     .ioctl = afs_ioctl,
116 #endif
117 #ifdef HAVE_COMPAT_IOCTL
118     .compat_ioctl = afs_unlocked_ioctl,
119 #endif
120 };
121
122 void
123 osi_ioctl_init(void)
124 {
125     struct proc_dir_entry *entry;
126
127     entry = create_proc_entry(PROC_SYSCALL_NAME, 0666, openafs_procfs);
128     entry->proc_fops = &afs_syscall_fops;
129 #if defined(STRUCT_PROC_DIR_ENTRY_HAS_OWNER)
130     entry->owner = THIS_MODULE;
131 #endif
132
133 #if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
134     if (register_ioctl32_conversion(VIOC_SYSCALL32, NULL) == 0) 
135         ioctl32_done = 1;
136 #endif
137 }
138
139 void
140 osi_ioctl_clean(void)
141 {
142     remove_proc_entry(PROC_SYSCALL_NAME, openafs_procfs);
143 #if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
144     if (ioctl32_done)
145             unregister_ioctl32_conversion(VIOC_SYSCALL32);
146 #endif
147 }