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, 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>
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;
66 "Usage: %s filename command-sequence\n"
67 " command-sequence items:\n"
69 " C[num] create with optional stripes\n"
71 " D open(O_DIRECTORY)\n"
73 " G gid get grouplock\n"
74 " g gid put grouplock\n"
78 " M rw mmap to EOF (must open and stat prior)\n"
81 " O open(O_CREAT|O_RDWR)\n"
82 " r[num] read [optional length]\n"
83 " R reference entire mmap-ed region\n"
87 " T[num] ftruncate [optional position, default 0]\n"
91 " w[num] write optional length\n"
92 " W write entire mmap-ed region\n"
95 " z[num] seek [optional position, default 0]\n"
96 " _ wait for signal\n";
98 void usr1_handler(int unused)
100 int saved_errno = errno;
103 * signal(7): POSIX.1-2004 ...requires an implementation to guarantee
104 * that the following functions can be safely called inside a signal
114 pop_arg(int argc, char *argv[])
116 static int cur_arg = 3;
121 return argv[cur_arg++];
124 struct flag_mapping {
128 {"O_RDONLY", O_RDONLY},
129 {"O_WRONLY", O_WRONLY},
131 {"O_CREAT", O_CREAT},
133 {"O_NOCTTY", O_NOCTTY},
134 {"O_TRUNC", O_TRUNC},
135 {"O_APPEND", O_APPEND},
136 {"O_NONBLOCK", O_NONBLOCK},
137 {"O_NDELAY", O_NDELAY},
140 {"O_DIRECT", O_DIRECT},
142 {"O_LARGEFILE", O_LARGEFILE},
143 {"O_DIRECTORY", O_DIRECTORY},
144 {"O_NOFOLLOW", O_NOFOLLOW},
148 int get_flags(char *data, int *rflags)
156 cloned_flags = strdup(data);
157 if (cloned_flags == NULL) {
158 fprintf(stderr, "Insufficient memory.\n");
162 for (tmp = strtok(cloned_flags, ":"); tmp;
163 tmp = strtok(NULL, ":")) {
166 size = tmp - cloned_flags;
167 for (i = 0; flag_table[i].flag != -1; i++) {
168 if (!strcmp(tmp, flag_table[i].string)){
169 flags |= flag_table[i].flag;
170 size += strlen(flag_table[i].string);
187 #define POP_ARG() (pop_arg(argc, argv))
189 int main(int argc, char **argv)
191 char *fname, *commands;
195 size_t mmap_len = 0, i;
196 unsigned char *mmap_ptr = NULL, junk = 0;
197 int rc, len, fd = -1;
205 fprintf(stderr, usage, argv[0]);
209 memset(&st, 0, sizeof(st));
210 sem_init(&sem, 0, 0);
211 /* use sigaction instead of signal to avoid SA_ONESHOT semantics */
212 sigaction(SIGUSR1, &(const struct sigaction){.sa_handler = &usr1_handler},
217 for (commands = argv[2]; *commands; commands++) {
224 len = atoi(commands+1);
226 len = 3600; /* 1 hour */
227 ts.tv_sec = time(NULL) + len;
229 while (sem_timedwait(&sem, &ts) < 0 && errno == EINTR);
232 if (close(fd) == -1) {
240 len = atoi(commands+1);
241 fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
245 perror("create stripe file");
250 if (mkdir(fname, 0755) == -1) {
252 perror("mkdir(0755)");
257 fd = open(fname, O_DIRECTORY);
260 perror("open(O_DIRECTORY)");
265 if (statfs(fname, &stfs) == -1) {
272 gid = atoi(commands+1);
273 if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) {
275 perror("ioctl(GROUP_LOCK)");
280 gid = atoi(commands+1);
281 if (ioctl(fd, LL_IOC_GROUP_UNLOCK, gid) == -1) {
283 perror("ioctl(GROUP_UNLOCK)");
291 if (symlink(fname, newfile)) {
301 if (link(fname, newfile)) {
308 if (mknod(fname, S_IFREG | 0644, 0) == -1) {
310 perror("mknod(S_IFREG|0644, 0)");
315 if (st.st_size == 0) {
316 fprintf(stderr, "mmap without preceeding stat, or on"
317 " zero length file.\n");
320 mmap_len = st.st_size;
321 mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
323 if (mmap_ptr == MAP_FAILED) {
333 if (rename (fname, newfile)) {
340 fd = open(fname, O_CREAT|O_RDWR, 0644);
343 perror("open(O_RDWR|O_CREAT)");
348 len = get_flags(commands+1, &flags);
351 fd = open(fname, flags, 0666);
353 fd = open(fname, flags);
361 len = atoi(commands+1);
365 buf = realloc(buf, len + ALIGN);
368 perror("allocating buf for read\n");
372 buf_align = (char *)((long)(buf + ALIGN) &
376 rc = read(fd, buf_align, len);
383 fprintf(stderr, "short read: %u/%u\n",
390 printf("%.*s\n", rc, buf_align);
394 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
398 if (stat(fname, &st) == -1) {
405 if (fstat(fd, &st) == -1) {
412 if (fchmod(fd, 0) == -1) {
419 len = atoi(commands+1);
420 if (ftruncate(fd, len) == -1) {
422 printf("ftruncate (%d,%d)\n", fd, len);
428 if (unlink(fname) == -1) {
435 if (munmap(mmap_ptr, mmap_len)) {
445 len = atoi(commands+1);
449 buf = realloc(buf, len + ALIGN);
452 perror("allocating buf for write\n");
456 buf_align = (char *)((long)(buf + ALIGN) &
458 strncpy(buf_align, msg, bufsize);
461 rc = write(fd, buf_align, len);
468 fprintf(stderr, "short write: %u/%u\n",
474 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
475 mmap_ptr[i] += junk++;
478 if (fsync(fd) == -1) {
485 if (fdatasync(fd) == -1) {
491 len = atoi(commands+1);
492 if (lseek(fd, len, SEEK_SET) == -1) {
510 fprintf(stderr, "unknown command \"%c\"\n", *commands);
511 fprintf(stderr, usage, argv[0]);