./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 set-flock.c and set-fcntl.c * define temporary CPP_FLAGS until glibc is updated * set-flock.c, set-fcntl.c: New files. * 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.7.git20160114/Makefile =================================================================== --- hurd-0.7.git20160114.orig/Makefile +++ hurd-0.7.git20160114/Makefile @@ -45,7 +45,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.7.git20160114/libfshelp-tests/Makefile =================================================================== --- /dev/null +++ hurd-0.7.git20160114/libfshelp-tests/Makefile @@ -0,0 +1,50 @@ +# Makefile libfshelp test cases +# +# Copyright (C) 2001, 2015 Free Software Foundation, Inc. +# +# Written by Neal H Walfield +# +# This file is part of the GNU Hurd. +# +# 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 the GNU Hurd. If not, see . + +dir := libfshelp-tests +makemode := utilities + +targets = race locks fork set-flock set-fcntl +SRCS = race.c locks.c fork.c set-flock.c set-fcntl.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 +set-flock: set-flock.o fsUser.o +set-fcntl: set-fcntl.o ../libfshelp/libfshelp.a + +race locks: ../libfshelp/libfshelp.a ../libports/libports.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 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 +fork-CPPFLAGS += $(EXTRA_CPP_FLAGS) +locks-CPPFLAGS += $(EXTRA_CPP_FLAGS) +race-CPPFLAGS += $(EXTRA_CPP_FLAGS) +set-flock-CPPFLAGS += $(EXTRA_CPP_FLAGS) +set-fcntl-CPPFLAGS += $(EXTRA_CPP_FLAGS) + +include ../Makeconf Index: hurd-0.7.git20160114/libfshelp-tests/README =================================================================== --- /dev/null +++ hurd-0.7.git20160114/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.7.git20160114/libfshelp-tests/fork.c =================================================================== --- /dev/null +++ hurd-0.7.git20160114/libfshelp-tests/fork.c @@ -0,0 +1,78 @@ +/* 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 the GNU Hurd. If not, see . */ + +#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.7.git20160114/libfshelp-tests/locks.c =================================================================== --- /dev/null +++ hurd-0.7.git20160114/libfshelp-tests/locks.c @@ -0,0 +1,326 @@ +/* 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 the GNU Hurd. If not, see . */ + +#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.7.git20160114/libfshelp-tests/locks-tests =================================================================== --- /dev/null +++ hurd-0.7.git20160114/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.7.git20160114/libfshelp-tests/race.c =================================================================== --- /dev/null +++ hurd-0.7.git20160114/libfshelp-tests/race.c @@ -0,0 +1,81 @@ +/* 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 the GNU Hurd. If not, see . */ + +#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.7.git20160114/libfshelp-tests/set-flock.c =================================================================== --- /dev/null +++ hurd-0.7.git20160114/libfshelp-tests/set-flock.c @@ -0,0 +1,143 @@ +/* set-flock.c: Set advisory open file locks. + Options: + flagss : O_READ | O_WRITE | O_RDWR + types : LOCK_SH, LOCK_EX, LOCK_UN + blocking : , LOCK_UN + + Copyright (C) 2016 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 the GNU Hurd. If not, see . */ + +#include +#include +#include +#include +#include +#include +#include + +#define USE_FLOCK + +int main (int argc, char **argv) +{ + error_t err; +#ifdef USE_FLOCK + int fd, op, blocking, flags; +#else + int fd, op, blocking, flags, mode; +#endif + char *flagsc = "O_READ"; + char *opc = "LOCK_SH"; + char *blockingc = "LOCK_NB"; + + if (argc < 2) + error (1, 0, "Usage: %s file [flags opeation blocking]\n \ + file : file name/device name\n \ + flags : O_READ(default) | O_WRITE | O_RDWR\n \ + operation : LOCK_SH(default) | LOCK_EX | LOCK_UN\n \ + blocking : (default) | LOCK_NB)\n", + argv[0]); + + if (argv[2] && strcmp(argv[2],"O_WRITE") == 0) + { + flagsc = "O_WRITE"; + flags = O_WRITE; + } + else if ( argv[2] && strcmp(argv[2],"O_RDWR") == 0) + { + flagsc = "O_RDWR"; + flags = O_RDWR; + } + else + { + flagsc = "O_READ"; + flags = O_READ; + } + + if (argv[3] && strcmp(argv[3],"LOCK_UN") == 0) + { + opc = "LOCK_UN"; + op = LOCK_UN; + } + else if (argv[3] && strcmp(argv[3],"LOCK_EX") == 0) + { + opc = "LOCK_EX"; + op = LOCK_EX; + } + else + { + opc = "LOCK_SH"; + op = LOCK_SH; + } + + if (argv[4] && (strcmp(argv[4],"LOCK_NB") == 0)) + { + blockingc = "LOCK_NB"; + blocking = LOCK_NB; + } + else + { + blockingc = ""; + blocking = 0; + } + + op = op | blocking; + + printf ("set-flock.c: GNU/Hurd\n"); + printf ("set-flock.c: operation = (LOCK_SH=1 | LOCK_EX=2 | LOCK_UN=8)\n"); + printf ("set-flock.c: blocking = ( | LOCK_NB=4)\n"); + printf ("set-flock.c: file = '%s', flags = '%s'\n", argv[1], flagsc); + printf ("set-flock.c: operation = '%s', blocking = '%s'\n", opc, blockingc); + +#ifdef USE_FLOCK + printf ("Before calling open\n"); + fd = open (argv[1], flags); + if (!fd) + error (1, errno, "open"); + printf ("After calling open\n"); + + printf ("Before calling flock\n"); + err = flock (fd, op); + if (err) + error (1, errno, "fcntl"); + printf ("After calling flock\n"); + close (fd); +#else + printf ("\nBefore calling file_name_lookup\n"); + if (flags == O_WRITE) + mode = 0444; + else if (flags == O_RDWR) + mode = 0644; + else + mode = 0222; + + fd = file_name_lookup (argv[1], flags, mode); + if (fd == MACH_PORT_NULL) + error (1, errno, "file_name_lookup"); + printf ("After calling file_name_lookup\n"); + + printf ("Before calling file_lock\n"); + err = file_lock (fd, op); + if (err) + error (1, errno, "file_lock"); + printf ("After calling file_lock\n"); + + mach_port_deallocate (mach_task_self (), fd); +#endif + + //pause (); + return 0; +} Index: hurd-0.7.git20160114/libfshelp-tests/set-fcntl.c =================================================================== --- /dev/null +++ hurd-0.7.git20160114/libfshelp-tests/set-fcntl.c @@ -0,0 +1,156 @@ +/* set-fcntl set advisory open file record locks. + Options: + flags : O_READ | O_WRITE | O_RDWR + types : F_RDLCK, F_WRLCK, or F_UNLCK with + commands : F_GETLK, F_SETLK or F_SETLKW + + Copyright (C) 2016 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 the GNU Hurd. If not, see . */ + +#include +#include +#include +#include +#include +#include +#include + +#define USE_FCNTL + +int main (int argc, char **argv) +{ + error_t err; + struct flock lock; +#ifdef USE_FCNTL + int fd, cmd, flags; +#else + int fd, cmd, flags, mode; +#endif + char *flagsc = "O_READ"; + char *cmdc = "F_GETLK"; + char *type = "F_UNLCK"; + + if (argc <2 ) + error (1, 0, "Usage: %s file [flags cmd type]\n \ + file : file name/device name\n \ + flags : O_READ(default) | O_WRITE | O_RDWR\n \ + cmd : F_SETLK(default) | F_SETLKW | F_GETLK\n \ + type : F_RDLCK(default) | F_WRLCK | F_UNLCK", + argv[0]); + + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = -1; + + if (argv[2] && strcmp(argv[2],"O_WRITE") == 0) + { + flagsc = "O_WRITE"; + flags = O_WRITE; + } + else if ( argv[2] && strcmp(argv[2],"O_RDWR") == 0) + { + flagsc = "O_RDWR"; + flags = O_RDWR; + } + else + { + flagsc = "O_READ"; + flags = O_READ; + } + + if (argv[3] && strcmp(argv[3],"F_GETLK") == 0) + { + cmdc = "F_GETLK"; + cmd = F_GETLK; + } + else if ( argv[3] && strcmp(argv[3],"F_SETLKW") == 0) + { + cmdc = "F_SETLKW"; + cmd = F_SETLKW; + } + else + { + cmdc = "F_SETLK"; + cmd = F_SETLK; + } + + if (argv[4] && strcmp(argv[4],"F_UNLCK") == 0) + { + type = "F_UNLCK"; + lock.l_type = F_UNLCK; + } + else if (argv[4] && strcmp(argv[4], "F_WRLCK") == 0) + { + type = "F_WRLCK"; + lock.l_type = F_WRLCK; + } + else + { + type = "F_RDLCK"; + lock.l_type = F_RDLCK; + } + + printf ("set-fcntl.c: GNU/Hurd\n"); + printf ("set-fcntl.c: lock.l_type = (F_RDLCK=1 | F_WRLCK=2 | F_UNLCK=3)\n"); + printf ("set-fcntl.c: lock.whence = (SEEK_SET=0 | SEEK_CUR=1 | SEEK_END=2)\n"); + printf ("set-fcntl.c: file = '%s', flags = '%s'\n", argv[1], flagsc); + printf ("set-fcntl.c: cmd = '%s', type = '%s'\n", cmdc, type); + 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); + +#ifdef USE_FCNTL + printf ("Before calling open\n"); + fd = open (argv[1], flags); + if (!fd) + error (1, errno, "open"); + printf ("After calling open\n"); + + printf ("Before calling fcntl\n"); + err = fcntl (fd, cmd, &lock); + if (err) + error (1, errno, "fcntl"); + printf ("After calling fcntl\n"); + close (fd); +#else + printf ("Before calling file_name_lookup\n"); + if (flags == O_WRITE) + mode = 0444; + else if (flags == O_RDWR) + mode = 0644; + else + mode = 0222; + + fd = file_name_lookup (argv[1], flags, mode); + if (fd == MACH_PORT_NULL) + error (1, errno, "file_name_lookup"); + printf ("After calling file_name_lookup\n"); + + printf ("Before calling file_record_lock\n"); + err = file_record_lock (fd, cmd, &lock); + if (err) + error (1, errno, "file_record_lock"); + printf ("After calling file_record_lock\n"); + mach_port_deallocate (mach_task_self (), fd); +#endif + + 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); + + //pause (); + return 0; +}