2 A ping-pong fcntl byte range lock test
4 Copyright (C) Andrew Tridgell 2002
5 Copyright (C) Michael Adam 2012
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 This measures the ping-pong byte range lock latency. It is
23 especially useful on a cluster of nodes sharing a common lock
24 manager as it will give some indication of the lock managers
25 performance under stress.
27 tridge@samba.org, February 2002
31 #define _XOPEN_SOURCE 500
43 static struct timeval tp1
,tp2
;
45 static int do_reads
, do_writes
, use_mmap
, do_check
;
47 static void start_timer(void)
49 gettimeofday(&tp1
,NULL
);
52 static double end_timer(void)
54 gettimeofday(&tp2
,NULL
);
55 return (tp2
.tv_sec
+ (tp2
.tv_usec
*1.0e-6)) -
56 (tp1
.tv_sec
+ (tp1
.tv_usec
*1.0e-6));
59 /* lock a byte range in a open file */
60 static int lock_range(int fd
, int offset
, int len
)
64 lock
.l_type
= F_WRLCK
;
65 lock
.l_whence
= SEEK_SET
;
66 lock
.l_start
= offset
;
70 return fcntl(fd
,F_SETLKW
,&lock
);
73 /* check whether we could place a lock */
74 static int check_lock(int fd
, int offset
, int len
)
79 lock
.l_type
= F_WRLCK
;
80 lock
.l_whence
= SEEK_SET
;
81 lock
.l_start
= offset
;
85 ret
= fcntl(fd
, F_GETLK
, &lock
);
87 printf("error calling fcntl F_GETLCK: %s\n", strerror(errno
));
91 if (lock
.l_type
== F_UNLCK
) {
92 /* we would be able to place the lock */
96 /* we would not be able to place lock */
97 printf("check_lock failed: lock held: "
98 "pid='%d', type='%d', start='%d', len='%d'\n",
99 (int)lock
.l_pid
, (int)lock
.l_type
, (int)lock
.l_start
, (int)lock
.l_len
);
103 /* unlock a byte range in a open file */
104 static int unlock_range(int fd
, int offset
, int len
)
108 lock
.l_type
= F_UNLCK
;
109 lock
.l_whence
= SEEK_SET
;
110 lock
.l_start
= offset
;
114 return fcntl(fd
,F_SETLKW
,&lock
);
117 /* run the ping pong test on fd */
118 static void ping_pong(int fd
, int num_locks
)
123 unsigned char incr
=0, last_incr
=0;
124 unsigned char *p
= NULL
;
127 ret
= ftruncate(fd
, num_locks
+1);
129 printf("ftruncate failed: %s\n", strerror(errno
));
134 p
= mmap(NULL
, num_locks
+1, PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, 0);
135 if (p
== MAP_FAILED
) {
136 printf("mmap failed: %s\n", strerror(errno
));
141 val
= (unsigned char *)calloc(num_locks
+1, sizeof(unsigned char));
143 printf("calloc failed\n");
149 lock_range(fd
, 0, 1);
153 if (lock_range(fd
, (i
+1) % num_locks
, 1) != 0) {
154 printf("lock at %d failed! - %s\n",
155 (i
+1) % num_locks
, strerror(errno
));
158 ret
= check_lock(fd
, i
, 1);
164 } else if (pread(fd
, &c
, 1, i
) != 1) {
165 printf("read failed at %d\n", i
);
174 } else if (pwrite(fd
, &c
, 1, i
) != 1) {
175 printf("write failed at %d\n", i
);
178 if (unlock_range(fd
, i
, 1) != 0) {
179 printf("unlock at %d failed! - %s\n",
182 i
= (i
+1) % num_locks
;
184 if (loops
> num_locks
&& incr
!= last_incr
) {
186 printf("data increment = %u\n", incr
);
189 if (end_timer() > 1.0) {
190 printf("%8u locks/sec\r",
191 (unsigned)(2*count
/end_timer()));
200 int main(int argc
, char *argv
[])
206 while ((c
= getopt(argc
, argv
, "rwmc")) != -1) {
221 fprintf(stderr
, "Unknown option '%c'\n", c
);
230 printf("ping_pong [options] <file> <num_locks>\n");
231 printf(" -r do reads\n");
232 printf(" -w do writes\n");
233 printf(" -m use mmap\n");
234 printf(" -c check locks\n");
239 num_locks
= atoi(argv
[1]);
240 if (num_locks
<= 0) {
241 printf("num_locks should be > 0\n");
245 fd
= open(fname
, O_CREAT
|O_RDWR
, 0600);
246 if (fd
== -1) exit(1);
248 ping_pong(fd
, num_locks
);