* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, Intel Corporation.
+ * Copyright (c) 2012, 2013, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#include <unistd.h>
#include <semaphore.h>
#include <time.h>
+#include <err.h>
+#include <lustre/lustre_idl.h>
#include <lustre/lustreapi.h>
#define T1 "write data before unlink\n"
char *buf, *buf_align;
int bufsize = 0;
sem_t sem;
-#define ALIGN 65535
+#define ALIGN_LEN 65535
char usage[] =
-"Usage: %s filename command-sequence\n"
+"Usage: %s filename command-sequence [path...]\n"
" command-sequence items:\n"
-" c close\n"
-" C[num] create with optional stripes\n"
-" d mkdir\n"
-" D open(O_DIRECTORY)\n"
-" f statfs\n"
-" G gid get grouplock\n"
-" g gid put grouplock\n"
-" L link\n"
-" l symlink\n"
-" m mknod\n"
-" M rw mmap to EOF (must open and stat prior)\n"
-" N rename\n"
-" o open(O_RDONLY)\n"
-" O open(O_CREAT|O_RDWR)\n"
-" r[num] read [optional length]\n"
-" R reference entire mmap-ed region\n"
-" s stat\n"
-" S fstat\n"
-" t fchmod\n"
-" T[num] ftruncate [optional position, default 0]\n"
-" u unlink\n"
-" U munmap\n"
-" v verbose\n"
-" w[num] write optional length\n"
-" W write entire mmap-ed region\n"
-" y fsync\n"
-" Y fdatasync\n"
-" z[num] seek [optional position, default 0]\n"
-" _ wait for signal\n";
+" c close\n"
+" B[num] call setstripe ioctl to create stripes\n"
+" C[num] create with optional stripes\n"
+" d mkdir\n"
+" D open(O_DIRECTORY)\n"
+" e[R|W|U] apply lease. R: Read; W: Write; U: Unlock\n"
+" E[+|-] get lease. +/-: expect lease to (not) exist\n"
+" f statfs\n"
+" F print FID\n"
+" H[num] create HSM released file with num stripes\n"
+" G gid get grouplock\n"
+" g gid put grouplock\n"
+" K link path to filename\n"
+" L link\n"
+" l symlink filename to path\n"
+" m mknod\n"
+" M rw mmap to EOF (must open and stat prior)\n"
+" n rename path to filename\n"
+" N rename filename to path\n"
+" o open(O_RDONLY)\n"
+" O open(O_CREAT|O_RDWR)\n"
+" r[num] read [optional length]\n"
+" R reference entire mmap-ed region\n"
+" s stat\n"
+" S fstat\n"
+" t fchmod\n"
+" T[num] ftruncate [optional position, default 0]\n"
+" u unlink\n"
+" U munmap\n"
+" v verbose\n"
+" V open a volatile file\n"
+" w[num] write optional length\n"
+" x get file data version\n"
+" W write entire mmap-ed region\n"
+" y fsync\n"
+" Y fdatasync\n"
+" z[num] seek [optional position, default 0]\n"
+" _ wait for signal\n";
void usr1_handler(int unused)
{
}
struct flag_mapping {
- const char *string;
- const int flag;
+ const char *string;
+ const int flag;
} flag_table[] = {
- {"O_RDONLY", O_RDONLY},
- {"O_WRONLY", O_WRONLY},
- {"O_RDWR", O_RDWR},
- {"O_CREAT", O_CREAT},
- {"O_EXCL", O_EXCL},
- {"O_NOCTTY", O_NOCTTY},
- {"O_TRUNC", O_TRUNC},
- {"O_APPEND", O_APPEND},
- {"O_NONBLOCK", O_NONBLOCK},
- {"O_NDELAY", O_NDELAY},
- {"O_SYNC", O_SYNC},
+ {"O_RDONLY", O_RDONLY},
+ {"O_WRONLY", O_WRONLY},
+ {"O_RDWR", O_RDWR},
+ {"O_CREAT", O_CREAT},
+ {"O_EXCL", O_EXCL},
+ {"O_NOCTTY", O_NOCTTY},
+ {"O_TRUNC", O_TRUNC},
+ {"O_APPEND", O_APPEND},
+ {"O_NONBLOCK", O_NONBLOCK},
+ {"O_NDELAY", O_NDELAY},
+ {"O_SYNC", O_SYNC},
#ifdef O_DIRECT
- {"O_DIRECT", O_DIRECT},
+ {"O_DIRECT", O_DIRECT},
#endif
- {"O_LARGEFILE", O_LARGEFILE},
- {"O_DIRECTORY", O_DIRECTORY},
- {"O_NOFOLLOW", O_NOFOLLOW},
- {"", -1}
+#ifdef O_NOATIME
+ {"O_NOATIME", O_NOATIME},
+#endif
+ {"O_LARGEFILE", O_LARGEFILE},
+ {"O_DIRECTORY", O_DIRECTORY},
+ {"O_NOFOLLOW", O_NOFOLLOW},
+ {"O_LOV_DELAY_CREATE", O_LOV_DELAY_CREATE},
+ {"", -1}
};
int get_flags(char *data, int *rflags)
int main(int argc, char **argv)
{
- char *fname, *commands;
- const char *newfile;
- struct stat st;
- struct statfs stfs;
- size_t mmap_len = 0, i;
- unsigned char *mmap_ptr = NULL, junk = 0;
- int rc, len, fd = -1;
- int flags;
- int save_errno;
- int verbose = 0;
- int gid = 0;
- struct timespec ts;
+ char *fname, *commands;
+ const char *newfile;
+ const char *oldpath;
+ struct stat st;
+ struct statfs stfs;
+ size_t mmap_len = 0, i;
+ unsigned char *mmap_ptr = NULL, junk = 0;
+ int rc, len, fd = -1;
+ int flags;
+ int save_errno;
+ int verbose = 0;
+ int gid = 0;
+ lustre_fid fid;
+ struct timespec ts;
+ struct lov_user_md_v3 lum;
+ __u64 dv;
if (argc < 3) {
fprintf(stderr, usage, argv[0]);
}
fd = -1;
break;
+ case 'B':
+ lum = (struct lov_user_md_v3) {
+ .lmm_magic = LOV_USER_MAGIC_V3,
+ .lmm_stripe_count = atoi(commands + 1),
+ };
+
+ if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum) < 0) {
+ save_errno = errno;
+ perror("LL_IOC_LOV_SETSTRIPE");
+ exit(save_errno);
+ }
+ break;
case 'C':
len = atoi(commands+1);
fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
exit(save_errno);
}
break;
- case 'f':
- if (statfs(fname, &stfs) == -1) {
- save_errno = errno;
- perror("statfs()");
- exit(save_errno);
- }
- break;
+ case 'e':
+ commands++;
+ switch (*commands) {
+ case 'U':
+ flags = F_UNLCK;
+ break;
+ case 'R':
+ flags = F_RDLCK;
+ break;
+ case 'W':
+ flags = F_WRLCK;
+ break;
+ default:
+ errx(-1, "unknown mode: %c", *commands);
+ }
+
+ rc = ioctl(fd, LL_IOC_SET_LEASE, flags);
+ if (rc < 0)
+ err(errno, "apply lease error");
+
+ if (flags != F_UNLCK)
+ break;
+
+ /* F_UNLCK, interpret return code */
+ if (rc > 0) {
+ const char *str = "Unknown";
+ if (rc == FMODE_READ)
+ str = "FMODE_READ";
+ else if (rc == FMODE_WRITE)
+ str = "FMODE_WRITE";
+ fprintf(stdout, "%s lease(%d) released.\n",
+ str, rc);
+ } else if (rc == 0) {
+ fprintf(stdout, "lease already broken.\n");
+ }
+ break;
+ case 'E':
+ commands++;
+ if (*commands != '-' && *commands != '+')
+ errx(-1, "unknown mode: %c\n", *commands);
+
+ rc = ioctl(fd, LL_IOC_GET_LEASE);
+ if (rc > 0) {
+ const char *str = "Unknown";
+
+ if (rc == FMODE_READ)
+ str = "FMODE_READ";
+ else if (rc == FMODE_WRITE)
+ str = "FMODE_WRITE";
+ fprintf(stdout, "%s lease(%d) has applied.\n",
+ str, rc);
+ if (*commands == '-')
+ errx(-1, "expect lease to not exist");
+ } else if (rc == 0) {
+ fprintf(stdout, "no lease applied.\n");
+ if (*commands == '+')
+ errx(-1, "expect lease exists");
+ } else {
+ err(errno, "free lease error");
+ }
+ break;
+ case 'f':
+ if (statfs(fname, &stfs) == -1)
+ errx(-1, "statfs()");
+ break;
+ case 'F':
+ if (fd == -1)
+ rc = llapi_path2fid(fname, &fid);
+ else
+ rc = llapi_fd2fid(fd, &fid);
+ if (rc != 0)
+ fprintf(stderr,
+ "llapi_path/fd2fid() on %d, rc=%d\n",
+ fd, rc);
+ else
+ printf(DFID"\n", PFID(&fid));
+ break;
case 'G':
gid = atoi(commands+1);
if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) {
exit(save_errno);
}
break;
+ case 'H':
+ len = atoi(commands+1);
+ fd = llapi_file_open(fname, O_CREAT | O_WRONLY,
+ 0644, 0, 0, len,
+ LOV_PATTERN_RAID0 | LOV_PATTERN_F_RELEASED);
+ if (fd == -1) {
+ save_errno = errno;
+ perror("create stripe file");
+ exit(save_errno);
+ }
+ break;
+ case 'K':
+ oldpath = POP_ARG();
+ if (oldpath == NULL)
+ oldpath = fname;
+
+ if (link(oldpath, fname)) {
+ save_errno = errno;
+ perror("link()");
+ exit(save_errno);
+ }
+ break;
case 'l':
newfile = POP_ARG();
if (!newfile)
exit(save_errno);
}
break;
- case 'L':
- newfile = POP_ARG();
- if (!newfile)
- newfile = fname;
- if (link(fname, newfile)) {
- save_errno = errno;
- perror("symlink()");
- exit(save_errno);
- }
- break;
+ case 'L':
+ newfile = POP_ARG();
+ if (newfile == NULL)
+ newfile = fname;
+
+ if (link(fname, newfile)) {
+ save_errno = errno;
+ perror("link()");
+ exit(save_errno);
+ }
+ break;
case 'm':
if (mknod(fname, S_IFREG | 0644, 0) == -1) {
save_errno = errno;
exit(save_errno);
}
break;
+ case 'n':
+ oldpath = POP_ARG();
+ if (oldpath == NULL)
+ oldpath = fname;
+
+ if (rename(oldpath, fname) < 0) {
+ save_errno = errno;
+ perror("rename()");
+ exit(save_errno);
+ }
+ break;
case 'N':
newfile = POP_ARG();
if (!newfile)
exit(save_errno);
}
break;
- case 'r':
- len = atoi(commands+1);
- if (len <= 0)
- len = 1;
- if (bufsize < len) {
- buf = realloc(buf, len + ALIGN);
- if (buf == NULL) {
- save_errno = errno;
- perror("allocating buf for read\n");
- exit(save_errno);
- }
- bufsize = len;
- buf_align = (char *)((long)(buf + ALIGN) &
- ~ALIGN);
- }
- while (len > 0) {
- rc = read(fd, buf_align, len);
- if (rc == -1) {
- save_errno = errno;
- perror("read");
- exit(save_errno);
- }
+ case 'r':
+ len = atoi(commands+1);
+ if (len <= 0)
+ len = 1;
+ if (bufsize < len) {
+ buf = realloc(buf, len + ALIGN_LEN);
+ if (buf == NULL) {
+ save_errno = errno;
+ perror("allocating buf for read\n");
+ exit(save_errno);
+ }
+ bufsize = len;
+ buf_align = (char *)((long)(buf + ALIGN_LEN) &
+ ~ALIGN_LEN);
+ }
+ while (len > 0) {
+ rc = read(fd, buf_align, len);
+ if (rc == -1) {
+ save_errno = errno;
+ perror("read");
+ exit(save_errno);
+ }
if (rc < len) {
fprintf(stderr, "short read: %u/%u\n",
rc, len);
if (rc == 0)
exit(ENODATA);
}
- len -= rc;
- if (verbose >= 2)
- printf("%.*s\n", rc, buf_align);
- }
- break;
+ len -= rc;
+ if (verbose >= 2)
+ printf("%.*s\n", rc, buf_align);
+ }
+ break;
case 'R':
for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
junk += mmap_ptr[i];
case 'v':
verbose++;
break;
- case 'w':
- len = atoi(commands+1);
- if (len <= 0)
- len = 1;
- if (bufsize < len) {
- buf = realloc(buf, len + ALIGN);
- if (buf == NULL) {
- save_errno = errno;
- perror("allocating buf for write\n");
- exit(save_errno);
- }
- bufsize = len;
- buf_align = (char *)((long)(buf + ALIGN) &
- ~ALIGN);
- strncpy(buf_align, msg, bufsize);
- }
- while (len > 0) {
- rc = write(fd, buf_align, len);
- if (rc == -1) {
- save_errno = errno;
- perror("write");
- exit(save_errno);
- }
- if (rc < len)
- fprintf(stderr, "short write: %u/%u\n",
- rc, len);
- len -= rc;
- }
- break;
- case 'W':
- for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
- mmap_ptr[i] += junk++;
- break;
+ case 'V':
+ len = get_flags(commands + 1, &flags);
+ commands += len;
+ fd = llapi_create_volatile(fname, flags);
+ if (fd < 0) {
+ perror("llapi_create_volatile");
+ exit(fd);
+ }
+ break;
+ case 'w':
+ len = atoi(commands+1);
+ if (len <= 0)
+ len = 1;
+ if (bufsize < len) {
+ buf = realloc(buf, len + ALIGN_LEN);
+ if (buf == NULL) {
+ save_errno = errno;
+ perror("allocating buf for write\n");
+ exit(save_errno);
+ }
+ bufsize = len;
+ buf_align = (char *)((long)(buf + ALIGN_LEN) &
+ ~ALIGN_LEN);
+ strncpy(buf_align, msg, bufsize);
+ }
+ while (len > 0) {
+ rc = write(fd, buf_align, len);
+ if (rc == -1) {
+ save_errno = errno;
+ perror("write");
+ exit(save_errno);
+ }
+ if (rc < len)
+ fprintf(stderr, "short write: %u/%u\n",
+ rc, len);
+ len -= rc;
+ }
+ break;
+ case 'W':
+ for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
+ mmap_ptr[i] += junk++;
+ break;
+ case 'x':
+ rc = llapi_get_data_version(fd, &dv, 0);
+ if (rc) {
+ fprintf(stderr, "cannot get file data version"
+ " %d\n", rc);
+ exit(-rc);
+ }
+ printf("dataversion is "LPU64"\n", dv);
+ break;
case 'y':
if (fsync(fd) == -1) {
save_errno = errno;
}
break;
case 'Y':
- if (fdatasync(fd) == -1) {
- save_errno = errno;
- perror("fdatasync");
- exit(save_errno);
- }
+ if (fdatasync(fd) == -1) {
+ save_errno = errno;
+ perror("fdatasync");
+ exit(save_errno);
+ }
+ break;
case 'z':
len = atoi(commands+1);
if (lseek(fd, len, SEEK_SET) == -1) {
exit(save_errno);
}
break;
+ case '-':
case '0':
case '1':
case '2':