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 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) \
66 fprintf(stderr, "Starting test " #testfn " at %lld\n", \
67 (unsigned long long)time(NULL)); \
69 fprintf(stderr, "Finishing test " #testfn " at %lld\n", \
70 (unsigned long long)time(NULL)); \
73 /* Name of file/directory. Will be set once and will not change. */
74 static char mainpath[PATH_MAX];
75 static const char *maindir = "group_lock_test_name_9585766";
77 static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */
78 static char *lustre_dir; /* Test directory inside Lustre */
80 /* Cleanup our test file. */
81 static void cleanup(void)
87 /* Test lock / unlock */
88 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)
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);
233 static void helper_test20(int fd)
239 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
240 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
241 rc, strerror(errno));
244 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
245 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
246 rc, strerror(errno));
249 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
250 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
251 rc, strerror(errno));
254 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
255 ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
256 rc, strerror(errno));
259 /* Test lock / unlock on a directory */
260 static void test20(void)
264 char dname[PATH_MAX];
268 /* Try the mountpoint. Should fail. */
269 fd = open(fsmountdir, O_RDONLY | O_DIRECTORY);
270 ASSERTF(fd >= 0, "open failed for '%s': %s", mainpath, strerror(errno));
274 /* Try .lustre/ . Should fail. */
275 rc = snprintf(dname, sizeof(dname), "%s/.lustre", fsmountdir);
276 ASSERTF(rc < sizeof(dname), "Name too long");
278 fd = open(fsmountdir, O_RDONLY | O_DIRECTORY);
279 ASSERTF(fd >= 0, "open failed for '%s': %s", mainpath, strerror(errno));
283 /* A regular directory. */
284 rc = mkdir(mainpath, 0600);
285 ASSERTF(fd >= 0, "mkdir failed for '%s': %s",
286 mainpath, strerror(errno));
288 fd = open(mainpath, O_RDONLY | O_DIRECTORY);
289 ASSERTF(fd >= 0, "open failed for '%s': %s",
290 mainpath, strerror(errno));
295 /* Test locking between several fds. */
296 static void test30(void)
306 /* Create the test file, and open it. */
307 fd1 = creat(mainpath, 0);
308 ASSERTF(fd1 >= 0, "open failed for '%s': %s",
309 mainpath, strerror(errno));
311 /* Open a second time in non blocking mode. */
312 fd2 = open(mainpath, O_RDWR | O_NONBLOCK);
313 ASSERTF(fd2 >= 0, "open failed for '%s': %s",
314 mainpath, strerror(errno));
316 /* Valid command first. */
318 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
319 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
320 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
321 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
323 /* Lock on one fd, unlock on the other */
325 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
326 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
327 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
328 ASSERTF(rc == -1 && errno == EINVAL,
329 "unexpected unlock retval: %d %s", rc, strerror(errno));
330 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
331 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
335 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
336 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
337 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid);
338 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
339 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
340 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
341 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
342 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
344 /* Lock from both. Unlock in reverse order. */
346 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
347 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
348 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid);
349 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
350 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
351 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
352 rc = ioctl(fd2, LL_IOC_GROUP_UNLOCK, gid);
353 ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(errno));
355 /* Try to lock with different gids */
357 rc = ioctl(fd1, LL_IOC_GROUP_LOCK, gid);
358 ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(errno));
359 for (gid2 = -50; gid2 < 50; gid2++) {
360 rc = ioctl(fd2, LL_IOC_GROUP_LOCK, gid2);
362 ASSERTF(rc == -1 && errno == EINVAL,
363 "unexpected lock retval for gid %d: %s",
364 gid2, strerror(errno));
366 ASSERTF(rc == -1 && errno == EAGAIN,
367 "unexpected lock retval for gid %d: %s",
368 gid2, strerror(errno));
370 rc = ioctl(fd1, LL_IOC_GROUP_UNLOCK, gid);
371 ASSERTF(rc == 0, "cannot unlock '%s': %s",
372 mainpath, strerror(errno));
378 static void usage(char *prog)
380 fprintf(stderr, "Usage: %s [-d lustre_dir]\n", prog);
384 static void process_args(int argc, char *argv[])
388 while ((c = getopt(argc, argv, "d:")) != -1) {
395 fprintf(stderr, "Unknown option '%c'\n", optopt);
402 int main(int argc, char *argv[])
407 process_args(argc, argv);
408 if (lustre_dir == NULL)
409 lustre_dir = "/mnt/lustre";
411 rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
413 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
418 /* Play nice with Lustre test scripts. Non-line buffered output
419 * stream under I/O redirection may appear incorrectly. */
420 setvbuf(stdout, NULL, _IOLBF, 0);
422 /* Create a test filename and reuse it. Remove possibly old files. */
423 rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir, maindir);
424 ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");