Krishna iResearch Intelligent Cloud Platform - VIRtual Generic Os - VIRGO - Linux kernel extensions for cloud
 All Classes
virgo_cloudexec_fs.c
1 /***************************************************************************************
2 VIRGO - a linux module extension with CPU and Memory pooling with cloud capabilities
3 
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 3 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, see <http://www.gnu.org/licenses/>.
17 
18 --------------------------------------------------------------------------------------------------
19 Copyright (C):
20 Srinivasan Kannan (alias) Ka.Shrinivaasan (alias) Shrinivas Kannan
21 Independent Open Source Developer, Researcher and Consultant
22 Ph: 9789346927, 9003082186, 9791165980
23 Open Source Products Profile(Krishna iResearch): http://sourceforge.net/users/ka_shrinivaasan
24 Personal website(research): https://sites.google.com/site/kuja27/
25 emails: ka.shrinivaasan@gmail.com, shrinivas.kannan@gmail.com, kashrinivaasan@live.com
26 --------------------------------------------------------------------------------------------------
27 
28 *****************************************************************************************/
29 
30 #include <linux/virgo_fs.h>
31 #include <linux/virgocloudexecfssvc.h>
32 #include <linux/virgo_config.h>
33 
34 #include <linux/string.h>
35 #include <linux/kallsyms.h>
36 
37 /*
38  VIRGO File Systems Driver for virgo_open(), virgo_close(),virgo_read(),virgo_write()
39 */
40 
41 
42 /*
43 * The wrapper function that based on switch parameterIsExecutable (values 0,1,2) executes the binary or function data from virgo_fs
44 * system calls or telnet connections in either kernel or user address-spaces
45 * - Ka.Shrinivaasan
46 */
47 
48 int fs_func(void* args)
49 {
50  /*
51  * Lack of reflection kind of facilities requires map of function_names to pointers_to_functions to be executed
52  * on cloud. Function name has to be lookedup in the map to get pointer to function. This map is not scalable
53  * if number of functions are in millions and size of the map increases linearly. Also having it in memory is
54  * both CPU and memory intensive.
55  *
56  * Moreover this map has to be synchronized in all nodes for coherency and consistency which is another intensive task.
57  * Thus name to pointer function table is at present not implemented. Suitable way to call a function by name of the function
58  * is yet to be found out and references in this topic are scarce.
59  * - Ka.Shrinivaasan
60  */
61 
62  /*
63  *If parameterIsExecutable is set to 2, the data from virgo_fs client is a function and is executed within kernel address-space itself
64  *This invokes kmalloc() to allocate kernel memory. Intermodule function invocation functionality which enables complete takeover
65  *of lowlevel system cards, PCI, RAM etc., has been implemented
66  *
67  *If parameterIsExecutable is set to 1 the data received from virgo_fs is not a function but name of executable
68  *This executable is then run on usermode using call_usermodehelper() which internally takes care of queueing the workstruct
69  *and executes the binary as child of keventd and reaps silently. Thus workqueue component of kernel is indirectly made use of.
70  *This is sometimes more flexible alternative that executes a binary itself on cloud and
71  *is preferable to clone()ing a function on cloud. Virgo_fs syscall client or telnet needs to send the message with name of binary.
72  *
73  *If parameterIsExecutable is set to 0 then data received from virgo_fs client is name of a function and is executed in else clause
74  *using dlsym() lookup and pthread_create() in user space. This unifies both call_usermodehelper() and creating a userspace thread
75  *with a fixed binary which is same for any function. The dlsym lookup requires mangled function names which need to be sent by
76  *virgo_fs syscalls or telnet. This is far more efficient than a function pointer table.
77  *call_usermodehelper() Kernel upcall to usermode to exec a fixed binary that would inturn execute the fsFunction in userspace
78  *by spawning a pthread. fsFunction is name of the function and not binary. This clone function will be dlsym()ed
79  *and a pthread will be created by the fixed binary. Name of the fixed binary is hardcoded herein as
80  *"virgo_kernelupcall_plugin". This fixed binary takes malloc function as argument. For testing libvirgo_fs.so has been created from
81  *virgo_cloud_test.c and separate build script to build the cloud function binaries has been added.
82  *
83  *- Ka.Shrinivaasan
84  */
85 
86  char buffer[BUF_SIZE];
87  int ret=0;
88  char *argv[8];
89  char *envp[3];
90  char* fsFunction = (char*)args;
91  struct virgo_fs_args* vmargs=parse_virgofs_command(kstrdup(fsFunction,GFP_KERNEL));
92  void* virgo_fs_ret;
93 
94  if (parameterIsExecutable==2)
95  {
96  struct task_struct *task;
97  int woken_up_2=0;
98  printk(KERN_INFO "fs_func(): creating kernel thread and waking up, parameterIsExecutable=%d\n", parameterIsExecutable);
99  printk(KERN_INFO "Creating Kernel Thread for %s in virgo_cloud_fs_kernelspace fs driver module with fs_args[0]=%s, fs_args[1]=%s\n",vmargs->fs_cmd,vmargs->fs_args[0],vmargs->fs_args[1]);
100 
101  /*
102  Temporarily commenting kthread creation for the kernelspace virgo fs
103  ops execution as return value from a kthread function is needed which is
104  difficult and circuitous to do with kthread. Instead the functions in the
105  kernel module virgo_cloud_fs_kernelspace.ko are directly invoked using
106  intermodule kernelspace invocation.
107  */
108  /*task=kthread_create(toFuncPtr(kstrdup(strcat(vmargs->fs_cmd,"_kernelspace"),GFP_KERNEL)), (void*)vmargs, "fsFunction kernelspace thread");*/
109  virgo_fs_ret=toFuncPtr(kstrdup(strcat(kstrdup(vmargs->fs_cmd,GFP_KERNEL),"_kernelspace"),GFP_KERNEL))(vmargs);
110 
111  printk(KERN_INFO "fs_func(): virgo fs kernelspace module returns value virgo_fs_ret=%p\n", (char*)virgo_fs_ret);
112  /*
113  woken_up_2=wake_up_process(task);
114  */
115  }
116  else if(parameterIsExecutable==1)
117  {
118  file_stdout=filp_open("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cloudfs/virgo_cloudexec_fs_upcall_usermode_log.txt", O_RDWR|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
119  fd_install(1,file_stdout);
120  fd_install(2,file_stdout);
121  argv[0]=kstrdup(fsFunction,GFP_KERNEL);
122  argv[1]=NULL;
123  envp[0]="PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cloudfs/";
124  envp[1]="HOME=/home/kashrinivaasan";
125  envp[2]=NULL;
126  /* call_usermodehelper() Kernel upcall to usermode */
127  /* fsFunction contains name of the binary and not the name of the function */
128  printk("fs_func(): executing call_usermodehelper for data from virgo_fs : %s - parameterIsExecutable=%d\n",fsFunction, parameterIsExecutable);
129  ret=call_usermodehelper(fsFunction, argv, envp, UMH_WAIT_EXEC);
130  printk("fs_func(): call_usermodehelper() for binary %s returns ret=%d\n", fsFunction, ret);
131  filp_close(file_stdout,NULL);
132  }
133  else if (parameterIsExecutable==0)
134  {
135  file_stdout=filp_open("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cloudfs/virgo_cloudexec_fs_upcall_usermode_log.txt", O_RDWR|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
136  /*
137  Commented fd_install() due to crashes which were working in cpupooling driver. Same crash was occuring in memorypooling driver
138  also few months ago. Probably some other process has already done fd_install to these fd(s).
139  - Ka.Shrinivaasan 5May2014
140  */
141  /*
142  fd_install(1,file_stdout);
143  fd_install(2,file_stdout);
144  */
145  argv[0]=kstrdup("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cloudfs/virgo_kernelupcall_plugin",GFP_KERNEL);
146  argv[1]=kstrdup(fsFunction,GFP_KERNEL);
147  argv[2]=NULL;
148  envp[0]="PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games::/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cloudfs/";
149  envp[1]="HOME=/home/kashrinivaasan";
150  envp[2]=NULL;
151  printk(KERN_INFO "fs_func(): executing the virgo_fs function parameter in cloud - parameterIsExecutable=%d, fsFunction=%s\n",parameterIsExecutable,fsFunction);
152  ret=call_usermodehelper("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cloudfs/virgo_kernelupcall_plugin",argv,envp,UMH_WAIT_EXEC);
153 
154  printk("fs_func(): call_usermodehelper() for virgo_kernelupcall_plugin returns ret=%d\n", ret);
155  /*
156  Depending on scheduling priority either this or other message in virgocloudexec_fs_sendto() will be sent to
157  virgo_fs remote syscall
158  */
159  strcpy(buffer,"fs_func(): cloudclonethread executed for fs_func(), sending message to virgo_malloc() remote syscall client");
160  filp_close(file_stdout,NULL);
161  }
162  return virgo_fs_ret;
163 }
164 
165 char* strip_control_M(char* str)
166 {
167  printk("strip_control_M(): str=%s before strsep\n",str);
168  char* dupstr=kstrdup(str, GFP_KERNEL);
169  char* newstr=strsep(&dupstr, "\r\n");
170  printk("strip_control_M(): newstr=%s after carriage return newline strsep\n",newstr);
171  return newstr;
172 }
173 
174 int kernel_space_func(void* args)
175 {
176  printk(KERN_INFO "kernel_space_func(): parameterIsExecutable=2; executing function in kernel address space\n");
177  return 0;
178 }
179 
180 void read_virgo_config()
181 {
182  /* virgo_cloud.conf contains a string of comma separated list of IP addresses in the virgo cloud .Read and strsep() it. */
183 
184  loff_t bytesread=0;
185  loff_t pos=0;
186  mm_segment_t fs;
187 
188  /*
189  * It is redundant to use kallsyms_lookup for exported symbols for virgo cloud initialization.
190  * kallsyms_lookup is for non-exported symbols.
191  *
192  * - Ka.Shrinivaasan 10 July 2013
193  *
194 
195  node_ip_addrs_in_cloud=(char**)kallsyms_lookup_name("node_ip_addrs_in_cloud");
196  num_cloud_nodes=kallsyms_lookup_name("num_cloud_nodes");
197 
198  printk(KERN_INFO "virgo kernel service: read_virgo_config(): virgo_cloud config being read... \n");
199  printk(KERN_INFO "virgo kernel service: read_virgo_config(): num_cloud_nodes=%d #### node_ip_addrs_in_cloud=%s\n", num_cloud_nodes,node_ip_addrs_in_cloud);
200  */
201 
202  fs=get_fs();
203  set_fs(get_ds());
204  struct file* f=NULL;
205  f=filp_open("/etc/virgo_cloud.conf", O_RDONLY, 0);
206 
207  char buf[256];
208  int i=0;
209 
210  int k=0;
211  for(k=0;k<256;k++)
212  buf[k]=0;
213 
214  for(k=0; k < num_cloud_nodes; k++)
215  printk(KERN_INFO "virgo kernel service: read_virgo_config(): before reading virgo_cloud.conf - virgo_cloud ip address - %d: %s\n", k+1, node_ip_addrs_in_cloud[k]);
216 
217  printk(KERN_INFO "read_virgo_config(): virgo_cloud config file being read \n");
218 
219 
220  if(f !=NULL)
221  {
222  bytesread=vfs_read(f, buf, 256, &pos);
223  printk(KERN_INFO "do_virgo_cloud_init(): virgo_cloud config file string of comma separated IPs : %s \n",buf);
224  pos=pos+bytesread;
225  }
226  char* delim=",";
227  char* token=NULL;
228  char* bufdup=kstrdup(buf,GFP_KERNEL);
229  printk(KERN_INFO "tokenize_list_of_ip_addrs(): bufdup = %s\n",bufdup);
230  while(bufdup != NULL)
231  {
232  token=strsep(&bufdup, delim);
233  printk(KERN_INFO "tokenize_list_of_ip_addrs(): %s\n",token);
234  node_ip_addrs_in_cloud[i]=kstrdup(token,GFP_KERNEL);
235  printk(KERN_INFO "tokenize_list_of_ip_addrs(): node_ip_addrs_in_cloud[%d] = %s\n",i,node_ip_addrs_in_cloud[i]);
236  i++;
237  }
238  num_cloud_nodes=i;
239  set_fs(fs);
240  filp_close(f,NULL);
241 }
242 
243 /*
244 Above tokenization made into a function - if needed can be used as multipurpose exported function
245 */
246 int tokenize_list_of_ip_addrs(char* buf)
247 {
248  char* delim=",";
249  char* token=NULL;
250  char* bufdup=kstrdup(buf,GFP_KERNEL);
251  printk(KERN_INFO, "tokenize_list_of_ip_addrs(): bufdup = %s\n",bufdup);
252  int i=0;
253  while(bufdup != NULL)
254  {
255  token=strsep(&bufdup, delim);
256  printk(KERN_INFO, "tokenize_list_of_ip_addrs(): %s\n",token);
257  /*strcpy(node_ip_addrs_in_cloud[i], token);*/
258  i++;
259  }
260  return i;
261 }
262 
263 
264 static int __init
265 virgocloudexec_fs_init(void)
266 {
267  int error;
268  static struct sockaddr_in sin;
269 
270  printk(KERN_INFO "virgocloudexec_fs_init(): doing init() of virgocloudexec_fs kernel module\n");
271  printk(KERN_INFO "virgocloudexec_fs_init(): starting virgo cloudexec service kernel thread\n");
272 
273  printk(KERN_INFO "virgocloudexec_fs_init(): invoking read_virgo_config()\n");
274  read_virgo_config();
275 
276  memset(&sin, 0, sizeof(struct sockaddr_in));
277  sin.sin_family=AF_INET;
278  sin.sin_addr.s_addr=htonl(INADDR_ANY);
279  sin.sin_port=htons(50000);
280 
281  error = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
282  printk(KERN_INFO "virgocloudexec_fs_init(): sock_create() returns error code: %d\n",error);
283 
284  error = kernel_bind(sock, (struct sockaddr*)&sin, sizeof(struct sockaddr_in));
285  printk(KERN_INFO "virgocloudexec_fs_init(): kernel_bind() returns error code: %d\n",error);
286 
287  error = kernel_listen(sock, 2);
288  printk(KERN_INFO "virgocloudexec_fs_init(): kernel_listen() returns error code: %d\n", error);
289 
290  virgo_cloudexec_fs_service(NULL);
291 
292  return 0;
293 }
294 EXPORT_SYMBOL(virgocloudexec_fs_init);
295 
296 int virgocloudexec_fs_create(void)
297 {
298  int error;
299 
300  /*
301  Blocking mode works in this commit again. No changes were made in virgo_malloc() or driver code.
302  Hence making it a blocking socket. Root cause for this weird behaviour remains unknown.
303  -Ka.Shrinivaasan
304  */
305 
306  /*
307  Multithreaded VIRGO Kernel Service
308  ----------------------------------
309  */
310  struct socket *clientsock;
311 
312  clientsock=NULL;
313  error = kernel_accept(sock, &clientsock, 0);
314 
315  /*
316  Blocking mode was working and kernel thread was listening and accepting connections without blocking the bootup till previous commit,
317  but suddenly it started to block on startup. Reason unknown (could be anything from hardware microcode update to external
318  causes viz., intrusion. These kind of events recur with high frequency. Needs further investigation).
319  There seems to be no error in the driver kernel service thread or syscall client.
320 
321  Making it temporarily O_NONBLOCK which seems to be quite a cleaner way despite EAGAIN to accept connections as this is always
322  in a while loop for server.
323 
324  Moreover the driver modules_install places it in /lib/modules/`uname -r`/extra which did not occur in previous commit. Origin
325  again mysterious.
326 
327  -Ka.Shrinivaasan
328  error = kernel_accept(sock, &clientsock, O_NONBLOCK);
329  */
330  /*
331  if(error==-EAGAIN)
332  printk(KERN_INFO "kernel_accept() returns -EAGAIN\n");
333  printk(KERN_INFO "virgocloudexec_fs_create(): kernel_accept() returns error code: %d\n",error);
334  printk(KERN_INFO "virgocloudexec_fs_create(): kernel_accept() clientsock: %u\n",clientsock);
335  */
336  return clientsock;
337 }
338 EXPORT_SYMBOL(virgocloudexec_fs_create);
339 
340 void* virgocloudexec_fs_recvfrom(struct socket* clsock)
341 {
342  char* fsFunction;
343  struct sockaddr_in sin;
344  void* virgo_fs_func_ret;
345 
346  /*
347  Multithreaded VIRGO Kernel Service
348  ----------------------------------
349  */
350  struct socket *clientsock=clsock;
351  struct kvec iov;
352  struct msghdr msg = { NULL, };
353  int buflen=BUF_SIZE;
354  void *args=NULL;
355  int nr=1;
356 
357  struct task_struct *task;
358  int error;
359  char buffer[BUF_SIZE];
360  int len=0;
361 
362  char* client_ip_str;
363 
364  /*
365  do kernel_recvmsg() to get the function data to be executed on a thread
366  */
367  if(clientsock != NULL )
368  {
369  printk(KERN_INFO "virgocloudexec_fs_recvfrom(): before kernel_recvmsg()\n");
370  memset(buffer, 0, BUF_SIZE);
371  iov.iov_base=(void*)buffer;
372  iov.iov_len=BUF_SIZE;
373  msg.msg_name = (struct sockaddr *) &sin;
374  msg.msg_namelen = sizeof(struct sockaddr);
375  msg.msg_iov = (struct iovec *) &iov;
376  msg.msg_iovlen = 1;
377  msg.msg_control = NULL;
378  msg.msg_controllen = 0;
379  msg.msg_flags=MSG_NOSIGNAL;
380 
381  len = kernel_recvmsg(clientsock, &msg, &iov, 1, buflen, msg.msg_flags);
382  printk(KERN_INFO "virgocloudexec_fs_recvfrom(): kernel_recvmsg() returns len: %d\n",len);
383  /*
384  parse the message and invoke kthread_create()
385  do kernel_sendmsg() with the results
386  */
387  fsFunction = strip_control_M(kstrdup(buffer,GFP_KERNEL));
388 
389  printk(KERN_INFO "virgocloudexec_fs_recvfrom(): kernel_recvmsg() returns in recv: iov.iov_base=%s, buffer: %s\n", iov.iov_base, buffer);
390  print_buffer(buffer);
391  le32_to_cpus(buffer);
392  printk(KERN_INFO "virgocloudexec_fs_recvfrom(): kernel_recvmsg() le32 to cpu %s\n", buffer);
393  printk(KERN_INFO "virgocloudexec_fs_recvfrom(): fsFunction : %s \n", fsFunction);
394  args=(void*)fsFunction;
395 
396  /*
397  Temporarily commenting kthread creation for the kernelspace virgo fs ops
398  execution as return value from a kthread function is needed which is difficult
399  and circuitous to do with kthread. Instead the fs_func is directly invoked.
400  */
401  /*task=kthread_create(fs_func, (void*)args, "fs_func thread");*/
402  virgo_fs_func_ret=fs_func((void*)args);
403 
404  /*
405  int woken_up=wake_up_process(task);
406  printk(KERN_INFO "virgocloudexec_fs_recvfrom(): clone thread woken_up : %d\n",woken_up);
407  */
408 
409  }
410  return virgo_fs_func_ret;
411 }
412 EXPORT_SYMBOL(virgocloudexec_fs_recvfrom);
413 
414 void print_buffer(char* buffer)
415 {
416  printk(KERN_INFO "virgo_cloudexec_fs: print_buffer(): ");
417  int i=0;
418  for(i=0; i < BUF_SIZE; i++)
419  printk(KERN_INFO "%c", buffer[i]);
420  printk(KERN_INFO "\n");
421 }
422 
423 int virgocloudexec_fs_sendto(struct socket* clsock, void* virgo_fs_ret)
424 {
425 
426  /*
427  Multithreaded VIRGO Kernel Service
428  ----------------------------------
429  */
430 
431  struct sockaddr_in sin;
432  struct socket *clientsock=clsock;
433  struct kvec iov;
434  struct msghdr msg = { NULL, };
435  int buflen=BUF_SIZE;
436  void *args=NULL;
437  int nr=1;
438 
439  struct task_struct *task;
440  int error;
441  char buffer[BUF_SIZE];
442  int len=0;
443 
444  if(clientsock != NULL)
445  {
446 
447  printk(KERN_INFO "virgocloudexec_fs_sendto(): virgo_fs_ret=%s\n",virgo_fs_ret);
448  if(virgo_fs_ret != NULL)
449  {
450  /*
451  VFS file descriptor allocated by VFS kernelspace is sent to the remote client that is used in
452  subsequent read/write calls
453  - Ka.Shrinivaasan 4 May 2014
454  */
455  printk(KERN_INFO "virgocloudexec_fs_sendto(): data sent=%s\n",virgo_fs_ret);
456  strcpy(buffer,virgo_fs_ret);
457  }
458  iov.iov_base=buffer;
459  iov.iov_len=BUF_SIZE;
460  msg.msg_name = (struct sockaddr *) &sin;
461  msg.msg_namelen = sizeof(struct sockaddr);
462  msg.msg_iov = (struct iovec *) &iov;
463  msg.msg_iovlen = 1;
464  msg.msg_control = NULL;
465  msg.msg_controllen = 0;
466  msg.msg_flags=0;
467 
468  int ret;
469  printk(KERN_INFO "virgocloudexec_fs_sendto(): before kernel_sendmsg() for send buffer: %s\n", buffer);
470  ret = kernel_sendmsg(clientsock, &msg, &iov, 1, buflen);
471  printk(KERN_INFO "virgocloudexec_fs_sendto(): kernel_sendmsg() returns ret: %d\n",ret);
472  sock_release(clientsock);
473  printk(KERN_INFO "virgocloudexec_fs_sendto(): sock_release invoked on client socket \n");
474  }
475  return 0;
476 }
477 EXPORT_SYMBOL(virgocloudexec_fs_sendto);
478 
479 
480 static void __exit
481 virgocloudexec_fs_exit(void)
482 {
483  printk(KERN_INFO "exiting virgocloudexec_fs kernel module \n");
484  do_exit(1);
485 }
486 EXPORT_SYMBOL(virgocloudexec_fs_exit);
487 
488 /*
489 Arguments Parser for VIRGO memory pooling commands-virgo_cloud_malloc,virgo_cloud_free
490 virgo_cloud_set,virgo_cloud_get- sent from virgo_malloc syscall
491 */
492 
493 struct virgo_fs_args* parse_virgofs_command(char* fsFunction)
494 {
495  struct virgo_fs_args* vmargs=kmalloc(sizeof(struct virgo_fs_args),GFP_KERNEL);
496  vmargs->fs_cmd=kstrdup(strsep(&fsFunction, "("),GFP_KERNEL);
497  printk(KERN_INFO "parse_virgofs_command: vmargs->fs_cmd: %s\n", vmargs->fs_cmd);
498 
499  if(strcmp(vmargs->fs_cmd,"virgo_cloud_open")==0 || strcmp(vmargs->fs_cmd,"virgo_cloud_close")==0)
500  {
501  vmargs->fs_args[0]=kstrdup(strsep(&fsFunction,")"),GFP_KERNEL);
502  printk(KERN_INFO "parse_virgofs_command: vmargs->fs_args[0]: %s\n", vmargs->fs_args[0]);
503  vmargs->fs_args[1]=NULL;
504  }
505  else
506  {
507  vmargs->fs_args[0]=kstrdup(strsep(&fsFunction,","),GFP_KERNEL);
508  vmargs->fs_args[1]=kstrdup(strsep(&fsFunction,","),GFP_KERNEL);
509  vmargs->fs_args[2]=kstrdup(strsep(&fsFunction,","),GFP_KERNEL);
510  vmargs->fs_args[3]=kstrdup(strsep(&fsFunction,")"),GFP_KERNEL);
511  printk(KERN_INFO "parse_virgofs_command: vmargs->fs_args[0]: %s\n", vmargs->fs_args[0]);
512  printk(KERN_INFO "parse_virgofs_command: vmargs->fs_args[1]: %s\n", vmargs->fs_args[1]);
513  printk(KERN_INFO "parse_virgofs_command: vmargs->fs_args[2]: %d\n", vmargs->fs_args[2]);
514  printk(KERN_INFO "parse_virgofs_command: vmargs->fs_args[3]: %d\n", vmargs->fs_args[3]);
515  vmargs->fs_args[4]=NULL;
516  }
517  return vmargs;
518 }
519 
520 FPTR toFuncPtr(char* functionName)
521 {
522  if(strcmp(functionName, "virgo_cloud_open_kernelspace")==0)
523  return virgo_cloud_open_kernelspace;
524  if(strcmp(functionName, "virgo_cloud_close_kernelspace")==0)
525  return virgo_cloud_close_kernelspace;
526  if(strcmp(functionName, "virgo_cloud_read_kernelspace")==0)
527  return virgo_cloud_read_kernelspace;
528  if(strcmp(functionName, "virgo_cloud_write_kernelspace")==0)
529  return virgo_cloud_write_kernelspace;
530 }
531 
532 MODULE_LICENSE("GPL");
533 module_init(virgocloudexec_fs_init);
534 module_exit(virgocloudexec_fs_exit);