1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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.
|