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>
47 #define ERROR(fmt, ...) \
48 fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
49 program_invocation_short_name, __FILE__, __LINE__, \
50 __func__, ## __VA_ARGS__);
52 #define DIE(fmt, ...) \
54 ERROR(fmt, ## __VA_ARGS__); \
58 #define ASSERTF(cond, fmt, ...) \
61 DIE("assertion '%s' failed: "fmt, \
62 #cond, ## __VA_ARGS__); \
65 #define PERFORM(testfn) \
68 fprintf(stderr, "Starting test " #testfn " at %lld\n", \
69 (unsigned long long)time(NULL)); \
71 fprintf(stderr, "Finishing test " #testfn " at %lld\n", \
72 (unsigned long long)time(NULL)); \
76 /* Name of file/directory. Will be set once and will not change. */
77 static char mainpath[PATH_MAX];
78 static const char *maindir = "group_lock_test_name_9585766";
80 static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */
81 static char *lustre_dir; /* Test directory inside Lustre */
83 /* Cleanup our test file. */
84 static void cleanup(void)
90 /* Test lock / unlock */
91 static void test10(void)
98 /* Create the test file, and open it. */
99 fd = creat(mainpath, 0);
100 ASSERTF(fd >= 0, "creat failed for '%s': %s",
101 mainpath, strerror(errno));
103 /* Valid command first. */
105 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
106 ASSERTF(rc == 0, "cannot lock '%s': %s",
107 mainpath, strerror(errno));
108 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
109 ASSERTF(rc == 0, "cannot unlock '%s': %s",
110 mainpath, strerror(errno));
114 for (i = 0; i < 1000; i++) {
115 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
117 "cannot lock '%s': %s (loop %d)",
118 mainpath, strerror(errno), i);
119 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
121 "cannot unlock '%s': %s (loop %d)",
122 mainpath, strerror(errno), i);
127 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
128 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
129 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
130 ASSERTF(rc == -1 && errno == EINVAL,
131 "lock unexpectedly granted for '%s': %s",
132 mainpath, strerror(errno));
133 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
134 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
135 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
136 ASSERTF(rc == -1 && errno == EINVAL, "unexpected unlock retval: %d %s",
137 rc, strerror(errno));
139 /* 0 is an invalid gid */
141 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
142 ASSERTF(rc == -1 && errno == EINVAL, "unexpected lock retval: %s",
145 /* Lock/unlock with a different gid */
147 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
148 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
149 for (gid = -10; gid < 10; gid++) {
150 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
151 ASSERTF(rc == -1 && errno == EINVAL,
152 "unexpected unlock retval: %d %s (gid %d)",
153 rc, strerror(errno), gid);
156 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
157 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
162 /* Test open/lock/close without unlocking */
163 static void test11(void)
170 /* Create the test file. */
171 fd = creat(mainpath, 0);
172 ASSERTF(fd >= 0, "creat failed for '%s': %s",
173 mainpath, strerror(errno));
174 memset(buf, 0x5a, sizeof(buf));
175 rc = write(fd, buf, sizeof(buf));
176 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
177 mainpath, strerror(errno));
180 /* Open/lock and close many times. Open with different
182 for (gid = 1; gid < 10000; gid++) {
183 int oflags = O_RDONLY;
193 oflags = O_WRONLY | O_APPEND;
196 oflags = O_WRONLY | O_CLOEXEC;
199 oflags = O_WRONLY | O_DIRECT;
202 oflags = O_WRONLY | O_NOATIME;
205 oflags = O_WRONLY | O_SYNC;
208 oflags = O_RDONLY | O_DIRECT;
214 oflags = O_RDONLY | O_LOV_DELAY_CREATE;
218 fd = open(mainpath, oflags);
219 ASSERTF(fd >= 0, "open failed for '%s': %s (oflags=%d, gid=%d)",
220 mainpath, strerror(errno), oflags, gid);
222 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
223 ASSERTF(rc == 0, "cannot lock '%s': %s (oflags=%d, gid=%d)",
224 mainpath, strerror(errno), oflags, gid);
230 /* Lock / unlock a volatile file, with different creation flags */
231 static void test12(void)
237 rc = mkdir(mainpath, 0600);
238 ASSERTF(rc == 0, "mkdir failed for '%s': %s",
239 mainpath, strerror(errno));
241 fd = llapi_create_volatile_idx(mainpath, -1, O_CREAT | O_WRONLY);
242 ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
243 mainpath, strerror(-fd));
246 rc = llapi_group_lock(fd, gid);
247 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
249 rc = llapi_group_unlock(fd, gid);
250 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
254 fd = llapi_create_volatile_idx(mainpath, -1,
255 O_CREAT | O_WRONLY | O_LOV_DELAY_CREATE);
256 ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
257 mainpath, strerror(-fd));
260 rc = llapi_group_lock(fd, gid);
261 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
263 rc = llapi_group_unlock(fd, gid);
264 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
268 fd = llapi_create_volatile_idx(mainpath, -1, O_RDONLY);
269 ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
270 mainpath, strerror(-fd));
273 rc = llapi_group_lock(fd, gid);
274 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
276 rc = llapi_group_unlock(fd, gid);
277 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
282 static void helper_test20(int fd)
288 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
289 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
290 rc, strerror(errno));
293 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
294 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
295 rc, strerror(errno));
298 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
299 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
300 rc, strerror(errno));
303 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
304 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
305 rc, strerror(errno));
308 /* Test lock / unlock on a directory */
309 static void test20(void)
313 char dname[PATH_MAX];
315 /* Try the mountpoint. Should fail. */
316 fd = open(fsmountdir, O_RDONLY | O_DIRECTORY);
317 ASSERTF(fd >= 0, "open failed for '%s': %s", mainpath, strerror(errno));
321 /* Try .lustre/ . Should fail. */
322 rc = snprintf(dname, sizeof(dname), "%s/.lustre", fsmountdir);
323 ASSERTF(rc < sizeof(dname), "Name too long");
325 fd = open(fsmountdir, O_RDONLY | O_DIRECTORY);
326 ASSERTF(fd >= 0, "open failed for '%s': %s", mainpath, strerror(errno));
330 /* A regular directory. */
331 rc = mkdir(mainpath, 0600);
332 ASSERTF(rc == 0, "mkdir failed for '%s': %s",
333 mainpath, strerror(errno));
335 fd = open(mainpath, O_RDONLY | O_DIRECTORY);
336 ASSERTF(fd >= 0, "open failed for '%s': %s",
337 mainpath, strerror(errno));
342 /* Test locking between several fds. */
343 static void test30(void)
351 /* Create the test file, and open it. */
352 fd1 = creat(mainpath, 0);
353 ASSERTF(fd1 >= 0, "open failed for '%s': %s",
354 mainpath, strerror(errno));
356 /* Open a second time in non blocking mode. */
357 fd2 = open(mainpath, O_RDWR | O_NONBLOCK);
358 ASSERTF(fd2 >= 0, "open failed for '%s': %s",
359 mainpath, strerror(errno));
361 /* Valid command first. */
363 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
364 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
365 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
366 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
368 /* Lock on one fd, unlock on the other */
370 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
371 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
372 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
373 ASSERTF(rc == -1 && errno == EINVAL,
374 "unexpected unlock retval: %d %s", rc, strerror(errno));
375 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
376 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
380 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
381 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
382 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid);
383 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
384 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
385 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
386 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
387 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
389 /* Lock from both. Unlock in reverse order. */
391 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
392 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
393 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid);
394 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
395 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
396 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
397 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
398 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
400 /* Try to lock with different gids */
402 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
403 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
404 for (gid2 = -50; gid2 < 50; gid2++) {
405 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid2);
407 ASSERTF(rc == -1 && errno == EINVAL,
408 "unexpected lock retval for gid %d: %s",
409 gid2, strerror(errno));
411 ASSERTF(rc == -1 && errno == EAGAIN,
412 "unexpected lock retval for gid %d: %s",
413 gid2, strerror(errno));
415 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
416 ASSERTF(rc == 0, "cannot unlock '%s': %s",
417 mainpath, strerror(errno));
423 static void usage(char *prog)
425 fprintf(stderr, "Usage: %s [-d lustre_dir]\n", prog);
429 static void process_args(int argc, char *argv[])
433 while ((c = getopt(argc, argv, "d:")) != -1) {
440 fprintf(stderr, "Unknown option '%c'\n", optopt);
447 int main(int argc, char *argv[])
452 process_args(argc, argv);
453 if (lustre_dir == NULL)
454 lustre_dir = "/mnt/lustre";
456 rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
458 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
463 /* Play nice with Lustre test scripts. Non-line buffered output
464 * stream under I/O redirection may appear incorrectly. */
465 setvbuf(stdout, NULL, _IOLBF, 0);
467 /* Create a test filename and reuse it. Remove possibly old files. */
468 rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir, maindir);
469 ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");