1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
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>
52 #include <semaphore.h>
53 #include <lustre/liblustreapi.h>
56 #define T1 "write data before unlink\n"
57 #define T2 "write data after unlink\n"
58 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";
59 char *buf, *buf_align;
63 #define MAX_SHIFT 4096
66 "Usage: %s filename command-sequence\n"
67 " command-sequence items:\n"
68 " b[num] write optional length from random in-memory offset\n"
70 " C[num] create with optional stripes\n"
72 " D open(O_DIRECTORY)\n"
77 " M rw mmap to EOF (must open and stat prior)\n"
80 " O open(O_CREAT|O_RDWR)\n"
81 " r[num] read [optional length]\n"
82 " R reference entire mmap-ed region\n"
86 " T[num] ftruncate [optional position, default 0]\n"
89 " w[num] write optional length\n"
90 " W write entire mmap-ed region\n"
93 " z[num] seek [optional position, default 0]\n"
94 " _ wait for signal\n";
96 void usr1_handler(int unused)
98 int saved_errno = errno;
101 * signal(7): POSIX.1-2004 ...requires an implementation to guarantee
102 * that the following functions can be safely called inside a signal
112 pop_arg(int argc, char *argv[])
114 static int cur_arg = 3;
119 return argv[cur_arg++];
122 struct flag_mapping {
126 {"O_RDONLY", O_RDONLY},
127 {"O_WRONLY", O_WRONLY},
129 {"O_CREAT", O_CREAT},
131 {"O_NOCTTY", O_NOCTTY},
132 {"O_TRUNC", O_TRUNC},
133 {"O_APPEND", O_APPEND},
134 {"O_NONBLOCK", O_NONBLOCK},
135 {"O_NDELAY", O_NDELAY},
138 {"O_DIRECT", O_DIRECT},
140 {"O_LARGEFILE", O_LARGEFILE},
141 {"O_DIRECTORY", O_DIRECTORY},
142 {"O_NOFOLLOW", O_NOFOLLOW},
146 int get_flags(char *data, int *rflags)
154 cloned_flags = strdup(data);
155 if (cloned_flags == NULL) {
156 fprintf(stderr, "Insufficient memory.\n");
160 for (tmp = strtok(cloned_flags, ":"); tmp;
161 tmp = strtok(NULL, ":")) {
164 size = tmp - cloned_flags;
165 for (i = 0; flag_table[i].flag != -1; i++) {
166 if (!strcmp(tmp, flag_table[i].string)){
167 flags |= flag_table[i].flag;
168 size += strlen(flag_table[i].string);
185 #define POP_ARG() (pop_arg(argc, argv))
186 #define min(a,b) ((a)>(b)?(b):(a))
188 int main(int argc, char **argv)
190 char *fname, *commands;
194 size_t mmap_len = 0, i;
195 unsigned char *mmap_ptr = NULL, junk = 0;
196 int rc, len, fd = -1;
202 fprintf(stderr, usage, argv[0]);
206 memset(&st, 0, sizeof(st));
207 sem_init(&sem, 0, 0);
208 /* use sigaction instead of signal to avoid SA_ONESHOT semantics */
209 sigaction(SIGUSR1, &(const struct sigaction){.sa_handler = &usr1_handler},
215 for (commands = argv[2]; *commands; commands++) {
222 while (sem_wait(&sem) == -1 && errno == EINTR);
225 if (close(fd) == -1) {
233 len = atoi(commands+1);
234 fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
238 perror("create stripe file");
243 if (mkdir(fname, 0755) == -1) {
245 perror("mkdir(0755)");
250 fd = open(fname, O_DIRECTORY);
253 perror("open(O_DIRECTORY)");
258 if (statfs(fname, &stfs) == -1) {
268 if (symlink(fname, newfile)) {
278 if (link(fname, newfile)) {
285 if (mknod(fname, S_IFREG | 0644, 0) == -1) {
287 perror("mknod(S_IFREG|0644, 0)");
292 if (st.st_size == 0) {
293 fprintf(stderr, "mmap without preceeding stat, or on"
294 " zero length file.\n");
297 mmap_len = st.st_size;
298 mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
300 if (mmap_ptr == MAP_FAILED) {
310 if (rename (fname, newfile)) {
317 fd = open(fname, O_CREAT|O_RDWR, 0644);
320 perror("open(O_RDWR|O_CREAT)");
325 len = get_flags(commands+1, &flags);
328 fd = open(fname, flags, 0666);
330 fd = open(fname, flags);
338 len = atoi(commands+1);
342 buf = realloc(buf, len + ALIGN);
345 perror("allocating buf for read\n");
349 buf_align = (char *)((long)(buf + ALIGN) &
353 rc = read(fd, buf_align, len);
360 fprintf(stderr, "short read: %u/%u\n",
366 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
370 if (stat(fname, &st) == -1) {
377 if (fstat(fd, &st) == -1) {
384 if (fchmod(fd, 0) == -1) {
391 len = atoi(commands+1);
392 if (ftruncate(fd, len) == -1) {
394 printf("ftruncate (%d,%d)\n", fd, len);
400 if (unlink(fname) == -1) {
407 if (munmap(mmap_ptr, mmap_len)) {
418 len = atoi(commands+1);
422 int shift = (*commands == 'b') ?
423 (random() % MAX_SHIFT) : 0;
424 buf = realloc(buf, len + ALIGN + shift);
427 perror("allocating buf for write\n");
431 buf_align = (char *)((long)(buf + ALIGN) &
433 strncpy(buf_align, msg, bufsize);
436 rc = write(fd, buf_align, len);
443 fprintf(stderr, "short write: %u/%u\n",
449 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
450 mmap_ptr[i] += junk++;
453 if (fsync(fd) == -1) {
460 if (fdatasync(fd) == -1) {
466 len = atoi(commands+1);
467 if (lseek(fd, len, SEEK_SET) == -1) {
485 fprintf(stderr, "unknown command \"%c\"\n", *commands);
486 fprintf(stderr, usage, argv[0]);