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/types.h>
43 #include <lustre/lustreapi.h>
44 #include <lustre/lustre_idl.h>
46 #define ERROR(fmt, ...) \
47 fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
48 program_invocation_short_name, __FILE__, __LINE__, \
49 __func__, ## __VA_ARGS__);
51 #define DIE(fmt, ...) \
53 ERROR(fmt, ## __VA_ARGS__); \
57 #define ASSERTF(cond, fmt, ...) \
60 DIE("assertion '%s' failed: "fmt, \
61 #cond, ## __VA_ARGS__); \
64 #define PERFORM(testfn) \
67 fprintf(stderr, "Starting test " #testfn " at %lld\n", \
68 (unsigned long long)time(NULL)); \
70 fprintf(stderr, "Finishing test " #testfn " at %lld\n", \
71 (unsigned long long)time(NULL)); \
75 /* Name of file/directory. Will be set once and will not change. */
76 static char mainpath[PATH_MAX];
77 static const char *maindir = "group_lock_test_name_9585766";
79 static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */
80 static char *lustre_dir; /* Test directory inside Lustre */
82 /* Cleanup our test file. */
83 static void cleanup(void)
89 /* Test lock / unlock */
90 static void test10(void)
97 /* Create the test file, and open it. */
98 fd = creat(mainpath, 0);
99 ASSERTF(fd >= 0, "creat failed for '%s': %s",
100 mainpath, strerror(errno));
102 /* Valid command first. */
104 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
105 ASSERTF(rc == 0, "cannot lock '%s': %s",
106 mainpath, strerror(errno));
107 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
108 ASSERTF(rc == 0, "cannot unlock '%s': %s",
109 mainpath, strerror(errno));
113 for (i = 0; i < 1000; i++) {
114 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
116 "cannot lock '%s': %s (loop %d)",
117 mainpath, strerror(errno), i);
118 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
120 "cannot unlock '%s': %s (loop %d)",
121 mainpath, strerror(errno), i);
126 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
127 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
128 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
129 ASSERTF(rc == -1 && errno == EINVAL,
130 "lock unexpectedly granted for '%s': %s",
131 mainpath, strerror(errno));
132 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
133 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
134 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
135 ASSERTF(rc == -1 && errno == EINVAL, "unexpected unlock retval: %d %s",
136 rc, strerror(errno));
138 /* 0 is an invalid gid */
140 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
141 ASSERTF(rc == -1 && errno == EINVAL, "unexpected lock retval: %s",
144 /* Lock/unlock with a different gid */
146 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
147 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
148 for (gid = -10; gid < 10; gid++) {
149 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
150 ASSERTF(rc == -1 && errno == EINVAL,
151 "unexpected unlock retval: %d %s (gid %d)",
152 rc, strerror(errno), gid);
155 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
156 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
161 /* Test open/lock/close without unlocking */
162 static void test11(void)
169 /* Create the test file. */
170 fd = creat(mainpath, 0);
171 ASSERTF(fd >= 0, "creat failed for '%s': %s",
172 mainpath, strerror(errno));
173 memset(buf, 0x5a, sizeof(buf));
174 rc = write(fd, buf, sizeof(buf));
175 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
176 mainpath, strerror(errno));
179 /* Open/lock and close many times. Open with different
181 for (gid = 1; gid < 10000; gid++) {
182 int oflags = O_RDONLY;
192 oflags = O_WRONLY | O_APPEND;
195 oflags = O_WRONLY | O_CLOEXEC;
198 oflags = O_WRONLY | O_DIRECT;
201 oflags = O_WRONLY | O_NOATIME;
204 oflags = O_WRONLY | O_SYNC;
207 oflags = O_RDONLY | O_DIRECT;
213 oflags = O_RDONLY | O_LOV_DELAY_CREATE;
217 fd = open(mainpath, oflags);
218 ASSERTF(fd >= 0, "open failed for '%s': %s (oflags=%d, gid=%d)",
219 mainpath, strerror(errno), oflags, gid);
221 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
222 ASSERTF(rc == 0, "cannot lock '%s': %s (oflags=%d, gid=%d)",
223 mainpath, strerror(errno), oflags, gid);
229 /* Lock / unlock a volatile file, with different creation flags */
230 static void test12(void)
236 rc = mkdir(mainpath, 0600);
237 ASSERTF(rc == 0, "mkdir failed for '%s': %s",
238 mainpath, strerror(errno));
240 fd = llapi_create_volatile_idx(mainpath, -1, O_CREAT | O_WRONLY);
241 ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
242 mainpath, strerror(-fd));
245 rc = llapi_group_lock(fd, gid);
246 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
248 rc = llapi_group_unlock(fd, gid);
249 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
253 fd = llapi_create_volatile_idx(mainpath, -1,
254 O_CREAT | O_WRONLY | O_LOV_DELAY_CREATE);
255 ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
256 mainpath, strerror(-fd));
259 rc = llapi_group_lock(fd, gid);
260 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
262 rc = llapi_group_unlock(fd, gid);
263 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
267 fd = llapi_create_volatile_idx(mainpath, -1, O_RDONLY);
268 ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
269 mainpath, strerror(-fd));
272 rc = llapi_group_lock(fd, gid);
273 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
275 rc = llapi_group_unlock(fd, gid);
276 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
281 static void helper_test20(int fd)
287 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
288 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
289 rc, strerror(errno));
292 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
293 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
294 rc, strerror(errno));
297 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
298 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
299 rc, strerror(errno));
302 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
303 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
304 rc, strerror(errno));
307 /* Test lock / unlock on a directory */
308 static void test20(void)
312 char dname[PATH_MAX];
314 /* Try the mountpoint. Should fail. */
315 fd = open(fsmountdir, O_RDONLY | O_DIRECTORY);
316 ASSERTF(fd >= 0, "open failed for '%s': %s", mainpath, strerror(errno));
320 /* Try .lustre/ . Should fail. */
321 rc = snprintf(dname, sizeof(dname), "%s/.lustre", fsmountdir);
322 ASSERTF(rc < sizeof(dname), "Name too long");
324 fd = open(fsmountdir, O_RDONLY | O_DIRECTORY);
325 ASSERTF(fd >= 0, "open failed for '%s': %s", mainpath, strerror(errno));
329 /* A regular directory. */
330 rc = mkdir(mainpath, 0600);
331 ASSERTF(rc == 0, "mkdir failed for '%s': %s",
332 mainpath, strerror(errno));
334 fd = open(mainpath, O_RDONLY | O_DIRECTORY);
335 ASSERTF(fd >= 0, "open failed for '%s': %s",
336 mainpath, strerror(errno));
341 /* Test locking between several fds. */
342 static void test30(void)
350 /* Create the test file, and open it. */
351 fd1 = creat(mainpath, 0);
352 ASSERTF(fd1 >= 0, "open failed for '%s': %s",
353 mainpath, strerror(errno));
355 /* Open a second time in non blocking mode. */
356 fd2 = open(mainpath, O_RDWR | O_NONBLOCK);
357 ASSERTF(fd2 >= 0, "open failed for '%s': %s",
358 mainpath, strerror(errno));
360 /* Valid command first. */
362 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
363 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
364 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
365 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
367 /* Lock on one fd, unlock on the other */
369 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
370 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
371 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
372 ASSERTF(rc == -1 && errno == EINVAL,
373 "unexpected unlock retval: %d %s", rc, strerror(errno));
374 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
375 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
379 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
380 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
381 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid);
382 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
383 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
384 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
385 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
386 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
388 /* Lock from both. Unlock in reverse order. */
390 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
391 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
392 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid);
393 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
394 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
395 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
396 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
397 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
399 /* Try to lock with different gids */
401 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
402 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
403 for (gid2 = -50; gid2 < 50; gid2++) {
404 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid2);
406 ASSERTF(rc == -1 && errno == EINVAL,
407 "unexpected lock retval for gid %d: %s",
408 gid2, strerror(errno));
410 ASSERTF(rc == -1 && errno == EAGAIN,
411 "unexpected lock retval for gid %d: %s",
412 gid2, strerror(errno));
414 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
415 ASSERTF(rc == 0, "cannot unlock '%s': %s",
416 mainpath, strerror(errno));
422 static void usage(char *prog)
424 fprintf(stderr, "Usage: %s [-d lustre_dir]\n", prog);
428 static void process_args(int argc, char *argv[])
432 while ((c = getopt(argc, argv, "d:")) != -1) {
439 fprintf(stderr, "Unknown option '%c'\n", optopt);
446 int main(int argc, char *argv[])
451 process_args(argc, argv);
452 if (lustre_dir == NULL)
453 lustre_dir = "/mnt/lustre";
455 rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
457 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
462 /* Play nice with Lustre test scripts. Non-line buffered output
463 * stream under I/O redirection may appear incorrectly. */
464 setvbuf(stdout, NULL, _IOLBF, 0);
466 /* Create a test filename and reuse it. Remove possibly old files. */
467 rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir, maindir);
468 ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");