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, 2017, 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/lustreapi.h>
57 #define T1 "write data before unlink\n"
58 #define T2 "write data after unlink\n"
59 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";
60 char *buf, *buf_align;
63 #define ALIGN_LEN 65535
64 #define XATTR "user.multiop"
67 "Usage: %s filename command-sequence [path...]\n"
68 " command-sequence items:\n"
69 " A fsetxattr(\"user.multiop\")\n"
70 " a fgetxattr(\"user.multiop\")\n"
72 " B[num] call setstripe ioctl to create stripes\n"
73 " C[num] create with optional stripes\n"
75 " D open(O_DIRECTORY)\n"
76 " e[R|W|U] apply lease. R: Read; W: Write; U: Unlock\n"
77 " E[+|-] get lease. +/-: expect lease to (not) exist\n"
80 " H[num] create HSM released file with num stripes\n"
81 " G gid get grouplock\n"
82 " g gid put grouplock\n"
83 " K link path to filename\n"
85 " l symlink filename to path\n"
87 " M rw mmap to EOF (must open and stat prior)\n"
88 " n rename path to filename\n"
89 " N rename filename to path\n"
91 " O open(O_CREAT|O_RDWR)\n"
92 " r[num] read [optional length]\n"
93 " R reference entire mmap-ed region\n"
97 " T[num] ftruncate [optional position, default 0]\n"
101 " V open a volatile file\n"
102 " w[num] write optional length\n"
103 " x get file data version\n"
104 " W write entire mmap-ed region\n"
107 " z[num] seek [optional position, default 0]\n"
108 " _ wait for signal\n";
110 void usr1_handler(int unused)
112 int saved_errno = errno;
115 * signal(7): POSIX.1-2004 ...requires an implementation to guarantee
116 * that the following functions can be safely called inside a signal
126 pop_arg(int argc, char *argv[])
128 static int cur_arg = 3;
133 return argv[cur_arg++];
136 struct flag_mapping {
140 {"O_RDONLY", O_RDONLY},
141 {"O_WRONLY", O_WRONLY},
143 {"O_CREAT", O_CREAT},
145 {"O_NOCTTY", O_NOCTTY},
146 {"O_TRUNC", O_TRUNC},
147 {"O_APPEND", O_APPEND},
148 {"O_NONBLOCK", O_NONBLOCK},
149 {"O_NDELAY", O_NDELAY},
152 {"O_DIRECT", O_DIRECT},
155 {"O_NOATIME", O_NOATIME},
157 {"O_LARGEFILE", O_LARGEFILE},
158 {"O_DIRECTORY", O_DIRECTORY},
159 {"O_NOFOLLOW", O_NOFOLLOW},
160 {"O_LOV_DELAY_CREATE", O_LOV_DELAY_CREATE},
164 int get_flags(char *data, int *rflags)
172 cloned_flags = strdup(data);
173 if (cloned_flags == NULL) {
174 fprintf(stderr, "Insufficient memory.\n");
178 for (tmp = strtok(cloned_flags, ":"); tmp;
179 tmp = strtok(NULL, ":")) {
182 size = tmp - cloned_flags;
183 for (i = 0; flag_table[i].flag != -1; i++) {
184 if (!strcmp(tmp, flag_table[i].string)){
185 flags |= flag_table[i].flag;
186 size += strlen(flag_table[i].string);
203 #define POP_ARG() (pop_arg(argc, argv))
205 int main(int argc, char **argv)
207 char *fname, *commands;
212 size_t mmap_len = 0, i;
213 unsigned char *mmap_ptr = NULL, junk = 0;
214 int rc, len, fd = -1;
221 struct lov_user_md_v3 lum;
224 fprintf(stderr, usage, argv[0]);
228 memset(&st, 0, sizeof(st));
229 sem_init(&sem, 0, 0);
230 /* use sigaction instead of signal to avoid SA_ONESHOT semantics */
231 sigaction(SIGUSR1, &(const struct sigaction){.sa_handler = &usr1_handler},
236 for (commands = argv[2]; *commands; commands++) {
243 len = atoi(commands+1);
245 len = 3600; /* 1 hour */
246 ts.tv_sec = time(NULL) + len;
248 while (sem_timedwait(&sem, &ts) < 0 && errno == EINTR);
251 if (fsetxattr(fd, XATTR, "multiop", 8, 0)) {
258 if (fgetxattr(fd, XATTR, NULL, 0) == -1) {
265 if (close(fd) == -1) {
273 lum = (struct lov_user_md_v3) {
274 .lmm_magic = LOV_USER_MAGIC_V3,
275 .lmm_stripe_count = atoi(commands + 1),
278 if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum) < 0) {
280 perror("LL_IOC_LOV_SETSTRIPE");
285 len = atoi(commands+1);
286 fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
290 perror("create stripe file");
295 if (mkdir(fname, 0755) == -1) {
297 perror("mkdir(0755)");
302 fd = open(fname, O_DIRECTORY);
305 perror("open(O_DIRECTORY)");
313 rc = llapi_lease_release(fd);
316 rc = llapi_lease_acquire(fd, LL_LEASE_RDLCK);
319 rc = llapi_lease_acquire(fd, LL_LEASE_WRLCK);
322 errx(-1, "unknown mode: %c", *commands);
325 err(errno, "apply/unlock lease error");
327 if (flags != LL_LEASE_UNLCK)
330 /* F_UNLCK, interpret return code */
332 const char *str = "unknown";
333 if (rc == LL_LEASE_RDLCK)
335 else if (rc == LL_LEASE_WRLCK)
337 fprintf(stdout, "%s lease(%d) released.\n",
339 } else if (rc == 0) {
340 fprintf(stdout, "lease already broken.\n");
345 if (*commands != '-' && *commands != '+')
346 errx(-1, "unknown mode: %c\n", *commands);
348 rc = llapi_lease_check(fd);
350 const char *str = "unknown";
352 if (rc == LL_LEASE_RDLCK)
354 else if (rc == LL_LEASE_WRLCK)
356 fprintf(stdout, "%s lease(%d) has applied.\n",
358 if (*commands == '-')
359 errx(-1, "expect lease to not exist");
360 } else if (rc == 0) {
361 fprintf(stdout, "no lease applied.\n");
362 if (*commands == '+')
363 errx(-1, "expect lease exists");
365 err(errno, "free lease error");
369 if (statfs(fname, &stfs) == -1)
370 errx(-1, "statfs()");
374 rc = llapi_path2fid(fname, &fid);
376 rc = llapi_fd2fid(fd, &fid);
379 "llapi_path/fd2fid() on %d, rc=%d\n",
382 printf(DFID"\n", PFID(&fid));
385 gid = atoi(commands+1);
386 if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) {
388 perror("ioctl(GROUP_LOCK)");
393 gid = atoi(commands+1);
394 if (ioctl(fd, LL_IOC_GROUP_UNLOCK, gid) == -1) {
396 perror("ioctl(GROUP_UNLOCK)");
401 len = atoi(commands+1);
402 fd = llapi_file_open(fname, O_CREAT | O_WRONLY,
404 LOV_PATTERN_RAID0 | LOV_PATTERN_F_RELEASED);
407 perror("create stripe file");
412 if (flock(fd, LOCK_EX) == -1)
420 if (link(oldpath, fname)) {
430 if (symlink(fname, newfile)) {
441 if (link(fname, newfile)) {
448 if (mknod(fname, S_IFREG | 0644, 0) == -1) {
450 perror("mknod(S_IFREG|0644, 0)");
455 if (st.st_size == 0) {
456 fprintf(stderr, "mmap without preceeding stat, or on"
457 " zero length file.\n");
460 mmap_len = st.st_size;
461 mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
463 if (mmap_ptr == MAP_FAILED) {
474 if (rename(oldpath, fname) < 0) {
484 if (rename (fname, newfile)) {
491 fd = open(fname, O_CREAT|O_RDWR, 0644);
494 perror("open(O_RDWR|O_CREAT)");
499 len = get_flags(commands+1, &flags);
502 fd = open(fname, flags, 0666);
504 fd = open(fname, flags);
512 len = atoi(commands+1);
517 tmp = realloc(buf, len + ALIGN_LEN);
521 perror("allocating buf for read\n");
526 buf_align = (char *)((long)(buf + ALIGN_LEN) &
530 rc = read(fd, buf_align, len);
537 fprintf(stderr, "short read: %u/%u\n",
544 printf("%.*s\n", rc, buf_align);
548 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
552 if (stat(fname, &st) == -1) {
559 if (fstat(fd, &st) == -1) {
566 if (fchmod(fd, 0) == -1) {
573 len = atoi(commands+1);
574 if (ftruncate(fd, len) == -1) {
576 printf("ftruncate (%d,%d)\n", fd, len);
582 if (unlink(fname) == -1) {
589 if (munmap(mmap_ptr, mmap_len)) {
599 len = get_flags(commands + 1, &flags);
601 fd = llapi_create_volatile(fname, flags);
603 perror("llapi_create_volatile");
608 len = atoi(commands+1);
613 tmp = realloc(buf, len + ALIGN_LEN);
617 perror("allocating buf for write\n");
622 buf_align = (char *)((long)(buf + ALIGN_LEN) &
624 strncpy(buf_align, msg, bufsize);
627 rc = write(fd, buf_align, len);
634 fprintf(stderr, "short write: %u/%u\n",
640 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
641 mmap_ptr[i] += junk++;
646 rc = llapi_get_data_version(fd, &dv, 0);
648 fprintf(stderr, "cannot get file data version"
652 printf("dataversion is %ju\n", (uintmax_t)dv);
656 __u32 layout_version;
658 rc = llapi_get_ost_layout_version(fd, &layout_version);
660 fprintf(stderr, "cannot get ost layout version"
664 printf("ostlayoutversion: %u\n", layout_version);
668 if (fsync(fd) == -1) {
675 if (fdatasync(fd) == -1) {
682 len = atoi(commands+1);
683 if (lseek(fd, len, SEEK_SET) == -1) {
702 fprintf(stderr, "unknown command \"%c\"\n", *commands);
703 fprintf(stderr, usage, argv[0]);