1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2003 Silicon Graphics, Inc.
4 * Copyright (c) 2019 Intel Corp.
9 * Synchronized byte range lock and lease exerciser
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <netinet/tcp.h>
24 #include <sys/types.h>
32 #define HEX_2_ASC(x) ((x) > 9) ? (x)-10+'a' : (x)+'0'
33 #define FILE_SIZE 1024
34 #define PLATFORM_INIT() /*no-op*/
35 #define PLATFORM_CLEANUP() /*no-op*/
40 #define inet_aton(STRING, INADDRP) \
41 (((INADDRP)->s_addr = inet_addr(STRING)) == -1 ? 0 : 1)
43 /* this assumes 32 bit pointers */
44 #define PTR_TO_U64(P) ((unsigned __int64)(unsigned int)(P))
45 #define U64_TO_PTR(T,U) ((T)(void *)(unsigned int)(U))
47 #if __BYTE_ORDER == __LITTLE_ENDIAN
48 #define bswap_uint16(x) (uint16_t)bswap_16(x)
49 #define bswap_uint32(x) (uint32_t)bswap_32(x)
50 #define bswap_uint64(x) (uint64_t)bswap_64(x)
52 #define bswap_uint16(x) x
53 #define bswap_uint32(x) x
54 #define bswap_uint64(x) x
58 #define SOCKET_READ read
59 #define SOCKET_WRITE write
60 #define SOCKET_CLOSE(S) (close(S))
61 #define INVALID_SOCKET -1
66 #define INVALID_HANDLE -1
67 #define SEEK(H, O) (lseek(H, O, SEEK_SET))
68 #define READ(H, B, L) (read(H, B, L))
69 #define WRITE(H, B, L) (write(H, B, L))
70 #define CLOSE(H) (close(H))
72 #define RAND() (rand())
73 #define SRAND(s) (srand(s))
75 #define MIN(A,B) (((A)<(B))?(A):(B))
76 #define MAX(A,B) (((A)>(B))?(A):(B))
78 #define ALLOC_ALIGNED(S) (memalign(65536, S))
79 #define FREE_ALIGNED(P) (free(P))
82 static char *filename = 0;
84 static int server = 1;
86 static int testnumber = -1;
87 static int saved_errno = 0;
88 static int got_sigio = 0;
90 static SOCKET s_fd = -1; /* listen socket */
91 static SOCKET c_fd = -1; /* IPC socket */
92 static HANDLE f_fd = INVALID_HANDLE; /* shared file */
101 #define CMD_SETLEASE 7
102 #define CMD_GETLEASE 8
104 #define CMD_WAIT_SIGIO 10
105 #define CMD_TRUNCATE 11
119 #define FLAGS 2 /* index 2 is also used for do_open() flag, see below */
120 #define ARG FLAGS /* Arguments for Lease operations */
121 #define TIME FLAGS /* Time for waiting on sigio */
123 static char *get_cmd_str(int cmd)
126 case CMD_WRLOCK: return "write lock"; break;
127 case CMD_RDLOCK: return "read lock"; break;
128 case CMD_UNLOCK: return "unlock"; break;
129 case CMD_CLOSE: return "close"; break;
130 case CMD_OPEN: return "open"; break;
131 case CMD_WRTEST: return "Wait for SIGIO"; break;
132 case CMD_RDTEST: return "Truncate"; break;
133 case CMD_SETLEASE: return "Set Lease"; break;
134 case CMD_GETLEASE: return "Get Lease"; break;
135 case CMD_SIGIO: return "Setup SIGIO"; break;
136 case CMD_WAIT_SIGIO: return "Wait for SIGIO"; break;
137 case CMD_TRUNCATE: return "Truncate"; break;
142 * flags for Mac OS X do_open()
159 * When adding tests be sure to add to both the descriptions AND tests array.
160 * Also, be sure to undo whatever is set for each test (eg unlock any locks)
161 * There is no need to have a matching client command for each server command
165 char *lock_descriptions[] = {
166 /* 1 */"Add a lock to an empty lock list",
167 /* 2 */"Add a lock to the start and end of a list - no overlaps",
168 /* 3 */"Add a lock to the middle of a list - no overlap",
169 /* 4 */"Add different lock types to middle of the list - overlap exact match",
170 /* 5 */"Add new lock which completely overlaps any old lock in the list",
171 /* 6 */"Add new lock which itself is completely overlaped by any old lock in the list",
172 /* 7 */"Add new lock which starts before any old lock in the list",
173 /* 8 */"Add new lock which starts in the middle of any old lock in the list and ends after",
174 /* 9 */"Add different new lock types which completely overlaps any old lock in the list",
175 /* 10 */"Add different new locks which are completely overlaped by an old lock in the list",
176 /* 11 */"Add different new lock types which start before the old lock in the list",
177 /* 12 */"Add different new lock types which start in the middle of an old lock in the list and end after",
178 /* 13 */"Add new lock, differing types and processes, to middle of the list - exact overlap match",
179 /* 14 */"Add new lock, differing types and processes, which completely overlap any of the locks in the list",
180 /* 15 */"Add new lock, differing types and processes, which are completely overlaped by locks in the list",
181 /* 16 */"Add new lock, differing types and processes, which start before a lock in the list",
182 /* 17 */"Add new lock, differing types and processes, which starts in the middle of a lock, and ends after",
183 /* 18 */"Acquire write locks with overlapping ranges",
184 /* 19 */"Acquire write locks with non-overlapping ranges extending beyond EOF",
185 /* 20 */"Acquire write locks with overlapping ranges extending beyond EOF",
186 /* 21 */"Acquire write locks on whole files",
187 /* 22 */"Acquire write lock on whole file and range write lock",
188 /* 23 */"Acquire read locks with non-overlapping ranges",
189 /* 24 */"Acquire read locks with overlapping ranges",
190 /* 25 */"Acquire read and write locks with no overlapping ranges",
191 /* 26 */"Acquire read and write locks with overlapping ranges",
192 /* 27 */"Acquire whole file write lock and then close without unlocking (and attempt a lock)",
193 /* 28 */"Acquire two read locks, close and reopen the file, and test if the inital lock is still there",
194 /* 29 */"Verify that F_GETLK for F_WRLCK doesn't require that file be opened for write",
196 /* 30 */"Close the opened file and open the file with SHLOCK, other client will try to open with SHLOCK too",
197 /* 31 */"Close the opened file and open the file with SHLOCK, other client will try to open with EXLOCK",
198 /* 32 */"Close the opened file and open the file with EXLOCK, other client will try to open with EXLOCK too"
202 static int64_t lock_tests[][6] =
203 /* test # Action [offset|flags] length expected server/client */
205 /* Various simple tests exercising the list */
207 /* SECTION 1: WRITE and CMD_UNLOCK with the same process (SERVER) */
208 /* Add a lock to an empty list */
209 {1, CMD_WRLOCK, 1, 10, PASS, SERVER },
210 {1, CMD_UNLOCK, 1, 10, PASS, SERVER },
212 /* Add a lock to the start and end of a list - 1, 13 - no overlap */
213 {2, CMD_WRLOCK, 10, 10, PASS, SERVER },
214 {2, CMD_WRLOCK, 30, 10, PASS, SERVER },
215 {2, CMD_WRLOCK, 50, 10, PASS, SERVER },
216 {2, CMD_WRLOCK, 1, 5, PASS, SERVER },
217 {2, CMD_WRLOCK, 70, 5, PASS, SERVER },
219 {2, CMD_UNLOCK, 10, 10, PASS, SERVER },
220 {2, CMD_UNLOCK, 30, 10, PASS, SERVER },
221 {2, CMD_UNLOCK, 50, 10, PASS, SERVER },
222 {2, CMD_UNLOCK, 1, 5, PASS, SERVER },
223 {2, CMD_UNLOCK, 70, 5, PASS, SERVER },
225 /* Add a lock to the middle of a list - no overlap */
226 {3, CMD_WRLOCK, 10, 10, PASS, SERVER },
227 {3, CMD_WRLOCK, 30, 10, PASS, SERVER },
228 {3, CMD_WRLOCK, 50, 10, PASS, SERVER },
229 {3, CMD_WRLOCK, 42, 5, PASS, SERVER },
231 {3, CMD_UNLOCK, 10, 10, PASS, SERVER },
232 {3, CMD_UNLOCK, 30, 10, PASS, SERVER },
233 {3, CMD_UNLOCK, 50, 10, PASS, SERVER },
234 {3, CMD_UNLOCK, 42, 5, PASS, SERVER },
236 /* Add different lock types to middle of the list - overlap exact match - 3 */
237 {4, CMD_WRLOCK, 10, 10, PASS, SERVER },
238 {4, CMD_WRLOCK, 30, 10, PASS, SERVER },
239 {4, CMD_WRLOCK, 50, 10, PASS, SERVER },
240 /* Exact match - same lock type */
241 {4, CMD_WRLOCK, 30, 10, PASS, SERVER },
242 /* Exact match - different lock type */
243 {4, CMD_RDLOCK, 30, 10, PASS, SERVER },
244 /* Exact match - unlock */
245 {4, CMD_UNLOCK, 30, 10, PASS, SERVER },
246 /* New lock - as above, inserting in the list again */
247 {4, CMD_WRLOCK, 30, 10, PASS, SERVER },
249 {4, CMD_UNLOCK, 10, 10, PASS, SERVER },
250 {4, CMD_UNLOCK, 30, 10, PASS, SERVER },
251 {4, CMD_UNLOCK, 50, 10, PASS, SERVER },
253 /* Add new lock which completely overlaps any old lock in the list - 4,5,6 */
254 {5, CMD_WRLOCK, 10, 10, PASS, SERVER },
255 {5, CMD_WRLOCK, 30, 10, PASS, SERVER },
256 {5, CMD_WRLOCK, 50, 10, PASS, SERVER },
257 /* The start is the same, end overlaps */
258 {5, CMD_WRLOCK, 30, 15, PASS, SERVER },
259 /* The start is before, end is the same */
260 {5, CMD_WRLOCK, 25, 20, PASS, SERVER },
261 /* Both start and end overlap */
262 {5, CMD_WRLOCK, 22, 26, PASS, SERVER },
264 {5, CMD_UNLOCK, 10, 10, PASS, SERVER },
265 {5, CMD_UNLOCK, 22, 26, PASS, SERVER },
266 {5, CMD_UNLOCK, 50, 10, PASS, SERVER },
268 /* Add new lock which itself is completely overlaped by any old lock in the list - 7,8,10 */
269 {6, CMD_WRLOCK, 10, 10, PASS, SERVER },
270 {6, CMD_WRLOCK, 30, 10, PASS, SERVER },
271 {6, CMD_WRLOCK, 50, 10, PASS, SERVER },
272 /* The start is the same, end is in the middle of old lock - NOP */
273 {6, CMD_WRLOCK, 30, 5, PASS, SERVER },
274 /* The start and end are in the middle of old lock - NOP */
275 {6, CMD_WRLOCK, 32, 6, PASS, SERVER },
276 /* Start in the middle and end is the same - NOP */
277 {6, CMD_WRLOCK, 32, 8, PASS, SERVER },
279 {6, CMD_UNLOCK, 10, 10, PASS, SERVER },
280 {6, CMD_UNLOCK, 30, 10, PASS, SERVER },
281 {6, CMD_UNLOCK, 32, 8, PASS, SERVER },
282 {6, CMD_UNLOCK, 50, 10, PASS, SERVER },
284 /* Add new lock which starts before any old lock in the list - 2,9 */
285 {7, CMD_WRLOCK, 10, 10, PASS, SERVER },
286 {7, CMD_WRLOCK, 30, 10, PASS, SERVER },
287 {7, CMD_WRLOCK, 50, 10, PASS, SERVER },
288 /* Here is the new lock */
289 {7, CMD_WRLOCK, 27, 10, PASS, SERVER },
290 /* Go again with the end of the new lock matching the start of old lock */
291 {7, CMD_WRLOCK, 25, 2, PASS, SERVER },
293 {7, CMD_UNLOCK, 10, 10, PASS, SERVER },
294 {7, CMD_UNLOCK, 25, 15, PASS, SERVER },
295 {7, CMD_UNLOCK, 50, 10, PASS, SERVER },
297 /* Add new lock which starts in the middle of any old lock in the list and ends after - 11,12 */
298 {8, CMD_WRLOCK, 10, 10, PASS, SERVER },
299 {8, CMD_WRLOCK, 30, 10, PASS, SERVER },
300 {8, CMD_WRLOCK, 50, 10, PASS, SERVER },
301 /* Here is the new lock */
302 {8, CMD_WRLOCK, 35, 10, PASS, SERVER },
303 /* Go again with the end of the new lock matching the start of old lock */
304 {8, CMD_WRLOCK, 45, 2, PASS, SERVER },
306 {8, CMD_UNLOCK, 10, 10, PASS, SERVER },
307 {8, CMD_UNLOCK, 30, 17, PASS, SERVER },
308 {8, CMD_UNLOCK, 50, 10, PASS, SERVER },
309 /* SECTION 2: Overlapping READ and WRITE and CMD_UNLOCK with the same process (SERVER) */
310 /* Add different new lock types which completely overlaps any old lock in the list - 4,5,6 */
311 {9, CMD_WRLOCK, 10, 10, PASS, SERVER },
312 {9, CMD_WRLOCK, 30, 10, PASS, SERVER },
313 {9, CMD_WRLOCK, 50, 10, PASS, SERVER },
314 /* The start is the same, end overlaps */
315 {9, CMD_RDLOCK, 30, 15, PASS, SERVER },
316 /* The start is before, end is the same */
317 {9, CMD_WRLOCK, 25, 20, PASS, SERVER },
318 /* Both start and end overlap */
319 {9, CMD_RDLOCK, 22, 26, PASS, SERVER },
321 {9, CMD_UNLOCK, 10, 10, PASS, SERVER },
322 {9, CMD_UNLOCK, 22, 26, PASS, SERVER },
323 {9, CMD_UNLOCK, 50, 10, PASS, SERVER },
325 /* Add different new locks which are completely overlaped by an old lock in the list - 7,8,10 */
326 {10, CMD_WRLOCK, 10, 10, PASS, SERVER },
327 {10, CMD_WRLOCK, 30, 10, PASS, SERVER },
328 {10, CMD_WRLOCK, 50, 10, PASS, SERVER },
329 /* The start is the same, end is in the middle of old lock */
330 {10, CMD_RDLOCK, 30, 5, PASS, SERVER },
331 /* The start and end are in the middle of a lock */
332 {10, CMD_WRLOCK, 32, 2, PASS, SERVER },
333 /* Start in the middle and end is the same */
334 {10, CMD_RDLOCK, 36, 5, PASS, SERVER },
336 {10, CMD_UNLOCK, 10, 10, PASS, SERVER },
337 {10, CMD_UNLOCK, 30, 11, PASS, SERVER },
338 {10, CMD_UNLOCK, 50, 10, PASS, SERVER },
340 /* Add different new lock types which start before the old lock in the list - 2,9 */
341 {11, CMD_WRLOCK, 10, 10, PASS, SERVER },
342 {11, CMD_WRLOCK, 30, 10, PASS, SERVER },
343 {11, CMD_WRLOCK, 50, 10, PASS, SERVER },
344 /* Here is the new lock */
345 {11, CMD_RDLOCK, 27, 10, PASS, SERVER },
346 /* Go again with the end of the new lock matching the start of lock */
347 {11, CMD_WRLOCK, 25, 3, PASS, SERVER },
349 {11, CMD_UNLOCK, 10, 10, PASS, SERVER },
350 {11, CMD_UNLOCK, 25, 15, PASS, SERVER },
351 {11, CMD_UNLOCK, 50, 10, PASS, SERVER },
353 /* Add different new lock types which start in the middle of an old lock in the list and end after - 11,12 */
354 {12, CMD_WRLOCK, 10, 10, PASS, SERVER },
355 {12, CMD_WRLOCK, 30, 10, PASS, SERVER },
356 {12, CMD_WRLOCK, 50, 10, PASS, SERVER },
357 /* Here is the new lock */
358 {12, CMD_RDLOCK, 35, 10, PASS, SERVER },
359 /* Go again with the end of the new lock matching the start of old lock */
360 {12, CMD_WRLOCK, 44, 3, PASS, SERVER },
362 {12, CMD_UNLOCK, 10, 10, PASS, SERVER },
363 {12, CMD_UNLOCK, 30, 18, PASS, SERVER },
364 {12, CMD_UNLOCK, 50, 10, PASS, SERVER },
366 /* SECTION 3: Overlapping READ and WRITE and CMD_UNLOCK with the different processes (CLIENT/SERVER) */
367 /* Add new lock, differing types and processes, to middle of the list - exact overlap match - 3 */
368 {13, CMD_WRLOCK, 10, 10, PASS, SERVER },
369 {13, CMD_WRLOCK, 30, 10, PASS, SERVER },
370 {13, CMD_RDLOCK, 50, 10, PASS, SERVER },
371 /* Same lock type, different process */
372 {13, CMD_WRLOCK, 30, 10, FAIL, CLIENT },
373 {13, CMD_RDLOCK, 50, 10, PASS, CLIENT },
374 /* Exact match - different lock type, different process */
375 {13, CMD_RDLOCK, 30, 10, FAIL, CLIENT },
376 /* Exact match - unlock */
377 {13, CMD_UNLOCK, 30, 10, PASS, CLIENT },
378 /* New lock - as above, inserting in the list again */
379 {13, CMD_UNLOCK, 30, 10, PASS, SERVER },
380 /* Exact match - same lock type, different process */
381 {13, CMD_WRLOCK, 30, 10, PASS, CLIENT },
383 {13, CMD_UNLOCK, 10, 10, PASS, SERVER },
384 {13, CMD_UNLOCK, 30, 10, PASS, CLIENT },
385 {13, CMD_UNLOCK, 50, 10, PASS, SERVER },
387 /* Add new lock, differing types and processes, which completely overlap any of the locks in the list - 4,5,6 */
388 {14, CMD_WRLOCK, 10, 10, PASS, SERVER },
389 {14, CMD_WRLOCK, 30, 10, PASS, SERVER },
390 {14, CMD_RDLOCK, 50, 10, PASS, SERVER },
391 /* The start is the same, end overlaps */
392 {14, CMD_RDLOCK, 30, 15, FAIL, CLIENT },
393 {14, CMD_WRLOCK, 30, 15, FAIL, CLIENT },
394 /* The start is before, end is the same */
395 {14, CMD_RDLOCK, 25, 20, FAIL, CLIENT },
396 {14, CMD_WRLOCK, 25, 20, FAIL, CLIENT },
397 /* Both start and end overlap */
398 {14, CMD_RDLOCK, 22, 26, FAIL, CLIENT },
399 {14, CMD_WRLOCK, 22, 26, FAIL, CLIENT },
401 /* The start is the same, end overlaps */
402 {14, CMD_RDLOCK, 50, 15, PASS, CLIENT },
403 {14, CMD_WRLOCK, 50, 17, FAIL, CLIENT },
404 /* The start is before, end is the same */
405 {14, CMD_RDLOCK, 45, 20, PASS, CLIENT },
406 {14, CMD_WRLOCK, 43, 22, FAIL, CLIENT },
407 /* Both start and end overlap */
408 {14, CMD_RDLOCK, 42, 26, PASS, CLIENT },
409 {14, CMD_WRLOCK, 41, 28, FAIL, CLIENT },
411 {14, CMD_UNLOCK, 10, 10, PASS, SERVER },
412 {14, CMD_UNLOCK, 22, 26, PASS, SERVER },
413 {14, CMD_UNLOCK, 42, 26, PASS, CLIENT },
415 /* Add new lock, differing types and processes, which are completely overlaped by an old lock in the list - 7,8,10 */
416 {15, CMD_WRLOCK, 10, 10, PASS, SERVER },
417 {15, CMD_RDLOCK, 30, 10, PASS, SERVER },
418 {15, CMD_WRLOCK, 50, 10, PASS, SERVER },
419 /* The start is the same, end is in the middle of old lock */
420 {15, CMD_RDLOCK, 50, 5, FAIL, CLIENT },
421 {15, CMD_WRLOCK, 50, 5, FAIL, CLIENT },
422 /* The start and end are in the middle of old lock */
423 {15, CMD_RDLOCK, 52, 6, FAIL, CLIENT },
424 {15, CMD_WRLOCK, 52, 6, FAIL, CLIENT },
425 /* Start in the middle and end is the same */
426 {15, CMD_RDLOCK, 52, 8, FAIL, CLIENT },
427 {15, CMD_WRLOCK, 52, 8, FAIL, CLIENT },
428 /* The start is the same, end is in the middle of old lock */
429 {15, CMD_RDLOCK, 30, 5, PASS, CLIENT },
430 {15, CMD_WRLOCK, 30, 5, FAIL, CLIENT },
431 /* The start and end are in the middle of old lock */
432 {15, CMD_RDLOCK, 32, 6, PASS, CLIENT },
433 {15, CMD_WRLOCK, 32, 6, FAIL, CLIENT },
434 /* Start in the middle and end is the same */
435 {15, CMD_RDLOCK, 32, 8, PASS, CLIENT },
436 {15, CMD_WRLOCK, 32, 8, FAIL, CLIENT },
438 {15, CMD_UNLOCK, 10, 10, PASS, SERVER },
439 {15, CMD_UNLOCK, 30, 10, PASS, SERVER },
440 {15, CMD_UNLOCK, 50, 10, PASS, SERVER },
441 /* Add new lock, differing types and processes, which start before a lock in the list - 2,9 */
442 {16, CMD_RDLOCK, 10, 10, PASS, SERVER },
443 {16, CMD_WRLOCK, 50, 10, PASS, SERVER },
444 /* Start is before, end is the start of the old lock in list */
445 {16, CMD_RDLOCK, 5, 6, PASS, CLIENT },
446 {16, CMD_WRLOCK, 5, 6, FAIL, CLIENT },
447 /* Start is before, end is in the middle of the old lock */
448 {16, CMD_RDLOCK, 5, 10, PASS, CLIENT },
449 {16, CMD_WRLOCK, 5, 10, FAIL, CLIENT },
450 /* Start is before, end is the start of the old lock in list */
451 {16, CMD_RDLOCK, 45, 6, FAIL, CLIENT },
452 {16, CMD_WRLOCK, 45, 6, FAIL, CLIENT },
453 /* Start is before, end is in the middle of the old lock */
454 {16, CMD_RDLOCK, 45, 10, FAIL, CLIENT },
455 {16, CMD_WRLOCK, 45, 10, FAIL, CLIENT },
457 {16, CMD_UNLOCK, 5, 15, PASS, CLIENT },
458 {16, CMD_UNLOCK, 30, 10, PASS, SERVER },
459 {16, CMD_UNLOCK, 50, 10, PASS, SERVER },
461 /* Add new lock, differing types and processes, which starts in the middle of a lock, and ends after - 11,12 */
462 {17, CMD_WRLOCK, 10, 10, PASS, SERVER },
463 {17, CMD_RDLOCK, 30, 10, PASS, SERVER },
464 {17, CMD_WRLOCK, 50, 10, PASS, SERVER },
465 /* Start in the middle, end after lock in list */
466 {17, CMD_WRLOCK, 35, 10, FAIL, CLIENT },
467 /* Start matches end of lock in list */
468 {17, CMD_RDLOCK, 35, 10, PASS, CLIENT },
469 {17, CMD_RDLOCK, 44, 2, PASS, CLIENT },
470 /* Start in the middle, end after lock in list */
471 {17, CMD_RDLOCK, 55, 10, FAIL, CLIENT },
472 {17, CMD_WRLOCK, 55, 10, FAIL, CLIENT },
473 /* Start matches end of lock in list */
474 {17, CMD_RDLOCK, 59, 5, FAIL, CLIENT },
475 {17, CMD_WRLOCK, 59, 5, FAIL, CLIENT },
477 {17, CMD_UNLOCK, 10, 10, PASS, SERVER },
478 {17, CMD_UNLOCK, 30, 16, PASS, CLIENT },
479 {17, CMD_UNLOCK, 50, 10, PASS, SERVER },
481 /* SECTION 4: overlapping and EOF tests */
482 /* Acquire overlapping ranges */
483 {18, CMD_WRLOCK, 11, 7, PASS, SERVER },
484 {18, CMD_WRLOCK, 13, 8, FAIL, CLIENT },
485 {18, CMD_UNLOCK, 11, 7, PASS, SERVER },
486 /* Acquire different ranges beyond EOF */
487 {19, CMD_WRLOCK, 10, FILE_SIZE, PASS, SERVER },
488 {19, CMD_WRLOCK, FILE_SIZE + 10, 10, PASS, CLIENT },
489 {19, CMD_UNLOCK, 10, FILE_SIZE, PASS, SERVER },
490 {19, CMD_UNLOCK, FILE_SIZE + 10, 10, PASS, CLIENT },
491 /* Acquire same range beyong EOF */
492 {20, CMD_WRLOCK, 10, FILE_SIZE, PASS, SERVER, },
493 {20, CMD_WRLOCK, 10, FILE_SIZE, FAIL, CLIENT, },
494 {20, CMD_UNLOCK, 10, FILE_SIZE, PASS, SERVER, },
495 /* Acquire whole file lock */
496 {21, CMD_WRLOCK, 0, 0, PASS, SERVER, },
497 {21, CMD_WRLOCK, 0, 0, FAIL, CLIENT, },
498 {21, CMD_UNLOCK, 0, 0, PASS, SERVER, },
499 /* Acquire whole file lock, then range */
500 {22, CMD_WRLOCK, 0, 0, PASS, SERVER, },
501 {22, CMD_WRLOCK, 1, 5, FAIL, CLIENT, },
502 {22, CMD_UNLOCK, 0, 0, PASS, SERVER, },
503 /* Acquire non-overlapping read locks */
504 {23, CMD_RDLOCK, 1, 5, PASS, SERVER, },
505 {23, CMD_RDLOCK, 7, 6, PASS, CLIENT, },
506 {23, CMD_UNLOCK, 1, 5, PASS, SERVER, },
507 {23, CMD_UNLOCK, 7, 6, PASS, CLIENT, },
508 /* Acquire overlapping read locks */
509 {24, CMD_RDLOCK, 1, 5, PASS, SERVER, },
510 {24, CMD_RDLOCK, 2, 6, PASS, CLIENT, },
511 {24, CMD_UNLOCK, 1, 5, PASS, SERVER, },
512 {24, CMD_UNLOCK, 1, 7, PASS, CLIENT, },
513 /* Acquire non-overlapping read and write locks */
514 {25, CMD_RDLOCK, 1, 5, PASS, SERVER, },
515 {25, CMD_WRLOCK, 7, 6, PASS, CLIENT, },
516 {25, CMD_UNLOCK, 1, 5, PASS, SERVER, },
517 {25, CMD_UNLOCK, 7, 6, PASS, CLIENT, },
518 /* Acquire overlapping read and write locks */
519 {26, CMD_RDLOCK, 1, 5, PASS, SERVER, },
520 {26, CMD_WRLOCK, 2, 6, FAIL, CLIENT, },
521 {26, CMD_UNLOCK, 1, 5, PASS, SERVER, },
522 /* Acquire whole file lock, then close (without unlocking) */
523 {27, CMD_WRLOCK, 0, 0, PASS, SERVER, },
524 {27, CMD_WRLOCK, 1, 5, FAIL, CLIENT, },
525 {27, CMD_CLOSE,0, 0, PASS, SERVER, },
526 {27, CMD_WRLOCK, 1, 5, PASS, CLIENT, },
527 {27, CMD_OPEN, O_RDWR, 0, PASS, SERVER, },
528 {27, CMD_UNLOCK, 1, 5, PASS, CLIENT, },
529 /* Acquire two read locks, close one file and then reopen to check that first lock still exists */
530 {28, CMD_RDLOCK, 1, 5, PASS, SERVER, },
531 {28, CMD_RDLOCK, 1, 5, PASS, CLIENT, },
532 {28, CMD_CLOSE,0, 0, PASS, SERVER, },
533 {28, CMD_OPEN, O_RDWR, 0, PASS, SERVER, },
534 {28, CMD_WRLOCK, 0, 0, FAIL, SERVER, },
535 {28, CMD_UNLOCK, 1, 5, PASS, SERVER, },
536 /* Verify that F_GETLK for F_WRLCK doesn't require that file be opened for write */
537 {29, CMD_CLOSE, 0, 0, PASS, SERVER, },
538 {29, CMD_OPEN, O_RDONLY, 0, PASS, SERVER, },
539 {29, CMD_WRTEST, 0, 0, PASS, SERVER, },
540 {29, CMD_CLOSE,0, 0, PASS, SERVER, },
541 {29, CMD_OPEN, O_RDWR, 0, PASS, SERVER, },
543 /* Close the opened file and open the file with SHLOCK, other client will try to open with SHLOCK too */
544 {30, CMD_CLOSE,0, 0, PASS, SERVER, },
545 {30, CMD_OPEN, O_RDWR|O_SHLOCK|O_NONBLOCK, 0, PASS, SERVER, },
546 {30, CMD_CLOSE,0, 0, PASS, CLIENT, },
547 {30, CMD_OPEN, O_RDWR|O_SHLOCK|O_NONBLOCK, 0, PASS, CLIENT, },
548 /* Close the opened file and open the file with SHLOCK, other client will try to open with EXLOCK */
549 {31, CMD_CLOSE,0, 0, PASS, SERVER, },
550 {31, CMD_CLOSE,0, 0, PASS, CLIENT, },
551 {31, CMD_OPEN, O_RDWR|O_SHLOCK|O_NONBLOCK, 0, PASS, SERVER, },
552 {31, CMD_OPEN, O_RDWR|O_EXLOCK|O_NONBLOCK, 0, FAIL, CLIENT, },
553 /* Close the opened file and open the file with EXLOCK, other client will try to open with EXLOCK too */
554 {32, CMD_CLOSE,0, 0, PASS, SERVER, },
555 {32, CMD_CLOSE,0, 0, FAIL, CLIENT, },
556 {32, CMD_OPEN, O_RDWR|O_EXLOCK|O_NONBLOCK, 0, PASS, SERVER, },
557 {32, CMD_OPEN, O_RDWR|O_EXLOCK|O_NONBLOCK, 0, FAIL, CLIENT, },
558 {32, CMD_CLOSE,0, 0, PASS, SERVER, },
559 {32, CMD_CLOSE,0, 0, FAIL, CLIENT, },
560 {32, CMD_OPEN, O_RDWR, 0, PASS, SERVER, },
561 {32, CMD_OPEN, O_RDWR, 0, PASS, CLIENT, },
564 /* indicate end of array */
570 char *lease_descriptions[] = {
571 /* 1 */"Take Read Lease",
572 /* 2 */"Take Write Lease",
573 /* 3 */"Fail Write Lease if file is open somewhere else",
574 /* 4 */"Fail Read Lease if opened with write permissions",
575 /* 5 */"Read lease gets SIGIO on write open",
576 /* 6 */"Write lease gets SIGIO on read open",
577 /* 7 */"Read lease does _not_ get SIGIO on read open",
578 /* 8 */"Read lease gets SIGIO on write open",
579 /* 9 */"Write lease gets SIGIO on truncate",
580 /* 10 */"Read lease gets SIGIO on truncate",
583 static int64_t lease_tests[][6] =
584 /* test # Action [offset|flags|arg] length expected server/client */
585 /* [sigio_wait_time] */
587 /* Various tests to exercise leases */
589 /* SECTION 1: Simple verification of being able to take leases */
590 /* Take Read Lease */
591 {1, CMD_CLOSE, 0, 0, PASS, CLIENT },
592 {1, CMD_OPEN, O_RDONLY, 0, PASS, CLIENT },
593 {1, CMD_CLOSE, 0, 0, PASS, SERVER },
594 {1, CMD_OPEN, O_RDONLY, 0, PASS, SERVER },
595 {1, CMD_SETLEASE, F_RDLCK, 0, PASS, SERVER },
596 {1, CMD_GETLEASE, F_RDLCK, 0, PASS, SERVER },
597 {1, CMD_SETLEASE, F_UNLCK, 0, PASS, SERVER },
598 {1, CMD_CLOSE, 0, 0, PASS, SERVER },
599 {1, CMD_CLOSE, 0, 0, PASS, CLIENT },
601 /* Take Write Lease */
602 {2, CMD_OPEN, O_RDWR, 0, PASS, SERVER },
603 {2, CMD_SETLEASE, F_WRLCK, 0, PASS, SERVER },
604 {2, CMD_GETLEASE, F_WRLCK, 0, PASS, SERVER },
605 {2, CMD_SETLEASE, F_UNLCK, 0, PASS, SERVER },
606 {2, CMD_CLOSE, 0, 0, PASS, SERVER },
607 /* Fail Write Lease with other users */
608 {3, CMD_OPEN, O_RDONLY, 0, PASS, CLIENT },
609 {3, CMD_OPEN, O_RDWR, 0, PASS, SERVER },
610 {3, CMD_SETLEASE, F_WRLCK, 0, FAIL, SERVER },
611 {3, CMD_GETLEASE, F_WRLCK, 0, FAIL, SERVER },
612 {3, CMD_CLOSE, 0, 0, PASS, SERVER },
613 {3, CMD_CLOSE, 0, 0, PASS, CLIENT },
614 /* Fail Read Lease if opened for write */
615 {4, CMD_OPEN, O_RDWR, 0, PASS, SERVER },
616 {4, CMD_SETLEASE, F_RDLCK, 0, FAIL, SERVER },
617 {4, CMD_GETLEASE, F_RDLCK, 0, FAIL, SERVER },
618 {4, CMD_CLOSE, 0, 0, PASS, SERVER },
620 /* SECTION 2: Proper SIGIO notifications */
621 /* Get SIGIO when read lease is broken by write */
622 {5, CMD_OPEN, O_RDONLY, 0, PASS, CLIENT },
623 {5, CMD_SETLEASE, F_RDLCK, 0, PASS, CLIENT },
624 {5, CMD_GETLEASE, F_RDLCK, 0, PASS, CLIENT },
625 {5, CMD_SIGIO, 0, 0, PASS, CLIENT },
626 {5, CMD_OPEN, O_RDWR, 0, PASS, SERVER },
627 {5, CMD_WAIT_SIGIO, 5, 0, PASS, CLIENT },
628 {5, CMD_CLOSE, 0, 0, PASS, SERVER },
629 {5, CMD_CLOSE, 0, 0, PASS, CLIENT },
631 /* Get SIGIO when write lease is broken by read */
632 {6, CMD_OPEN, O_RDWR, 0, PASS, CLIENT },
633 {6, CMD_SETLEASE, F_WRLCK, 0, PASS, CLIENT },
634 {6, CMD_GETLEASE, F_WRLCK, 0, PASS, CLIENT },
635 {6, CMD_SIGIO, 0, 0, PASS, CLIENT },
636 {6, CMD_OPEN, O_RDONLY, 0, PASS, SERVER },
637 {6, CMD_WAIT_SIGIO, 5, 0, PASS, CLIENT },
638 {6, CMD_CLOSE, 0, 0, PASS, SERVER },
639 {6, CMD_CLOSE, 0, 0, PASS, CLIENT },
641 /* Don't get SIGIO when read lease is taken by read */
642 {7, CMD_OPEN, O_RDONLY, 0, PASS, CLIENT },
643 {7, CMD_SETLEASE, F_RDLCK, 0, PASS, CLIENT },
644 {7, CMD_GETLEASE, F_RDLCK, 0, PASS, CLIENT },
645 {7, CMD_SIGIO, 0, 0, PASS, CLIENT },
646 {7, CMD_OPEN, O_RDONLY, 0, PASS, SERVER },
647 {7, CMD_WAIT_SIGIO, 5, 0, FAIL, CLIENT },
648 {7, CMD_CLOSE, 0, 0, PASS, SERVER },
649 {7, CMD_CLOSE, 0, 0, PASS, CLIENT },
651 /* Get SIGIO when Read lease is broken by Write */
652 {8, CMD_OPEN, O_RDONLY, 0, PASS, CLIENT },
653 {8, CMD_SETLEASE, F_RDLCK, 0, PASS, CLIENT },
654 {8, CMD_GETLEASE, F_RDLCK, 0, PASS, CLIENT },
655 {8, CMD_SIGIO, 0, 0, PASS, CLIENT },
656 {8, CMD_OPEN, O_RDWR, 0, PASS, SERVER },
657 {8, CMD_WAIT_SIGIO, 5, 0, PASS, CLIENT },
658 {8, CMD_CLOSE, 0, 0, PASS, SERVER },
659 {8, CMD_CLOSE, 0, 0, PASS, CLIENT },
661 /* Get SIGIO when Write lease is broken by Truncate */
662 {9, CMD_OPEN, O_RDWR, 0, PASS, CLIENT },
663 {9, CMD_SETLEASE, F_WRLCK, 0, PASS, CLIENT },
664 {9, CMD_GETLEASE, F_WRLCK, 0, PASS, CLIENT },
665 {9, CMD_SIGIO, 0, 0, PASS, CLIENT },
666 {9, CMD_TRUNCATE, FILE_SIZE/2, 0, PASS, CLIENT },
667 {9, CMD_WAIT_SIGIO, 5, 0, PASS, CLIENT },
668 {9, CMD_CLOSE, 0, 0, PASS, CLIENT },
670 /* Get SIGIO when Read lease is broken by Truncate */
671 {10, CMD_OPEN, O_RDONLY, 0, PASS, CLIENT },
672 {10, CMD_SETLEASE, F_RDLCK, 0, PASS, CLIENT },
673 {10, CMD_GETLEASE, F_RDLCK, 0, PASS, CLIENT },
674 {10, CMD_SIGIO, 0, 0, PASS, CLIENT },
675 {10, CMD_TRUNCATE, FILE_SIZE/2, 0, PASS, SERVER },
676 {10, CMD_WAIT_SIGIO, 5, 0, PASS, CLIENT },
677 {10, CMD_CLOSE, 0, 0, PASS, CLIENT },
680 /* indicate end of array */
693 int32_t padding; /* So mac and irix have the same size struct (bloody alignment) */
700 fprintf(stderr, "Usage: %s [options] sharedfile\n\
703 -p port TCP/IP port number for client-server communication\n\
704 -d enable debug tracing\n\
705 -n # test number to run\n\
706 -h host run as client and connect to server on remote host\n\
707 [default run as server]\n", prog);
711 #define INIT_BUFSZ 512
714 initialize(HANDLE fd)
720 int togo = FILE_SIZE;
722 ibuf = (char*)malloc(INIT_BUFSZ);
723 memset(ibuf, ':', INIT_BUFSZ);
728 j = togo > INIT_BUFSZ ? INIT_BUFSZ : togo;
730 if ((nwrite = WRITE(fd, ibuf, j)) != j) {
732 perror("initialize write:");
734 fprintf(stderr, "initialize: write() returns %d, not %d as expected\n",
743 static int do_truncate(size_t length)
748 fprintf(stderr, "truncating to %ld\n", length);
751 rc = truncate(filename, length);
752 if (rc && errno == EINTR)
758 fprintf(stderr, "%s %d : %s\n",
759 __FILE__, errno, strerror(errno));
761 return (rc == 0 ? PASS:FAIL);
764 void release_lease(int fd)
768 rc = fcntl(fd, F_SETLEASE, F_UNLCK);
770 fprintf(stderr, "%s Failed to remove lease %d : %d %s\n",
771 __FILE__, rc, errno, strerror(errno));
774 void lease_break(int sig, siginfo_t *info, void *p)
777 fprintf(stderr, "lease break %d %p fd %d\n",
778 sig, info, info->si_fd);
783 struct sigaction lease_break_action = {
784 .sa_sigaction = lease_break,
785 .sa_flags = SA_SIGINFO,
788 int do_setup_sigio(int fd)
794 rc = sigaction(SIGIO, &lease_break_action, NULL);
796 fprintf(stderr, "%s Set '%s' sigaction failed %d\n",
797 __FILE__, strsignal(SIGIO), rc);
802 fprintf(stderr, "Set '%s' sigaction on %d\n",
803 strsignal(SIGIO), fd);
805 rc = fcntl(fd, F_SETSIG, SIGIO);
807 fprintf(stderr, "%s Set '%s' sigaction failed %d\n",
808 __FILE__, strsignal(SIGIO), rc);
810 return (rc == 0 ? PASS : FAIL);
813 int do_wait_sigio(int32_t time)
818 while (!got_sigio && time--) {
822 if (debug > 1 && !got_sigio)
823 fprintf(stderr, "%s failed to get sigio\n",
826 return (got_sigio ? PASS: FAIL);
829 int do_open(int flag)
831 int flags = flag|O_CREAT|O_BINARY;
834 fprintf(stderr, "do_open %s 0x%x\n", filename, flags);
836 if ((f_fd = open(filename, flags, 0666)) == INVALID_HANDLE) {
837 perror("shared file create");
844 static int do_lock(int cmd, int type, int start, int length)
851 fprintf(stderr, "do_lock: cmd=%d type=%d start=%d, length=%d\n", cmd, type, start, length);
859 fl.l_whence = SEEK_SET;
865 ret = fcntl(filedes, cmd, &fl);
869 fprintf(stderr, "do_lock: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
871 return(ret==0?PASS:FAIL);
874 static int do_lease(int cmd, int arg, int expected)
879 fprintf(stderr, "do_lease: cmd=%d arg=%d exp=%X\n",
887 ret = fcntl(f_fd, cmd, arg);
890 if (expected && (expected == ret))
894 fprintf(stderr, "%s do_lease: ret = %d, errno = %d (%s)\n",
895 __FILE__, ret, errno, strerror(errno));
897 return(ret==0?PASS:FAIL);
903 fprintf(stderr, "do_close\n");
908 f_fd = INVALID_HANDLE;
913 fprintf(stderr, "%s errno = %d (%s)\n",
914 __FILE__, errno, strerror(errno));
920 static void init_ctl(int64_t tests[][6], int32_t index)
922 ctl.test= (int32_t)tests[index][TEST_NUM];
923 ctl.command = (int32_t)tests[index][COMMAND];
924 ctl.offset = tests[index][OFFSET];
925 ctl.length = tests[index][LENGTH];
927 ctl.result = (int32_t)tests[index][RESULT];
937 fprintf(stderr, "send_ctl: test=%d, command=%d offset=%"LL"d, length=%"LL"d, result=%d, error=%d\n",
938 ctl.test, ctl.command, (long long)ctl.offset, (long long)ctl.length,ctl.result, ctl.error);
941 ctl.test= bswap_uint32(ctl.test);
942 ctl.command = bswap_uint32(ctl.command);
943 ctl.offset = bswap_uint64(ctl.offset);
944 ctl.length = bswap_uint64(ctl.length);
945 ctl.result = bswap_uint32(ctl.result);
946 ctl.index= bswap_uint32(ctl.index);
947 ctl.error = bswap_uint32(ctl.error);
948 nwrite = SOCKET_WRITE(c_fd, (char*)&ctl, sizeof(ctl));
950 ctl.test= bswap_uint32(ctl.test);
951 ctl.command = bswap_uint32(ctl.command);
952 ctl.offset = bswap_uint64(ctl.offset);
953 ctl.length = bswap_uint64(ctl.length);
954 ctl.result = bswap_uint32(ctl.result);
955 ctl.index= bswap_uint32(ctl.index);
956 ctl.error= bswap_uint32(ctl.error);
957 if (nwrite != sizeof(ctl)) {
959 perror("send_ctl: write");
961 fprintf(stderr, "send_ctl[%d]: write() returns %d, not %zu as expected\n",
962 ctl.test, nwrite, sizeof(ctl));
973 if ((nread = SOCKET_READ(c_fd, (char*)&ctl, sizeof(ctl))) != sizeof(ctl)) {
977 perror("recv_ctl: read");
979 fprintf(stderr, "recv_ctl[%d]: read() returns %d, not %zu as expected\n",
980 ctl.test, nread, sizeof(ctl));
981 fprintf(stderr, "socket might has been closed by other locktest\n");
986 ctl.test= bswap_uint32(ctl.test);
987 ctl.command = bswap_uint32(ctl.command);
988 ctl.offset = bswap_uint64(ctl.offset);
989 ctl.length = bswap_uint64(ctl.length);
990 ctl.result = bswap_uint32(ctl.result);
991 ctl.index= bswap_uint32(ctl.index);
992 ctl.error= bswap_uint32(ctl.error);
995 fprintf(stderr, "recv_ctl: test=%d, command=%d offset=%"LL"d, length=%"LL"d, result=%d, error=%d\n",
996 ctl.test, ctl.command, (long long)ctl.offset, (long long)ctl.length, ctl.result, ctl.error);
1016 run(int64_t tests[][6], char *descriptions[]);
1019 main(int argc, char *argv[])
1023 struct sockaddr_in myAddr;
1024 struct linger noLinger = {1, 0};
1029 extern char *optarg;
1033 int test_setlease = 0;
1039 /* trim command name of leading directory components */
1041 for (p = prog; *p; p++) {
1046 while ((c = getopt(argc, argv, "dLn:h:p:t?")) != EOF) {
1049 case 'd': /* debug flag */
1053 case 'L': /* Lease testing */
1057 case 'h': /* (server) hostname */
1063 testnumber = atoi(optarg);
1066 case 'p': /* TCP/IP port */
1067 port = (int)strtol(optarg, &endnum, 10);
1068 if (*endnum != '\0') {
1069 fprintf(stderr, "%s: -p argument must be a numeric\n",
1087 if (errflag || optind != argc-1) {
1092 filename=argv[optind];
1094 fprintf(stderr, "Working on file : %s\n", filename);
1095 if (do_open(O_RDWR) == FAIL)
1098 if (test_setlease == 1) {
1099 fcntl(f_fd, F_SETLEASE, F_UNLCK);
1100 saved_errno = errno;
1105 setbuf(stderr, NULL);
1110 s_fd = socket(AF_INET, SOCK_STREAM, 0);
1111 if (s_fd == INVALID_SOCKET) {
1116 if (setsockopt(s_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) < 0) {
1117 perror("setsockopt(nodelay)");
1121 if (setsockopt(s_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one))<0) {
1122 perror("setsockopt(reuseaddr)");
1127 if (setsockopt(s_fd, SOL_SOCKET, SO_REUSEPORT, (char*)&one, sizeof(one))<0) {
1128 perror("setsockopt(reuseport)");
1134 memset(&myAddr, 0, sizeof(myAddr));
1135 myAddr.sin_family = AF_INET;
1136 myAddr.sin_addr.s_addr = htonl(INADDR_ANY);
1137 myAddr.sin_port = htons((short)port);
1138 sts = bind(s_fd, (struct sockaddr*)&myAddr, sizeof(myAddr));
1145 sts = listen(s_fd, 5); /* Max. of 5 pending connection requests */
1153 socklen_t addr_len = sizeof(myAddr);
1155 if (getsockname(s_fd, &myAddr, &addr_len)) {
1156 perror("getsockname");
1160 port = ntohs(myAddr.sin_port);
1163 printf("server port: %d\n", port);
1166 c_fd = accept(s_fd, NULL, NULL);
1167 if (c_fd == INVALID_SOCKET) {
1173 if (debug) fprintf(stderr, "Client accepted\n");
1177 struct hostent *servInfo;
1179 if ((servInfo = gethostbyname(host)) == NULL) {
1180 fprintf(stderr, "Couldn't get hostbyname for %s", host);
1181 if (h_errno == HOST_NOT_FOUND)
1182 fprintf(stderr, ": host not found");
1183 fprintf(stderr, "\n");
1188 c_fd = socket(AF_INET, SOCK_STREAM, 0);
1189 if (c_fd == INVALID_SOCKET) {
1194 /* avoid 200 ms delay */
1195 if (setsockopt(c_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)) < 0) {
1196 perror("setsockopt(nodelay)");
1200 /* Don't linger on close */
1201 if (setsockopt(c_fd, SOL_SOCKET, SO_LINGER, (char *)&noLinger, sizeof(noLinger)) < 0) {
1202 perror("setsockopt(nolinger)");
1207 memset(&myAddr, 0, sizeof(myAddr)); /* Arrgh! &myAddr, not myAddr */
1208 myAddr.sin_family = AF_INET;
1209 memcpy(&myAddr.sin_addr, servInfo->h_addr, servInfo->h_length);
1210 myAddr.sin_port = htons((short)port);
1212 if (connect(c_fd, (struct sockaddr*)&myAddr, sizeof(myAddr)) < 0) {
1213 perror("unable to connect");
1214 fprintf(stderr, "Server might still initializing the shared file\n ");
1219 if (debug) fprintf(stderr, "Connected to server\n");
1224 /* only server need do shared file */
1228 * TCP/IP connection to be established, safe to proceed.
1230 * real work is in here ...
1233 fail_count = run(lease_tests, lease_descriptions);
1235 fail_count = run(lock_tests, lock_descriptions);
1241 int run(int64_t tests[][6], char *descriptions[])
1247 int test_count = -1;
1252 if(testnumber > 0) {
1253 last_test = testnumber - 1;
1254 while(tests[index][TEST_NUM] != testnumber && tests[index][TEST_NUM] != 0) {
1258 /* If we have a server command, deal with it */
1259 if(tests[index][WHO] == SERVER) {
1261 fprintf(stderr, "Got a server command (%d)\n", index);
1262 if(tests[index][TEST_NUM] == 0) {
1266 memset(&ctl, 0, sizeof(ctl));
1267 ctl.test = tests[index][TEST_NUM];
1269 if(tests[index][TEST_NUM] != 0) {
1270 switch(tests[index][COMMAND]) {
1272 result = do_lock(F_SETLK, F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
1275 result = do_lock(F_SETLK, F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
1278 result = do_lock(F_SETLK, F_UNLCK, tests[index][OFFSET], tests[index][LENGTH]);
1281 result = do_close();
1284 result = do_open(tests[index][FLAGS]);
1287 result = do_lock(F_GETLK, F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
1290 result = do_lock(F_GETLK, F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
1293 result = do_lease(F_SETLEASE, tests[index][ARG], 0);
1296 result = do_lease(F_GETLEASE, tests[index][ARG], tests[index][ARG]);
1299 result = do_setup_sigio(f_fd);
1301 case CMD_WAIT_SIGIO:
1302 result = do_wait_sigio(tests[index][TIME]);
1305 result = do_truncate(tests[index][OFFSET]);
1308 if( result != tests[index][RESULT]) {
1310 /* We have a failure */
1311 fprintf(stderr, " ***** Server failure *****\n");
1312 fprintf(stderr, " in test %d, while %sing using offset %lld, length %lld - err = %d:%s\n",
1313 ctl.test, get_cmd_str(tests[index][COMMAND]),
1314 (long long)tests[index][OFFSET],
1315 (long long)tests[index][LENGTH],
1316 saved_errno, strerror(saved_errno));
1317 fprintf(stderr, " %d:%s\n",
1318 ctl.test, descriptions[ctl.test - 1]);
1321 /* else send it off to the client */
1322 } else if (tests[index][WHO] == CLIENT) {
1323 if(tests[index][TEST_NUM] == 0) {
1327 /* get the client to do something */
1328 init_ctl(tests, index);
1330 fprintf(stderr, "Sending command to client (%d) - %s - %lld:%lld\n",
1332 get_cmd_str(ctl.command),
1333 (long long)tests[index][OFFSET],
1334 (long long)tests[index][LENGTH]);
1335 /* get the client to do something */
1339 /* Get the clients response */
1341 /* this is the whether the test passed or failed,
1342 * not what the command returned */
1343 if( ctl.result == FAIL ) {
1345 fprintf(stderr, " ***** Client failure *****\n");
1346 fprintf(stderr, " in test %d, while %sing using offset %lld, length %lld - err = %d:%s\n",
1347 ctl.test, get_cmd_str(ctl.command),
1348 (long long)ctl.offset, (long long)ctl.length,
1349 ctl.error, strerror(ctl.error));
1350 fprintf(stderr, " %d:%s\n",
1351 ctl.test, descriptions[ctl.test - 1]);
1356 if(last_test != tests[index][TEST_NUM]) {
1361 last_test = tests[index][TEST_NUM];
1365 } else { /* CLIENT */
1367 fprintf(stderr,"client: waiting...\n");
1368 /* wait for the server to do something */
1371 /* check for a client command */
1373 if (tests[index][WHO] != CLIENT) {
1374 fprintf(stderr, "not a client command index (%d)\n", index);
1383 switch(ctl.command) {
1385 result = do_lock(F_SETLK, F_WRLCK, ctl.offset, ctl.length);
1388 result = do_lock(F_SETLK, F_RDLCK, ctl.offset, ctl.length);
1391 result = do_lock(F_SETLK, F_UNLCK, ctl.offset, ctl.length);
1394 result = do_close();
1397 result = do_open(tests[index][FLAGS]);
1400 result = do_lock(F_GETLK, F_WRLCK, ctl.offset, ctl.length);
1403 result = do_lock(F_GETLK, F_RDLCK, ctl.offset, ctl.length);
1405 /* NOTE offset carries the argument values */
1407 result = do_lease(F_SETLEASE, ctl.offset, 0);
1410 result = do_lease(F_GETLEASE, ctl.offset, ctl.offset);
1413 result = do_setup_sigio(f_fd);
1415 case CMD_WAIT_SIGIO:
1416 result = do_wait_sigio(ctl.offset);
1419 result = do_truncate(ctl.offset);
1422 if( result != ctl.result ) {
1423 fprintf(stderr,"Failure in %d:%s\n",
1424 ctl.test, descriptions[ctl.test - 1]);
1425 fprintf(stderr," Got %d, wanted %d\n",
1426 result, ctl.result);
1428 ctl.error = saved_errno;
1435 fprintf(stderr,"client: sending result to server (%d)\n", ctl.index);
1436 /* Send result to the server */
1438 if(last_test != tests[index][TEST_NUM]) {
1440 last_test = tests[index][TEST_NUM];
1444 fprintf(stderr, "%d tests run, %d failed\n", test_count, fail_count);