remove trailing whitespaces
[dpdk.git] / examples / vhost / eventfd_link / eventfd_link.c
1 /*-
2  *  * GPL LICENSE SUMMARY
3  *  *
4  *  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *  *
6  *  *   This program is free software; you can redistribute it and/or modify
7  *  *   it under the terms of version 2 of the GNU General Public License as
8  *  *   published by the Free Software Foundation.
9  *  *
10  *  *   This program is distributed in the hope that it will be useful, but
11  *  *   WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  *   General Public License for more details.
14  *  *
15  *  *   You should have received a copy of the GNU General Public License
16  *  *   along with this program; if not, write to the Free Software
17  *  *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18  *  *   The full GNU General Public License is included in this distribution
19  *  *   in the file called LICENSE.GPL.
20  *  *
21  *  *   Contact Information:
22  *  *   Intel Corporation
23  *   */
24
25 #include <linux/eventfd.h>
26 #include <linux/miscdevice.h>
27 #include <linux/module.h>
28 #include <linux/moduleparam.h>
29 #include <linux/rcupdate.h>
30 #include <linux/file.h>
31 #include <linux/slab.h>
32 #include <linux/fs.h>
33 #include <linux/mmu_context.h>
34 #include <linux/sched.h>
35 #include <asm/mmu_context.h>
36 #include <linux/fdtable.h>
37
38 #include "eventfd_link.h"
39
40
41 /*
42  * get_files_struct is copied from fs/file.c
43  */
44 struct files_struct *
45 get_files_struct (struct task_struct *task)
46 {
47         struct files_struct *files;
48
49         task_lock (task);
50         files = task->files;
51         if (files)
52                 atomic_inc (&files->count);
53         task_unlock (task);
54
55         return files;
56 }
57
58 /*
59  * put_files_struct is extracted from fs/file.c
60  */
61 void
62 put_files_struct (struct files_struct *files)
63 {
64         if (atomic_dec_and_test (&files->count))
65         {
66                 BUG ();
67         }
68 }
69
70
71 static long
72 eventfd_link_ioctl (struct file *f, unsigned int ioctl, unsigned long arg)
73 {
74         void __user *argp = (void __user *) arg;
75         struct task_struct *task_target = NULL;
76         struct file *file;
77         struct files_struct *files;
78         struct fdtable *fdt;
79         struct eventfd_copy eventfd_copy;
80
81         switch (ioctl)
82         {
83                 case EVENTFD_COPY:
84                         if (copy_from_user (&eventfd_copy, argp, sizeof (struct eventfd_copy)))
85                                 return -EFAULT;
86
87                         /*
88                          * Find the task struct for the target pid
89                          */
90                         task_target =
91                                 pid_task (find_vpid (eventfd_copy.target_pid), PIDTYPE_PID);
92                         if (task_target == NULL)
93                         {
94                                 printk (KERN_DEBUG "Failed to get mem ctx for target pid\n");
95                                 return -EFAULT;
96                         }
97
98                         files = get_files_struct (current);
99                         if (files == NULL)
100                         {
101                                 printk (KERN_DEBUG "Failed to get files struct\n");
102                                 return -EFAULT;
103                         }
104
105                         rcu_read_lock ();
106                         file = fcheck_files (files, eventfd_copy.source_fd);
107                         if (file)
108                         {
109                                 if (file->f_mode & FMODE_PATH
110                                                 || !atomic_long_inc_not_zero (&file->f_count))
111                                         file = NULL;
112                         }
113                         rcu_read_unlock ();
114                         put_files_struct (files);
115
116                         if (file == NULL)
117                         {
118                                 printk (KERN_DEBUG "Failed to get file from source pid\n");
119                                 return 0;
120                         }
121
122                         /*
123                          * Release the existing eventfd in the source process
124                          */
125                         spin_lock (&files->file_lock);
126                         filp_close (file, files);
127                         fdt = files_fdtable (files);
128                         fdt->fd[eventfd_copy.source_fd] = NULL;
129                         spin_unlock (&files->file_lock);
130
131                         /*
132                          * Find the file struct associated with the target fd.
133                          */
134
135                         files = get_files_struct (task_target);
136                         if (files == NULL)
137                         {
138                                 printk (KERN_DEBUG "Failed to get files struct\n");
139                                 return -EFAULT;
140                         }
141
142                         rcu_read_lock ();
143                         file = fcheck_files (files, eventfd_copy.target_fd);
144                         if (file)
145                         {
146                                 if (file->f_mode & FMODE_PATH
147                                                 || !atomic_long_inc_not_zero (&file->f_count))
148                                         file = NULL;
149                         }
150                         rcu_read_unlock ();
151                         put_files_struct (files);
152
153                         if (file == NULL)
154                         {
155                                 printk (KERN_DEBUG "Failed to get file from target pid\n");
156                                 return 0;
157                         }
158
159
160                         /*
161                          * Install the file struct from the target process into the
162                          * file desciptor of the source process,
163                          */
164
165                         fd_install (eventfd_copy.source_fd, file);
166
167                         return 0;
168
169                 default:
170                         return -ENOIOCTLCMD;
171         }
172 }
173
174 static const struct file_operations eventfd_link_fops = {
175         .owner = THIS_MODULE,
176         .unlocked_ioctl = eventfd_link_ioctl,
177 };
178
179
180 static struct miscdevice eventfd_link_misc = {
181         .name = "eventfd-link",
182         .fops = &eventfd_link_fops,
183 };
184
185 static int __init
186 eventfd_link_init (void)
187 {
188         return misc_register (&eventfd_link_misc);
189 }
190
191 module_init (eventfd_link_init);
192
193 static void __exit
194 eventfd_link_exit (void)
195 {
196         misc_deregister (&eventfd_link_misc);
197 }
198
199 module_exit (eventfd_link_exit);
200
201 MODULE_VERSION ("0.0.1");
202 MODULE_LICENSE ("GPL v2");
203 MODULE_AUTHOR ("Anthony Fee");
204 MODULE_DESCRIPTION ("Link eventfd");
205 MODULE_ALIAS ("devname:eventfd-link");