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 ([email protected]) + */ + +#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; +} + +
I'm sorry but thunderbird apparently crippled the path. Resending as the
attachment.
- [KVM-AUTOTEST PATCH 0/2] Add KSM test Lukáš Doktor
- Re: [KVM-AUTOTEST PATCH 1/2] Add KSM test Lukáš Doktor
- Re: [KVM-AUTOTEST PATCH 1/2] Add KSM test Lukáš Doktor
- Re: [KVM-AUTOTEST PATCH 1/2] Add KSM test Dor Laor
- Re: [KVM-AUTOTEST PATCH 2/2] Add KSM test Lukáš Doktor
- Re: [KVM-AUTOTEST PATCH 2/2] Add KSM test Lukáš Doktor
- Re: [KVM-AUTOTEST PATCH 2/2] Add KSM test Dor Laor
- Re: [KVM-AUTOTEST PATCH 0/2] Add KSM test Uri Lublin
