Krishna iResearch Intelligent Cloud Platform - VIRtual Generic Os - VIRGO - Linux kernel extensions for cloud
 All Classes
virgo_malloc.c
1 /***************************************************************************************
2 VIRGO - VIRtual Generic Os - linux kernel extensions for cloud
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/kernel.h>
31 #include <linux/kthread.h>
32 #include <linux/sched.h>
33 #include <linux/module.h>
34 #include <linux/errno.h>
35 #include <linux/fcntl.h>
36 #include <linux/net.h>
37 #include <linux/in.h>
38 #include <linux/inet.h>
39 #include <linux/udp.h>
40 #include <linux/tcp.h>
41 #include <linux/string.h>
42 #include <linux/unistd.h>
43 #include <linux/slab.h>
44 #include <linux/netdevice.h>
45 #include <linux/skbuff.h>
46 #include <linux/file.h>
47 #include <linux/freezer.h>
48 #include <net/sock.h>
49 #include <net/checksum.h>
50 #include <net/ip.h>
51 #include <net/ipv6.h>
52 #include <net/tcp.h>
53 #include <net/tcp_states.h>
54 #include <asm/uaccess.h>
55 #include <asm/ioctls.h>
56 #include <trace/events/skb.h>
57 
58 #include <linux/module.h>
59 #include <linux/types.h>
60 #include <linux/uio.h>
61 #include <linux/unistd.h>
62 #include <linux/init.h>
63 
64 #include <linux/random.h>
65 
66 #include <linux/virgo_config.h>
67 #include <linux/virgo_mempool.h>
68 
69 #define BUF_SIZE 3000
70 
71 #define PER_NODE_MALLOC_CHUNK_SIZE 1000
72 
73 
74 struct hostport* get_least_loaded_hostport_from_cloud_mempool()
75 {
76  /*
77  Either a loadtracking algorithm or a pseudorandom generator based loadbalancing algorithm is invoked to
78  get the host ip for next virgo_malloc() function kernel thread execution
79  */
80 
81  /*char *LBAlgorithm = "Loadtrack";*/
82  char *LBAlgorithm = "PRG";
83  struct hostport* hopo = kmalloc(sizeof(struct hostport),GFP_KERNEL);
84  if(strcmp(LBAlgorithm, "Loadtrack")==0)
85  {
86  char* cloud_host = get_host_from_cloud_Loadtrack_mempool();
87  hopo->hostip=kstrdup(cloud_host, GFP_KERNEL);
88  printk(KERN_INFO "get_least_loaded_hostport_from_cloud(): get_host_from_cloud_Loadtrack_mempool() returns host ip: %s \n",hopo->hostip);
89  hopo->port=30000;
90  }
91  else if(strcmp(LBAlgorithm, "PRG")==0)
92  {
93  char* cloud_host = get_host_from_cloud_PRG_mempool();
94  printk(KERN_INFO "get_least_loaded_hostport_from_cloud(): get_host_from_cloud_PRG_mempool() - cloud_host(before kstrdup): %s \n",cloud_host);
95  hopo->hostip=kstrdup(cloud_host, GFP_KERNEL);
96  printk(KERN_INFO "get_least_loaded_hostport_from_cloud(): get_host_from_cloud_PRG_mempool() returns host ip: %s \n",hopo->hostip);
97  hopo->port=30000;
98  }
99  return hopo;
100 }
101 
102 /*
103  Loadtracking algorithm for nodes in the cloud
104 */
105 
106 char* get_host_from_cloud_Loadtrack_mempool()
107 {
108  return NULL;
109 }
110 
111 /*
112 Pseudorandom number generator based algorithm to distribute virgo_malloc() requests amongst cloud nodes
113 */
114 
115 char* get_host_from_cloud_PRG_mempool()
116 {
117  unsigned int rand_int = get_random_int();
118  /*
119  maps a pseudo random integer in range 0 to 2^32-1 to 0 to num_of_cloud_nodes
120  - Ka.Shrinivaasan 12 July 2013
121 
122  unsigned int rand_host_id = (num_cloud_nodes) * rand_int / (65536-1);
123  */
124 
125  /*
126  Instead of range mapping, rand_int (mod) num_cloud_nodes is also sufficient
127  - Ka.Shrinivaasan 12 July 2013
128  */
129  unsigned int rand_host_id = rand_int % num_cloud_nodes;
130 
131  printk(KERN_INFO "get_host_from_cloud_PRG_mempool() - get_random_int() returned %u \n",rand_int);
132  printk(KERN_INFO "get_host_from_cloud_PRG_mempool() range mapping for %d cloud nodes(num_cloud_nodes) returns random integer %d, host ip(nodes_ip_addrs_in_cloud): %s \n",num_cloud_nodes,rand_host_id, node_ip_addrs_in_cloud[rand_host_id]);
133  return node_ip_addrs_in_cloud[rand_host_id];
134 
135 }
136 
137 
138 /*asmlinkage char* sys_virgo_get(struct virgo_address* vaddr)*/
139 asmlinkage long sys_virgo_get(unsigned long vuid, char __user *data_out)
140 {
141  int nr;
142  struct kvec iov;
143  struct msghdr msg;
144  int error;
145  struct socket *sock;
146  struct sockaddr_in sin;
147  int sfd, s, j;
148  size_t len;
149  ssize_t nread;
150  char buf[BUF_SIZE];
151  char tempbuf[BUF_SIZE];
152  /*char *buf;*/
153 
154  int chunk_size=0;
155  int sum_alloc_size=0;
156 
157  printk("virgo_get() system call: before virgo_unique_id_to_addr()\n");
158  struct virgo_address* vaddr=virgo_unique_id_to_addr(vuid);
159  printk("virgo_get() system call: vuid=%ld, virgo address to retrieve data from is vaddr=%p\n",vuid, vaddr);
160 
161  sin.sin_family=AF_INET;
162  in4_pton(vaddr->hstprt->hostip, strlen(vaddr->hstprt->hostip), &sin.sin_addr.s_addr, '\0',NULL);
163  sin.sin_port=htons(vaddr->hstprt->port);
164 
165  char* virgo_get_cmd;
166  char* vaddr_addr_str=addr_to_str(vaddr->addr);
167  strcpy(tempbuf,"virgo_cloud_get(");
168  virgo_get_cmd=strcat(tempbuf,vaddr_addr_str);
169  virgo_get_cmd=strcat(tempbuf, ")");
170  strcpy(buf,tempbuf);
171 
172  printk(KERN_INFO "virgo_get() system call: tempbuf=%s, buf=%s, virgo_get_cmd=%s\n",tempbuf,buf,virgo_get_cmd);
173 
174  /*iov.iov_base=buf;*/
175  iov.iov_base=buf;
176  /*iov.iov_base=buf;*/
177  /*iov.iov_len=sizeof(buf);*/
178  /*iov.iov_len=BUF_SIZE;*/
179  iov.iov_len=strlen(buf);
180  msg.msg_name = (struct sockaddr *) &sin;
181  msg.msg_namelen = sizeof(struct sockaddr);
182  msg.msg_iov = (struct iovec *) &iov;
183  msg.msg_iovlen = 1;
184  msg.msg_control = NULL;
185  msg.msg_controllen = 0;
186  msg.msg_flags = 0;
187  nr=1;
188 
189  error = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
190  printk(KERN_INFO "virgo_get() syscall: created client kernel socket\n");
191  kernel_connect(sock, (struct sockaddr*)&sin, sizeof(sin) , 0);
192  printk(KERN_INFO "virgo_get() syscall: connected kernel client to virgo cloudexec kernel service\n ");
193  kernel_sendmsg(sock, &msg, &iov, nr, BUF_SIZE);
194  printk(KERN_INFO "virgo_get() syscall: sent message: %s \n", buf);
195  len = kernel_recvmsg(sock, &msg, &iov, nr, BUF_SIZE, msg.msg_flags);
196  printk(KERN_INFO "virgo_get() syscall: received message: %s \n", buf);
197 
198  le32_to_cpus(buf);
199  printk(KERN_INFO "virgo_get() syscall: le32_to_cpus(buf): %s \n", buf);
200  /*
201  sock_release(sock);
202  printk(KERN_INFO "virgo_get() syscall: virgo_get() client socket_release() invoked\n");
203  */
204  long ret=copy_to_user(data_out,buf,strlen(buf));
205  printk(KERN_INFO "virgo_get() syscall: copy_to_user() returns ret=%u, data_out=%s\n",ret,data_out);
206  return ret;
207 }
208 
209 
210 asmlinkage long sys_virgo_set(unsigned long vuid, const char __user *data_in)
211 {
212  int nr;
213  struct kvec iov;
214  struct msghdr msg;
215  int error;
216  struct socket *sock;
217  struct sockaddr_in sin;
218  int sfd, s, j;
219  size_t len;
220  ssize_t nread;
221  char buf[BUF_SIZE];
222  char tempbuf[BUF_SIZE];
223  /*char* buf;*/
224  printk(KERN_INFO "virgo_set() system call: before virgo_unique_id_to_addr()\n");
225  struct virgo_address* vaddr=virgo_unique_id_to_addr(vuid);
226  printk(KERN_INFO "virgo_set() system call: after virgo_unique_id_to_addr(), vaddr=%p\n", vaddr);
227  char data[BUF_SIZE];
228  /*printk(KERN_INFO "virgo_set() system call: before copy_from_user, data_in=%s\n",data_in);
229  printk(KERN_INFO "virgo_set() system call: __builtin_constant_p(BUF_SIZE-1)=%d\n",__builtin_constant_p(BUF_SIZE-1));
230  long copyret=copy_from_user((void*)data,(const void __user *)data_in,BUF_SIZE-1);
231  printk(KERN_INFO "virgo_set() system call: copy_from_user returned copyret = %ld\n",copyret);*/
232 
233  printk(KERN_INFO "virgo_set() system call: vuid=%ld, virgo address to set is vaddr=%p\n",vuid, vaddr);
234  printk(KERN_INFO "virgo_set() system_call: before memcpy()\n");
235  memcpy(data,data_in,sizeof(data)-1);
236  printk(KERN_INFO "virgo_set() system_call: after memcpy()\n");
237  printk(KERN_INFO "virgo_set() system call: vuid=%ld, data to set=%s\n", vuid, data);
238  int chunk_size=0;
239  int sum_alloc_size=0;
240  sin.sin_family=AF_INET;
241  in4_pton(vaddr->hstprt->hostip, strlen(vaddr->hstprt->hostip), &sin.sin_addr.s_addr, '\0',NULL);
242  sin.sin_port=htons(vaddr->hstprt->port);
243 
244  char* virgo_set_cmd;
245  char* vaddr_addr_str=addr_to_str(vaddr->addr);
246  printk(KERN_INFO "virgo_set() system call: vaddr_addr_str=[%s]",vaddr_addr_str);
247  /*virgo_set_cmd=kstrdup(strcat("virgo_cloud_set(",vaddr_addr_str),GFP_KERNEL);*/
248  strcpy(tempbuf,"virgo_cloud_set(");
249  virgo_set_cmd=strcat(tempbuf,vaddr_addr_str);
250  printk(KERN_INFO "virgo_set() system call: 1. virgo_set_cmd=%s",virgo_set_cmd);
251  /*virgo_set_cmd=kstrdup(strcat(virgo_set_cmd,","),GFP_KERNEL);*/
252  virgo_set_cmd=strcat(tempbuf,",");
253  printk(KERN_INFO "virgo_set() system call: 2. virgo_set_cmd=%s,data=%s",virgo_set_cmd, data);
254  /*virgo_set_cmd=kstrdup(strcat(virgo_set_cmd, data),GFP_KERNEL);*/
255  virgo_set_cmd=strcat(tempbuf, data);
256  printk(KERN_INFO "virgo_set() system call: 3. virgo_set_cmd=%s",virgo_set_cmd);
257  /*virgo_set_cmd=kstrdup(strcat(virgo_set_cmd, ")"),GFP_KERNEL);*/
258  virgo_set_cmd=strcat(tempbuf, ")");
259  printk(KERN_INFO "virgo_set() system call: 4. virgo_set_cmd=%s",virgo_set_cmd);
260  strcpy(buf,tempbuf);
261 
262  printk(KERN_INFO "virgo_set() system call: tempbuf=%s, buf=%s, virgo_set_cmd = %s\n",tempbuf, buf, virgo_set_cmd);
263 
264  iov.iov_base=buf;
265  iov.iov_len=strlen(buf);
266  msg.msg_name = (struct sockaddr *) &sin;
267  msg.msg_namelen = sizeof(struct sockaddr);
268  msg.msg_iov = (struct iovec *) &iov;
269  msg.msg_iovlen = 1;
270  msg.msg_control = NULL;
271  msg.msg_controllen = 0;
272  msg.msg_flags = 0;
273  nr=1;
274 
275  /*strcpy(iov.iov_base, buf);*/
276  error = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
277  printk(KERN_INFO "virgo_set() syscall: created client kernel socket\n");
278  kernel_connect(sock, (struct sockaddr*)&sin, sizeof(sin) , 0);
279  printk(KERN_INFO "virgo_set() syscall: connected kernel client to virgo cloudexec kernel service\n ");
280  kernel_sendmsg(sock, &msg, &iov, nr, BUF_SIZE);
281  printk(KERN_INFO "virgo_set() syscall: sent message: %s \n", buf);
282  len = kernel_recvmsg(sock, &msg, &iov, nr, BUF_SIZE, msg.msg_flags);
283  printk(KERN_INFO "virgo_set() syscall: received message: %s \n", buf);
284 
285  le32_to_cpus(buf);
286  printk(KERN_INFO "virgo_set() syscall: le32_to_cpus(buf): %s \n", buf);
287  /*
288  sock_release(sock);
289  printk(KERN_INFO "virgo_set() syscall: virgo_set() client socket_release() invoked\n");
290  */
291  /*return buf;*/
292  return 0;
293 }
294 
295 
296 /*asmlinkage struct virgo_address* sys_virgo_malloc(int size)*/
297 asmlinkage long sys_virgo_malloc(int size, unsigned long __user *vuid)
298 {
299  int no_of_chunks=1;
300  /*
301  int nr;
302  struct kvec iov;
303  */
304  /*
305  struct msghdr msg = {
306  .msg_flags = MSG_EOF,
307  };
308  */
309  /*
310  struct msghdr msg;
311  int error;
312  */
313 
314  /*
315  struct socket *sock;
316  struct sockaddr_in sin;
317  */
318 
319  /*
320  struct addrinfo hints;
321  struct addrinfo *result, *rp;
322  */
323  /*
324  int sfd, s, j;
325  size_t len;
326  ssize_t nread;
327  */
328  /*char buf[BUF_SIZE];*/
329  /*
330  char *buf;
331  char *malloc_cmd;
332  */
333 
334  /*
335  memset(&hints, 0, sizeof(struct addrinfo));
336  hints.ai_family = AF_UNSPEC; / Allow IPv4 or IPv6 /
337  hints.ai_socktype = SOCK_STREAM; / Datagram socket /
338  hints.ai_flags = 0;
339  hints.ai_protocol = 0; / Any protocol /
340  */
341 
342  /*
343  struct hostport* leastloadedhostport = get_least_loaded_hostport_from_cloud();
344  s = getaddrinfo(leastloadedhostport->host, leastloadedhostport->port, &hints, &result);
345  */
346 
347  int chunk_size=0;
348  int sum_alloc_size=0;
349  int i=0;
350  int this_allocation_start_entry=next_vtable_entry;
351 
352  /*
353  Mutex lock and unlock also causes a kernel panic, hence commented as of now
354  - Ka.Shrinivaasan 22October2013
355  */
356 
357  /*mutex_lock(&vtranstable.vtable_fragment_mutex);*/
358  while(true)
359  {
360  /*char *buf;*/
361  char buf[BUF_SIZE];
362  char tempbuf[BUF_SIZE];
363  char *malloc_cmd;
364  int sfd, s, j;
365  size_t len;
366  ssize_t nread;
367  struct msghdr msg;
368  int error;
369  int nr;
370  struct kvec iov;
371  struct hostport* leastloadedhostport = get_least_loaded_hostport_from_cloud_mempool();
372  struct socket *sock;
373  struct sockaddr_in sin;
374  if(leastloadedhostport->hostip==NULL)
375  {
376  printk(KERN_INFO "virgo_malloc() syscall: leastloadedhostport->hostip == NULL, hardcoding it to loopback address");
377  leastloadedhostport->hostip="127.0.0.1";
378  }
379  if(leastloadedhostport->port != 30000)
380  {
381  printk(KERN_INFO "virgo_malloc() syscall: leastloadedhostport->port != 30000, hardcoding it to 30000");
382  leastloadedhostport->port=30000;
383  }
384  printk(KERN_INFO "virgo_malloc() syscall: leastloadedhostport->port=%d",leastloadedhostport->port);
385  printk(KERN_INFO "virgo_malloc() syscall: leastloadedhostport->hostip=%s",leastloadedhostport->hostip);
386  in4_pton(leastloadedhostport->hostip, strlen(leastloadedhostport->hostip), &sin.sin_addr.s_addr, '\0',NULL);
387  sin.sin_family=AF_INET;
388  sin.sin_port=htons(leastloadedhostport->port);
389  printk(KERN_INFO "virgo_malloc() syscall: after in4_pton and htons, leastloadedhostport->hostip=%s, leastloadedhostport->port=%d, sin.sin_addr.s_addr=%x, sin.sin_port=%x\n",leastloadedhostport->hostip,leastloadedhostport->port, sin.sin_addr.s_addr, sin.sin_port);
390  printk(KERN_INFO "virgo_malloc() syscall: size=%d, sum_alloc_size=%d \n", size,sum_alloc_size);
391 
392  if(sum_alloc_size + PER_NODE_MALLOC_CHUNK_SIZE <= size)
393  {
394  chunk_size=PER_NODE_MALLOC_CHUNK_SIZE;
395  printk(KERN_INFO "virgo_malloc() syscall: size=%d, sum_alloc_size=%d, chunk_size=1000",size,sum_alloc_size);
396  strcpy(buf,"virgo_cloud_malloc(1000)");
397  }
398  else
399  {
400  chunk_size=size-sum_alloc_size;
401  printk(KERN_INFO "virgo_malloc() syscall: size=%d, sum_alloc_size=%d, chunk_size==%d",size,sum_alloc_size,chunk_size);
402  /* This should not happen and should have broken earlier in the loop*/
403  if(chunk_size <= 0)
404  {
405  printk(KERN_INFO "virgo_malloc() syscall: size=%d, sum_alloc_size=%d, chunk_size <= 0, but this should not get printed and should have exited earlier",size,sum_alloc_size);
406  break;
407  }
408  strcpy(tempbuf,"virgo_cloud_malloc(");
409  char* chunk_size_str=int_to_str(chunk_size);
410  malloc_cmd=strcat(tempbuf,chunk_size_str);
411  malloc_cmd=strcat(tempbuf, ")");
412  strcpy(buf,tempbuf);
413  printk(KERN_INFO "virgo_malloc() syscall: malloc_cmd=%s, buf=%s, tempbuf=%s",malloc_cmd,buf,tempbuf);
414  }
415 
416  printk(KERN_INFO "virgo_malloc() syscall: buf=%s, malloc_cmd=%s\n",buf, malloc_cmd);
417 
418  iov.iov_base=buf;
419  iov.iov_len=strlen(buf);
420  msg.msg_name = (struct sockaddr *) &sin;
421  msg.msg_namelen = sizeof(struct sockaddr);
422  msg.msg_iov = (struct iovec *) &iov;
423  msg.msg_iovlen = 1;
424  msg.msg_control = NULL;
425  msg.msg_controllen = 0;
426  msg.msg_flags = 0;
427  nr=1;
428 
429  /*strcpy(iov.iov_base, buf);*/
430  error = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
431  printk(KERN_INFO "virgo_malloc() syscall: created client kernel socket\n");
432  kernel_connect(sock, (struct sockaddr*)&sin, sizeof(sin) , 0);
433  printk(KERN_INFO "virgo_malloc() syscall: connected kernel client to virgo cloudexec kernel service\n ");
434  len = kernel_sendmsg(sock, &msg, &iov, nr, BUF_SIZE);
435  printk(KERN_INFO "virgo_malloc() syscall: sent len=%d; iov.iov_base=%s, sent message: %s \n", len, iov.iov_base, buf);
436  len = kernel_recvmsg(sock, &msg, &iov, nr, BUF_SIZE, msg.msg_flags);
437  printk(KERN_INFO "virgo_malloc() syscall: recv len=%d; received message buf: [%s] \n", len, buf);
438  printk(KERN_INFO "virgo_malloc() syscall: received iov.iov_base: %s \n", iov.iov_base);
439 
440  /*
441  str_to_addr() doesnot work which uses various %p qualifiers.
442  Only simple_strtoll() in str_to_addr2() works. But invoking
443  both for printing debug info to kern.log
444  - Ka.Shrinivaasan 22October2013
445  */
446  /*vtranstable.vtable[next_vtable_entry].addr=(void*)str_to_addr(buf);*/
447  vtranstable.vtable[next_vtable_entry].addr=(void*)str_to_addr2(buf);
448 
449  printk(KERN_INFO "virgo_malloc() syscall: vtranstable.vtable[%d].addr=%p \n", next_vtable_entry, (char*)vtranstable.vtable[next_vtable_entry].addr);
450  vtranstable.vtable[next_vtable_entry].node_id=next_vtable_entry;
451  vtranstable.vtable[next_vtable_entry].hstprt=leastloadedhostport;
452  vtranstable.vtable[next_vtable_entry].cloud_alloc_id=alloc_id;
453  vtranstable.vtable[next_vtable_entry].refcount=1;
454  vtranstable.fragment_is_disk_persisted=0;
455 
456  printk(KERN_INFO "virgo_malloc() syscall: next_vtable_entry=%d, vtranstable.vtable[next_vtable_entry].node_id=%d, vtranstable.vtable[next_vtable_entry].addr=%p, vtranstable.vtable[next_vtable_entry].hstprt->hostip=%s, vtranstable.vtable[next_vtable_entry].hstprt->port=%d \n",next_vtable_entry, vtranstable.vtable[next_vtable_entry].node_id, (char*)vtranstable.vtable[next_vtable_entry].addr, vtranstable.vtable[next_vtable_entry].hstprt->hostip, vtranstable.vtable[next_vtable_entry].hstprt->port);
457 
458  le32_to_cpus(buf);
459  printk(KERN_INFO "virgo_malloc() syscall: le32_to_cpus(buf): %s \n", buf);
460 
461  /*
462  Mysteriously sock_release() causes kernel panic repeatedly. Hence commenting this
463  temporarily.
464  - Ka.Shrinivaasan 22October2013
465  */
466  /*
467  if(sock)
468  {
469  sock_release(sock);
470  printk(KERN_INFO "virgo_malloc() syscall: virgo_malloc() client socket_release() invoked\n");
471  }
472  else
473  printk(KERN_INFO "virgo_malloc() syscall: sock is NULL\n");
474  */
475 
476  sum_alloc_size+=chunk_size;
477  next_vtable_entry++;
478  no_of_chunks++;
479  printk(KERN_INFO "virgo_malloc() syscall: size to be allocated = %d, sum_alloc_size = %d \n", size, sum_alloc_size);
480 
481  /*
482  If sum of sizes of chunks allocated so far is equal to size then break
483  */
484  if(sum_alloc_size == size)
485  {
486  printk(KERN_INFO "virgo_malloc() syscall: sum_alloc_size == size, breaking while loop\n");
487  break;
488  }
489  }
490  alloc_id++;
491  /*mutex_unlock(&vtranstable.vtable_fragment_mutex);*/
492 
493  printk(KERN_INFO "virgo_malloc() syscall: returning &(vtranstable.vtable[this_allocation_start_entry]) == %p\n",&(vtranstable.vtable[this_allocation_start_entry]));
494  unsigned long virgo_unique_id=addr_to_virgo_unique_id(&(vtranstable.vtable[this_allocation_start_entry]));
495  long copy_ret=copy_to_user(vuid,&virgo_unique_id,sizeof(unsigned long));
496  return copy_ret;
497 }
498 
499 /*asmlinkage char* sys_virgo_free(struct virgo_address* vaddr)*/
500 asmlinkage long sys_virgo_free(unsigned long vuid)
501 {
502  int nr;
503  struct kvec iov;
504  struct msghdr msg;
505  int error;
506  struct socket *sock;
507  struct sockaddr_in sin;
508  int sfd, s, j;
509  size_t len;
510  ssize_t nread;
511  char buf[BUF_SIZE];
512  char tempbuf[BUF_SIZE];
513  /*char* buf;*/
514  char* free_cmd;
515 
516  struct virgo_address* vaddr=virgo_unique_id_to_addr(vuid);
517 
518  sin.sin_family=AF_INET;
519  in4_pton(vaddr->hstprt->hostip, strlen(vaddr->hstprt->hostip), &sin.sin_addr.s_addr, '\0',NULL);
520  sin.sin_port=htons(vaddr->hstprt->port);
521 
522  char* vaddr_addr_str=addr_to_str(vaddr->addr);
523  strcpy(tempbuf,"virgo_cloud_free(");
524  free_cmd=strcat(tempbuf,vaddr_addr_str);
525  free_cmd=strcat(tempbuf, ")");
526  strcpy(buf,tempbuf);
527 
528  printk(KERN_INFO "virgo_free() system call: tempbuf=%d, buf=%s, free_cmd=%s \n",tempbuf, buf, free_cmd);
529 
530  iov.iov_base=buf;
531  iov.iov_len=strlen(buf);
532  msg.msg_name = (struct sockaddr *) &sin;
533  msg.msg_namelen = sizeof(struct sockaddr);
534  msg.msg_iov = (struct iovec *) &iov;
535  msg.msg_iovlen = 1;
536  msg.msg_control = NULL;
537  msg.msg_controllen = 0;
538  msg.msg_flags = 0;
539  nr=1;
540 
541  /*strcpy(iov.iov_base, buf);*/
542  error = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
543  printk(KERN_INFO "virgo_free() syscall: created client kernel socket\n");
544  kernel_connect(sock, (struct sockaddr*)&sin, sizeof(sin) , 0);
545  printk(KERN_INFO "virgo_free() syscall: connected kernel client to virgo cloudexec kernel service\n ");
546  kernel_sendmsg(sock, &msg, &iov, nr, BUF_SIZE);
547  printk(KERN_INFO "virgo_free() syscall: sent message: %s \n", buf);
548  len = kernel_recvmsg(sock, &msg, &iov, nr, BUF_SIZE, msg.msg_flags);
549  printk(KERN_INFO "virgo_free() syscall: received message: %s \n", buf);
550 
551  le32_to_cpus(buf);
552  printk(KERN_INFO "virgo_free() syscall: le32_to_cpus(buf): %s \n", buf);
553  /*
554  sock_release(sock);
555  printk(KERN_INFO "virgo_free() syscall: virgo_free() client socket_release() invoked\n");
556  */
557  /*return buf;*/
558  return 0;
559 }
560 
561 char* int_to_str(int n)
562 {
563  char* ret=(char*)kmalloc(50,GFP_KERNEL);
564  sprintf(ret,"%d",n);
565  printk(KERN_INFO "int_to_str(): n=%d\n",n);
566  printk(KERN_INFO "int_to_str(): ret=[%s]\n",ret);
567  return ret;
568 }
569 
570 char* addr_to_str(char* addr)
571 {
572  char* ret=(char*)kmalloc(50,GFP_KERNEL);
573  sprintf(ret,"%p",addr);
574  printk(KERN_INFO "addr_to_str(): addr=%p\n",addr);
575  printk(KERN_INFO "addr_to_str(): ret=[%s]\n",ret);
576  return ret;
577 }
578 
579 
580 /*
581 This function parses the address within the string straddr and returns as the pointer address
582 Example: "0x0000ffff" to 0x0000ffff
583 */
584 char* str_to_addr(char* straddr)
585 {
586  char *ptr=NULL;
587  void *voidptr=NULL;
588  void *voidptr_vargs=NULL;
589  sscanf(straddr,"%p",(void**)&ptr);
590  sscanf(straddr,"%p",&voidptr);
591  var_sscanf(straddr, "%p", (void**)&voidptr_vargs);
592  printk(KERN_INFO "str_to_addr(): straddr=[%s], address scanned ptr=%p, address scanned voidptr=%p \n", straddr, ptr, voidptr);
593  printk(KERN_INFO "str_to_addr(): after var_sscanf(): straddr=[%s], voidptr_vargs by vsscanf: %p \n", straddr, voidptr_vargs);
594 
595  var_sscanf(straddr, "%pK", (void**)&voidptr_vargs);
596  printk(KERN_INFO "str_to_addr()pK: straddr=[%s], address scanned ptr=%pK, address scanned voidptr=%pK \n", straddr, ptr, voidptr);
597  printk(KERN_INFO "str_to_addr()pK: after var_sscanf(): straddr=[%s], voidptr_vargs by vsscanf: %pK \n", straddr, voidptr_vargs);
598 
599 
600  var_sscanf(straddr, "%pF", (void**)&voidptr_vargs);
601  printk(KERN_INFO "str_to_addr()pF: straddr=[%s], address scanned ptr=%pF, address scanned voidptr=%pF \n", straddr, ptr, voidptr);
602  printk(KERN_INFO "str_to_addr()pF: after var_sscanf(): straddr=[%s], voidptr_vargs by vsscanf: %pF \n", straddr, voidptr_vargs);
603 
604 
605  var_sscanf(straddr, "%pS", (void**)&voidptr_vargs);
606  printk(KERN_INFO "str_to_addr()pS: straddr=[%s], address scanned ptr=%pS, address scanned voidptr=%pS \n", straddr, ptr, voidptr);
607  printk(KERN_INFO "str_to_addr()pS: after var_sscanf(): straddr=[%s], voidptr_vargs by vsscanf: %pS \n", straddr, voidptr_vargs);
608  return (char*)voidptr_vargs;
609 }
610 
611 /*
612 carried over from test/sscanftest.c for debugging null sscanf
613 */
614 
615 void var_sscanf(char *str, const char* fmt, ...)
616 {
617  va_list vargs;
618  va_start(vargs, fmt);
619  vsscanf(str, fmt, vargs);
620  va_end(vargs);
621 }
622 
623 /*
624 carried over from test/sscanftest.c for debugging null sscanf
625 */
626 
627 char* str_to_addr2(char* straddr)
628 {
629  /*
630  bit of a hack but a nice one when sscanf() doesn't work the way it is expected to be.
631  scan the pointer address in string into a unsigned long and in base 16 and reinterpret cast
632  it to void*.
633  */
634  char* endptr;
635  unsigned long ll=simple_strtoll(straddr, &endptr, 16);
636  void* lltovoidptr= (void*)ll;
637  printk(KERN_INFO "str_to_addr2(): straddr=[%s], lltovoidptr = %p\n", straddr, lltovoidptr);
638  return (char*)lltovoidptr;
639 }
640 
641 /*
642 Follwing functions map a machine address to a unique virgo id (UVID)
643 and inversely map a unique virgo id (VID) to a machine address. These have
644 been added to hide and abstract machine address to the userspace programs.
645 
646 At present only pointer to unsigned long cast is done and more sophisticated
647 Unique ID generation scheme has to be implemented if
648 needed later.
649 
650 Such a unique id is very much necessary for scalable persistent key-value store.
651 - Ka.Shrinivaasan 25October2013
652 */
653 unsigned long addr_to_virgo_unique_id(struct virgo_address* vaddr)
654 {
655  unsigned long uvid=(unsigned long)vaddr;
656  printk(KERN_INFO "addr_to_virgo_unique_id(): vaddr=%p, uvid=%u\n",vaddr,uvid);
657  return uvid;
658 }
659 
660 struct virgo_address* virgo_unique_id_to_addr(unsigned long virgo_unique_id)
661 {
662  struct virgo_address* vaddr=(struct virgo_address*)virgo_unique_id;
663  printk(KERN_INFO "virgo_unique_id_to_addr(): vaddr=%p, virgo_unique_id=%u\n",vaddr,virgo_unique_id);
664  return vaddr;
665 }
666