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
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2012, 2015, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
30 * Lustre is a trademark of Sun Microsystems, Inc.
34 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
41 #include <sys/types.h>
45 #include <sys/ioctl.h>
46 #include <sys/xattr.h>
51 #include <semaphore.h>
55 #include <lustre/lustre_idl.h>
56 #include <lustre/lustreapi.h>
58 #define T1 "write data before unlink\n"
59 #define T2 "write data after unlink\n"
60 char msg[] = "yabba dabba doo, I'm coming for you, I live in a shoe, I don't know what to do.\n'Bigger, bigger,and bigger yet!' cried the Creator. 'You are not yet substantial enough for my boundless intents!' And ever greater and greater the object became, until all was lost 'neath its momentus bulk.\n";
61 char *buf, *buf_align;
64 #define ALIGN_LEN 65535
65 #define XATTR "user.multiop"
68 "Usage: %s filename command-sequence [path...]\n"
69 " command-sequence items:\n"
70 " A fsetxattr(\"user.multiop\")\n"
71 " a fgetxattr(\"user.multiop\")\n"
73 " B[num] call setstripe ioctl to create stripes\n"
74 " C[num] create with optional stripes\n"
76 " D open(O_DIRECTORY)\n"
77 " e[R|W|U] apply lease. R: Read; W: Write; U: Unlock\n"
78 " E[+|-] get lease. +/-: expect lease to (not) exist\n"
81 " H[num] create HSM released file with num stripes\n"
82 " G gid get grouplock\n"
83 " g gid put grouplock\n"
84 " K link path to filename\n"
86 " l symlink filename to path\n"
88 " M rw mmap to EOF (must open and stat prior)\n"
89 " n rename path to filename\n"
90 " N rename filename to path\n"
92 " O open(O_CREAT|O_RDWR)\n"
93 " r[num] read [optional length]\n"
94 " R reference entire mmap-ed region\n"
98 " T[num] ftruncate [optional position, default 0]\n"
102 " V open a volatile file\n"
103 " w[num] write optional length\n"
104 " x get file data version\n"
105 " W write entire mmap-ed region\n"
108 " z[num] seek [optional position, default 0]\n"
109 " _ wait for signal\n";
111 void usr1_handler(int unused)
113 int saved_errno = errno;
116 * signal(7): POSIX.1-2004 ...requires an implementation to guarantee
117 * that the following functions can be safely called inside a signal
127 pop_arg(int argc, char *argv[])
129 static int cur_arg = 3;
134 return argv[cur_arg++];
137 struct flag_mapping {
141 {"O_RDONLY", O_RDONLY},
142 {"O_WRONLY", O_WRONLY},
144 {"O_CREAT", O_CREAT},
146 {"O_NOCTTY", O_NOCTTY},
147 {"O_TRUNC", O_TRUNC},
148 {"O_APPEND", O_APPEND},
149 {"O_NONBLOCK", O_NONBLOCK},
150 {"O_NDELAY", O_NDELAY},
153 {"O_DIRECT", O_DIRECT},
156 {"O_NOATIME", O_NOATIME},
158 {"O_LARGEFILE", O_LARGEFILE},
159 {"O_DIRECTORY", O_DIRECTORY},
160 {"O_NOFOLLOW", O_NOFOLLOW},
161 {"O_LOV_DELAY_CREATE", O_LOV_DELAY_CREATE},
165 int get_flags(char *data, int *rflags)
173 cloned_flags = strdup(data);
174 if (cloned_flags == NULL) {
175 fprintf(stderr, "Insufficient memory.\n");
179 for (tmp = strtok(cloned_flags, ":"); tmp;
180 tmp = strtok(NULL, ":")) {
183 size = tmp - cloned_flags;
184 for (i = 0; flag_table[i].flag != -1; i++) {
185 if (!strcmp(tmp, flag_table[i].string)){
186 flags |= flag_table[i].flag;
187 size += strlen(flag_table[i].string);
204 #define POP_ARG() (pop_arg(argc, argv))
206 int main(int argc, char **argv)
208 char *fname, *commands;
213 size_t mmap_len = 0, i;
214 unsigned char *mmap_ptr = NULL, junk = 0;
215 int rc, len, fd = -1;
222 struct lov_user_md_v3 lum;
226 fprintf(stderr, usage, argv[0]);
230 memset(&st, 0, sizeof(st));
231 sem_init(&sem, 0, 0);
232 /* use sigaction instead of signal to avoid SA_ONESHOT semantics */
233 sigaction(SIGUSR1, &(const struct sigaction){.sa_handler = &usr1_handler},
238 for (commands = argv[2]; *commands; commands++) {
245 len = atoi(commands+1);
247 len = 3600; /* 1 hour */
248 ts.tv_sec = time(NULL) + len;
250 while (sem_timedwait(&sem, &ts) < 0 && errno == EINTR);
253 if (fsetxattr(fd, XATTR, "multiop", 8, 0)) {
260 if (fgetxattr(fd, XATTR, NULL, 0) == -1) {
267 if (close(fd) == -1) {
275 lum = (struct lov_user_md_v3) {
276 .lmm_magic = LOV_USER_MAGIC_V3,
277 .lmm_stripe_count = atoi(commands + 1),
280 if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum) < 0) {
282 perror("LL_IOC_LOV_SETSTRIPE");
287 len = atoi(commands+1);
288 fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
292 perror("create stripe file");
297 if (mkdir(fname, 0755) == -1) {
299 perror("mkdir(0755)");
304 fd = open(fname, O_DIRECTORY);
307 perror("open(O_DIRECTORY)");
315 flags = LL_LEASE_UNLCK;
318 flags = LL_LEASE_RDLCK;
321 flags = LL_LEASE_WRLCK;
324 errx(-1, "unknown mode: %c", *commands);
327 rc = ioctl(fd, LL_IOC_SET_LEASE, flags);
329 err(errno, "apply lease error");
331 if (flags != LL_LEASE_UNLCK)
334 /* F_UNLCK, interpret return code */
336 const char *str = "unknown";
337 if (rc == LL_LEASE_RDLCK)
339 else if (rc == LL_LEASE_WRLCK)
341 fprintf(stdout, "%s lease(%d) released.\n",
343 } else if (rc == 0) {
344 fprintf(stdout, "lease already broken.\n");
349 if (*commands != '-' && *commands != '+')
350 errx(-1, "unknown mode: %c\n", *commands);
352 rc = ioctl(fd, LL_IOC_GET_LEASE);
354 const char *str = "unknown";
356 if (rc == LL_LEASE_RDLCK)
358 else if (rc == LL_LEASE_WRLCK)
360 fprintf(stdout, "%s lease(%d) has applied.\n",
362 if (*commands == '-')
363 errx(-1, "expect lease to not exist");
364 } else if (rc == 0) {
365 fprintf(stdout, "no lease applied.\n");
366 if (*commands == '+')
367 errx(-1, "expect lease exists");
369 err(errno, "free lease error");
373 if (statfs(fname, &stfs) == -1)
374 errx(-1, "statfs()");
378 rc = llapi_path2fid(fname, &fid);
380 rc = llapi_fd2fid(fd, &fid);
383 "llapi_path/fd2fid() on %d, rc=%d\n",
386 printf(DFID"\n", PFID(&fid));
389 gid = atoi(commands+1);
390 if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) {
392 perror("ioctl(GROUP_LOCK)");
397 gid = atoi(commands+1);
398 if (ioctl(fd, LL_IOC_GROUP_UNLOCK, gid) == -1) {
400 perror("ioctl(GROUP_UNLOCK)");
405 len = atoi(commands+1);
406 fd = llapi_file_open(fname, O_CREAT | O_WRONLY,
408 LOV_PATTERN_RAID0 | LOV_PATTERN_F_RELEASED);
411 perror("create stripe file");
416 if (flock(fd, LOCK_EX) == -1)
424 if (link(oldpath, fname)) {
434 if (symlink(fname, newfile)) {
445 if (link(fname, newfile)) {
452 if (mknod(fname, S_IFREG | 0644, 0) == -1) {
454 perror("mknod(S_IFREG|0644, 0)");
459 if (st.st_size == 0) {
460 fprintf(stderr, "mmap without preceeding stat, or on"
461 " zero length file.\n");
464 mmap_len = st.st_size;
465 mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
467 if (mmap_ptr == MAP_FAILED) {
478 if (rename(oldpath, fname) < 0) {
488 if (rename (fname, newfile)) {
495 fd = open(fname, O_CREAT|O_RDWR, 0644);
498 perror("open(O_RDWR|O_CREAT)");
503 len = get_flags(commands+1, &flags);
506 fd = open(fname, flags, 0666);
508 fd = open(fname, flags);
516 len = atoi(commands+1);
521 tmp = realloc(buf, len + ALIGN_LEN);
525 perror("allocating buf for read\n");
530 buf_align = (char *)((long)(buf + ALIGN_LEN) &
534 rc = read(fd, buf_align, len);
541 fprintf(stderr, "short read: %u/%u\n",
548 printf("%.*s\n", rc, buf_align);
552 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
556 if (stat(fname, &st) == -1) {
563 if (fstat(fd, &st) == -1) {
570 if (fchmod(fd, 0) == -1) {
577 len = atoi(commands+1);
578 if (ftruncate(fd, len) == -1) {
580 printf("ftruncate (%d,%d)\n", fd, len);
586 if (unlink(fname) == -1) {
593 if (munmap(mmap_ptr, mmap_len)) {
603 len = get_flags(commands + 1, &flags);
605 fd = llapi_create_volatile(fname, flags);
607 perror("llapi_create_volatile");
612 len = atoi(commands+1);
617 tmp = realloc(buf, len + ALIGN_LEN);
621 perror("allocating buf for write\n");
626 buf_align = (char *)((long)(buf + ALIGN_LEN) &
628 strncpy(buf_align, msg, bufsize);
631 rc = write(fd, buf_align, len);
638 fprintf(stderr, "short write: %u/%u\n",
644 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
645 mmap_ptr[i] += junk++;
648 rc = llapi_get_data_version(fd, &dv, 0);
650 fprintf(stderr, "cannot get file data version"
654 printf("dataversion is %ju\n", (uintmax_t)dv);
657 if (fsync(fd) == -1) {
664 if (fdatasync(fd) == -1) {
671 len = atoi(commands+1);
672 if (lseek(fd, len, SEEK_SET) == -1) {
691 fprintf(stderr, "unknown command \"%c\"\n", *commands);
692 fprintf(stderr, usage, argv[0]);