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.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2012, 2013, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
38 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
44 #include <sys/types.h>
48 #include <sys/ioctl.h>
52 #include <semaphore.h>
56 #include <lustre/lustre_idl.h>
57 #include <lustre/lustreapi.h>
59 #define T1 "write data before unlink\n"
60 #define T2 "write data after unlink\n"
61 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";
62 char *buf, *buf_align;
65 #define ALIGN_LEN 65535
68 "Usage: %s filename command-sequence [path...]\n"
69 " command-sequence items:\n"
71 " B[num] call setstripe ioctl to create stripes\n"
72 " C[num] create with optional stripes\n"
74 " D open(O_DIRECTORY)\n"
75 " e[R|W|U] apply lease. R: Read; W: Write; U: Unlock\n"
76 " E[+|-] get lease. +/-: expect lease to (not) exist\n"
79 " H[num] create HSM released file with num stripes\n"
80 " G gid get grouplock\n"
81 " g gid put grouplock\n"
82 " K link path to filename\n"
84 " l symlink filename to path\n"
86 " M rw mmap to EOF (must open and stat prior)\n"
87 " n rename path to filename\n"
88 " N rename filename to path\n"
90 " O open(O_CREAT|O_RDWR)\n"
91 " r[num] read [optional length]\n"
92 " R reference entire mmap-ed region\n"
96 " T[num] ftruncate [optional position, default 0]\n"
100 " V open a volatile file\n"
101 " w[num] write optional length\n"
102 " x get file data version\n"
103 " W write entire mmap-ed region\n"
106 " z[num] seek [optional position, default 0]\n"
107 " _ wait for signal\n";
109 void usr1_handler(int unused)
111 int saved_errno = errno;
114 * signal(7): POSIX.1-2004 ...requires an implementation to guarantee
115 * that the following functions can be safely called inside a signal
125 pop_arg(int argc, char *argv[])
127 static int cur_arg = 3;
132 return argv[cur_arg++];
135 struct flag_mapping {
139 {"O_RDONLY", O_RDONLY},
140 {"O_WRONLY", O_WRONLY},
142 {"O_CREAT", O_CREAT},
144 {"O_NOCTTY", O_NOCTTY},
145 {"O_TRUNC", O_TRUNC},
146 {"O_APPEND", O_APPEND},
147 {"O_NONBLOCK", O_NONBLOCK},
148 {"O_NDELAY", O_NDELAY},
151 {"O_DIRECT", O_DIRECT},
153 {"O_LARGEFILE", O_LARGEFILE},
154 {"O_DIRECTORY", O_DIRECTORY},
155 {"O_NOFOLLOW", O_NOFOLLOW},
156 {"O_LOV_DELAY_CREATE", O_LOV_DELAY_CREATE},
160 int get_flags(char *data, int *rflags)
168 cloned_flags = strdup(data);
169 if (cloned_flags == NULL) {
170 fprintf(stderr, "Insufficient memory.\n");
174 for (tmp = strtok(cloned_flags, ":"); tmp;
175 tmp = strtok(NULL, ":")) {
178 size = tmp - cloned_flags;
179 for (i = 0; flag_table[i].flag != -1; i++) {
180 if (!strcmp(tmp, flag_table[i].string)){
181 flags |= flag_table[i].flag;
182 size += strlen(flag_table[i].string);
199 #define POP_ARG() (pop_arg(argc, argv))
201 int main(int argc, char **argv)
203 char *fname, *commands;
208 size_t mmap_len = 0, i;
209 unsigned char *mmap_ptr = NULL, junk = 0;
210 int rc, len, fd = -1;
217 struct lov_user_md_v3 lum;
221 fprintf(stderr, usage, argv[0]);
225 memset(&st, 0, sizeof(st));
226 sem_init(&sem, 0, 0);
227 /* use sigaction instead of signal to avoid SA_ONESHOT semantics */
228 sigaction(SIGUSR1, &(const struct sigaction){.sa_handler = &usr1_handler},
233 for (commands = argv[2]; *commands; commands++) {
240 len = atoi(commands+1);
242 len = 3600; /* 1 hour */
243 ts.tv_sec = time(NULL) + len;
245 while (sem_timedwait(&sem, &ts) < 0 && errno == EINTR);
248 if (close(fd) == -1) {
256 lum = (struct lov_user_md_v3) {
257 .lmm_magic = LOV_USER_MAGIC_V3,
258 .lmm_stripe_count = atoi(commands + 1),
261 if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum) < 0) {
263 perror("LL_IOC_LOV_SETSTRIPE");
268 len = atoi(commands+1);
269 fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
273 perror("create stripe file");
278 if (mkdir(fname, 0755) == -1) {
280 perror("mkdir(0755)");
285 fd = open(fname, O_DIRECTORY);
288 perror("open(O_DIRECTORY)");
305 errx(-1, "unknown mode: %c", *commands);
308 rc = ioctl(fd, LL_IOC_SET_LEASE, flags);
310 err(errno, "apply lease error");
312 if (flags != F_UNLCK)
315 /* F_UNLCK, interpret return code */
317 const char *str = "Unknown";
318 if (rc == FMODE_READ)
320 else if (rc == FMODE_WRITE)
322 fprintf(stdout, "%s lease(%d) released.\n",
324 } else if (rc == 0) {
325 fprintf(stdout, "lease already broken.\n");
330 if (*commands != '-' && *commands != '+')
331 errx(-1, "unknown mode: %c\n", *commands);
333 rc = ioctl(fd, LL_IOC_GET_LEASE);
335 const char *str = "Unknown";
337 if (rc == FMODE_READ)
339 else if (rc == FMODE_WRITE)
341 fprintf(stdout, "%s lease(%d) has applied.\n",
343 if (*commands == '-')
344 errx(-1, "expect lease to not exist");
345 } else if (rc == 0) {
346 fprintf(stdout, "no lease applied.\n");
347 if (*commands == '+')
348 errx(-1, "expect lease exists");
350 err(errno, "free lease error");
354 if (statfs(fname, &stfs) == -1)
355 errx(-1, "statfs()");
359 rc = llapi_path2fid(fname, &fid);
361 rc = llapi_fd2fid(fd, &fid);
364 "llapi_path/fd2fid() on %d, rc=%d\n",
367 printf(DFID"\n", PFID(&fid));
370 gid = atoi(commands+1);
371 if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) {
373 perror("ioctl(GROUP_LOCK)");
378 gid = atoi(commands+1);
379 if (ioctl(fd, LL_IOC_GROUP_UNLOCK, gid) == -1) {
381 perror("ioctl(GROUP_UNLOCK)");
386 len = atoi(commands+1);
387 fd = llapi_file_open(fname, O_CREAT | O_WRONLY,
389 LOV_PATTERN_RAID0 | LOV_PATTERN_F_RELEASED);
392 perror("create stripe file");
401 if (link(oldpath, fname)) {
411 if (symlink(fname, newfile)) {
422 if (link(fname, newfile)) {
429 if (mknod(fname, S_IFREG | 0644, 0) == -1) {
431 perror("mknod(S_IFREG|0644, 0)");
436 if (st.st_size == 0) {
437 fprintf(stderr, "mmap without preceeding stat, or on"
438 " zero length file.\n");
441 mmap_len = st.st_size;
442 mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
444 if (mmap_ptr == MAP_FAILED) {
455 if (rename(oldpath, fname) < 0) {
465 if (rename (fname, newfile)) {
472 fd = open(fname, O_CREAT|O_RDWR, 0644);
475 perror("open(O_RDWR|O_CREAT)");
480 len = get_flags(commands+1, &flags);
483 fd = open(fname, flags, 0666);
485 fd = open(fname, flags);
493 len = atoi(commands+1);
497 buf = realloc(buf, len + ALIGN_LEN);
500 perror("allocating buf for read\n");
504 buf_align = (char *)((long)(buf + ALIGN_LEN) &
508 rc = read(fd, buf_align, len);
515 fprintf(stderr, "short read: %u/%u\n",
522 printf("%.*s\n", rc, buf_align);
526 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
530 if (stat(fname, &st) == -1) {
537 if (fstat(fd, &st) == -1) {
544 if (fchmod(fd, 0) == -1) {
551 len = atoi(commands+1);
552 if (ftruncate(fd, len) == -1) {
554 printf("ftruncate (%d,%d)\n", fd, len);
560 if (unlink(fname) == -1) {
567 if (munmap(mmap_ptr, mmap_len)) {
577 len = get_flags(commands + 1, &flags);
579 fd = llapi_create_volatile(fname, flags);
581 perror("llapi_create_volatile");
586 len = atoi(commands+1);
590 buf = realloc(buf, len + ALIGN_LEN);
593 perror("allocating buf for write\n");
597 buf_align = (char *)((long)(buf + ALIGN_LEN) &
599 strncpy(buf_align, msg, bufsize);
602 rc = write(fd, buf_align, len);
609 fprintf(stderr, "short write: %u/%u\n",
615 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
616 mmap_ptr[i] += junk++;
619 rc = llapi_get_data_version(fd, &dv, 0);
621 fprintf(stderr, "cannot get file data version"
625 printf("dataversion is "LPU64"\n", dv);
628 if (fsync(fd) == -1) {
635 if (fdatasync(fd) == -1) {
642 len = atoi(commands+1);
643 if (lseek(fd, len, SEEK_SET) == -1) {
662 fprintf(stderr, "unknown command \"%c\"\n", *commands);
663 fprintf(stderr, usage, argv[0]);