kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dor Laor <dlaor@redhat.com>
To: "Lukáš Doktor" <ldoktor@redhat.com>
Cc: KVM list <kvm@vger.kernel.org>,
	Autotest mailing list <autotest@test.kernel.org>
Subject: Re: [KVM-AUTOTEST PATCH 1/2] Add KSM test
Date: Mon, 07 Sep 2009 15:03:52 +0300	[thread overview]
Message-ID: <4AA4F6A8.5010609@redhat.com> (raw)
In-Reply-To: <4A9B9956.9000209@redhat.com>

On 08/31/2009 12:35 PM, Lukáš Doktor wrote:
> allocator.c is a program, which allocates pages in the memory and allow
> us to fill or test those pages. It's controlled using sockets.


After a quick review I have the following questions:
1. Why did you implement the guest tool in 'c' and not in python?
    Python is much simpler and you can share some code with the server.
    This 'test protocol' would also be easier to understand this way.
2. IMHO there is no need to use select, you can do blocking read.
3. Also you can use plain malloc without the more complex ( a bit) mmap.

>
> Signed-off-by: Lukáš Doktor<ldoktor@redhat.com>
> Signed-off-by: Jiří Župka<jzupka@redhat.com>
> ---
>    client/tests/kvm/allocator.c |  571
> ++++++++++++++++++++++++++++++++++++++++++
>    1 files changed, 571 insertions(+), 0 deletions(-)
>    create mode 100644 client/tests/kvm/allocator.c
>
> diff --git a/client/tests/kvm/allocator.c b/client/tests/kvm/allocator.c
> new file mode 100644
> index 0000000..89e8ce4
> --- /dev/null
> +++ b/client/tests/kvm/allocator.c
> @@ -0,0 +1,571 @@
> +/*
> + * KSM test program.
> + * Copyright(C) 2009 Redhat
> + * Jason Wang (jasowang@redhat.com)
> + */
> +
> +#include<sys/types.h>
> +#include<sys/stat.h>
> +#include<sys/mman.h>
> +#include<stdio.h>
> +#include<stdlib.h>
> +#include<unistd.h>
> +#include<fcntl.h>
> +#include<string.h>
> +#include<errno.h>
> +#include<syscall.h>
> +#include<time.h>
> +#include<stdint.h>
> +//socket linux
> +#include<sys/socket.h>
> +#include<arpa/inet.h>
> +#include<netinet/in.h>
> +#include<signal.h>
> +//TODO: socket windows
> +
> +
> +
> +#define PS (4096)
> +long PAGE_SIZE = PS;
> +long intInPage = PS/sizeof(int);
> +#define MAP_FLAGS ( MAP_ANON | MAP_SHARED )
> +#define PROT_FLAGS ( PROT_WRITE )
> +#define FILE_MODE ( O_RDWR | O_CREAT )
> +#define LOG_FILE "/var/log/vksmd"
> +#define FIFO_FILE "/tmp/vksmd"
> +#define MODE 0666
> +#define FILE_BASE "/tmp/ksm_file"
> +#define MAX_SIZESIZE 6
> +#define MAX_COMMANDSIZE 50
> +#define BLOCK_COUNT 8
> +
> +int log_fd = -1;
> +int base_fd = -1;
> +int checkvalue = 0;
> +
> +
> +//Socket
> +struct sockaddr_in sockName;
> +struct sockaddr_in clientInfo;
> +int mainSocket,clientSocket;
> +int port;
> +
> +socklen_t addrlen;
> +
> +
> +
> +
> +const uint32_t random_mask = UINT32_MAX>>1;
> +uint32_t random_x = 0;
> +const uint32_t random_a = 1103515245;
> +const uint32_t random_m = 2^32;
> +const uint32_t random_c = 12345;
> +
> +int statickey = 0;
> +int dynamickey = 0;
> +
> +typedef enum _COMMANDS
> +{
> +  wrongcommad,
> +  ninit,
> +  nrandom,
> +  nexit,
> +  nsrandom,
> +  nsrverify,
> +  nfillzero,
> +  nfillvalue,
> +  ndfill,
> +  nverify
> +} COMMANDS;
> +
> +void sigpipe (int param)
> +{
> +  fprintf(stderr,"write error\n");
> +  //exit(-1); //uncomment end if network connetion is down
> +}
> +
> +int writefull(int socket,char * data,int size){
> +  int sz = 0;
> +  while (sz<  size)
> +    sz += write(socket, data+sz, size-sz);
> +  return sz;
> +}
> +
> +
> +int write_message(int s,char * message){
> +  size_t len = strlen(message);
> +  char buf[10];
> +  sprintf(buf,"%d:",(unsigned int)len);
> +  size_t size = strlen(buf);
> +
> +  struct timeval tv;
> +  fd_set writeset;
> +  fd_set errorset;
> +  FD_ZERO(&writeset);
> +  FD_ZERO(&errorset);
> +  FD_SET(clientSocket,&writeset);
> +  FD_SET(clientSocket,&errorset);
> +  tv.tv_sec = 0;
> +  tv.tv_usec = 100;
> +  int max = s+1;
> +  tv.tv_sec = 10;
> +  tv.tv_usec = 0;
> +  int ret = select(max, NULL,&writeset, NULL,&tv);
> +  if (ret == -1)
> +  {
> +    return -1;
> +  }
> +  if (ret == 0)
> +  {
> +    return -1;
> +  }
> +  if (FD_ISSET(s,&writeset))
> +  {
> +    if (writefull(s, buf, size) != size){
> +      return -1;
> +    }
> +    if (writefull(s, message, len) != len){
> +      return -1;
> +    }
> +  }
> +  return 0;
> +}
> +
> +void log_info(char *str)
> +{
> +  if (write_message(clientSocket, str) != 0){
> +    fprintf(stderr,"write error\n");
> +  }
> +}
> +
> +/* fill pages with zero */
> +void zero_pages(void **page_array,int npages)
> +{
> +  int n = 0;
> +  for(n=0;n<npages;n++)
> +    memset(page_array[n],0,intInPage);
> +}
> +
> +/* fill pages with zero */
> +void value_to_pages(void **page_array,int npages,char value)
> +{
> +  int n = 0;
> +  for(n=0;n<npages;n++)
> +    memset(page_array[n],value,PAGE_SIZE/sizeof(char));
> +}
> +
> +/* initialise page_array */
> +void **map_zero_page(unsigned long npages)
> +{
> +  void **page_array=(void **)malloc(sizeof(void *)*npages);
> +  long n = 0;
> +
> +  if ( page_array == NULL ) {
> +    log_info("page array allocated failed\n");
> +    return NULL;
> +  }
> +
> +#if 0
> +  /* Map the /dev/zero in order to be detected by KSM */
> +  for( n=0 ; n<  npages; n++){
> +    int i;
> +    void *addr=(void *)mmap(0,PAGE_SIZE,PROT_FLAGS,MAP_FLAGS,0,0);
> +    if ( addr == MAP_FAILED ){
> +      log_info("map failed!\n");
> +      for (i=0;i<n;i++)
> +	munmap( page_array[i], 0);
> +      free(page_array);
> +      return NULL;
> +    }
> +
> +    page_array[n] = addr;
> +  }
> +#endif
> +
> + void *addr = (void *)mmap(0,PAGE_SIZE*npages,PROT_FLAGS,MAP_FLAGS,0,0);
> +  if (addr == MAP_FAILED){
> +    log_info("FAIL: map failed!\n");
> +    free(page_array);
> +    return NULL;
> +  }
> +
> +  for (n=0;n<npages;n++)
> +    page_array[n] = addr+PAGE_SIZE*n;
> +
> +  zero_pages(page_array,npages);
> +
> +  return page_array;
> +}
> +
> +/* fill page with random data */
> +void random_fill(void **page_array, unsigned long npages)
> +{
> +  int n = 0;
> +  int value = 0;
> +  int offset = 0;
> +  void *addr = NULL;
> +
> +  for( n = 0; n<  npages; n++){
> +    offset = rand() % (intInPage);
> +    value = rand();
> +    addr = page_array[n] + offset;
> +    *((int *)addr) = value;
> +  }
> +}
> +
> +
> +/*set random series seed*/
> +void mrseed(int seed){
> +  random_x = seed;
> +}
> +
> +/*Generate random number*/
> +int mrand(){
> +  random_x  = random_a*random_x+random_c;
> +  return random_x&  random_mask;
> +}
> +
> +/* Generate randomcode array*/
> +int* random_code_array(int nblock)
> +{
> +  int * randArray = malloc(PAGE_SIZE*nblock);
> +  int n = 0;
> +  for (;n<  nblock;n++){
> +    int i = 0;
> +    for (;i<  intInPage;i++){
> +      randArray[n*intInPage+i]=mrand();
> +    }
> +  }
> +  return randArray;
> +}
> +
> +/* fill page with static random series data*/
> +void static_random_fill(void **page_array, unsigned long npages,int nblock)
> +{
> +  mrseed(dynamickey);
> +  int* randomArray = random_code_array(nblock);
> +  int n = 0;
> +  int q = -1;
> +  int blocksize = npages/nblock;
> +  int offset = 0;
> +  void *addr = NULL;
> +
> +  mrseed(randomArray[0]);
> +  for (;n<  npages;n++){
> +    if (n%(blocksize) == 0) q++;
> +    memcpy(page_array[n],&randomArray[q*intInPage],PAGE_SIZE);
> +    offset = mrand() % (intInPage);
> +    addr = ((int *)page_array[n]) + offset;
> +    *((int *)addr) = n;
> +  }
> +  free(randomArray);
> +  return;
> +}
> +
> +/* fill page with static random series data*/
> +int static_random_verify(void **page_array, unsigned long npages,int
> nblock)
> +{
> +  int* p = malloc(PAGE_SIZE);
> +  mrseed(dynamickey);
> +  int* randomArray = random_code_array(nblock);
> +  int n = 0;
> +  int q = -1;
> +  int blocksize = npages/nblock;
> +  int offset = 0;
> +  void *addr = NULL;
> +  char buf[128];
> +
> +  int ret = 1;
> +
> +  mrseed(randomArray[0]);
> +  for (;n<  npages;n++){
> +    if (n%(blocksize) == 0) q++;
> +    memcpy(p,&randomArray[q*intInPage],PAGE_SIZE);
> +    offset = mrand() % (intInPage);
> +    p[offset] = n;
> +    addr = ((int*)page_array[n]) + offset;
> +    int r = memcmp(p,page_array[n],PAGE_SIZE);
> +    if (r != 0){
> +      for (r = 0;r<  intInPage;r++){
> +        addr = ((int *)page_array[n]) + r;
> +        if (*((int *)addr) != p[r]){
> +          sprintf(buf,"verify failed [0x%p] %d instead of
> %d\n",addr,*((int *)addr),n);
> +          log_info(buf);
> +          ret = 0;
> +        }
> +      }
> +    }
> +  }
> +  free(randomArray);
> +  free(p);
> +  return ret;
> +}
> +
> +
> +/* verify value */
> +int verify_address_space(void **page_array, unsigned long npages, int
> checkvalue)
> +{
> +  int m,n;
> +  char buf[128];
> +  sprintf(buf,"verify value = %d\n",checkvalue);
> +  log_info(buf);
> +  if ( checkvalue == -1 ){
> +    return 1;
> +  }
> +  for( n = 0; n<  npages; n++ ){
> +    for ( m = 0; m<  PAGE_SIZE ; m++ ){
> +      char *address = (char *)(page_array[n]+m);
> +      if (*address != checkvalue) {
> +	sprintf(buf,"verify failed [0x%p] %d instead of %d\n", address,
> *address, checkvalue);
> +	log_info(buf);
> +	return 0;
> +      }
> +    }
> +  }
> +  return 1;
> +}
> +
> +
> +/* Parse command from message*/
> +COMMANDS parse_command(const char* data,int size,const char** startOfData)
> +{
> +  char command[MAX_COMMANDSIZE];
> +  memset(command,0,MAX_COMMANDSIZE);
> +  COMMANDS retc;
> +  int i=0;
> +  for(;i<  MAX_COMMANDSIZE&&  data[i] != ':';i++){
> +    command[i] = data[i];
> +  }
> +  *startOfData =&data[i+1];
> +
> +  if (strcmp(command,"init") == 0){
> +    if ((size-i-1) == 7){
> +      retc = ninit;
> +    }
> +  }else if(strcmp(command,"random") == 0){
> +    retc = nrandom;
> +  }else if(strcmp(command,"srandom") == 0){
> +    retc = nsrandom;
> +  }else if(strcmp(command,"srverify") == 0){
> +    retc = nsrverify;
> +  }else if(strcmp(command,"fillzero") == 0){
> +    retc = nfillzero;
> +  }else if(strcmp(command,"fillvalue") == 0){
> +    retc = nfillvalue;
> +  }else if(strcmp(command,"verify") == 0){
> +      retc = nverify;
> +  }else if(strcmp(command,"exit") == 0){
> +    retc = nexit;
> +  }
> +  return retc;
> +}
> +
> +void daemon_loop(void **page_array, unsigned long npages, int socket)
> +{
> +  COMMANDS com = wrongcommad;
> +  char csize[MAX_SIZESIZE+1];  //size max
> +  memset(csize,0,MAX_SIZESIZE+1);
> +  int end = 0;
> +  while(!end){
> +
> +    /*Data
> +    size:xxx:xxx;
> +    */
> +
> +    //Read data size
> +    char * data;
> +    const char * startOfData = NULL;
> +
> +    int i = 0;
> +    for (;(i<= MAX_SIZESIZE)&&  (csize[i-1] != ':');i++){
> +      recv(socket,&csize[i],1,0);
> +    }
> +    if (i<= MAX_SIZESIZE) { //data is good
> +      int size = atoi(csize)-1;
> +      data = malloc(size*sizeof(char)+1);
> +      int sz = 0;
> +      while (sz<  size)
> +        sz += recv(socket,data+sz,size-sz,0);
> +      if (data[size-1] == ';'){//Decode data
> +        com = parse_command(data,size,&startOfData);
> +      }
> +    }
> +
> +    char buf[128];
> +    switch(com){
> +    case nfillzero: /* Zero all pages */
> +      log_info("into zero mapped mode\n");
> +      zero_pages(page_array, npages);
> +      checkvalue = 0;
> +      log_info("PASS: zero mapped mode\n");
> +      break;
> +    case nfillvalue: /* Zero all pages */
> +      log_info("fill value statickey\n");
> +      checkvalue = statickey;
> +      value_to_pages(page_array, npages, checkvalue);
> +      sprintf(buf,"PASS: filled by %c\n", statickey);
> +      log_info(buf);
> +      break;
> +    case nrandom: /* Fill all pages with random number */
> +      log_info("into random fill mode\n");
> +      random_fill(page_array, npages);
> +      checkvalue = -1;
> +      log_info("PASS: filled by random value\n");
> +      break;
> +    case nexit: /* Do exit */
> +      log_info("PASS: exit\n");
> +      end = 1;
> +      break;
> +    case nverify: /* verify */
> +      log_info("veriy value\n");
> +
> +      if (!verify_address_space(page_array,npages,checkvalue)){
> +	sprintf(buf,"value %d verify error\n",checkvalue);
> +	log_info(buf);
> +	sprintf(buf,"FAIL: verification with checkvalue = %x\n", checkvalue);
> +	log_info(buf);
> +      }else{
> +        sprintf(buf,"PASS: verification with checkvalue = %x\n",
> checkvalue);
> +        log_info(buf);
> +      }
> +      break;
> +    case nsrandom:/*Generate static random series*/
> +      log_info("fill static random series\n");
> +      clock_t starttime = clock();
> +      static_random_fill(page_array, npages,BLOCK_COUNT);
> +      clock_t endtime = clock();
> +      sprintf(buf,"PASS: filling duration = %ld
> ms\n",(long)(1.0*(endtime-starttime))/(CLOCKS_PER_SEC/1000));
> +      log_info(buf);
> +      break;
> +    case nsrverify: /* verify */
> +      log_info("veriy value\n");
> +
> +      if (!static_random_verify(page_array,npages,BLOCK_COUNT)){
> +        sprintf(buf,"value %d verify error\n",checkvalue);
> +        log_info(buf);
> +        log_info("FAIL: random series verification\n");
> +      }else{
> +        log_info("PASS: random series verification\n");
> +      }
> +      break;
> +    case ninit:/*Parametrs*/
> +      memset(buf,0,5);
> +      log_info("Init daemon\n");
> +      strncpy(buf,&startOfData[0],3);
> +      statickey = atoi(buf);
> +      strncpy(buf,&startOfData[3],3);
> +      dynamickey = atoi(buf);
> +      sprintf(buf,"PASS: Static key %d; Dynamic key
> %d\n",statickey,dynamickey);
> +      log_info(buf);
> +      break;
> +    default:
> +      log_info("FAIL: Wrong command!\n");
> +      exit(EBADMSG);
> +      break;
> +    }
> +    free(data);
> +  }
> +}
> +
> +int main(int argc,char *argv[])
> +{
> +  int n = 0;
> +  unsigned long npages = 0;
> +  int ret;
> +  void **page_array = NULL;
> +
> +
> +  void (*prev_fn)(int);
> +
> +  prev_fn = signal (SIGPIPE,sigpipe);
> +
> +
> +  if (argc != 3){
> +    fprintf(stderr,"Usage %s size(MB) port\n",argv[0]);
> +    return -1;
> +  }
> +
> +  port = atoi(argv[2]);
> +  // Vytvoříme soket - viz minulý díl
> +  if ((mainSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
> +  {
> +    fprintf(stderr,"Could not create socket!\n");
> +    return -1;
> +  }
> +
> +  sockName.sin_family = AF_INET;
> +  sockName.sin_port = htons(port);
> +  sockName.sin_addr.s_addr = INADDR_ANY;
> +
> +
> +  if (bind(mainSocket, (struct sockaddr *)&sockName, sizeof(sockName))
> == -1)
> +  {
> +    fprintf(stderr,"Could not bind socket!\n");
> +    return -1;
> +  }
> +
> +  if (listen(mainSocket, 1) == -1)
> +  {
> +    fprintf(stderr,"Could not listen socket!\n");
> +    return -1;
> +  }
> +
> +  unlink(FIFO_FILE);
> +  unlink(LOG_FILE);
> +  PAGE_SIZE = getpagesize();
> +  intInPage = PAGE_SIZE/sizeof(int);
> +  long page = atoi(argv[1]);
> +  npages = (page * 1024 * 1024)/PAGE_SIZE;
> +
> +  ret = daemon(0,0);
> +  if(ret == -1){
> +    log_info("FAIL: failed to run in daemon mode\n");
> +    return -1;
> +  }
> +
> +  addrlen = sizeof(clientInfo);
> +
> +  clientSocket = accept(mainSocket, (struct sockaddr*)&clientInfo,
> &addrlen);
> +  int set = 1;
> +  setsockopt(clientSocket, SOL_SOCKET, SO_KEEPALIVE, (void *)&set,
> sizeof(int));
> +  if (clientSocket == -1)
> +  {
> +    fprintf(stderr,"Could not connect client\n");
> +    return -1;
> +  }
> +
> +  log_info("Initialising zero mapped pages!\n");
> +  page_array = map_zero_page(npages);
> +  if (page_array == NULL){
> +    log_info("FAIL: could not initialise maps\n");
> +    return -1;
> +  }
> +  log_info("PASS: first start\n");
> +
> +  srand(getpid());
> +  daemon_loop(page_array, npages, clientSocket);
> +
> +
> +  log_info("Free page array\n");
> +  for(n=0;n<npages;n++){
> +    munmap(page_array[n],0);
> +  }
> +  free(page_array);
> +
> +  log_info("exit");
> +
> +  sleep(5);
> +
> +
> +  char ch;
> +  while (recv(clientSocket,&ch,1,0)>  0);
> +
> +  close(clientSocket);
> +  close(mainSocket);
> +
> +  if (prev_fn==SIG_IGN) signal (SIGTERM,SIG_IGN);
> +
> +  return 0;
> +}
> +
> +


  parent reply	other threads:[~2009-09-07 12:03 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-31  9:29 [KVM-AUTOTEST PATCH 0/2] Add KSM test Lukáš Doktor
2009-08-31  9:35 ` [KVM-AUTOTEST PATCH 1/2] " Lukáš Doktor
2009-09-01  8:49   ` Lukáš Doktor
2009-09-07 12:03   ` Dor Laor [this message]
2009-08-31  9:48 ` [KVM-AUTOTEST PATCH 2/2] " Lukáš Doktor
2009-09-01  8:50   ` Lukáš Doktor
2009-09-07 13:00   ` Dor Laor
2009-09-07 12:37 ` [KVM-AUTOTEST PATCH 0/2] " Uri Lublin
     [not found] <1785968988.186531253041095308.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
2009-09-15 18:58 ` [KVM-AUTOTEST PATCH 1/2] " Jiri Zupka
2009-09-16  8:56   ` Dor Laor
     [not found] <83259492.232221253106465155.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
2009-09-16 13:09 ` Jiri Zupka
2009-09-16 13:21   ` Dor Laor
     [not found] <830286859.775301253870289468.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
2009-09-25  9:22 ` Jiri Zupka
2009-09-29 15:50   ` Lucas Meneghel Rodrigues
2009-09-30 12:23     ` Dor Laor

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4AA4F6A8.5010609@redhat.com \
    --to=dlaor@redhat.com \
    --cc=autotest@test.kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=ldoktor@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).