Merge branch 'dev' of 106.109.8.71:/srv/git/dbi into dev
[kernel/swap-modules.git] / driver / device_driver.c
1 ////////////////////////////////////////////////////////////////////////////////////
2 //
3 //      FILE:           device_driver.c
4 //
5 //      DESCRIPTION:
6 //      This file is C source for SWAP driver.
7 //
8 //      SEE ALSO:       device_driver.h
9 //      AUTHOR:         L.Komkov, S.Dianov, S.Grekhov, A.Gerenkov
10 //      COMPANY NAME:   Samsung Research Center in Moscow
11 //      DEPT NAME:      Advanced Software Group 
12 //      CREATED:        2008.02.15
13 //      VERSION:        1.0
14 //      REVISION DATE:  2008.12.03
15 //
16 ////////////////////////////////////////////////////////////////////////////////////
17
18 #include "module.h"
19 #include "device_driver.h"      // device driver
20 #include "CProfile.h"
21 #include <linux/notifier.h>
22
23 #ifdef OVERHEAD_DEBUG
24 extern unsigned long swap_sum_time;
25 extern unsigned long swap_sum_hit;
26 #endif
27
28 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
29 static BLOCKING_NOTIFIER_HEAD(swap_notifier_list);
30 #endif
31 pid_t gl_nNotifyTgid;
32 EXPORT_SYMBOL_GPL(gl_nNotifyTgid);
33
34 DECLARE_WAIT_QUEUE_HEAD (notification_waiters_queue);
35 volatile unsigned notification_count;
36
37 static int device_mmap (struct file *filp, struct vm_area_struct *vma);
38 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
39 static int device_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
40 #else
41 static int device_ioctl (struct file *file, unsigned int cmd, unsigned long arg);
42 #endif
43 static int device_open(struct inode *, struct file *);
44 static int device_release(struct inode *, struct file *);
45 static ssize_t device_read(struct file *, char *, size_t, loff_t *);
46 static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
47
48 static int gl_nDeviceOpened = 0;
49 static struct file_operations device_fops = {
50         .owner = THIS_MODULE,
51         .mmap = device_mmap,
52 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
53         .ioctl = device_ioctl,
54 #else
55         .unlocked_ioctl = device_ioctl,
56 #endif
57         .read = device_read,
58         .write = device_write,
59         .open = device_open,
60         .release = device_release
61 };
62
63 int device_init (void)
64 {
65         int nReserved = 0;
66         int nRetVal = register_chrdev(device_major, device_name, &device_fops);
67         if (nRetVal < 0) {
68                 EPRINTF("Cannot register character device! [%s, %d]", device_name, device_major);
69                 nReserved = register_chrdev(0, device_name, &device_fops);
70                 if(nReserved >= 0)
71                         EPRINTF("Please, create a new device node with major number [%d],\n\tand pass it as module parameter!", nReserved);
72                 return -1;
73         } else if(nRetVal > 0) {
74                 EPRINTF("Cannot register this device major number! [%d]\n\tTrying a new one. [%d]", device_major, nRetVal);
75                 device_major = nRetVal;
76         }
77         return 0;
78 }
79
80 void device_down (void)
81 {
82         unregister_chrdev(device_major, device_name);
83 }
84
85 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
86 void swap_register_notify (struct notifier_block *nb)
87 {
88         blocking_notifier_chain_register(&swap_notifier_list, nb);
89 }
90 EXPORT_SYMBOL_GPL(swap_register_notify);
91
92 void swap_unregister_notify (struct notifier_block *nb)
93 {
94         blocking_notifier_chain_unregister(&swap_notifier_list, nb);
95 }
96 EXPORT_SYMBOL_GPL(swap_unregister_notify);
97 #endif
98
99 void notify_user (event_id_t event_id)
100 {
101         ec_info.events_counters[event_id] += 1;
102
103         if (EVENT_EC_PROBE_RECORD == event_id)
104         {
105                 // EC_PROBE_RECORD events happen to often. To reduce overhead user
106                 // space will be notified only once per each EVENTS_AGGREGATION_USEC
107                 static uint64_t timestamp_usec = 0;
108
109                 uint64_t current_usec;
110                 uint64_t delta_usec;
111
112                 struct timeval tv;
113
114                 do_gettimeofday (&tv);
115                 current_usec = 1000000ULL * (unsigned) tv.tv_sec + (unsigned) tv.tv_usec;
116
117                 if (current_usec < timestamp_usec)
118                 {
119                         // Note: time from do_gettimeofday() may go backward
120                         EPRINTF ("current_usec=%llu timestamp_usec=%llu", current_usec, timestamp_usec);
121                 }
122                 else
123                 {
124                         delta_usec = current_usec - timestamp_usec;
125                         if (EVENTS_AGGREGATION_USEC > delta_usec)
126                         {
127                                 // wait the time left
128 #if defined(__DEBUG)
129                                 unsigned UNUSED left_usec = EVENTS_AGGREGATION_USEC - delta_usec;
130 #endif /* defined(__DEBUG) */
131                                 return; // supress notification
132                         }
133                 }
134                 timestamp_usec = current_usec;  // remember new time for the future use
135         } else if (EVENT_EC_START_CONDITION_SEEN == event_id) {
136                 return;         // supress notification
137         } else if (EVENT_EC_STOP_CONDITION_SEEN == event_id) {
138                 return;         // supress notification
139         }
140
141         ++notification_count;
142         wake_up_interruptible (&notification_waiters_queue);
143 }
144
145 static int device_mmap (struct file *filp UNUSED, struct vm_area_struct *vma)
146 {
147         if(!p_buffer) {
148                 EPRINTF("Null pointer to buffer!");
149                 return -1;
150         }
151         return remap_vmalloc_range (vma, p_buffer, 0);
152 }
153
154 static int device_open(struct inode *inode, struct file *file)
155 {
156         /*if (gl_nDeviceOpened)
157                 return -EBUSY;*/
158         gl_nDeviceOpened++;
159         // TODO
160         try_module_get(THIS_MODULE);
161         return 0;
162 }
163  
164 static int device_release(struct inode *inode, struct file *file)
165 {
166         gl_nDeviceOpened--;
167         module_put(THIS_MODULE);
168         return 0;
169 }
170  
171 static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t * offset)
172 {
173         EPRINTF("Operation <<read>> not supported!");
174         return -1;
175 }
176  
177 static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
178 {
179         EPRINTF("Operation <<write>> not supported!");
180         return -1;
181 }
182 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
183 static int device_ioctl (struct inode *inode UNUSED, struct file *file UNUSED, unsigned int cmd, unsigned long arg)
184 #else
185 static int device_ioctl (struct file *file UNUSED, unsigned int cmd, unsigned long arg)
186 #endif
187 {
188         unsigned long spinlock_flags = 0L;
189         int result = -1;
190 //      DPRINTF("Command=%d", cmd);
191         switch (cmd)
192         {
193         case EC_IOCTL_SET_EC_MODE:
194                 {
195                         ioctl_general_t param;
196                         unsigned long nIgnoredBytes = 0;
197                         memset(&param, '0', sizeof(ioctl_general_t));
198                         nIgnoredBytes = copy_from_user (&param, (void*)arg, sizeof(ioctl_general_t));
199                         if (nIgnoredBytes > 0) {
200                                 result = -1;
201                                 break;
202                         }
203                         if(SetECMode(param.m_unsignedLong) == -1) {
204                                 result = -1;
205                                 break;
206                         }
207                         result = 0;
208                         DPRINTF("Set EC Mode = %lu", param.m_unsignedLong);
209                         break;
210                 }
211         case EC_IOCTL_GET_EC_MODE:
212                 {
213                         ioctl_general_t param;
214                         unsigned long nIgnoredBytes = 0;
215                         memset(&param, '0', sizeof(ioctl_general_t));
216                         param.m_unsignedLong = GetECMode();
217                         nIgnoredBytes = copy_to_user ((void*)arg, &param, sizeof (ioctl_general_t));
218                         if (nIgnoredBytes > 0) {
219                                 result = -1;
220                                 break;
221                         }
222                         result = 0;
223 //                      DPRINTF("Get EC Mode = %lu", param.m_unsignedLong);  // Frequent call
224                         break;
225                 }
226         case EC_IOCTL_SET_BUFFER_SIZE:
227                 {
228                         ioctl_general_t param;
229                         unsigned long nIgnoredBytes = 0;
230                         memset(&param, '0', sizeof(ioctl_general_t));
231                         nIgnoredBytes = copy_from_user (&param, (void*)arg, sizeof(ioctl_general_t));
232                         if (nIgnoredBytes > 0) {
233                                 result = -1;
234                                 break;
235                         }
236                         if (SetBufferSize(param.m_unsignedLong) == -1) {
237                                 result = -1;
238                                 break;
239                         }
240                         result = 0;
241                         DPRINTF("Set Buffer Size = %lu", param.m_unsignedLong);
242                         break;
243                 }
244         case EC_IOCTL_GET_BUFFER_SIZE:
245                 {
246                         ioctl_general_t param;
247                         unsigned long nIgnoredBytes = 0;
248                         memset(&param, '0', sizeof(ioctl_general_t));
249                         param.m_unsignedLong = GetBufferSize();
250                         nIgnoredBytes = copy_to_user ((void*)arg, &param, sizeof (ioctl_general_t));
251                         if (nIgnoredBytes > 0) {
252                                 result = -1;
253                                 break;
254                         }
255                         result = 0;
256                         DPRINTF("Get Buffer Size = %lu", param.m_unsignedLong);
257                         break;
258                 }
259         case EC_IOCTL_RESET_BUFFER:
260                 {
261                         if (ResetBuffer() == -1) {
262                                 result = -1;
263                                 break;
264                         }
265                         result = 0;
266                         DPRINTF("Reset Buffer");
267                         break;
268                 }
269         case EC_IOCTL_GET_EC_INFO:
270                 {
271                         if (copy_ec_info_to_user_space ((ec_info_t *) arg) != 0) {
272                                 result = -1;
273                                 break;
274                         }
275                         result = 0;
276 //                      DPRINTF("Get Buffer Status"); // Frequent call
277                         break;
278                 }
279         case EC_IOCTL_CONSUME_BUFFER:
280                 {
281                         static ec_info_t ec_info_copy;
282                         int nIgnoredBytes = 0;
283 #ifndef __DISABLE_RELAYFS
284                         struct rchan* pRelayChannel = NULL;
285                         struct rchan_buf *buf = NULL;
286                         unsigned int nNumOfSubbufs = 0;
287                         void* pConsume = NULL;
288                         unsigned int nPaddingLength = 0;
289                         unsigned int nSubbufSize = 0;
290                         unsigned int nDataSize = 0;
291                         unsigned int nEffectSize = 0;
292                         unsigned int nSubbufDiscardedCount = 0;
293 #endif
294                         nIgnoredBytes = copy_from_user (&ec_info_copy, (ec_info_t *) arg, sizeof (ec_info_t));
295                         if(nIgnoredBytes > 0)
296                         {
297                                 EPRINTF ("copy_from_user(%08X,%08X)=%d", (unsigned) arg, (unsigned) &ec_info_copy, nIgnoredBytes);
298                                 result = -1;
299                                 break;
300                         }
301
302                         spin_lock_irqsave (&ec_spinlock, spinlock_flags);
303                         if((ec_info_copy.m_nMode & MODEMASK_MULTIPLE_BUFFER) == 0) {
304                                 // Original buffer
305                                 if(ec_info.after_last > ec_info.first) {
306                                         ec_info.buffer_effect = ec_info.buffer_size;
307                                 }
308                                 if (ec_info.after_last == ec_info.buffer_effect) {
309                                      ec_info.first = 0;
310                                 } else {
311                                      ec_info.first = ec_info_copy.after_last;
312                                 }
313                                 ec_info.trace_size = ec_info.trace_size - ec_info_copy.trace_size;
314
315                         } else {
316                                 // Relay FS buffer
317 #ifndef __DISABLE_RELAYFS
318                                 pRelayChannel = GetRelayChannel();
319                                 if(pRelayChannel == NULL) {
320                                         EPRINTF("Null pointer to relay channel!");
321                                         result = -1;
322                                         break;
323                                 }
324                                 buf = pRelayChannel->buf[0];
325                                 nNumOfSubbufs = pRelayChannel->n_subbufs;
326
327                                 nSubbufSize = pRelayChannel->subbuf_size;
328                                 pConsume = buf->start + buf->subbufs_consumed % nNumOfSubbufs * nSubbufSize;
329                                 memcpy(&nPaddingLength, pConsume, sizeof(unsigned int));
330                                 memcpy(&nSubbufDiscardedCount, pConsume + sizeof(unsigned int), sizeof(unsigned int));
331                                 nEffectSize = nSubbufSize - nPaddingLength;
332                                 nDataSize = nEffectSize - RELAY_SUBBUF_HEADER_SIZE;
333                                 relay_subbufs_consumed(pRelayChannel, 0, 1);
334                                 ec_info.m_nBeginSubbufNum = buf->subbufs_consumed % nNumOfSubbufs;
335                                 ec_info.m_nEndSubbufNum = buf->subbufs_produced % nNumOfSubbufs;
336                                 ec_info.buffer_effect -= nEffectSize;
337                                 ec_info.trace_size -= nDataSize;
338                                 buf->dentry->d_inode->i_size = ec_info.trace_size;
339 #endif
340                         }
341                         spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
342                         result = 0;
343 //                      DPRINTF("Consume Buffer"); // Frequent call
344                         break;
345                 }
346         case EC_IOCTL_ADD_PROBE:
347                 {
348                         unsigned long addr = arg;
349                         result = add_probe(addr);
350
351                         break;
352                 }
353         //@AGv: remove_probe expects probe address instead of name
354         /*case EC_IOCTL_REMOVE_PROBE:
355                 {
356                         char *probe_name = (char *) arg;
357                         result = remove_probe (probe_name);
358
359                         break;
360                 }*/
361         case EC_IOCTL_SET_APPDEPS:
362         {
363                 size_t size;
364                 result = copy_from_user(&size, (void *)arg, sizeof(size_t));
365                 if (result) {
366                         EPRINTF("Cannot copy deps size!");
367                         result = -1;
368                         break;
369                 }
370                 DPRINTF("Deps size has been copied (%d)", size);
371
372                 if (size == 0) {
373                         DPRINTF("Deps are size of 0");
374                         break;
375                 }
376
377                 deps = vmalloc(size);
378                 if (deps == NULL) {
379                         EPRINTF("Cannot alloc mem for deps!");
380                         result = -1;
381                         break;
382                 }
383                 DPRINTF("Mem for deps has been allocated");
384
385                 result = copy_from_user(deps, (void *)arg, size);
386                 if (result) {
387                         EPRINTF("Cannot copy deps!");
388                         result = -1;
389                         break;
390                 }
391                 DPRINTF("Deps has been copied successfully");
392
393                 break;
394         }
395         case EC_IOCTL_SET_PID:
396         {
397                 unsigned int _pid;
398
399                 result = copy_from_user(&_pid, (void *)arg, sizeof(unsigned int));
400                 if (result) {
401                         EPRINTF("Cannot copy pid!");
402                         result = -1;
403                         break;
404                 }
405
406                 inst_pid = _pid;
407
408                 DPRINTF("EC_IOCTL_SET_PID pid:%d", inst_pid);
409
410                 break;
411         }
412         case EC_IOCTL_SET_PROFILEBUNDLE:
413         {
414                 size_t size;
415
416                 result = copy_from_user(&size, (void *)arg, sizeof(size_t));
417                 if (result) {
418                         EPRINTF("Cannot copy bundle size!");
419                         result = -1;
420                         break;
421                 }
422                 DPRINTF("Bundle size has been copied");
423
424                 bundle = vmalloc(size);
425                 if (bundle == NULL) {
426                         EPRINTF("Cannot alloc mem for bundle!");
427                         result = -1;
428                         break;
429                 }
430                 DPRINTF("Mem for bundle has been alloced");
431
432                 result = copy_from_user(bundle, (void *)arg, size);
433                 if (result) {
434                         EPRINTF("Cannot copy bundle!");
435                         result = -1;
436                         break;
437                 }
438                 DPRINTF("Bundle has been copied successfully");
439
440                 if (link_bundle() == -1) {
441                         EPRINTF("Cannot link profile bundle!");
442                         result = -1;
443                         break;
444                 }
445
446                 break;
447         }
448         case EC_IOCTL_RESET_PROBES:
449                 {
450                         result = reset_probes();
451
452                         break;
453                 }
454         case EC_IOCTL_UPDATE_CONDS:
455                 {
456                         int args_cnt, i;
457                         struct cond *c, *c_tmp, *p_cond;
458                         unsigned char *p_data;
459                         int err;
460                         result = 0;
461                         err = copy_from_user(&args_cnt, (void *)arg, sizeof(int));
462                         if (err) {
463                                 result = -1;
464                                 break;
465                         }
466                         /* first, delete all the conds */
467                         list_for_each_entry_safe(c, c_tmp, &cond_list.list, list) {
468                                 list_del(&c->list);
469                                 kfree(c);
470                         }
471                         /* second, add new conds */
472                         p_data = (unsigned char *)(arg + sizeof(int));
473                         for (i = 0; i < args_cnt; i++) {
474                                 p_cond = kmalloc(sizeof(struct cond), GFP_KERNEL);
475                                 if (!p_cond) {
476                                         DPRINTF("Cannot alloc cond!");
477                                         result = -1;
478                                         break;
479                                 }
480                                 err = copy_from_user(&p_cond->tmpl, p_data, sizeof(struct event_tmpl));
481                                 if (err) {
482                                         DPRINTF("Cannot copy cond from user!");
483                                         result = -1;
484                                         break;
485                                 }
486                                 p_cond->applied = 0;
487                                 list_add(&(p_cond->list), &(cond_list.list));
488                                 p_data += sizeof(struct event_tmpl);
489                         }
490                         break;
491                 }
492         case EC_IOCTL_ATTACH:
493                 result = ec_user_attach ();
494 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
495                 DPRINTF("EC_IOCTL_ATTACH calling notification chain");
496                 blocking_notifier_call_chain(&swap_notifier_list, EC_IOCTL_ATTACH, (void*)NULL);
497 #endif
498                 DPRINTF("Attach Probes");
499                 break;
500         case EC_IOCTL_ACTIVATE:
501                 result = ec_user_activate ();
502                 DPRINTF("Activate Probes");
503                 break;
504         case EC_IOCTL_STOP_AND_DETACH:
505         {
506                 unsigned long nIgnoredBytes = 0;
507
508 #ifdef OVERHEAD_DEBUG
509                 printk("\nswap_sum_time = %ld in kprobe_handler()\n", swap_sum_time);
510                 printk("swap_sum_hit = %ld in kprobe_handler()\n", swap_sum_hit);
511                 swap_sum_time = 0;
512                 swap_sum_hit = 0;
513 #endif
514                 if(ec_user_stop() != 0) {
515                         result = -1;
516                         break;
517                 }
518                 nIgnoredBytes = copy_ec_info_to_user_space ((ec_info_t*)arg);
519                 if(nIgnoredBytes > 0) {
520                         result = -1;
521                         break;
522                 }
523                 vfree(bundle);
524                 result = 0;
525                 DPRINTF("Stop and Detach Probes");
526 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
527                 DPRINTF("EC_IOCTL_STOP_AND_DETACH calling notification chain");
528                 blocking_notifier_call_chain(&swap_notifier_list, EC_IOCTL_STOP_AND_DETACH, (void*)&gl_nNotifyTgid);
529 #endif
530                 break;
531         }
532         case EC_IOCTL_WAIT_NOTIFICATION:
533                 {
534                         static ec_info_t ec_info_copy;
535
536                         ioctl_wait_notification_t ioctl_args;
537
538                         result = copy_from_user (&ioctl_args, (void *) arg, sizeof (ioctl_args));
539                         if (result)
540                         {
541                                 result = -1;
542                                 break;
543                         }
544
545                         result = wait_event_interruptible (notification_waiters_queue, ioctl_args.notification_count != notification_count);
546                         if (result)
547                         {
548                                 result = -EINTR;        // woken by signal (ERESTARTSYS 512)
549                                 break;
550                         }
551
552                         ioctl_args.notification_count = notification_count;
553
554                         result = copy_to_user ((void *) arg, &ioctl_args, sizeof (ioctl_args));
555                         if (result)
556                         {
557                                 result = -1;
558                                 break;
559                         }
560
561                         // FIXME: synchronization is necessary here (ec_info must be locked).
562                         // ENTER_CRITICAL_SECTION
563                         memcpy (&ec_info_copy, &ec_info, sizeof (ec_info_copy));
564                         // LEAVE_CRITICAL_SECTION
565
566                         result = copy_to_user ((void *) ioctl_args.p_ec_info, &ec_info_copy, sizeof (ec_info_t));
567                         if (result)
568                         {
569                                 EPRINTF ("copy_to_user(%08X,%08X)=%d", (unsigned) ioctl_args.p_ec_info, (unsigned) &ec_info_copy, result);
570                                 result = -1;
571                                 break;
572                         }
573                         DPRINTF("Wake up");
574                         break;
575                 }
576         case EC_IOCTL_US_EVENT:
577                 {
578                         ioctl_us_event_t ioctl_args;
579                         result = copy_from_user (&ioctl_args, (void *) arg, sizeof (ioctl_args));
580                         if (result)
581                         {
582                                 result = -1;
583                                 EPRINTF ("copy_from_user() failure");
584                         }
585                         else
586                         {
587                                 if(ioctl_args.len == 0){
588                                         result = -EINVAL;
589                                         EPRINTF ("invalid event length!");                                      
590                                 }
591                                 else {
592                                         char *buf = kmalloc(ioctl_args.len, GFP_KERNEL);
593                                         if(!buf){
594                                                 result = -ENOMEM;
595                                                 EPRINTF ("failed to alloc mem for event!");                                     
596                                         }
597                                         else {
598                                                 result = copy_from_user (buf, (void *) ioctl_args.data, ioctl_args.len);
599                                                 if (result){
600                                                         result = -1;
601                                                         EPRINTF ("failed to copy event from user space!");
602                                                 }
603                                                 else
604                                                         result = put_us_event(buf, ioctl_args.len);
605                                                 kfree(buf);
606                                         }
607                                 }
608                         }
609 //                      DPRINTF("User Space Event"); // Frequent call
610                         break;
611                 }
612                 
613         case EC_IOCTL_SET_EVENT_MASK:
614                 {
615                         int mask;
616                         result = copy_from_user (&mask, (void *) arg, sizeof (mask));
617                         if (result)
618                         {
619                                 result = -EFAULT;
620                                 break;
621                         }
622
623                         result = set_event_mask (mask);
624                         if (result)
625                         {
626                                 break;
627                         }
628                         DPRINTF("Set Event Mask = %d", mask);
629                         break;
630                 }
631
632         case EC_IOCTL_GET_EVENT_MASK:
633                 {
634                         int mask = 0;
635                         result = get_event_mask(&mask);
636                         if (result)
637                         {
638                                 result = -EFAULT;
639                         }
640                         result = copy_to_user ((void *) arg, &mask, sizeof (mask));
641                         if (result)
642                         {
643                                 result = -EFAULT;
644                         }
645                         DPRINTF("Get Event Mask = %d", mask);
646                         break;
647                 }
648
649         case EC_IOCTL_SET_PREDEF_UPROBES:
650                 {
651                         ioctl_predef_uprobes_info_t data;
652                         result = copy_from_user (&data, (void *) arg, sizeof (data));
653                         if (result)
654                         {
655                                 result = -EFAULT;
656                                 break;
657                         }
658
659                         result = set_predef_uprobes (&data);
660                         if (result)
661                         {
662                                 break;
663                         }
664                         DPRINTF("Set Predefined User Space Probes");
665                         break;
666                 }
667                 
668         case EC_IOCTL_GET_PREDEF_UPROBES:
669                 {
670                         result = get_predef_uprobes((ioctl_predef_uprobes_info_t *)arg);
671                         if (result)
672                         {
673                                 result = -EFAULT;
674                         }
675                         DPRINTF("Get Predefined User Space Probes");
676                         break;
677                 }
678                 
679         case EC_IOCTL_GET_PREDEF_UPROBES_SIZE:
680                 {
681                         int size = 0;
682                         result = get_predef_uprobes_size(&size);
683                         if (result)
684                         {
685                                 result = -EFAULT;
686                         }
687                         result = copy_to_user ((void *) arg, &size, sizeof (size));
688                         if (result)
689                         {
690                                 result = -EFAULT;
691                         }
692                         DPRINTF("Get Size of Predefined User Space Probes");
693                         break;
694                 }
695         
696         default:
697                 EPRINTF ("Unknown driver command = %u", cmd);
698                 result = -EINVAL;
699                 break;
700         }
701
702         return result;
703 }