Import Upstream version 1.8.5
[hcoop/debian/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
18 #include <linux/module.h> /* early to avoid printf->printk mapping */
19 #include "afs/sysincludes.h"
20 #include "afsincludes.h"
21 #include <linux/unistd.h> /* For syscall numbers. */
22 #include <linux/mm.h>
23
24 #ifdef AFS_AMD64_LINUX20_ENV
25 #include <asm/ia32_unistd.h>
26 #endif
27
28 #if defined(AFS_SPARC64_LINUX26_ENV) && defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
29 #include <linux/ioctl32.h>
30 #endif
31
32 #include <linux/slab.h>
33 #include <linux/init.h>
34 #include <linux/sched.h>
35 #include <linux/kernel.h>
36
37 #include "osi_compat.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 # if defined(AFS_S390X_LINUX26_ENV)
61 if (test_thread_flag(TIF_31BIT))
62 # elif defined(AFS_AMD64_LINUX20_ENV)
63 if (test_thread_flag(TIF_IA32))
64 # else
65 if (test_thread_flag(TIF_32BIT))
66 # endif /* AFS_S390X_LINUX26_ENV */
67 {
68 if (copy_from_user(&sysargs32, (void *)arg,
69 sizeof(struct afsprocdata32)))
70 return -EFAULT;
71
72 return afs_syscall((unsigned long)sysargs32.syscall,
73 (unsigned long)sysargs32.param1,
74 (unsigned long)sysargs32.param2,
75 (unsigned long)sysargs32.param3,
76 (unsigned long)sysargs32.param4);
77 } else
78 #endif /* NEED_IOCTL32 */
79 {
80 if (copy_from_user(&sysargs, (void *)arg, sizeof(struct afsprocdata)))
81 return -EFAULT;
82
83 return afs_syscall(sysargs.syscall, sysargs.param1,
84 sysargs.param2, sysargs.param3, sysargs.param4);
85 }
86 }
87
88 #if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
89 static long afs_unlocked_ioctl(struct file *file, unsigned int cmd,
90 unsigned long arg) {
91 return afs_ioctl(FILE_INODE(file), file, cmd, arg);
92 }
93 #endif
94
95 static struct file_operations afs_syscall_fops = {
96 #ifdef HAVE_UNLOCKED_IOCTL
97 .unlocked_ioctl = afs_unlocked_ioctl,
98 #else
99 .ioctl = afs_ioctl,
100 #endif
101 #ifdef HAVE_COMPAT_IOCTL
102 .compat_ioctl = afs_unlocked_ioctl,
103 #endif
104 };
105
106 void
107 osi_ioctl_init(void)
108 {
109 struct proc_dir_entry *entry;
110
111 entry = afs_proc_create(PROC_SYSCALL_NAME, 0666, openafs_procfs, &afs_syscall_fops);
112 #if defined(STRUCT_PROC_DIR_ENTRY_HAS_OWNER)
113 if (entry)
114 entry->owner = THIS_MODULE;
115 #endif
116
117 #if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
118 if (register_ioctl32_conversion(VIOC_SYSCALL32, NULL) == 0)
119 ioctl32_done = 1;
120 #endif
121 }
122
123 void
124 osi_ioctl_clean(void)
125 {
126 remove_proc_entry(PROC_SYSCALL_NAME, openafs_procfs);
127 #if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
128 if (ioctl32_done)
129 unregister_ioctl32_conversion(VIOC_SYSCALL32);
130 #endif
131 }