4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
24 * Copyright 2014, 2015 Cray Inc, all rights reserved.
27 * A few portions are extracted from llapi_layout_test.c
29 * The purpose of this test is to exert the group lock ioctls.
31 * The program will exit as soon as a non zero error code is returned.
38 #include <sys/ioctl.h>
39 #include <sys/types.h>
45 #include <lustre/lustreapi.h>
46 #include <lustre/lustre_idl.h>
48 #define ERROR(fmt, ...) \
49 fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
50 program_invocation_short_name, __FILE__, __LINE__, \
51 __func__, ## __VA_ARGS__);
53 #define DIE(fmt, ...) \
55 ERROR(fmt, ## __VA_ARGS__); \
59 #define ASSERTF(cond, fmt, ...) \
62 DIE("assertion '%s' failed: "fmt, \
63 #cond, ## __VA_ARGS__); \
66 #define PERFORM(testfn) \
69 fprintf(stderr, "Starting test " #testfn " at %lld\n", \
70 (unsigned long long)time(NULL)); \
72 fprintf(stderr, "Finishing test " #testfn " at %lld\n", \
73 (unsigned long long)time(NULL)); \
77 /* Name of file/directory. Will be set once and will not change. */
78 static char mainpath[PATH_MAX];
79 static const char *maindir = "group_lock_test_name_9585766";
81 static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */
82 static char *lustre_dir; /* Test directory inside Lustre */
84 /* Cleanup our test file. */
85 static void cleanup(void)
91 /* Test lock / unlock */
92 static void test10(void)
99 /* Create the test file, and open it. */
100 fd = creat(mainpath, 0);
101 ASSERTF(fd >= 0, "creat failed for '%s': %s",
102 mainpath, strerror(errno));
104 /* Valid command first. */
106 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
107 ASSERTF(rc == 0, "cannot lock '%s': %s",
108 mainpath, strerror(errno));
109 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
110 ASSERTF(rc == 0, "cannot unlock '%s': %s",
111 mainpath, strerror(errno));
115 for (i = 0; i < 1000; i++) {
116 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
118 "cannot lock '%s': %s (loop %d)",
119 mainpath, strerror(errno), i);
120 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
122 "cannot unlock '%s': %s (loop %d)",
123 mainpath, strerror(errno), i);
128 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
129 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
130 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
131 ASSERTF(rc == -1 && errno == EINVAL,
132 "lock unexpectedly granted for '%s': %s",
133 mainpath, strerror(errno));
134 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
135 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
136 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
137 ASSERTF(rc == -1 && errno == EINVAL, "unexpected unlock retval: %d %s",
138 rc, strerror(errno));
140 /* 0 is an invalid gid */
142 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
143 ASSERTF(rc == -1 && errno == EINVAL, "unexpected lock retval: %s",
146 /* Lock/unlock with a different gid */
148 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
149 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
150 for (gid = -10; gid < 10; gid++) {
151 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
152 ASSERTF(rc == -1 && errno == EINVAL,
153 "unexpected unlock retval: %d %s (gid %d)",
154 rc, strerror(errno), gid);
157 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
158 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
163 /* Test open/lock/close without unlocking */
164 static void test11(void)
171 /* Create the test file. */
172 fd = creat(mainpath, 0);
173 ASSERTF(fd >= 0, "creat failed for '%s': %s",
174 mainpath, strerror(errno));
175 memset(buf, 0x5a, sizeof(buf));
176 rc = write(fd, buf, sizeof(buf));
177 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
178 mainpath, strerror(errno));
181 /* Open/lock and close many times. Open with different
183 for (gid = 1; gid < 10000; gid++) {
184 int oflags = O_RDONLY;
194 oflags = O_WRONLY | O_APPEND;
197 oflags = O_WRONLY | O_CLOEXEC;
200 oflags = O_WRONLY | O_DIRECT;
203 oflags = O_WRONLY | O_NOATIME;
206 oflags = O_WRONLY | O_SYNC;
209 oflags = O_RDONLY | O_DIRECT;
215 oflags = O_RDONLY | O_LOV_DELAY_CREATE;
219 fd = open(mainpath, oflags);
220 ASSERTF(fd >= 0, "open failed for '%s': %s (oflags=%d, gid=%d)",
221 mainpath, strerror(errno), oflags, gid);
223 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
224 ASSERTF(rc == 0, "cannot lock '%s': %s (oflags=%d, gid=%d)",
225 mainpath, strerror(errno), oflags, gid);
231 /* Lock / unlock a volatile file, with different creation flags */
232 static void test12(void)
238 rc = mkdir(mainpath, 0600);
239 ASSERTF(rc == 0, "mkdir failed for '%s': %s",
240 mainpath, strerror(errno));
242 fd = llapi_create_volatile_idx(mainpath, -1, O_CREAT | O_WRONLY);
243 ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
244 mainpath, strerror(-fd));
247 rc = llapi_group_lock(fd, gid);
248 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
250 rc = llapi_group_unlock(fd, gid);
251 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
255 fd = llapi_create_volatile_idx(mainpath, -1,
256 O_CREAT | O_WRONLY | O_LOV_DELAY_CREATE);
257 ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
258 mainpath, strerror(-fd));
261 rc = llapi_group_lock(fd, gid);
262 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
264 rc = llapi_group_unlock(fd, gid);
265 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
269 fd = llapi_create_volatile_idx(mainpath, -1, O_RDONLY);
270 ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
271 mainpath, strerror(-fd));
274 rc = llapi_group_lock(fd, gid);
275 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
277 rc = llapi_group_unlock(fd, gid);
278 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
283 static void helper_test20(int fd)
289 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
290 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
291 rc, strerror(errno));
294 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
295 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
296 rc, strerror(errno));
299 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
300 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
301 rc, strerror(errno));
304 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
305 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
306 rc, strerror(errno));
309 /* Test lock / unlock on a directory */
310 static void test20(void)
314 char dname[PATH_MAX];
316 /* Try the mountpoint. Should fail. */
317 fd = open(fsmountdir, O_RDONLY | O_DIRECTORY);
318 ASSERTF(fd >= 0, "open failed for '%s': %s", mainpath, strerror(errno));
322 /* Try .lustre/ . Should fail. */
323 rc = snprintf(dname, sizeof(dname), "%s/.lustre", fsmountdir);
324 ASSERTF(rc < sizeof(dname), "Name too long");
326 fd = open(fsmountdir, O_RDONLY | O_DIRECTORY);
327 ASSERTF(fd >= 0, "open failed for '%s': %s", mainpath, strerror(errno));
331 /* A regular directory. */
332 rc = mkdir(mainpath, 0600);
333 ASSERTF(rc == 0, "mkdir failed for '%s': %s",
334 mainpath, strerror(errno));
336 fd = open(mainpath, O_RDONLY | O_DIRECTORY);
337 ASSERTF(fd >= 0, "open failed for '%s': %s",
338 mainpath, strerror(errno));
343 /* Test locking between several fds. */
344 static void test30(void)
352 /* Create the test file, and open it. */
353 fd1 = creat(mainpath, 0);
354 ASSERTF(fd1 >= 0, "open failed for '%s': %s",
355 mainpath, strerror(errno));
357 /* Open a second time in non blocking mode. */
358 fd2 = open(mainpath, O_RDWR | O_NONBLOCK);
359 ASSERTF(fd2 >= 0, "open failed for '%s': %s",
360 mainpath, strerror(errno));
362 /* Valid command first. */
364 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
365 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
366 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
367 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
369 /* Lock on one fd, unlock on the other */
371 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
372 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
373 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
374 ASSERTF(rc == -1 && errno == EINVAL,
375 "unexpected unlock retval: %d %s", rc, strerror(errno));
376 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
377 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
381 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
382 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
383 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid);
384 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
385 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
386 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
387 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
388 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
390 /* Lock from both. Unlock in reverse order. */
392 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
393 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
394 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid);
395 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
396 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
397 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
398 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
399 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
401 /* Try to lock with different gids */
403 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
404 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
405 for (gid2 = -50; gid2 < 50; gid2++) {
406 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid2);
408 ASSERTF(rc == -1 && errno == EINVAL,
409 "unexpected lock retval for gid %d: %s",
410 gid2, strerror(errno));
412 ASSERTF(rc == -1 && errno == EAGAIN,
413 "unexpected lock retval for gid %d: %s",
414 gid2, strerror(errno));
416 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
417 ASSERTF(rc == 0, "cannot unlock '%s': %s",
418 mainpath, strerror(errno));
424 static void usage(char *prog)
426 fprintf(stderr, "Usage: %s [-d lustre_dir]\n", prog);
430 static void process_args(int argc, char *argv[])
434 while ((c = getopt(argc, argv, "d:")) != -1) {
441 fprintf(stderr, "Unknown option '%c'\n", optopt);
448 int main(int argc, char *argv[])
453 process_args(argc, argv);
454 if (lustre_dir == NULL)
455 lustre_dir = "/mnt/lustre";
457 rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
459 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
464 /* Play nice with Lustre test scripts. Non-line buffered output
465 * stream under I/O redirection may appear incorrectly. */
466 setvbuf(stdout, NULL, _IOLBF, 0);
468 /* Create a test filename and reuse it. Remove possibly old files. */
469 rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir, maindir);
470 ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");