fsstress: Add fallocate zero range operation

This commit adds fzero operation support for fsstress, which is meant to
exercise fallocate FALLOC_FL_ZERO_RANGE support.

Also reorganise the common fallocate code into a single do_fallocate()
function and use flags use the right mode.

Also in order to make more obvious which fallocate mode fsstress is
testing translate fallocate flags into human readable strings.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
Lukas Czerner
2014-03-13 15:19:53 +11:00
committed by Dave Chinner
parent 2dc43e03e6
commit 2d2d853625
+120 -58
View File
@@ -70,6 +70,7 @@ typedef enum {
OP_MKDIR,
OP_MKNOD,
OP_PUNCH,
OP_ZERO,
OP_READ,
OP_READLINK,
OP_RENAME,
@@ -114,6 +115,17 @@ typedef struct pathname {
char *path;
} pathname_t;
struct print_flags {
unsigned long mask;
const char *name;
};
struct print_string {
char *buffer;
int len;
int max;
};
#define FT_DIR 0
#define FT_DIRm (1 << FT_DIR)
#define FT_REG 1
@@ -155,6 +167,7 @@ void link_f(int, long);
void mkdir_f(int, long);
void mknod_f(int, long);
void punch_f(int, long);
void zero_f(int, long);
void read_f(int, long);
void readlink_f(int, long);
void rename_f(int, long);
@@ -192,6 +205,7 @@ opdesc_t ops[] = {
{ OP_MKDIR, "mkdir", mkdir_f, 2, 1 },
{ OP_MKNOD, "mknod", mknod_f, 2, 1 },
{ OP_PUNCH, "punch", punch_f, 1, 1 },
{ OP_ZERO, "zero", zero_f, 1, 1 },
{ OP_READ, "read", read_f, 1, 0 },
{ OP_READLINK, "readlink", readlink_f, 1, 0 },
{ OP_RENAME, "rename", rename_f, 2, 1 },
@@ -243,6 +257,7 @@ int verifiable_log = 0;
sig_atomic_t should_stop = 0;
char *execute_cmd = NULL;
int execute_freq = 1;
struct print_string flag_str = {0};
void add_to_flist(int, int, int);
void append_pathname(pathname_t *, char *);
@@ -548,6 +563,73 @@ int main(int argc, char **argv)
return 0;
}
int
add_string(struct print_string *str, const char *add)
{
int len = strlen(add);
if (len <= 0)
return 0;
if (len > (str->max - 1) - str->len) {
str->len = str->max - 1;
return 0;
}
memcpy(str->buffer + str->len, add, len);
str->len += len;
str->buffer[str->len] = '\0';
return len;
}
char *
translate_flags(int flags, const char *delim,
const struct print_flags *flag_array)
{
int i, mask, first = 1;
const char *add;
if (!flag_str.buffer) {
flag_str.buffer = malloc(4096);
flag_str.max = 4096;
flag_str.len = 0;
}
if (!flag_str.buffer)
return NULL;
flag_str.len = 0;
flag_str.buffer[0] = '\0';
for (i = 0; flag_array[i].name && flags; i++) {
mask = flag_array[i].mask;
if ((flags & mask) != mask)
continue;
add = flag_array[i].name;
flags &= ~mask;
if (!first && delim)
add_string(&flag_str, delim);
else
first = 0;
add_string(&flag_str, add);
}
/* Check whether there are any leftover flags. */
if (flags) {
int ret;
char number[11];
if (!first && delim)
add_string(&flag_str, delim);
ret = snprintf(number, 11, "0x%x", flags) > 0;
if (ret > 0 && ret <= 11)
add_string(&flag_str, number);
}
return flag_str.buffer;
}
void
add_to_flist(int ft, int id, int parent)
{
@@ -2083,8 +2165,23 @@ dwrite_f(int opno, long r)
close(fd);
}
#ifdef HAVE_LINUX_FALLOC_H
struct print_flags falloc_flags [] = {
{ FALLOC_FL_KEEP_SIZE, "KEEP_SIZE"},
{ FALLOC_FL_PUNCH_HOLE, "PUNCH_HOLE"},
{ FALLOC_FL_NO_HIDE_STALE, "NO_HIDE_STALE"},
{ FALLOC_FL_COLLAPSE_RANGE, "COLLAPSE_RANGE"},
{ FALLOC_FL_ZERO_RANGE, "ZERO_RANGE"},
{ -1, NULL}
};
#define translate_falloc_flags(mode) \
({translate_flags(mode, "|", falloc_flags);})
#endif
void
fallocate_f(int opno, long r)
do_fallocate(int opno, long r, int mode)
{
#ifdef HAVE_LINUX_FALLOC_H
int e;
@@ -2096,28 +2193,26 @@ fallocate_f(int opno, long r)
struct stat64 stb;
int v;
char st[1024];
int mode = 0;
init_pathname(&f);
if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
if (v)
printf("%d/%d: fallocate - no filename\n", procid, opno);
printf("%d/%d: do_fallocate - no filename\n", procid, opno);
free_pathname(&f);
return;
}
fd = open_path(&f, O_RDWR);
e = fd < 0 ? errno : 0;
check_cwd();
if (fd < 0) {
if (v)
printf("%d/%d: fallocate - open %s failed %d\n",
procid, opno, f.path, e);
printf("%d/%d: do_fallocate - open %s failed %d\n",
procid, opno, f.path, errno);
free_pathname(&f);
return;
}
check_cwd();
if (fstat64(fd, &stb) < 0) {
if (v)
printf("%d/%d: fallocate - fstat64 %s failed %d\n",
printf("%d/%d: do_fallocate - fstat64 %s failed %d\n",
procid, opno, f.path, errno);
free_pathname(&f);
close(fd);
@@ -2131,14 +2226,21 @@ fallocate_f(int opno, long r)
mode |= FALLOC_FL_KEEP_SIZE & random();
e = fallocate(fd, mode, (loff_t)off, (loff_t)len) < 0 ? errno : 0;
if (v)
printf("%d/%d: fallocate(%d) %s %st %lld %lld %d\n",
procid, opno, mode,
printf("%d/%d: fallocate(%s) %s %st %lld %lld %d\n",
procid, opno, translate_falloc_flags(mode),
f.path, st, (long long)off, (long long)len, e);
free_pathname(&f);
close(fd);
#endif
}
void
fallocate_f(int opno, long r)
{
#ifdef HAVE_LINUX_FALLOC_H
do_fallocate(opno, r, 0);
#endif
}
void
fdatasync_f(int opno, long r)
@@ -2509,55 +2611,15 @@ void
punch_f(int opno, long r)
{
#ifdef HAVE_LINUX_FALLOC_H
int e;
pathname_t f;
int fd;
__int64_t lr;
off64_t off;
off64_t len;
struct stat64 stb;
int v;
char st[1024];
int mode = FALLOC_FL_PUNCH_HOLE;
do_fallocate(opno, r, FALLOC_FL_PUNCH_HOLE);
#endif
}
init_pathname(&f);
if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
if (v)
printf("%d/%d: punch hole - no filename\n", procid, opno);
free_pathname(&f);
return;
}
fd = open_path(&f, O_RDWR);
e = fd < 0 ? errno : 0;
check_cwd();
if (fd < 0) {
if (v)
printf("%d/%d: punch hole - open %s failed %d\n",
procid, opno, f.path, e);
free_pathname(&f);
return;
}
if (fstat64(fd, &stb) < 0) {
if (v)
printf("%d/%d: punch hole - fstat64 %s failed %d\n",
procid, opno, f.path, errno);
free_pathname(&f);
close(fd);
return;
}
inode_info(st, sizeof(st), &stb, v);
lr = ((__int64_t)random() << 32) + random();
off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
off %= maxfsize;
len = (off64_t)(random() % (1024 * 1024));
mode |= FALLOC_FL_KEEP_SIZE & random();
e = fallocate(fd, mode, (loff_t)off, (loff_t)len) < 0 ? errno : 0;
if (v)
printf("%d/%d: punch hole(%d) %s %s %lld %lld %d\n",
procid, opno, mode,
f.path, st, (long long)off, (long long)len, e);
free_pathname(&f);
close(fd);
void
zero_f(int opno, long r)
{
#ifdef HAVE_LINUX_FALLOC_H
do_fallocate(opno, r, FALLOC_FL_ZERO_RANGE);
#endif
}