Update of /cvsroot/ltp/ltp/testcases/network/nfsv4/locks In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv6395 Modified Files: Makefile locktests.c Added Files: DEPLOY README VERSION locktests locktests.h locktests.py netsync.c Log Message: A patch that addes new functionality into the NFSvf lock tests. -fixes bugs -adds the capability to stress a server with multiple clients --- NEW FILE: DEPLOY --- locktest.py script aims to help deploying and running locktests over multiple NFS clients accessing the same server. The source code of NFS client test is in ./deploy/locktests-2.tar.gz Setting up lock test with several test machines. ================================================ ./locktests.py --setup -c <machine1> [machine2 ...] -s <my_nfs_server>:</> --setup : Option to setup the test -c <machine> [...] : Setup test on these clients -s <server>:<mountpoint> : NFS server to use, followed by full directory to mount Example: ./locktests.py --setup -c client1 client2 client3 -s NFS_Server:/exported/directory Running lock test over several test machines. ============================================= Run test on already configured test machines. ./locktests.py -n <pid> -f <file> -c <machine1> [machine2 ...] -n <process_id> : Process number each test machine will lauch to perform the test -f <file> : Test file. That must be the same on each machine -c <machine> [...] : Clients. run tests from this clients Example: ./locktests.py -n 50 -f /mnt/nfsv4/testfile -c testmachine1 testmachine2 _________________________________ Vincent ROQUETA - Bull SA - 2005 vin...@ex... --- NEW FILE: locktests.py --- #!/usr/bin/python # This script aims to help to run locktests with several clients. # # Report bugs to Vincent ROQUETA : vin...@ex... import encodings import shutil import os, sys import getopt, sys import string import socket from stat import * from sys import * from os import * NFS4_PATH="/mnt/nfsv4" NFS4_SERVER="" TEST_HOME="/home/vincent/locks/" testfile=NFS4_PATH+"/testfile" app="locktests" SRC="locktests-2.tar.gz" SRC_PATH="deploy" install="'tar xzf "+SRC+"; cd locks; make `" user="root" class Machine: def mkdir(self,dir): self.command="mkdir -p "+dir self.do() def rmdir(self,dir): self.command="rm -rf "+dir self.do() def printc(self): print "->"+self.command print "\n" class Client(Machine): def __init__(self, machine): self.command="" self.machine=machine self.mountPath=NFS4_PATH def do(self): self.command="ssh "+user+"@"+self.machine+" "+self.command os.system(self.command) def isomount(self, dir): export=NFS4_SERVER mntpoint=NFS4_PATH self.command="'mkdir -p "+mntpoint+"; mount -t nfs4 "+export+" "+mntpoint+"'" self.do() def umount(self, dir): mntpoint=self.mountPath+"/"+dir self.command="umount "+mntpoint self.do() def install(self, path): self.command="'cd "+path+"; tar xzf "+SRC+"; cd locks; make'" self.do() def run(self, appli): self.command=appli self.do() def cp(self, fichier, path): command="scp "+fichier+" "+user+"@"+self.machine+":"+path os.system(command) class Serveur(Machine): def __init__(self, ip, exportPath): self.SERVEUR=ip self.exportPath=exportPath def do(self): self.command="ssh "+self.SERVEUR+" "+self.command os.system(self.command) def configure(self, dir): exportDir=self.exportPath+'/'+dir self. mkdir(exportDir) #self.printc() self.export(exportDir) #self.printc() def clean(self, dir): unexportDir=self.exportPath+'/'+dir self.unexport(unexportDir) self.rmdir(unexportDir) def usage(): print "\n" print "usage:" print "locktests.py <-n process -f testfile ><--setup -s fs_server> -c host1, host2, host3 ... " print "--setup : setup the configuration, deploy test on other test machines; This option also requires -c and -s" print "-c <machine> : host list to deploy/run/clean the test" print "-s <machine> : NFS server to use to setup the test" print "-n <num> : number of processes each test machine will lauch to perform the test" print "-f <file> : test file. This must be the same on each machine" print " " print "Example :" print "=========" print "*Setup machines for testing" print "./locktests.py --setup -c testmachine1 testmachine2 testmachine3 -s my_nfs_server:/" print "\n" print "*Run test on testmachine1,testmachine2 with 50 process on each machine using /mnt/nfsv4/testfile" print "./locktests.py -n 50 -f /mnt/nfsv4/testfile -c testmachine1 testmachine2" print "\n" print "_________________________________" print "Vincent ROQUETA - Bull SA - 2005\n" return 0 def setup(): path=os.path.abspath(".") fichier=SRC_PATH+"/"+SRC commande="" for i in clients: print "Setting up machine "+i c=Client(i) c.mkdir(path) c.cp(fichier, path) c.install(path) c.isomount(NFS4_PATH) #Setup localhost print "Setting up localhost" commande="make; mkdir -p "+NFS4_PATH+" ; mount -t nfs4 "+NFS4_SERVER+" "+NFS4_PATH+" &" os.system(commande) def run(): path=os.path.abspath(".") nbreClients=len(clients) hostname=socket.gethostname() # Lancement du serveur en local # Launch the server locally commande=path+"/"+app+" -n "+nbreProcess+" -f "+filename+" -c "+str(nbreClients)+" &" os.system(commande) commande=path+"/locks/"+app+" --server "+hostname for i in clients: c=Client(i) c.run(commande) def clean(): for i in clients: client.umount(NFS4_PATH) args=sys.argv[1:] rge=range(len(args)) a="" r=True s=False nfsServer=False c=False f=False n=False clients=[] for i in rge: if args[i] in ("--install", "-i", "--setup"): r=False s=True continue if args[i] in ("-s", "--server"): a="nfsServer" nfsServer=True continue if args[i] in ("-h", "--help"): usage() sys.exit(1) if args[i] in ("--clients", "-c"): a="clients" c=True continue if args[i] == "-n": a="nbre" n=True continue if args[i] == "-f": a="file" f=True continue if a=="clients": clients.append(args[i]) continue if a=="file": filename=args[i] continue if a=="nbre": nbreProcess=args[i] continue if a=="nfsServer": NFS4_SERVER=args[i] continue usage() # For ... if s: if (not c) or (not nfsServer): usage() sys.exit(1) print "Setup" print NFS4_SERVER setup() print "Setup complete" if r: if (not c) or (not f) or (not n): usage() sys.exit(1) print "Running test" run() Index: Makefile =================================================================== RCS file: /cvsroot/ltp/ltp/testcases/network/nfsv4/locks/Makefile,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Makefile 23 Feb 2006 00:35:45 -0000 1.6 --- Makefile 11 Sep 2006 20:40:52 -0000 1.7 *************** *** 1,12 **** ! TARGETS := locktests ! ! all: $(TARGETS) ! ! locktests: locktests.c ! $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lpthread ! ! install: $(TARGETS) ! ln -f locktests ../../../bin/locktests ! ! clean: ! $(RM) locktests --- 1,4 ---- ! All: ! gcc -Wall -o locktests locktests.c netsync.c ! clean : ! rm -f *.o;rm -f locktests Index: locktests.c =================================================================== RCS file: /cvsroot/ltp/ltp/testcases/network/nfsv4/locks/locktests.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** locktests.c 28 Nov 2005 14:18:34 -0000 1.2 --- locktests.c 11 Sep 2006 20:40:52 -0000 1.3 *************** *** 6,21 **** * RUN : ./locktests -n <number of concurent process> -f <test file> [-P] * ! * GOAL : This tests try to stress fcntl locking functions. A master process set a lock on a file region (byte range locking). ! * Some slaves process tries to perform operations on this region, like read, write, set a new lock ... Expected results of this ! * operations are known. If the operation result is the same as the expected one, the test sucess, else it fails. ! * ! * Slaves are concurent processes or thread. ! * -n : Number of thread is defined by the -n option (mandatory). ! * -f : The test is ran on a test file defined by the -f option (mandatory). ! * -P : Use pthreads instead of forked processes (optional). Result table is different. [...1647 lines suppressed...] + }else{ + maitreClient(); + free(dp.fname); + } + clean(); + return 0; } *************** *** 863,866 **** ! --- 1117,1120 ---- ! --- NEW FILE: VERSION --- * 08/02/06 copyediting (bryce) * 03/01/06 remove unicode and translate comments in english. * 21/12/05 free alocated memory before exiting --- NEW FILE: locktests --- (This appears to be a binary file; contents omitted.) --- NEW FILE: README --- COMPILE : make RUN LOCAL: ./locktests -n <number of concurent process> -f <test file> [-T] GOAL : This test is aimed at stressing the fcntl locking functions. A master process sets a lock on a file region (byte range locking). Several slave processes try to perform operations on this region, such as: read, write, set a new lock ... The expected results of these operations are known. If the operation's result is the same as the expected one, the test succeeds, otherwise it fails. HISTORY : This program was been written to stress NFSv4 locks. Slaves are concurrent processes or threads. -n <num> : Number of threads to use (mandatory). -f <file> : Run the test on a test file defined by the -f option (mandatory). -T : Use threads instead of processes (optional). * RUN NETWORK * Test server: ./locktests -n <number of concurent processes> -f <test file> -c <number of clients> Test clients: ./locktests --server <server host name> Multiple clients options _______________________ These options have been developed to test NFSv4 locking when multiple clients try to use the same file. It uses a test server and several test clients. -------------- | | | NFS SERVER | | | -------------- | | ----------------------------------------------- | | | | | | ------------------ ------------------- ------------------ | NFS Client 1 | | NFS Client 1 | | NFS Client 1 | | running | | running | | running | | a CLIENT TEST | | the SERVER TEST | | a CLIENT TEST | ------------------ ------------------- ------------------ See the DEPLOY file to know how to configure client test on each client. Server options are: -n <num> : Number of threads to use (mandatory). -f <file> : Run the test on given test file defined by the -f option (mandatory). -c <num> : Number of clients to connect before starting the tests. Client options ______________ --server <server hostname> * EXAMPLES * ============ Local testing: ./locktests -n 50 -f /file/system/to/test Multiple clients: -on the test server (called host1): ./locktest -n 50 -f /network/file/system/to/test -c 3 (Server waiting for 3 clients to be connected) -test clients: ./locktest --server host1 HOW TO UNDERSTAND TEST RESULTS ============================== Ten tests are performed: 1. WRITE ON A READ LOCK 2. WRITE ON A WRITE LOCK 3. READ ON A READ LOCK 4. READ ON A WRITE LOCK 5. SET A READ LOCK ON A READ LOCK 6. SET A WRITE LOCK ON A WRITE LOCK 7. SET A WRITE LOCK ON A READ LOCK 8. SET A READ LOCK ON A WRITE LOCK 9. READ LOCK THE WHOLE FILE BYTE BY BYTE 10. WRITE LOCK THE WHOLE FILE BYTE BY BYTE For each test, the MASTER process takes a lock (READ/WRITE LOCK) and the SLAVE processes try to perform the following operations on the locked section: - WRITE - READ - SET A WRITE LOCK - SET A WRITE LOCK If a slave process performs its test operation without error it prints "=", otherwise it prints "x". An operation performed "without error" means: - The operation (write, read, fcntl ...) returns no error code, and - errno is not changed. However, "the slave performs its test operation without error" does NOT mean the "result is correct". For example, a slave process is NOT allowed to set a READ LOCK on an already-set WRITE LOCK. When such operations are performed, the correct and expected result is that the tested function returns the EAGAIN error code. When all tests have been processed, the result of each process for each test is compared with the table of expected results, and a new table is displayed: For example: 200 processes of 200 successfully ran test : READ ON A READ LOCK 200 processes of 200 successfully ran test : SET A READ LOCK ON A WRITE LOCK This result lists the process/thread both on local and remote machines. Note that the testing locks with thread on multiple clients is disabled because it does not make sense: 2 different clients obviously run at least 2 different processes (thread information cannot be shared between this thread over the network). EXPECTED RESULTS ================ Here is the table of expected results, depending on : - Slave test operations (READ, WRITE, SET A WRITE LOCK ... ) - Master Operation (SET A READ/A WRITE LOCK ) - Slave types (Processes, threads) - Locking profile (POSIX locking, Mandatory locking) ================================================================================================ | Master process/thread | ===================================|===========================================================| Slave type | Test operation | advisory locking | mandatory locking | ___________________________________|______________________________|____________________________| | | read lock write lock | read lock write lock | ___________________________________|______________________________|____________________________| thread | set a read lock | Allowed Allowed | Allowed Allowed | | set a write lock | Allowed Allowed | Allowed Allowed | | read | Allowed Allowed | Allowed Allowed | | write | Allowed Allowed | Allowed Allowed | ===================================+==============================+============================| process | set a read lock | Allowed Denied | Allowed Denied | | set a write lock | Denied Denied | Denied Denied | | read | Allowed Allowed | Denied Allowed | | write | Allowed Allowed | Denied Denied | ================================================================================================ ************** Bull SA - 2006 - http://nfsv4.bullopensource.org Tony Reix: ton...@bu... Aurélien Charbon: aurelien.charbon@ext bull.net ************** --- NEW FILE: locktests.h --- /* ************************************************* * *********** README ****************************** * ************************************************* * * COMPILE : make * RUN : ./locktests -n <number of concurent process> -f <test file> [-P] * * GOAL : This test tries to stress the fcntl locking functions. A * master process sets a lock on a file region (this is called "byte * range locking"). Some slave processes try to perform operations on * this region, such as read, write, set a new lock ... The expected * results of these operations are known. If the operation's result is * the same as the expected one, the test suceeds, else it fails. * * Slaves are either concurent processes or threads. * -n <num> : Number of threads to use (mandatory). * -f <file> : Run the test on a test file defined by the -f option (mandatory). * -T : Use threads instead of processes (optional). * * HISTORY : This program has been written to stress NFSv4 locks. -P * option was created to verify NFSv4 locking was thread-aware, and so, * locking behaviour over NFSv4 was POSIX correct both using threads and * process. This option may not be usefull to stress. * * EXAMPLE : ./locktests -n 50 -f /file/system/to/test * * * Vincent ROQUETA 2005 - vin...@ex... * BULL S.A. */ #include <stdio.h> #include <stdlib.h> #include <stdlib.h> #include <signal.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <math.h> #ifdef STDARG #include <stdarg.h> #endif #include <sys/types.h> #include <sys/wait.h> #include <sys/param.h> #include <sys/times.h> #ifdef MMAP #include <sys/mman.h> #endif #include <inttypes.h> #include <pthread.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/select.h> #ifdef O_SYNC #define OPENFLAGS (O_CREAT | O_RDWR | O_SYNC ) #else #define OPENFLAGS (O_CREAT | O_RDWR ) #endif #define OPENMODES (0600) #define MANDMODES (0600) /*(02666)*/ #define SUCCES 1 #define ECHEC 0 #define TRUE 1 #define FALSE 0 #define PROCESS 0 #define THREAD 1 //#define DEBUG #ifdef DEBUG #define E(a) perror(a) #define P(a,b) printf(a,b) #else #define E(a) #define P(a,b) #endif #ifndef LOCKTESTS_H #define LOCKTESTS_H #define M_SIZE 512 int writeToAllClients(char *foo);//#define DEBUG int serverReceiveNet(); int clientReceiveNet(); int serverReceiveClient(int n); int setupClients(int type, char *fname, int nThread); int serverCloseConnection(); int getConfiguration(int *type, char *fname, int *nThread); int readFromServer(char *message); int serverSendClient(int n); enum etat_t { CLEAN, RDONLY, RESULTAT, WRONLY, SELECT, LOCK, SYNC, FIN, READLOCK, WRITELOCK, BYTELOCK, BYTELOCK_READ, BYTELOCK_WRITE }; /* Donnees communes aà tous les processu */ /* Public data */ struct donneesPub { /* Nombre de clients */ /* Number of clients */ int nclnt; /* Liste des clients (liste des tubes)*/ /* List of master to slave pipes */ int **lclnt; /* Tube de communication avec le maitre */ /* Slave to master pipe */ int maitre[2]; /* Liste des threads */ /* Thread list */ pthread_t *lthreads; /* nom du fichier test */ /* test file name */ char *fname; /* descripteur du fichier test */ /* test file file-descriptor */ int fd; /* Affichage des messages d'erreur */ /* Detailed error messages */ int verbose; }; /* Donnees privees aux processus */ /* private data */ struct donneesPriv { /* Numero de thread. */ /* thread number */ int whoami; }; struct donneesFils{ struct donneesPub *dp; struct donneesPriv *dpr; }; struct s_test { int test; int type; char *nom; int resAtt; }; int configureServeur(int max); int configureClient(char *s); #endif --- NEW FILE: netsync.c --- #include "locktests.h" #include <netdb.h> #include <string.h> #define PORT 12346 #define MAX_CONNECTION 16 int maxClients; int *fdClient; char *serveur; int fdServeur; extern char message[M_SIZE]; int serverReceiveClient(int c){ char tmp[M_SIZE]; int r,s; /* Il faut etre sur que l'on lit _exactement_ la trame envoyee (M_SIZE) */ /* Ensure we read _exactly_ M_SIZE characters in the message */ memset(message,0,M_SIZE); memset(tmp,0,M_SIZE); r=0; s=0; while(s<M_SIZE){ r=read(fdClient[c],tmp, M_SIZE-s); /* On complete le message au fur et a mesure */ /* Loop until we have a complete message */ strncpy(message+s,tmp,r); s+=r; } return s; } int serverSendClient(int n){ return write(fdClient[n],message, M_SIZE); } int clientReceiveNet(){ readFromServer(message); return 0; } int setupConnectionServeur(){ struct sockaddr_in local; int size,c; int sock; struct sockaddr_in remote; if((sock = socket (AF_INET, SOCK_STREAM, 0))<0){ perror ("socket"); exit(1); } bzero(&local, sizeof(local)); local.sin_family = AF_INET; local.sin_port = htons(PORT); local.sin_addr.s_addr = INADDR_ANY; bzero(&(local.sin_zero), 8); if(bind(sock, (struct sockaddr *)&local, sizeof(struct sockaddr))== -1){ perror("bind"); exit(1); } if(listen(sock, MAX_CONNECTION) == -1){ perror("listen"); return 1; } size = sizeof(struct sockaddr_in); for(c=0;c<maxClients; c++){ /* On accepte les connections clientes */ /* Accept incoming connections */ if((fdClient[c]=accept(sock, (struct sockaddr *)&remote, &size)) == -1){ perror("accept"); return 1; } } return 0; } int writeToClient(int c, char *message){ return write(fdClient[c], message, 512); } int serverCloseConnection(){ int c; for(c=0;c<maxClients;c++) close(fdClient[c]); return 0; } int writeToAllClients(char *foo){ int c; for(c=0;c<maxClients;c++) writeToClient(c, foo); return 0; } int setupClients(int type, char *fname, int nThread){ /* * Envoi des parametres a tous les clients * * on doit envoyer 3 parametres : * - l'emplacement du fichier test * - Le nombre d'esclaves * - Le type de sous processus : thread ou process */ /* * Send parameters to all slaves : * * We must send : * - the position of the test file * - the number of slaves for each client * - The kind of slaves : process or thread */ char message[512]; sprintf(message,"%d:%s:%d::", type,fname,nThread); writeToAllClients(message); return 0; } int configureServeur(int max){ maxClients=max; fdClient=(int *)malloc(sizeof(int)*max); setupConnectionServeur(); return 0; } int setupConnectionClient(){ struct hostent *server; struct sockaddr_in serv_addr; if (! (server=gethostbyname(serveur))){ printf("erreur DNS\n"); return 1; } fdServeur = socket (AF_INET, SOCK_STREAM, 0); if (fdServeur < 0){ perror ("socket"); return 1; } serv_addr.sin_addr = *(struct in_addr*)server->h_addr; serv_addr.sin_port = htons(PORT); serv_addr.sin_family = AF_INET; if (connect(fdServeur, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){ perror("connect"); return 1; } return 0; } int readFromServer(char *message){ char tmp[M_SIZE]; int r,s; /* Il faut etre sur que l'on lit _exactement_ la trame envoyee de taille M_SIZE */ /* Ensure we read exactly M_SIZE characters */ memset(message,0,M_SIZE); memset(tmp,0,M_SIZE); r=0; s=0; while(s<M_SIZE){ r=read(fdServeur,tmp, M_SIZE-s); /* On complete le message au fur et a mesure */ /* Loop until we have a complete message */ strncpy(message+s,tmp,r); s+=r; } return s; } int getConfiguration(int *type, char *fname, int *nThread){ char conf[M_SIZE]; char *p; int i; readFromServer(conf); p=strtok(conf,":"); printf("%s\n",p); *type=atoi(p); p=strtok(NULL,":"); i=strlen(p); strncpy(fname, p,i); p=strtok(NULL,":"); *nThread=atoi(p); return 0; } int configureClient(char *s){ serveur=s; setupConnectionClient(); return 0; } |