Merge branch 'kernel' of ssh://106.109.8.71/srv/git/dbi into kernel
[kernel/swap-modules.git] / driver / device_driver.c
1 /*
2  *  SWAP device driver
3  *  modules/driver/device_driver.c
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Copyright (C) Samsung Electronics, 2013
20  *
21  * 2013  Alexander Aksenov <a.aksenov@samsung.com>: SWAP device driver implement
22  *
23  */
24
25 #include <linux/types.h>
26 #include <linux/fs.h>
27 #include <linux/cdev.h>
28 #include <linux/err.h>
29 #include <linux/device.h>
30 #include <linux/ioctl.h>
31 #include <linux/slab.h>
32 #include <linux/mm.h>
33 #include <linux/splice.h>
34 #include <linux/sched.h>
35 #include <linux/module.h>
36 #include <linux/wait.h>
37 #include <asm/uaccess.h>
38
39 #include <ksyms/ksyms.h>
40
41 #include "device_driver.h"
42 #include "swap_driver_errors.h"
43 #include "driver_to_buffer.h"
44 #include "swap_ioctl.h"
45 #include "driver_defs.h"
46 #include "device_driver_to_driver_to_buffer.h"
47 #include "driver_to_buffer.h"
48 #include "driver_to_msg.h"
49
50 #define SWAP_DEVICE_NAME "swap_device"
51
52 /* swap_device driver routines */
53 static int swap_device_open(struct inode *inode, struct file *filp);
54 static int swap_device_release(struct inode *inode, struct file *file);
55 static ssize_t swap_device_read(struct file *filp, char __user *buf,
56                                                                 size_t count, loff_t *f_pos);
57 static ssize_t swap_device_write(struct file *filp, const char __user *buf,
58                                                                  size_t count, loff_t *f_pos);
59 static long swap_device_ioctl(struct file *filp, unsigned int cmd,
60                                                          unsigned long arg);
61 static ssize_t swap_device_splice_read(struct file *filp, loff_t *ppos,
62                                                                            struct pipe_inode_info *pipe, size_t len,
63                                                                            unsigned int flags);
64
65 /* File operations structure */
66 const struct file_operations swap_device_fops = {
67         .read = swap_device_read,
68         .write = swap_device_write,
69         .open = swap_device_open,
70         .release = swap_device_release,
71         .unlocked_ioctl = swap_device_ioctl,
72         .splice_read = swap_device_splice_read,
73 };
74
75 /* Typedefs for splice_* funcs. Prototypes are for linux-3.8.6 */
76 typedef ssize_t(*splice_to_pipe_p_t)(struct pipe_inode_info *pipe,
77                                          struct splice_pipe_desc *spd);
78 typedef int(*splice_grow_spd_p_t)(const struct pipe_inode_info *pipe,
79                                         struct splice_pipe_desc *spd);
80
81 static splice_to_pipe_p_t splice_to_pipe_p = NULL;
82 static splice_grow_spd_p_t splice_grow_spd_p = NULL;
83
84 static msg_handler_t msg_handler = NULL;
85
86 /* Device numbers */
87 static dev_t swap_device_no = 0;
88
89 /* Device cdev struct */
90 static struct cdev *swap_device_cdev = NULL;
91
92 /* Device class struct */
93 static struct class *swap_device_class = NULL;
94
95 /* Device device struct */
96 static struct device *swap_device_device = NULL;
97
98 /* Reading tasks queue */
99 static DECLARE_WAIT_QUEUE_HEAD(swap_device_wait);
100
101 /* We need this realization of splice_shrink_spd() because of the its desing
102  * frequent changes that I have encountered in custom kernels */
103 void swap_device_splice_shrink_spd(struct pipe_inode_info *pipe,
104                                    struct splice_pipe_desc *spd)
105 {
106         if (pipe->buffers <= PIPE_DEF_BUFFERS)
107                 return;
108
109         kfree(spd->pages);
110         kfree(spd->partial);
111 }
112
113
114 /* Register device TODO Think of permanent major */
115 int swap_device_init(void)
116 {
117         int result;
118
119         /* Allocating device major and minor nums for swap_device */
120         result = alloc_chrdev_region(&swap_device_no, 0, 1, SWAP_DEVICE_NAME);
121         if (result < 0) {
122                 print_crit("Major number allocation has failed\n");
123                 result = -E_SD_ALLOC_CHRDEV_FAIL;
124                 goto init_fail;
125         }
126
127         /* Creating device class. Using IS_ERR, because class_create returns ERR_PTR
128          * on error. */
129         swap_device_class = class_create(THIS_MODULE, SWAP_DEVICE_NAME);
130         if (IS_ERR(swap_device_class)) {
131                 print_crit("Class creation has failed\n");
132                 result = -E_SD_CLASS_CREATE_FAIL;
133                 goto init_fail;
134         }
135
136         /* Cdev allocation */
137         swap_device_cdev = cdev_alloc();
138         if (!swap_device_cdev) {
139                 print_crit("Cdev structure allocation has failed\n");
140                 result = -E_SD_CDEV_ALLOC_FAIL;
141                 goto init_fail;
142         }
143
144         /* Cdev intialization and setting file operations */
145         cdev_init(swap_device_cdev, &swap_device_fops);
146
147         /* Adding cdev to system */
148         result = cdev_add(swap_device_cdev, swap_device_no, 1);
149         if (result < 0) {
150                 print_crit("Device adding has failed\n");
151                 result = -E_SD_CDEV_ADD_FAIL;
152                 goto init_fail;
153         }
154
155         /* Create device struct */
156         swap_device_device = device_create(swap_device_class, NULL, swap_device_no,
157                                                                            "%s", SWAP_DEVICE_NAME);
158         if (IS_ERR(swap_device_device)) {
159                 print_crit("Device struct creating has failed\n");
160                 result = -E_SD_DEVICE_CREATE_FAIL;
161                 goto init_fail;
162         }
163
164         /* Find splice_* funcs addresses */
165         splice_to_pipe_p = (splice_to_pipe_p_t)swap_ksyms("splice_to_pipe");
166         if (!splice_to_pipe_p) {
167                 print_err("splice_to_pipe() not found!\n");
168                 result = -E_SD_NO_SPLICE_FUNCS;
169                 goto init_fail;
170         }
171
172         splice_grow_spd_p = (splice_grow_spd_p_t)swap_ksyms("splice_grow_spd");
173         if (!splice_grow_spd_p) {
174                 print_err("splice_grow_spd() not found!\n");
175                 result = -E_SD_NO_SPLICE_FUNCS;
176                 goto init_fail;
177         }
178
179         return 0;
180
181 init_fail:
182         if (swap_device_cdev) {
183                 cdev_del(swap_device_cdev);
184         }
185         if (swap_device_class) {
186                 class_destroy(swap_device_class);
187         }
188         if (swap_device_no) {
189                 unregister_chrdev_region(swap_device_no, 1);
190         }
191         return result;
192 }
193
194 /* Unregister device TODO Check wether driver is registered */
195 void swap_device_exit(void)
196 {
197         splice_to_pipe_p = NULL;
198         splice_grow_spd_p = NULL;
199
200         device_destroy(swap_device_class, swap_device_no);
201         cdev_del(swap_device_cdev);
202         class_destroy(swap_device_class);
203         unregister_chrdev_region(swap_device_no, 1);
204 }
205
206 static int swap_device_open(struct inode *inode, struct file *filp)
207 {
208         // TODO MOD_INC_USE_COUNT
209         return 0;
210 }
211
212 static int swap_device_release(struct inode *inode, struct file *filp)
213 {
214         // TODO MOD_DEC_USE_COUNT
215         return 0;
216 }
217
218 static ssize_t swap_device_read(struct file *filp, char __user *buf,
219                                                                 size_t count, loff_t *f_pos)
220 {
221         /* Wait queue item that consists current task. It is used to be added in
222          * swap_device_wait queue if there is no data to be read. */
223         DEFINE_WAIT(wait);
224         int result;
225
226         //TODO : Think about spin_locks to prevent reading race condition.
227         while((result = driver_to_buffer_next_buffer_to_read()) != E_SD_SUCCESS) {
228
229                 /* Add process to the swap_device_wait queue and set the current task
230                  * state TASK_INTERRUPTIBLE. If there is any data to be read, then the
231                  * current task is removed from the swap_device_wait queue and its state
232                  * is changed to this. */
233                 prepare_to_wait(&swap_device_wait, &wait, TASK_INTERRUPTIBLE);
234
235                 if (result < 0) {
236                         result = 0;
237                         goto swap_device_read_error;
238                 } else if (result == E_SD_NO_DATA_TO_READ) {
239                         /* Yes, E_SD_NO_DATA_TO_READ should be positive, cause it's not
240                          * really an error */
241                         if (filp->f_flags & O_NONBLOCK) {
242                                 result = -EAGAIN;
243                                 goto swap_device_read_error;
244                         }
245                         if (signal_pending(current)) {
246                                 result = -ERESTARTSYS;
247                                 goto swap_device_read_error;
248                         }
249                         schedule();
250                         finish_wait(&swap_device_wait, &wait);
251                 }
252         }
253
254         result = driver_to_buffer_read(buf, count);
255         /* If there is an error - return 0 */
256         if (result < 0)
257                 result = 0;
258
259
260         return result;
261
262 swap_device_read_error:
263         finish_wait(&swap_device_wait, &wait);
264
265         return result;
266 }
267
268 static ssize_t swap_device_write(struct file *filp, const char __user *buf,
269                                                                  size_t count, loff_t *f_pos)
270 {
271         char *kern_buffer = NULL;
272         ssize_t result = 0;
273
274         kern_buffer = kmalloc(count, GFP_KERNEL);
275         if (!kern_buffer) {
276                 print_err("Error allocating memory for buffer\n");
277                 goto swap_device_write_out;
278         }
279
280         result = copy_from_user(kern_buffer, buf, count);
281
282         result = count - result;
283
284         /* Return 0 if there was an error while writing */
285         result = driver_to_buffer_write(result, kern_buffer);
286         if (result < 0)
287                 result = 0;
288
289         kfree(kern_buffer);
290
291 swap_device_write_out:
292         return result;
293 }
294
295 static long swap_device_ioctl(struct file *filp, unsigned int cmd,
296                                                          unsigned long arg)
297 {
298         int result;
299
300         switch(cmd) {
301                 case SWAP_DRIVER_BUFFER_INITIALIZE:
302                 {
303                         struct buffer_initialize initialize_struct;
304
305                         result = copy_from_user(&initialize_struct, (void*)arg,
306                                                                         sizeof(struct buffer_initialize));
307                         if (result) {
308                                 break;
309                         }
310
311                         result = driver_to_buffer_initialize(initialize_struct.size,
312                                                                                                  initialize_struct.count);
313                         if (result < 0) {
314                                 print_err("Buffer initialization failed %d\n", result);
315                                 break;
316                         }
317                         result = E_SD_SUCCESS;
318
319                         break;
320                 }
321                 case SWAP_DRIVER_BUFFER_UNINITIALIZE:
322                 {
323                         result = driver_to_buffer_uninitialize();
324                         if (result < 0)
325                         print_err("Buffer uninitialization failed %d\n", result);
326
327                         break;
328                 }
329                 case SWAP_DRIVER_NEXT_BUFFER_TO_READ:
330                 {
331                         /* Use this carefully */
332                         result = driver_to_buffer_next_buffer_to_read();
333                         if (result == E_SD_NO_DATA_TO_READ) {
334                                 /* TODO Do what we usually do when there are no subbuffers to
335                                  * read (make daemon sleep ?) */
336                         }
337                         break;
338                 }
339                 case SWAP_DRIVER_FLUSH_BUFFER:
340                 {
341                         result = driver_to_buffer_flush();
342                         break;
343                 }
344                 case SWAP_DRIVER_MSG:
345                         if (msg_handler) {
346                                 result = msg_handler((void __user *)arg);
347                         } else {
348                                 print_warn("msg_handler() is not register\n");
349                                 result = -EINVAL;
350                         }
351                         break;
352                 default:
353                         print_warn("Unknown command %d\n", cmd);
354                         result = -EINVAL;
355                         break;
356
357         }
358         return result;
359 }
360
361 static void swap_device_pipe_buf_release(struct pipe_inode_info *inode,
362                                                                                  struct pipe_buffer *pipe)
363 {
364         __free_page(pipe->page);
365 }
366
367 static void swap_device_page_release(struct splice_pipe_desc *spd,
368                                                                          unsigned int i)
369 {
370         __free_page(spd->pages[i]);
371 }
372
373 static const struct pipe_buf_operations swap_device_pipe_buf_ops = {
374         .can_merge = 0,
375         .map = generic_pipe_buf_map,
376         .unmap = generic_pipe_buf_unmap,
377         .confirm = generic_pipe_buf_confirm,
378         .release = swap_device_pipe_buf_release,
379         .steal = generic_pipe_buf_steal,
380         .get = generic_pipe_buf_get
381 };
382
383 static ssize_t swap_device_splice_read(struct file *filp, loff_t *ppos,
384                                                                            struct pipe_inode_info *pipe,
385                                                                            size_t len, unsigned int flags)
386 {
387         /* Wait queue item that consists current task. It is used to be added in
388          * swap_device_wait queue if there is no data to be read. */
389         DEFINE_WAIT(wait);
390
391         int result;
392         struct page *pages[PIPE_DEF_BUFFERS];
393         struct partial_page partial[PIPE_DEF_BUFFERS];
394         struct splice_pipe_desc spd = {
395                 .pages = pages,
396                 .partial = partial,
397 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 5))
398                 .nr_pages_max = PIPE_DEF_BUFFERS,
399 #endif
400                 .nr_pages = 0,
401                 .flags = flags,
402                 .ops = &swap_device_pipe_buf_ops,
403                 .spd_release = swap_device_page_release,
404         };
405
406         /* Get next buffer to read */
407         //TODO : Think about spin_locks to prevent reading race condition.
408         while((result = driver_to_buffer_next_buffer_to_read()) != E_SD_SUCCESS) {
409
410                 /* Add process to the swap_device_wait queue and set the current task
411                  * state TASK_INTERRUPTIBLE. If there is any data to be read, then the
412                  * current task is removed from the swap_device_wait queue and its state
413                  * is changed. */
414                 prepare_to_wait(&swap_device_wait, &wait, TASK_INTERRUPTIBLE);
415                 if (result < 0) {
416                         print_err("driver_to_buffer_next_buffer_to_read error %d\n", result);
417                         //TODO Error return to OS
418                         result = 0;
419                         goto swap_device_splice_read_error;
420                 } else if (result == E_SD_NO_DATA_TO_READ) {
421                         if (filp->f_flags & O_NONBLOCK) {
422                                 result = -EAGAIN;
423                                 goto swap_device_splice_read_error;
424                         }
425                         if (signal_pending(current)) {
426                                 result = -ERESTARTSYS;
427                                 goto swap_device_splice_read_error;
428                         }
429                         schedule();
430                         finish_wait(&swap_device_wait, &wait);
431                 }
432         }
433
434         if (splice_grow_spd_p(pipe, &spd)) {
435                 result = -ENOMEM;
436                 goto swap_device_splice_read_out;
437         }
438
439         result = driver_to_buffer_fill_spd(&spd);
440         if (result != 0) {
441                 print_err("Cannot fill spd for splice\n");
442                 goto swap_device_shrink_spd;
443         }
444
445         result = splice_to_pipe_p(pipe, &spd);
446
447 swap_device_shrink_spd:
448         swap_device_splice_shrink_spd(pipe, &spd);
449
450 swap_device_splice_read_out:
451         return result;
452
453 swap_device_splice_read_error:
454         finish_wait(&swap_device_wait, &wait);
455
456         return result;
457 }
458
459 void swap_device_wake_up_process(void)
460 {
461         wake_up_interruptible(&swap_device_wait);
462 }
463
464 void set_msg_handler(msg_handler_t mh)
465 {
466         msg_handler = mh;
467 }
468 EXPORT_SYMBOL_GPL(set_msg_handler);