Skip to content

Commit

Permalink
options: Support arbitrarily long pattern buffers
Browse files Browse the repository at this point in the history
Dynamically allocate the pattern buffer to remove the 512B length
restriction. To accomplish this, store a pointer instead of a fixed
block of memory for the buffers in the thread_options structure.
Then introduce and use the function parse_and_fill_pattern_alloc()
which will calculate the approprite size of the buffer and allocate
it before filling it.

The buffers will be freed, along with a number of string buffers
in free_thread_options_to_cpu(). They will also be reallocated (if
necessary) when receiving them over the wire with
convert_thread_options_to_cpu().

This allows for specifying real world compressible data (eg. The
Calgary Corpus) for the buffer_pattern option.

Signed-off-by: Logan Gunthorpe <[email protected]>
Signed-off-by: Vincent Fu <[email protected]>
  • Loading branch information
lsgunth authored and vincentkfu committed Nov 19, 2022
1 parent accccb1 commit 1dc47d6
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 18 deletions.
11 changes: 11 additions & 0 deletions cconv.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ static void free_thread_options_to_cpu(struct thread_options *o)
free(o->profile);
free(o->cgroup);

free(o->verify_pattern);
free(o->buffer_pattern);

for (i = 0; i < DDIR_RWDIR_CNT; i++) {
free(o->bssplit[i]);
free(o->zone_split[i]);
Expand Down Expand Up @@ -185,6 +188,10 @@ int convert_thread_options_to_cpu(struct thread_options *o,
thread_options_pack_size(o) > top_sz)
return -EINVAL;

o->verify_pattern = realloc(o->verify_pattern,
o->verify_pattern_bytes);
o->buffer_pattern = realloc(o->buffer_pattern,
o->buffer_pattern_bytes);
memcpy(o->verify_pattern, top->patterns, o->verify_pattern_bytes);
memcpy(o->buffer_pattern, &top->patterns[o->verify_pattern_bytes],
o->buffer_pattern_bytes);
Expand Down Expand Up @@ -651,8 +658,10 @@ int fio_test_cconv(struct thread_options *__o)
int ret;

o1.verify_pattern_bytes = 61;
o1.verify_pattern = malloc(o1.verify_pattern_bytes);
memset(o1.verify_pattern, 'V', o1.verify_pattern_bytes);
o1.buffer_pattern_bytes = 15;
o1.buffer_pattern = malloc(o1.buffer_pattern_bytes);
memset(o1.buffer_pattern, 'B', o1.buffer_pattern_bytes);

top_sz = thread_options_pack_size(&o1);
Expand All @@ -672,5 +681,7 @@ int fio_test_cconv(struct thread_options *__o)
free_thread_options_to_cpu(&o2);
free(top2);
free(top1);
free(o1.buffer_pattern);
free(o1.verify_pattern);
return ret;
}
52 changes: 47 additions & 5 deletions lib/pattern.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,11 +327,11 @@ static const char *parse_format(const char *in, char *out, unsigned int parsed,
*
* Returns number of bytes filled or err < 0 in case of failure.
*/
int parse_and_fill_pattern(const char *in, unsigned int in_len,
char *out, unsigned int out_len,
const struct pattern_fmt_desc *fmt_desc,
struct pattern_fmt *fmt,
unsigned int *fmt_sz_out)
static int parse_and_fill_pattern(const char *in, unsigned int in_len,
char *out, unsigned int out_len,
const struct pattern_fmt_desc *fmt_desc,
struct pattern_fmt *fmt,
unsigned int *fmt_sz_out)
{
const char *beg, *end, *out_beg = out;
unsigned int total = 0, fmt_rem = 0;
Expand Down Expand Up @@ -392,6 +392,48 @@ int parse_and_fill_pattern(const char *in, unsigned int in_len,
return total;
}

/**
* parse_and_fill_pattern_alloc() - Parses combined input, which consists of
* strings, numbers and pattern formats and
* allocates a buffer for the result.
*
* @in - string input
* @in_len - size of the input string
* @out - pointer to the output buffer pointer, this will be set to the newly
* allocated pattern buffer which must be freed by the caller
* @fmt_desc - array of pattern format descriptors [input]
* @fmt - array of pattern formats [output]
* @fmt_sz - pointer where the size of pattern formats array stored [input],
* after successful parsing this pointer will contain the number
* of parsed formats if any [output].
*
* See documentation on parse_and_fill_pattern() above for a description
* of the functionality.
*
* Returns number of bytes filled or err < 0 in case of failure.
*/
int parse_and_fill_pattern_alloc(const char *in, unsigned int in_len,
char **out, const struct pattern_fmt_desc *fmt_desc,
struct pattern_fmt *fmt, unsigned int *fmt_sz_out)
{
int count;

count = parse_and_fill_pattern(in, in_len, NULL, MAX_PATTERN_SIZE,
fmt_desc, fmt, fmt_sz_out);
if (count < 0)
return count;

*out = malloc(count);
count = parse_and_fill_pattern(in, in_len, *out, count, fmt_desc,
fmt, fmt_sz_out);
if (count < 0) {
free(*out);
*out = NULL;
}

return count;
}

/**
* dup_pattern() - Duplicates part of the pattern all over the buffer.
*
Expand Down
21 changes: 16 additions & 5 deletions lib/pattern.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
#ifndef FIO_PARSE_PATTERN_H
#define FIO_PARSE_PATTERN_H

/*
* The pattern is dynamically allocated, but that doesn't mean there
* are not limits. The network protocol has a limit of
* FIO_SERVER_MAX_CMD_MB and potentially two patterns must fit in there.
* There's also a need to verify the incoming data from the network and
* this provides a sensible check.
*
* 128MiB is an arbitrary limit that meets these criteria. The patterns
* tend to be truncated at the IO size anyway and IO sizes that large
* aren't terribly practical.
*/
#define MAX_PATTERN_SIZE (128 << 20)

/**
* Pattern format description. The input for 'parse_pattern'.
* Describes format with its name and callback, which should
Expand All @@ -21,11 +34,9 @@ struct pattern_fmt {
const struct pattern_fmt_desc *desc;
};

int parse_and_fill_pattern(const char *in, unsigned int in_len,
char *out, unsigned int out_len,
const struct pattern_fmt_desc *fmt_desc,
struct pattern_fmt *fmt,
unsigned int *fmt_sz_out);
int parse_and_fill_pattern_alloc(const char *in, unsigned int in_len,
char **out, const struct pattern_fmt_desc *fmt_desc,
struct pattern_fmt *fmt, unsigned int *fmt_sz_out);

int paste_format_inplace(char *pattern, unsigned int pattern_len,
struct pattern_fmt *fmt, unsigned int fmt_sz,
Expand Down
10 changes: 5 additions & 5 deletions options.c
Original file line number Diff line number Diff line change
Expand Up @@ -1488,8 +1488,8 @@ static int str_buffer_pattern_cb(void *data, const char *input)
int ret;

/* FIXME: for now buffer pattern does not support formats */
ret = parse_and_fill_pattern(input, strlen(input), td->o.buffer_pattern,
MAX_PATTERN_SIZE, NULL, NULL, NULL);
ret = parse_and_fill_pattern_alloc(input, strlen(input),
&td->o.buffer_pattern, NULL, NULL, NULL);
if (ret < 0)
return 1;

Expand Down Expand Up @@ -1537,9 +1537,9 @@ static int str_verify_pattern_cb(void *data, const char *input)
int ret;

td->o.verify_fmt_sz = FIO_ARRAY_SIZE(td->o.verify_fmt);
ret = parse_and_fill_pattern(input, strlen(input), td->o.verify_pattern,
MAX_PATTERN_SIZE, fmt_desc,
td->o.verify_fmt, &td->o.verify_fmt_sz);
ret = parse_and_fill_pattern_alloc(input, strlen(input),
&td->o.verify_pattern, fmt_desc, td->o.verify_fmt,
&td->o.verify_fmt_sz);
if (ret < 0)
return 1;

Expand Down
1 change: 0 additions & 1 deletion stat.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ enum block_info_state {
BLOCK_STATE_COUNT,
};

#define MAX_PATTERN_SIZE 512
#define FIO_JOBNAME_SIZE 128
#define FIO_JOBDESC_SIZE 256
#define FIO_VERROR_SIZE 128
Expand Down
4 changes: 2 additions & 2 deletions thread_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ struct thread_options {
unsigned int do_verify;
unsigned int verify_interval;
unsigned int verify_offset;
char verify_pattern[MAX_PATTERN_SIZE];
char *verify_pattern;
unsigned int verify_pattern_bytes;
struct pattern_fmt verify_fmt[8];
unsigned int verify_fmt_sz;
Expand Down Expand Up @@ -256,7 +256,7 @@ struct thread_options {
unsigned int zero_buffers;
unsigned int refill_buffers;
unsigned int scramble_buffers;
char buffer_pattern[MAX_PATTERN_SIZE];
char *buffer_pattern;
unsigned int buffer_pattern_bytes;
unsigned int compress_percentage;
unsigned int compress_chunk;
Expand Down

0 comments on commit 1dc47d6

Please sign in to comment.