From 7df31cb494a0cec411e08e22ee2ae837dff06807 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Jun 2000 13:53:56 +0000 Subject: added locktest2 this uses 16 open file descriptors on 2 servers, with each server accessed both via POSIX call and SMB calls. The idea is to test NFS/SMB locking interaction. Unfortunately the NT NFS locking implementation is so badly broken that we don't have anything to test against (This used to be commit 581498fe6b2efe44c1229dd12b9a6506b11747d0) --- source3/Makefile.in | 10 + source3/utils/locktest2.c | 626 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 636 insertions(+) create mode 100644 source3/utils/locktest2.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index f972085402..561d5781ea 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -273,6 +273,10 @@ MASKTEST_OBJ = utils/masktest.o $(LIBSMB_OBJ) $(PARAM_OBJ) \ LOCKTEST_OBJ = utils/locktest.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \ $(UBIQX_OBJ) $(LIB_OBJ) + +LOCKTEST2_OBJ = utils/locktest2.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \ + $(UBIQX_OBJ) $(LIB_OBJ) + RPCTORTURE_OBJ = utils/rpctorture.o \ rpcclient/display.o \ rpcclient/cmd_lsarpc.o \ @@ -331,6 +335,8 @@ masktest : CHECK bin/masktest locktest : CHECK bin/locktest +locktest2 : CHECK bin/locktest2 + rpctorture : CHECK bin/rpctorture debug2html : CHECK bin/debug2html @@ -505,6 +511,10 @@ bin/locktest: $(LOCKTEST_OBJ) bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(LIBS) +bin/locktest2: $(LOCKTEST2_OBJ) bin/.dummy + @echo Linking $@ + @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(LIBS) + bin/rpctorture: $(RPCTORTURE_OBJ) bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(RPCTORTURE_OBJ) $(LDFLAGS) $(LIBS) diff --git a/source3/utils/locktest2.c b/source3/utils/locktest2.c new file mode 100644 index 0000000000..36b32d6460 --- /dev/null +++ b/source3/utils/locktest2.c @@ -0,0 +1,626 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + byte range lock tester - with local filesystem support + Copyright (C) Andrew Tridgell 1999 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define NO_SYSLOG + +#include "includes.h" + +static fstring password; +static fstring username; +static int got_pass; +static int numops = 1000; +static BOOL showall; +static BOOL analyze; +static BOOL hide_unlock_fails; +static BOOL use_oplocks; + +#define FILENAME "\\locktest.dat" +#define LOCKRANGE 100 +#define LOCKBASE 0 + +/* +#define LOCKBASE (0x40000000 - 50) +*/ + +#define READ_PCT 50 +#define LOCK_PCT 25 +#define UNLOCK_PCT 65 +#define RANGE_MULTIPLE 1 + +#define NSERVERS 2 +#define NCONNECTIONS 2 +#define NUMFSTYPES 2 +#define NFILES 2 +#define LOCK_TIMEOUT 0 + +#define FSTYPE_SMB 0 +#define FSTYPE_NFS 1 + +struct record { + char r1, r2; + char conn, f, fstype; + unsigned start, len; + char needed; +}; + +static struct record *recorded; + +static int try_open(struct cli_state *c, char *nfs, int fstype, char *fname, int flags) +{ + pstring path; + + switch (fstype) { + case FSTYPE_SMB: + return cli_open(c, fname, flags, DENY_NONE); + + case FSTYPE_NFS: + slprintf(path, sizeof(path), "%s%s", nfs, fname); + pstring_sub(path,"\\", "/"); + return open(path, flags, 0666); + } + + return -1; +} + +static BOOL try_close(struct cli_state *c, int fstype, int fd) +{ + switch (fstype) { + case FSTYPE_SMB: + return cli_close(c, fd); + + case FSTYPE_NFS: + return close(fd) == 0; + } + + return False; +} + +static BOOL try_lock(struct cli_state *c, int fstype, + int fd, unsigned start, unsigned len, + int op) +{ + struct flock lock; + + switch (fstype) { + case FSTYPE_SMB: + return cli_lock(c, fd, start, len, LOCK_TIMEOUT, op); + + case FSTYPE_NFS: + lock.l_type = (op==READ_LOCK) ? F_RDLCK:F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = start; + lock.l_len = len; + lock.l_pid = getpid(); + return fcntl(fd,F_SETLK,&lock) == 0; + } + + return False; +} + +static BOOL try_unlock(struct cli_state *c, int fstype, + int fd, unsigned start, unsigned len) +{ + struct flock lock; + + switch (fstype) { + case FSTYPE_SMB: + return cli_unlock(c, fd, start, len); + + case FSTYPE_NFS: + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = start; + lock.l_len = len; + lock.l_pid = getpid(); + return fcntl(fd,F_SETLK,&lock) == 0; + } + + return False; +} + +static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, int pid, + enum brl_type lock_type, + br_off start, br_off size) +{ + printf("%6d %05x:%05x %s %.0f:%.0f(%.0f)\n", + (int)pid, (int)dev, (int)ino, + lock_type==READ_LOCK?"R":"W", + (double)start, (double)start+size-1,(double)size); + +} + +/***************************************************** +return a connection to a server +*******************************************************/ +struct cli_state *connect_one(char *share) +{ + struct cli_state *c; + struct nmb_name called, calling; + char *server_n; + fstring server; + struct in_addr ip; + extern struct in_addr ipzero; + fstring myname; + static int count; + + fstrcpy(server,share+2); + share = strchr(server,'\\'); + if (!share) return NULL; + *share = 0; + share++; + + server_n = server; + + ip = ipzero; + + slprintf(myname,sizeof(myname), "lock-%u-%u", getpid(), count++); + + make_nmb_name(&calling, myname, 0x0); + make_nmb_name(&called , server, 0x20); + + again: + ip = ipzero; + + /* have to open a new connection */ + if (!(c=cli_initialise(NULL)) || (cli_set_port(c, 139) == 0) || + !cli_connect(c, server_n, &ip)) { + DEBUG(0,("Connection to %s failed\n", server_n)); + return NULL; + } + + if (!cli_session_request(c, &calling, &called)) { + DEBUG(0,("session request to %s failed\n", called.name)); + cli_shutdown(c); + if (strcmp(called.name, "*SMBSERVER")) { + make_nmb_name(&called , "*SMBSERVER", 0x20); + goto again; + } + return NULL; + } + + DEBUG(4,(" session request ok\n")); + + if (!cli_negprot(c)) { + DEBUG(0,("protocol negotiation failed\n")); + cli_shutdown(c); + return NULL; + } + + if (!got_pass) { + char *pass = getpass("Password: "); + if (pass) { + pstrcpy(password, pass); + } + } + + if (!cli_session_setup(c, username, + password, strlen(password), + password, strlen(password), + lp_workgroup())) { + DEBUG(0,("session setup failed: %s\n", cli_errstr(c))); + return NULL; + } + + /* + * These next two lines are needed to emulate + * old client behaviour for people who have + * scripts based on client output. + * QUESTION ? Do we want to have a 'client compatibility + * mode to turn these on/off ? JRA. + */ + + if (*c->server_domain || *c->server_os || *c->server_type) + DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n", + c->server_domain,c->server_os,c->server_type)); + + DEBUG(4,(" session setup ok\n")); + + if (!cli_send_tconX(c, share, "?????", + password, strlen(password)+1)) { + DEBUG(0,("tree connect failed: %s\n", cli_errstr(c))); + cli_shutdown(c); + return NULL; + } + + DEBUG(4,(" tconx ok\n")); + + c->use_oplocks = use_oplocks; + + return c; +} + + +static void reconnect(struct cli_state *cli[NSERVERS][NCONNECTIONS], + char *nfs[NSERVERS], + int fnum[NSERVERS][NUMFSTYPES][NCONNECTIONS][NFILES], + char *share1, char *share2) +{ + int server, conn, f, fstype; + char *share[2]; + share[0] = share1; + share[1] = share2; + + fstype = FSTYPE_SMB; + + for (server=0;serverconn; + unsigned f = rec->f; + unsigned fstype = rec->fstype; + unsigned start = rec->start; + unsigned len = rec->len; + unsigned r1 = rec->r1; + unsigned r2 = rec->r2; + unsigned op; + int server; + BOOL ret[NSERVERS]; + + if (r1 < READ_PCT) { + op = READ_LOCK; + } else { + op = WRITE_LOCK; + } + + if (r2 < LOCK_PCT) { + /* set a lock */ + for (server=0;server %u:%u\n", + conn, fstype, f, + start, start+len-1, len, + op==READ_LOCK?"READ_LOCK":"WRITE_LOCK", + ret[0], ret[1]); + } + if (showall) brl_forall(print_brl); + if (ret[0] != ret[1]) return False; + } else if (r2 < LOCK_PCT+UNLOCK_PCT) { + /* unset a lock */ + for (server=0;server %u:%u\n", + conn, fstype, f, + start, start+len-1, len, + ret[0], ret[1]); + } + if (showall) brl_forall(print_brl); + if (!hide_unlock_fails && ret[0] != ret[1]) return False; + } else { + /* reopen the file */ + for (server=0;server