./ChangeLog 2014-08-21 Svante Signell * Makefile: Add sub-directory libfshelp-tests. libfshelp-tests/ChangeLog 2014-08-21 Svante Signell * Makefile: Link with pthread, add build of checklock * define temporary CPP_FLAGS until glibc is updated * checklock.c: New file. * Fix typos in README 2001-04-11 Neal H Walfield * ChangeLog: New file, mentioning itself in this sentence. * Makefile: New file. * README: Likewise. * fork.c: Likewise. * locks: Likewise. * locks-tests: Likewise. * locks.c: Likewise. * race.c: Likewise. Index: hurd-0.5.git20141210/Makefile =================================================================== --- hurd-0.5.git20141210.orig/Makefile +++ hurd-0.5.git20141210/Makefile @@ -37,7 +37,7 @@ prog-subdirs = auth proc exec term \ storeio pflocal pfinet defpager mach-defpager \ login daemons boot console \ hostmux usermux ftpfs trans \ - console-client utils sutils \ + console-client utils sutils libfshelp-tests \ benchmarks fstests \ random \ procfs \ Index: hurd-0.5.git20141210/libfshelp-tests/Makefile =================================================================== --- /dev/null +++ hurd-0.5.git20141210/libfshelp-tests/Makefile @@ -0,0 +1,47 @@ +# Makefile libfshelp test cases +# +# Copyright (C) 2001 Free Software Foundation, Inc. +# +# 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, 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. + +dir := libfshelp-tests +makemode := utilities + +targets = race locks fork checklock +SRCS = race.c locks.c fork.c checklock.c + +MIGSTUBS = fsUser.o ioUser.o +OBJS = $(SRCS:.c=.o) $(MIGSTUBS) +HURDLIBS = fshelp ports +LDLIBS += -lpthread + +race: race.o fsUser.o ioUser.o +fork: fork.o fsUser.o +locks: locks.o +checklock: checklock.o fsUser.o + +race locks: ../libfshelp/libfshelp.a ../libports/libports.a \ + ../libthreads/libthreads.a + +# Define the 64 bit versions of the second argument to fcntl() +# Can safely be removed when glibc is updated +EXTRA_CPP_FLAGS= -DF_GETLK64=10 -DF_SETLK64=11 -DF_SETLKW64=12 +fork-CPPFLAGS += $(EXTRA_CPP_FLAGS) +locks-CPPFLAGS += $(EXTRA_CPP_FLAGS) +race-CPPFLAGS += $(EXTRA_CPP_FLAGS) +checklock-CPPFLAGS += $(EXTRA_CPP_FLAGS) + +include ../Makeconf + Index: hurd-0.5.git20141210/libfshelp-tests/README =================================================================== --- /dev/null +++ hurd-0.5.git20141210/libfshelp-tests/README @@ -0,0 +1,102 @@ +These programs are used to help test the algorithms in the libfshelp +library. + +Record Locking +============== + +Race +---- + +Race locks a file, reads an integer, increments it, writes the result to +the file and then unlocks the file -- 10,000 times. It is intended that +multiple instances of this program be run at the same time. Race takes +three arguments: the file to use, the start of the lock and the length. +For obvious reasons, it is important that all instances of race have +locks that overlap. For example: + + # rm -f foo && ( ./race foo 2 0 & ./race foo 2 3 & \ + > ./race foo 0 3 ) + Was blocked 5482 times + Was blocked 5485 times + Was blocked 5479 times + # cat foo + 30000 + +We see here that each process was blocked several thousand times and that +the result in the file foo is 30000. Perfect. + +Locks +----- + +Locks is an interactive shell that has one ``file'' and ten open file +descriptors. Using some simple commands, one can test to see if locks +are established, cleared, and enforced. The principal command is +`lock,' which takes four parameters. The first is the file descriptor +to lock, the second is the start of the lock, the third is the length of +the lock (0 = until EOF) and the last is the type of lock to establish +from the set {0: F_UNLCK, 1: F_RDLCK, 2: F_WRLCK}. Help on the other +commands can be gotten using the `help' command. + +A small run: + + # ./locks + > lock 0 10 0 1 + 0: Start = 10; Length = 0; Type = F_RDLCK + +Lock from byte 10 through the EOF. + + > lock 0 20 0 0 + 0: Start = 10; Length = 10; Type = F_RDLCK + +Unlock from byte 20 through the EOF. + + > lock 0 11 8 2 + 0: Start = 10; Length = 1; Type = F_RDLCK + Start = 11; Length = 8; Type = F_WRLCK + Start = 19; Length = 1; Type = F_RDLCK + +Upgrade bytes 11 through 19 to a write lock. + + > lock 0 9 10 1 + 0: Start = 9; Length = 2; Type = F_RDLCK + Start = 11; Length = 8; Type = F_WRLCK + Start = 19; Length = 1; Type = F_RDLCK + +Add a read lock to byte 9. + + > lock 1 0 10 1 + 1: Start = 0; Length = 10; Type = F_RDLCK + +Read lock the first ten bytes of the file through file descriptor 1. + + > lock 1 10 0 1 + Resource temporarily unavailable + +Attempts to read lock the rest of the file. This, however, fails as +there are outstanding write locks held through file descriptor 1. + + > lock 1 10 0 0 + 1: Start = 0; Length = 10; Type = F_RDLCK + +What happens when file descriptor tries to unlock the blocked range? + + > lock 1 10 0 2 + Resource temporarily unavailable + +Nothing. + +A bunch of tests live in locks-tests. One can run them through the test +program using: `./locks < ./locks-test 2>&1 | less'. If it core dumps or +triggers an assertion, that is a bug. Report it. + +Fork +---- + +Tests to see if the a child inherits the locks across a fork. According +to POSIX, the child should not. + + # ./fork foo + Parent has a write lock; Others have a write lock. + Child has a write lock; Others have a write lock. + +We are not POSIX compliant. Index: hurd-0.5.git20141210/libfshelp-tests/fork.c =================================================================== --- /dev/null +++ hurd-0.5.git20141210/libfshelp-tests/fork.c @@ -0,0 +1,79 @@ +/* Test is a process inherits locks after a fork. + Copyright (C) 2001 Free Software Foundation, Inc. + + Written by Neal H Walfield + + 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, 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. */ + +#include +#include +#include +#include +#include +#include +#include "fs_U.h" +#include + +char *lock2str (int type) +{ + if (type & LOCK_SH) + return "read"; + if (type & LOCK_EX) + return "write"; + if (type & LOCK_UN) + return "unlocked"; + assert (! "Invalid"); + return NULL; +} + +int main (int argc, char **argv) +{ + error_t err; + struct flock64 lock; + int fd; + pid_t pid; + int mine, others; + + if (argc != 2) + error (1, 0, "Usage: %s file", argv[0]); + + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_type = F_WRLCK; + + fd = file_name_lookup (argv[1], O_READ | O_WRITE | O_CREAT, 0666); + if (fd == MACH_PORT_NULL) + error (1, errno, "file_name_lookup"); + + err = file_record_lock (fd, F_SETLK64, &lock); + if (err) + error (1, err, "file_record_lock"); + + pid = fork (); + if (pid == -1) + error (1, errno, "fork"); + + err = file_lock_stat (fd, &mine, &others); + if (err) + error (1, err, "file_lock_stat"); + + printf ("%s has a %s lock; Others have a %s lock.\n", + pid ? "Parent" : "Child", lock2str (mine), lock2str (others)); + + mach_port_deallocate (mach_task_self (), fd); + + return 0; +} Index: hurd-0.5.git20141210/libfshelp-tests/locks.c =================================================================== --- /dev/null +++ hurd-0.5.git20141210/libfshelp-tests/locks.c @@ -0,0 +1,327 @@ +/* Test record locking. + Copyright (C) 2001 Free Software Foundation, Inc. + + Written by Neal H Walfield + + 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, 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. */ + +#include "../libfshelp/fshelp.h" +#include "../libfshelp/rlock.h" +#include +#include +#include +#include + +#include "fs_U.h" + +#ifndef PEROPENS +#define PEROPENS 10 +#endif + +struct rlock_box box; +struct rlock_peropen peropens[PEROPENS]; +loff_t pointers[PEROPENS]; +loff_t file_size; + +struct command +{ + char *name; + int (*func)(char *cmds); + char *doc; +}; + +error_t cmd_help (char *); +error_t cmd_comment (char *); +error_t cmd_echo (char *); +error_t cmd_lock (char *); +error_t cmd_list (char *); +error_t cmd_seek (char *); +error_t cmd_exec (char *); + +struct command commands [] = + { + { "help", cmd_help, "Print this screen" }, + { "#", cmd_comment, "Comment (Must _start_ the line)." }, + { "echo", cmd_echo, "Echo the line." }, + { "lock", cmd_lock, + "po start length type\n" + "\ttype = { F_UNLCK=0, F_RDLCK,=1, F_WRLCK=2 }" }, + { "list", cmd_list, "list all locks' status" }, + { "seek", cmd_seek, "PO1 ... Print the position of the given po.\n" + "\tPO1=N ... Seek a given po." }, + { "exec", cmd_exec, "Execute a built in echoing the command."} + }; + +error_t +cmd_help (char *args) +{ + int i; + printf ("Commands:\n"); + for (i = 0; i < sizeof (commands) / sizeof (struct command); i ++) + printf ("%s\t%s\n", commands[i].name, commands[i].doc); + return 0; +} + +error_t +cmd_comment (char *args) +{ + return 0; +} + +error_t +cmd_echo (char *args) +{ + printf ("%s", args); + return 0; +} + +error_t +cmd_lock (char *args) +{ + int po, type; + loff_t start, len; + struct flock64 lock; + error_t err; + + if (4 != sscanf (args, "%d %ld %ld %d", &po, (long*)&start, (long*)&len, &type)) + { + printf ("Syntax error.\n"); + return 0; + } + + lock.l_type = type; + lock.l_whence = SEEK_CUR; + lock.l_start = (long)start; + lock.l_len = (long)len; + + if (po < 0 || po >= PEROPENS) + { + printf ("Unknown peropen: %d.\n", po); + return 0; + } + + switch (type) + { + case 0: lock.l_type = F_UNLCK; break; + case 1: lock.l_type = F_RDLCK; break; + case 2: lock.l_type = F_WRLCK; break; + default: printf ("Unknown type.\n"); return 0; + } + + err= fshelp_rlock_tweak (&box, NULL, &peropens[po], O_RDWR, + file_size, pointers[po], F_SETLK64, + &lock); + if (! err) + { + char buf[10]; + sprintf (buf, "%d\n", po); + cmd_list (buf); + } + return err; +} + +error_t +cmd_list (char *args) +{ + char *end; + + void dump (int i) + { + struct rlock_list *l; + + printf ("%3d:", i); + for (l = *peropens[i].locks; l; l = l->po.next) + { + printf ("\tStart = %4ld; Length = %4ld; Type = ", (long)l->start, (long)l->len); + switch (l->type) + { + case F_RDLCK: printf ("F_RDLCK"); break; + case F_WRLCK: printf ("F_WRLCK"); break; + case F_UNLCK: printf ("F_UNLCK"); break; + default: printf ("UNKNOWN"); break; + } + printf ("\n"); + } + + if (*peropens[i].locks == NULL) + printf ("\n"); + } + + while (*args == ' ') + args ++; + + if (*args == '\n' || *args == '\0') + { + int i; + + for (i = 0; i < PEROPENS; i ++) + dump (i); + return 0; + } + + while (1) + { + long int p = strtoll (args, &end, 0); + if (end == args) + { + printf ("Syntax error.\n"); + return 0; + } + + if (p < 0 || p > PEROPENS) + printf ("%3ld:\tOut of range.", p); + else + dump (p); + + while (*end == ' ') + end ++; + + if (*end == '\n' || *end == '\0') + return 0; + args = end; + } +} + +error_t +cmd_seek (char *args) +{ + char *end; + int p; + + while (*args == ' ') + args ++; + + if (*args == '\n' || *args == '\0') + { + int i; + for (i = 0; i < PEROPENS; i ++) + printf ("%3d: %ld\n", i, (long)pointers[i]); + return 0; + } + + while (1) + { + int set = 0; + long seek_to = 0; + + p = strtol (args, &end, 0); + if (end == args) + { + printf ("Syntax error.\n"); + return 0; + } + + if (*end == '=') + { + set = 1; + args = end + 1; + seek_to = strtol (args, &end, 0); + if (end == args) + { + printf ("Syntax error.\n"); + return 0; + } + } + + if (p < 0 || p > PEROPENS) + printf ("%3d: unknown peropen\n", p); + else + { + printf ("%3d: %ld", p, (long)pointers[p]); + if (set) + printf (" => %ld\n", (long)(pointers[p] = seek_to)); + else + printf ("\n"); + } + + while (*end == ' ') + end ++; + if (*end == '\0' || *end == '\n') + return 0; + args = end; + } +} + +error_t +interpret (char *buffer) +{ + int i; + + while (*buffer == ' ') + buffer ++; + + if (*buffer == '\n') + return 0; + + for (i = 0; i < sizeof (commands) / sizeof (struct command); i ++) + if (strncmp (commands[i].name, buffer, strlen (commands[i].name)) == 0) + { + error_t err; + err = commands[i].func (buffer + strlen (commands[i].name) + 1); + if (err) + printf ("%s\n", strerror (err)); + return err; + } + + printf ("Unknown command.\n"); + return 0; +} + +error_t +cmd_exec (char *arg) +{ + printf ("%s", arg); + interpret (arg); + return 0; +} + +int main (int argc, char *argv[]) +{ + int i; + + if (argc != 1) + { + printf ("Usage: %s\n" + "\tType `help' at the prompt.\n" + "\tUsed to test the record locking functions in libfshelp\n", + argv[0]); + return 1; + } + + fshelp_rlock_init (&box); + for (i = 0; i < PEROPENS; i ++) + fshelp_rlock_po_init (&peropens[i]); + + while (! feof (stdin)) + { + char b[1024]; + + printf ("> "); + fflush (stdout); + + if (! fgets (b, sizeof (b), stdin)) + { + if (feof (stdin)) + break; + else + continue; + } + + interpret (b); + } + + printf ("\n"); + return 0; +} Index: hurd-0.5.git20141210/libfshelp-tests/locks-tests =================================================================== --- /dev/null +++ hurd-0.5.git20141210/libfshelp-tests/locks-tests @@ -0,0 +1,585 @@ +echo Legend: +echo + => Shared region +echo x => Exclusive region +echo ' ' => Unlocked region +echo . => Clearing region +echo [] => Start/End of a region +echo After each lock command, the proposed region is shown followed +echo by the result of applying it. +echo * Established region wraps new region +echo ** Both boundaries align +echo [ +exec lock 0 1 10 1 +echo [+++++++++++++] +echo [ [+++++++++++++] +exec lock 0 1 10 1 +echo [+++++++++++++] +echo [ [+++++++++++++] +exec lock 0 1 10 2 +echo [xxxxxxxxxxxxx] +echo [ [xxxxxxxxxxxxx] +exec lock 0 1 10 1 +echo [+++++++++++++] +echo [ [xxxxxxxxxxxxx] +exec lock 0 1 10 2 +echo [xxxxxxxxxxxxx] +echo [ [xxxxxxxxxxxxx] +exec lock 0 1 10 0 +echo [.............] +echo [ +exec lock 0 10 0 1 +echo [++++++++ +echo [ [++++++++ +exec lock 0 10 0 1 +echo [++++++++ +echo [ [++++++++ +exec lock 0 10 0 2 +echo [xxxxxxxx +echo [ [xxxxxxxx +exec lock 0 10 0 2 +echo [xxxxxxxx +echo [ [xxxxxxxx +exec lock 0 10 0 1 +echo [++++++++ +echo [ [xxxxxxxx +exec lock 0 10 0 0 +echo [........ +echo [ +echo ** Left boundaries align +exec lock 0 1 10 1 +echo [+++++++++++] +echo [ [+++++++++++] +exec lock 0 1 5 1 +echo [+++++] +echo [ [+++++++++++] +exec lock 0 1 5 2 +echo [xxxxx] +echo [ [xxxxx][++++] +exec lock 0 1 3 1 +echo [++] +echo [ [xxxxx][++++] +exec lock 0 1 10 0 +echo [............ +echo [ +exec lock 0 1 10 1 +echo [+++++++++++] +echo [ [+++++++++++] +exec lock 0 1 9 2 +echo [xxxxxxxx] +echo [ [xxxxxxxx][+] +exec lock 0 1 5 0 +echo [...] +echo [ [***][+] +exec lock 0 6 3 0 +echo [.] +echo [ [*][+] +exec lock 0 9 1 0 +echo [.] +echo [ [+] +exec lock 0 10 1 0 +echo [.] +echo [ +exec lock 0 1 0 1 +echo [++++++++++++ +echo [ [++++++++++++ +exec lock 0 1 5 1 +echo [++++] +echo [ [++++++++++++ +exec lock 0 1 5 2 +echo [xxxx] +echo [ [xxxx][++++++ +exec lock 0 1 0 0 +echo [............ +echo [ +exec lock 0 5 0 2 +echo [xxxxxxxxxx +echo [ [xxxxxxxxxx +exec lock 0 5 5 1 +echo [++++] +echo [ [xxxxxxxxxx +exec lock 0 5 0 1 +echo [++++++++++ +echo [ [xxxxxxxxxx +exec lock 0 0 0 0 +echo [.............. +echo [ +echo ** Common right side +exec lock 0 5 5 1 +echo [+++++] +echo [ [+++++] +exec lock 0 9 1 1 +echo [+] +echo [ [+++++] +exec lock 0 9 1 2 +echo [x] +echo [ [++][x] +exec lock 0 5 4 2 +echo [xx] +echo [ [xxxxx] +exec lock 0 8 2 2 +echo [x] +echo [ [xxxxx] +exec lock 0 9 1 0 +echo [.] +echo [ [xxx] +exec lock 0 5 4 0 +echo [...] +echo [ +exec lock 0 5 0 1 +echo [++++++++++ +echo [ [++++++++++ +exec lock 0 10 0 1 +echo [+++++ +echo [ [++++++++++ +exec lock 0 10 0 2 +echo [xxxxx +echo [ [+++][xxxxx +exec lock 0 5 0 0 +echo [.......... +echo [ +echo ** Completely interior +exec lock 0 5 10 1 +echo [++++++++] +echo [ [++++++++] +exec lock 0 6 8 1 +echo [++++++] +echo [ [++++++++] +exec lock 0 8 3 1 +echo [+] +echo [ [++++++++] +exec lock 0 8 3 2 +echo [x] +echo [ [+][x][++] +exec lock 0 12 1 2 +echo x +echo [ [++xxx+x+] +exec lock 0 6 8 0 +echo [......] +echo [ [+] [+] +exec lock 0 0 0 0 +echo [.............. +echo [ +exec lock 0 5 0 1 +echo [+++++++++ +echo [ [+++++++++ +exec lock 0 10 0 1 +echo [++++ +echo [ [+++++++++ +exec lock 0 10 0 2 +echo [xxxx +echo [ [+++][xxxx +exec lock 0 11 0 0 +echo [.. +echo [ [+++][x] +exec lock 0 6 0 0 +echo [....... +echo [ [+] +exec lock 0 5 0 0 +echo [......... +echo [ +exec lock 0 10 0 1 +echo [+++++ +echo [ [+++++ +exec lock 0 11 0 1 +echo [+] +echo [ [+++++ +exec lock 0 11 0 1 +echo [+] +echo [ [+++++ +exec lock 0 11 1 2 +echo [x] +echo [ [+x+++ +exec lock 0 13 0 1 +echo [+] +echo [ [+x+++ +exec lock 0 10 0 0 +echo [..... +echo [ +echo * We wrap the locked region +echo ** Left boundaries align +exec lock 0 1 10 1 +echo [++++] +echo [[++++] +exec lock 0 1 15 1 +echo [++++++++] +echo [[++++++++] +exec lock 0 1 16 1 +echo [+++++++++] +echo [[+++++++++] +exec lock 0 1 20 2 +echo [xxxxxxxxxxxxx] +echo [[xxxxxxxxxxxxx] +exec lock 0 1 30 1 +echo [+++++++++++++++++++] +echo [[xxxxxxxxxxxxx][++++] +exec lock 0 22 11 2 +echo [xxx] +echo [[xxxxxxxxxxxxx][+][xx] +exec lock 0 1 40 0 +echo [.........................] +echo [ +exec lock 0 1 0 1 +echo [++++++++++ +echo [[++++++++++ +exec lock 0 1 0 1 +echo [++++++++++ +echo [[++++++++++ +exec lock 0 1 0 2 +echo [xxxxxxxxxx +echo [[xxxxxxxxxx +exec lock 0 0 0 0 +echo [........... +echo [ +exec lock 0 1 0 1 +echo [++++++++++ +echo [[++++++++++ +exec lock 0 10 0 1 +echo [+++++ +echo [[++++++++++ +exec lock 0 10 0 2 +echo [xxxxx +echo [[+++][xxxxx +exec lock 0 0 0 0 +echo [........... +echo [ +echo ** Right boundaries align +exec lock 0 5 10 1 +echo [++++++++] +echo [ [++++++++] +exec lock 0 4 11 1 +echo [+++++++++] +echo [ [+++++++++] +exec lock 0 3 12 2 +echo [xxxxxxxxxx] +echo [ [xxxxxxxxxx] +exec lock 0 0 15 2 +echo [xxxxxxxxxxxx] +echo [xxxxxxxxxxxx] +exec lock 0 0 0 0 +echo [............. +echo [ +exec lock 0 5 0 1 +echo [++++++++ +echo [ [++++++++ +exec lock 0 4 0 1 +echo [+++++++++ +echo [ [+++++++++ +exec lock 0 3 0 2 +echo [xxxxxxxxxx +echo [ [xxxxxxxxxx +exec lock 0 2 0 2 +echo [xxxxxxxxxxx +echo [ [xxxxxxxxxxx +exec lock 0 0 0 2 +echo [xxxxxxxxxxxxx +echo [xxxxxxxxxxxxx +exec lock 0 0 0 0 +echo [............. +echo [ +echo ** Consume locked region +exec lock 0 5 10 1 +echo [++++++++] +echo [ [++++++++] +exec lock 0 4 12 1 +echo [++++++++++] +echo [ [++++++++++] +exec lock 0 2 16 1 +echo [++++++++++++++] +echo [ [++++++++++++++] +exec lock 0 1 18 2 +echo [xxxxxxxxxxxxxxxx] +echo [[xxxxxxxxxxxxxxxx] +exec lock 0 0 24 2 +echo [xxxxxxxxxxxxxxxxxxxxx] +echo [xxxxxxxxxxxxxxxxxxxxx] +exec lock 0 0 30 0 +echo [.........................] +echo [ +exec lock 0 5 3 1 +echo [++] +echo [ [++] +exec lock 0 10 5 1 +echo [++++] +echo [ [++] [++++] +exec lock 0 20 5 2 +echo [xxxx] +echo [ [++] [++++] [xxxx] +exec lock 0 4 30 2 +echo [xxxxxxxxxxxxxxxxxxxxxxxxxx] +echo [ [xxxxxxxxxxxxxxxxxxxxxxxxxx] +exec lock 0 1 35 1 +echo [++++++++++++++++++++++++++++++] +echo [ [+[xxxxxxxxxxxxxxxxxxxxxxxxxx]+] +exec lock 0 0 40 1 +echo [+++++++++++++++++++++++++++++++++++] +echo [++][xxxxxxxxxxxxxxxxxxxxxxxxxx][+++] +exec lock 0 0 0 0 +echo [.................................... +echo [ +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 4 0 1 +echo [++++++] +echo [ [++++++] +exec lock 0 4 0 0 +echo [.......... +echo [ +exec lock 0 5 3 1 +echo [++] +echo [ [++] +exec lock 0 10 5 1 +echo [++++] +echo [ [++] [++++] +exec lock 0 0 0 1 +echo [++++++++++++++++++++ +echo [++++++++++++++++++++ +exec lock 0 0 0 0 +echo [.................... +echo [ +exec lock 0 5 3 1 +echo [++] +echo [ [++] +exec lock 0 10 3 1 +echo [++] +echo [ [++] [++] +exec lock 0 4 0 1 +echo [++++++++++++++ +echo [ [++++++++++++++ +exec lock 0 10 3 2 +echo [**] +echo [ [++++++][**][++ +exec lock 0 0 0 2 +echo [xxxxxxxxxxxxxxxxxx +echo [xxxxxxxxxxxxxxxxxx +exec lock 0 0 0 0 +echo [.................. +echo [ +echo * Our start is within the locked region or one byte after and our +echo end is after the end of the locked region. +echo ** The regions are the same type: Merge into a single large region +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 6 5 1 +echo [+++] +echo [ [++++] +exec lock 0 8 8 1 +echo [++++++] +echo [ [+++++++++] +exec lock 0 16 4 1 +echo [++] +echo [ [+++++++++++++] +exec lock 0 20 0 1 +echo [+++ +echo [ [++++++++++++++++++ +exec lock 0 5 16 0 +echo [..............] +echo [ [+++ +exec lock 0 20 0 0 +echo [... +echo [ +exec lock 0 6 6 2 +echo [xxxx] +echo [ [xxxx] +exec lock 0 7 7 2 +echo [xxxxx] +echo [ [xxxxxx] +exec lock 0 14 7 2 +echo [xxxxx] +echo [ [xxxxxxxxxxxxx] +exec lock 0 21 0 2 +echo [xx +echo [ [xxxxxxxxxxxxxxxxx +exec lock 0 6 0 0 +echo [................. +echo [ +echo ** Different types just after the end of the locked region +exec lock 0 1 3 1 +echo [++] +echo [[++] +exec lock 0 4 3 2 +echo [xx] +echo [[++][xx] +exec lock 0 7 3 1 +echo [++] +echo [[++][xx][++] +exec lock 0 10 0 2 +echo [xxx +echo [[++][xx][++][xxx +exec lock 0 5 0 0 +echo [......... +echo [[++]x +exec lock 0 5 0 1 +echo [+++ +echo [[++]x[+++ +exec lock 0 1 0 0 +echo [... +echo [ +echo ** New region consumes the intersection. +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 8 6 2 +echo [xxx] +echo [ [++][xxx] +exec lock 0 6 0 2 +echo [xxxxxx +echo [ [+][xxxxxx +exec lock 0 5 0 0 +echo [......... +echo [ +echo ** New region is dominated +exec lock 0 5 5 2 +echo [xxx] +echo [ [xxx] +exec lock 0 8 6 1 +echo [++++] +echo [ [xxx][++] +exec lock 0 6 0 1 +echo [++++++ +echo [ [xxx][+++ +exec lock 0 5 0 0 +echo [........ +echo [ +echo * Our start falls before the locked region. Our end falls just +echo before or with in the region (although we do not consume it) +echo ** The regions are the same type: Merge into a single large region +exec lock 0 10 5 1 +echo [+++] +echo [ [+++] +exec lock 0 5 5 1 +echo [+++] +echo [ [++++++++] +exec lock 0 4 4 1 +echo [++] +echo [ [+++++++++] +exec lock 0 0 10 1 +echo [+++++++++] +echo [+++++++++++++] +exec lock 0 0 15 0 +echo [...............] +echo [ +exec lock 0 10 0 1 +echo [++++ +echo [ [++++ +exec lock 0 5 5 1 +echo [+++] +echo [ [+++++++++ +exec lock 0 4 1 1 +echo + +echo [ [++++++++++ +exec lock 0 0 0 1 +echo [++++++++++++++ +echo [++++++++++++++ +exec lock 0 0 0 0 +echo [.... +echo [ +exec lock 0 10 5 2 +echo [xxx] +echo [ [xxx] +exec lock 0 5 5 2 +echo [xxx] +echo [ [xxxxxxxx] +exec lock 0 4 4 2 +echo [xx] +echo [ [xxxxxxxxx] +exec lock 0 0 10 2 +echo [xxxxxxxxx] +echo [xxxxxxxxxxxxx] +exec lock 0 0 15 0 +echo [...............] +echo [ +exec lock 0 10 0 2 +echo [xxxx +echo [ [xxxx +exec lock 0 5 5 2 +echo [xxx] +echo [ [xxxxxxxxx +exec lock 0 4 1 2 +echo x +echo [ [xxxxxxxxxx +exec lock 0 0 0 2 +echo [xxxxxxxxxxxxxx +echo [xxxxxxxxxxxxxx +exec lock 0 0 0 0 +echo [.... +echo [ +echo ** Different types just before the start of the locked region +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 3 2 2 +echo [x] +echo [ [x][+++] +exec lock 0 2 1 1 +echo + +echo [ +[x][+++] +exec lock 0 1 0 2 +echo [xxxx +echo [[xxxx +exec lock 0 0 1 1 +echo + +echo +[xxxx +exec lock 0 0 0 0 +echo [.... +echo [.... +exec lock 0 5 0 1 +echo [++++ +echo [ [++++ +exec lock 0 0 5 2 +echo [xxxxxxxxx +echo [xxxxxxxxx +exec lock 0 0 0 0 +echo [.... +echo [ +echo ** New region consumes the intersection. +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 4 3 2 +echo [x] +echo [ [x][+] +exec lock 0 2 0 2 +echo [xxxxxx +echo [ [xxxxxx +exec lock 0 0 0 0 +echo [.... +echo [ +exec lock 0 5 0 1 +echo [++++++ +echo [ [++++++ +exec lock 0 4 5 2 +echo [xxx] +echo [ [xxx][++ +exec lock 0 4 0 0 +echo [.... +echo [ +exec lock 0 5 0 1 +echo [++++ +echo [ [++++ +exec lock 0 0 0 2 +echo [xxxxxxxxxx +echo [xxxxxxxxxx +exec lock 0 0 0 0 +echo [.... +echo [ +echo ** New region is dominated +exec lock 0 5 5 2 +echo [xxx] +echo [ [xxx] +exec lock 0 4 5 1 +echo [+++] +echo [ +[xxx] +exec lock 0 0 0 0 +echo [... +echo [ +exec lock 0 5 0 2 +echo [xxxx +echo [ [xxxx +exec lock 0 0 0 1 +echo [++++++++ +echo [+++[xxxx +exec lock 0 0 0 0 +echo [.... +echo [ Index: hurd-0.5.git20141210/libfshelp-tests/race.c =================================================================== --- /dev/null +++ hurd-0.5.git20141210/libfshelp-tests/race.c @@ -0,0 +1,82 @@ +/* Test races in the record locking code. + Copyright (C) 2001 Free Software Foundation, Inc. + + Written by Neal H Walfield + + 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, 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. */ + +#include +#include +#include +#include +#include "fs_U.h" +#include +#include "io_U.h" + +int main (int argc, char **argv) +{ + error_t err; + struct flock64 lock; + int fd; + int i; + uint v; + int blocked = 0; + char buf[10] = ""; + char *bufp; + + if (argc != 4) + error (1, 0, "Usage: %s file start len", argv[0]); + + lock.l_whence = SEEK_SET; + lock.l_start = atoi (argv[2]); + lock.l_len = atoi (argv[3]); + + fd = file_name_lookup (argv[1], O_READ | O_WRITE | O_CREAT, 0666); + if (fd == MACH_PORT_NULL) + error (1, errno, "file_name_lookup"); + + for (i = 0; i < 10000; i ++) + { + lock.l_type = F_WRLCK; + err = file_record_lock (fd, F_SETLK64, &lock); + if (err) + { + blocked ++; + err = file_record_lock (fd, F_SETLKW64, &lock); + } + if (err) + error (1, err, "file_record_lock"); + + v = sizeof (buf); + bufp = buf; + io_read (fd, &bufp, &v, 0, v); + + v = atoi (bufp); + sprintf (buf, "%d\n", v + 1); + + v = 10; + io_write (fd, buf, sizeof (buf), 0, &v); + if (v == 0) + error (1, errno, "write (%d)", i); + + lock.l_type = F_UNLCK; + file_record_lock (fd, F_SETLK64, &lock); + } + + mach_port_deallocate (mach_task_self (), fd); + + printf ("Was blocked %d times\n", blocked); + return 0; +} Index: hurd-0.5.git20141210/libfshelp-tests/checklock.c =================================================================== --- /dev/null +++ hurd-0.5.git20141210/libfshelp-tests/checklock.c @@ -0,0 +1,66 @@ +/* This test checks the return types of F_GETLK64 + Copyright (C) 2014 Free Software Foundation, Inc. + + Written by Svante Signell + + 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, 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. */ + +#include +#include +#include +#include +#include +#include +#include "fs_U.h" +#include + +int main (int argc, char **argv) +{ + error_t err; + struct flock64 lock; + int fd; + + if (argc != 2) + error (1, 0, "Usage: %s file", argv[0]); + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 10; + lock.l_len = 20; + lock.l_pid = 1; + + printf("GNU/Hurd\n"); + printf("F_RDLCK = 1, F_WRLCK = 2, F_UNLCK = 3\n"); + printf("SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2\n"); + + printf("\nBefore calling file_record_lock\n"); + printf("{lock.l_type = %d lock.l_whence = %d lock.l_start = %ld lock.l_len = %ld lock.l_pid = %d}\n", + lock.l_type, lock.l_whence, (long)lock.l_start, (long)lock.l_len, lock.l_pid); + fd = file_name_lookup (argv[1], O_READ | O_WRITE | O_CREAT, 0666); + if (fd == MACH_PORT_NULL) + error (1, errno, "file_name_lookup"); + + err = file_record_lock (fd, F_GETLK64, &lock); + if (err) + error (1, err, "file_record_lock"); + + printf("\nAfter calling file_record_lock\n"); + printf("{lock.l_type = %d lock.l_whence = %d lock.l_start = %ld lock.l_len = %ld lock.l_pid = %d}\n", + lock.l_type, lock.l_whence, (long)lock.l_start, (long)lock.l_len, lock.l_pid); + + mach_port_deallocate (mach_task_self (), fd); + + return 0; +}