diff options
| author | Paul Buetow <pbuetow@mimecast.com> | 2018-03-30 10:21:02 +0100 |
|---|---|---|
| committer | Paul Buetow <pbuetow@mimecast.com> | 2018-03-30 10:21:02 +0100 |
| commit | 712a25f115bf34dc73f81e5a4f1971b586fb524a (patch) | |
| tree | 30a4620b9df7f72897d7bb0c4d587461cc748a61 | |
| parent | fd779da9cfd81db6bf1d01404149235d7dd3e9df (diff) | |
add file hole support
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | ioriot/src/datas/btree.c | 180 | ||||
| -rw-r--r-- | ioriot/src/datas/btree.h | 21 | ||||
| -rw-r--r-- | ioriot/src/datas/list.c | 1 | ||||
| -rw-r--r-- | ioriot/src/defaults.h | 8 | ||||
| -rw-r--r-- | ioriot/src/generate/generate.c | 29 | ||||
| -rw-r--r-- | ioriot/src/generate/gioop.c | 21 | ||||
| -rw-r--r-- | ioriot/src/generate/gioop.h | 1 | ||||
| -rw-r--r-- | ioriot/src/generate/vsize.c | 97 | ||||
| -rw-r--r-- | ioriot/src/generate/vsize.h | 23 | ||||
| -rw-r--r-- | ioriot/src/init/init.c | 20 | ||||
| -rw-r--r-- | ioriot/src/init/itask.c | 6 | ||||
| -rw-r--r-- | ioriot/src/init/itask.h | 3 | ||||
| -rw-r--r-- | ioriot/src/init/ithread.c | 10 | ||||
| -rw-r--r-- | ioriot/src/opcodes.h | 1 | ||||
| -rw-r--r-- | ioriot/src/replay/rioop.c | 1 | ||||
| -rw-r--r-- | ioriot/src/utests.c | 4 | ||||
| -rw-r--r-- | ioriot/src/utils/futils.c | 24 | ||||
| -rw-r--r-- | ioriot/src/utils/futils.h | 9 | ||||
| -rw-r--r-- | ioriot/src/utils/utils.c | 56 | ||||
| -rw-r--r-- | ioriot/tags | 661 | ||||
| -rw-r--r-- | systemtap/src/ioriot.stp | 14 | ||||
| -rw-r--r-- | systemtap/src/javaioriot.stp | 14 | ||||
| -rw-r--r-- | systemtap/src/targetedioriot.stp | 14 |
25 files changed, 428 insertions, 792 deletions
@@ -3,4 +3,5 @@ docs/html/ docs/latex/ ioriot/ioriot +ioriot/tags systemtap/downloads/ @@ -339,6 +339,7 @@ Currently, these file I/O related syscalls are supported (as of CentOS 7): open
openat
lseek
+llseek
fcntl
creat
write
diff --git a/ioriot/src/datas/btree.c b/ioriot/src/datas/btree.c index b150066..a70c442 100644 --- a/ioriot/src/datas/btree.c +++ b/ioriot/src/datas/btree.c @@ -37,7 +37,7 @@ void btree_destroy2(btree_s* b) free(b); } -int btree_insert(btree_s* b, int key, void *data) +int btree_insert(btree_s* b, long key, void *data) { int ret = 0; @@ -48,13 +48,13 @@ int btree_insert(btree_s* b, int key, void *data) ret = btreelem_insert_r(b->root, key, data); } - if (ret == 0) + if (ret == 1) b->size++; return ret; } -void* btree_get(btree_s* b, int key) +void* btree_get(btree_s* b, long key) { if (b->root == NULL) return NULL; @@ -62,17 +62,45 @@ void* btree_get(btree_s* b, int key) return btreelem_get_r(b->root, key); } +bool btree_has_range_l(btree_s* b, const long start, const long end) +{ + if (b->root == NULL) + return false; + + return btreelem_has_range_lr(b->root, start, end); +} + +long btree_get_l(btree_s* b, long key) +{ + void *data = btree_get(b, key); + if (data) + return (long)data; + else + return -1; +} + +void btree_ensure_range_l(btree_s* b, const long start, const long end, const long threshold) +{ + if (b->root == NULL) { + btree_insert(b, start, (void*)end); + } else { + if (1 == btreelem_ensure_range_lr(b->root, start, end, threshold)) + b->size++; + } +} + void btree_print(btree_s* b) { - btreelem_print_r(b->root, 0); + Put("btree:%p size:%d", (void*)b, b->size); + btreelem_print_r(b->root, 1); } -void btree_run_cb2(btree_s* b, void (*cb)(void *data, void *data2)) +void btree_run_cb2(btree_s* b, void (*cb)(long key, void *data, void *data2), void *data2) { - btreelem_run_cb2_r(b->root, cb); + btreelem_run_cb2_r(b->root, cb, data2); } -btreelem_s* btreelem_new(int key, void *data) +btreelem_s* btreelem_new(long key, void *data) { btreelem_s *e = Malloc(btreelem_s); @@ -105,7 +133,7 @@ void btreelem_destroy_r2(btreelem_s* e) free(e); } -int btreelem_insert_r(btreelem_s* e, int key, void *data) +int btreelem_insert_r(btreelem_s* e, long key, void *data) { int ret = 1; @@ -130,19 +158,65 @@ int btreelem_insert_r(btreelem_s* e, int key, void *data) return ret; } -void* btreelem_get_r(btreelem_s* e, int key) +int btreelem_ensure_range_lr(btreelem_s *e, const long start, const long end, const long threshold) +{ + int ret = 0; + long value = (long) e->data; + + //Debug("%ld %ld %ld", start, end, threshold); + + if (e->key == start) { + if (value < end) { + e->data = (void*) end; + } else { + // Nothing to do, range already present + } + + } else if (e->key > start) { + if (e->left == NULL) { + if (value <= end) { + e->key = start; + e->data = (void*)end; + } else { + e->left = btreelem_new(start, (void*)end); + ret = 1; + } + } else { + ret = btreelem_ensure_range_lr(e->left, start, end, threshold); + } + + } else { // if (e->key < start) + if (value >= start) { + if (value < end) { + e->data = (void*) end; + } else { + // Nothing to do, range already present + } + } else { + if (e->right == NULL) { + e->right = btreelem_new(start, (void*)end); + ret = 1; + } else { + ret = btreelem_ensure_range_lr(e->right, start, end, threshold); + } + } + } + + return ret; +} + +void* btreelem_get_r(btreelem_s* e, long key) { void *data = NULL; - if (e->key == key) + if (e->key == key) { data = e->data; - else if (e->key > key) { + } else if (e->key > key) { if (e->left) data = btreelem_get_r(e->left, key); - } - else { + } else { if (e->right) data = btreelem_get_r(e->right, key); } @@ -150,6 +224,27 @@ void* btreelem_get_r(btreelem_s* e, int key) return data; } +bool btreelem_has_range_lr(btreelem_s* e, const long start, const long end) +{ + long value = (long)e->data; + + if (e->key <= start && value >= end) { + return true; + + } else if (e->key > start) { + if (e->left) + return btreelem_has_range_lr(e->left, start, end); + else + return false; + + } else { + if (e->right) + return btreelem_has_range_lr(e->right, start, end); + else + return false; + } +} + void btreelem_print_r(btreelem_s* e, int depth) { if (!e) @@ -157,7 +252,7 @@ void btreelem_print_r(btreelem_s* e, int depth) for (int i = 0; i < depth; ++i) Out(" "); - Put("key:%d data:%ld\n", e->key, (long) e->data); + Put("key:%ld data:%ld", e->key, (long) e->data); if (e->left) btreelem_print_r(e->left, depth); @@ -166,18 +261,18 @@ void btreelem_print_r(btreelem_s* e, int depth) btreelem_print_r(e->right, depth+1); } -void btreelem_run_cb2_r(btreelem_s* e, void (*cb)(void *data, void *data2)) +void btreelem_run_cb2_r(btreelem_s* e, void (*cb)(long key, void *data, void *data2), void *data2) { if (!e) return; - cb((void*)(long)e->key, e->data); + cb(e->key, e->data, data2); if (e->left) - btreelem_run_cb2_r(e->left, cb); + btreelem_run_cb2_r(e->left, cb, data2); if (e->right) - btreelem_run_cb2_r(e->right, cb); + btreelem_run_cb2_r(e->right, cb, data2); } void btree_test(void) @@ -186,23 +281,68 @@ void btree_test(void) void* somedata = (void*)b; assert(1 == btree_insert(b, 1, (void*)1)); + assert(1 == b->size); assert(1 == btree_insert(b, 2, (void*)2)); + assert(2 == b->size); assert(1 == btree_insert(b, 3, (void*)3)); - assert(1 == (long)btree_get(b, 1)); + assert(3 == b->size); + assert(1 == btree_get_l(b, 1)); assert(1 == btree_insert(b, 1234, somedata)); + assert(4 == b->size); assert(1 == btree_insert(b, 13, somedata)); + assert(5 == b->size); assert(1 == btree_insert(b, 666, somedata)); + assert(6 == b->size); assert(0 == btree_insert(b, 13, somedata)); + assert(6 == b->size); assert(NULL != btree_get(b, 666)); assert(NULL == btree_get(b, 777)); assert(0 == btree_insert(b, 666, somedata)); assert(1 == btree_insert(b, 42, (void*)42)); - assert(42 == (long)btree_get(b, 42)); + assert(42 == btree_get_l(b, 42)); btree_print(b); + btree_destroy(b); + b = btree_new(); + assert(0 == b->size); + + btree_ensure_range_l(b, 0, 23, 0); + assert(btree_get_l(b, 0) == (long) btree_get(b, 0)); + assert(23 == btree_get_l(b, 0)); + assert(btree_has_range_l(b, 2, 10)); + + assert(!btree_has_range_l(b, 300, 325)); + btree_ensure_range_l(b, 300, 325, 0); + assert(2 == b->size); + assert(325 == btree_get_l(b, 300)); + assert(btree_has_range_l(b, 300, 325)); + assert(!btree_has_range_l(b, 300, 326)); + + btree_ensure_range_l(b, 200, 3321, 0); + assert(2 == b->size); + + btree_ensure_range_l(b, 200, 1000, 0); + assert(2 == b->size); + assert(3321 == btree_get_l(b, 200)); + + btree_ensure_range_l(b, 0, 23, 0); + btree_ensure_range_l(b, 10, 10, 0); + btree_ensure_range_l(b, 22, 25, 0); + assert(25 == btree_get_l(b, 0)); + assert(2 == b->size); + + assert(!btree_has_range_l(b, 4000, 4000)); + btree_ensure_range_l(b, 4000, 4000, 0); + assert(3 == b->size); + assert(btree_has_range_l(b, 4000, 4000)); + assert(!btree_has_range_l(b, 4000, 4001)); + assert(!btree_has_range_l(b, 3999, 4000)); + btree_print(b); + + btree_print(b); btree_destroy(b); } diff --git a/ioriot/src/datas/btree.h b/ioriot/src/datas/btree.h index acc5477..0a05cee 100644 --- a/ioriot/src/datas/btree.h +++ b/ioriot/src/datas/btree.h @@ -23,7 +23,7 @@ typedef struct btreelem_ { struct btreelem_ *left; /**< The next element to the left */ struct btreelem_ *right; /**< The next element to the right */ - int key; /**< The key of the element */ + long key; /**< The key of the element */ void *data; /**< A pointer to the data stored in this element */ } btreelem_s; @@ -38,18 +38,23 @@ typedef struct btree_s_ { btree_s* btree_new(); void btree_destroy(btree_s *b); void btree_destroy2(btree_s *b); -int btree_insert(btree_s *b, int key, void *data); -void* btree_get(btree_s *b, int key); +int btree_insert(btree_s *b, long key, void *data); +void* btree_get(btree_s *b, long key); +long btree_get_l(btree_s *b, long key); +bool btree_has_range_l(btree_s *b, const long start, const long end); +void btree_ensure_range_l(btree_s *b, const long start, const long end, const long threshold); void btree_print(btree_s *b); -void btree_run_cb2(btree_s* b, void (*cb)(void *data, void *data2)); +void btree_run_cb2(btree_s* b, void (*cb)(long key, void *data, void *data2), void *data2); void btree_test(void); -btreelem_s* btreelem_new(int key, void *data); +btreelem_s* btreelem_new(long key, void *data); void btreelem_destroy_r(btreelem_s *e); void btreelem_destroy_r2(btreelem_s *e); -int btreelem_insert_r(btreelem_s *e, int key, void *data); -void* btreelem_get_r(btreelem_s *e, int key); +int btreelem_insert_r(btreelem_s *e, long key, void *data); +void* btreelem_get_r(btreelem_s *e, long key); +bool btreelem_has_range_lr(btreelem_s *e, const long start, const long end); +int btreelem_ensure_range_lr(btreelem_s *e, const long start, const long end, const long threshold); void btreelem_print_r(btreelem_s *e, int depth); -void btreelem_run_cb2_r(btreelem_s* e, void (*cb)(void *data, void *data2)); +void btreelem_run_cb2_r(btreelem_s* e, void (*cb)(long key, void *data, void *data2), void *data2); #endif // BTREE_H diff --git a/ioriot/src/datas/list.c b/ioriot/src/datas/list.c index 9cc78db..81e3e57 100644 --- a/ioriot/src/datas/list.c +++ b/ioriot/src/datas/list.c @@ -14,7 +14,6 @@ #include "list.h" - list_s *list_new() { list_s *l = Malloc(list_s); diff --git a/ioriot/src/defaults.h b/ioriot/src/defaults.h index c0833c8..d822423 100644 --- a/ioriot/src/defaults.h +++ b/ioriot/src/defaults.h @@ -18,9 +18,9 @@ #include "utils/utils.h" /** Version of the supported .capture format */ -#define CAPTURE_VERSION 1 +#define CAPTURE_VERSION 2 /** Version of the supported .replay format */ -#define REPLAY_VERSION 1 +#define REPLAY_VERSION 2 /** Max amount of tokens per line in the .capture file */ #define MAX_TOKENS 10 /** Max line length in either .capture or .replay file */ @@ -30,11 +30,13 @@ /** Version of I/O Riot */ #define IORIOT_VERSION "0.4-develop" /** Copyright information */ -#define IORIOT_COPYRIGHT "Mimecast 2017, 2018 (c)" +#define IORIOT_COPYRIGHT "(c) Mimecast 2018" /** Max open files resource user limit */ #define SET_RLIMIT_NOFILE 369216 /** Max processes resource user limit */ #define SET_RLIMIT_NPROC 30768 +/** Ignore file hole size */ +#define IGNORE_FILE_HOLE_BYTES 1024*1024*10 // The following are for debugging purposes only diff --git a/ioriot/src/generate/generate.c b/ioriot/src/generate/generate.c index ee7178c..53751de 100644 --- a/ioriot/src/generate/generate.c +++ b/ioriot/src/generate/generate.c @@ -68,7 +68,6 @@ void generate_destroy(generate_s *g) free(g); } - status_e generate_run(options_s *opts) { generate_s *g = generate_new(opts); @@ -189,14 +188,30 @@ status_e generate_run(options_s *opts) return SUCCESS; } -void generate_write_init_cb(void *data) +void _write_ranges_cb(long start, void *data, void *data2) { - vsize_s *l = data; - generate_s *g = l->generate; + vsize_s *v = data2; + generate_s *g = v->generate; + long end = (long) data; + long bytes = end-start; + if (bytes > 0) { + fprintf(g->replay_fd, "%d|%d|%ld|%ld|%s|\n", + v->is_dir, v->is_file, start, bytes, v->path); + } +} - if (l->required && strlen(l->path) > 0) { - fprintf(g->replay_fd, "%d|%d|%ld|%s|\n", - l->is_dir, l->is_file, -l->vsize_deficit, l->path); +void generate_write_init_cb(void *data) +{ + vsize_s *v = data; + generate_s *g = v->generate; + + if (v->required && strlen(v->path) > 0) { + if (v->read_ranges) { + btree_run_cb2(v->read_ranges, _write_ranges_cb, data); + } else if (v->bytes >= 0) { + fprintf(g->replay_fd, "%d|%d|%ld|%ld|%s|\n", + v->is_dir, v->is_file, 0L, v->bytes, v->path); + } } } diff --git a/ioriot/src/generate/gioop.c b/ioriot/src/generate/gioop.c index 01701bc..d5b9a28 100644 --- a/ioriot/src/generate/gioop.c +++ b/ioriot/src/generate/gioop.c @@ -27,7 +27,7 @@ status_e gioop_run(gwriter_s *w, gtask_s *t) generate_s *g = w->generate; // Get the virtual process data object from the virtual PID space and store - // a pointer to it to t->gprocess + // a pointer to it at t->gprocess generate_gprocess_by_realpid(g, t); // One of the open syscalls may openes a file handle succesfully @@ -109,6 +109,9 @@ status_e gioop_run(gwriter_s *w, gtask_s *t) } else if (Eq(t->op, "lseek")) { Cleanup(gioop_lseek(w, t, g)); + } else if (Eq(t->op, "llseek")) { + Cleanup(gioop_llseek(w, t, g)); + } else if (Eq(t->op, "getdents")) { Cleanup(gioop_getdents(w, t, g)); @@ -559,6 +562,22 @@ status_e gioop_lseek(gwriter_s *w, gtask_s *t, generate_s *g) return SUCCESS; } +status_e gioop_llseek(gwriter_s *w, gtask_s *t, generate_s *g) +{ + if (!t->has_fd) { + return ERROR; + } + + generate_vsize_by_path(g, t, t->vfd->path); + Gioop_write(LLSEEK, "%ld|%ld|%ld|%ld|llseek", + t->mapped_fd, t->offset, t->whence, t->bytes); + + if (t->bytes >= 0) + vsize_seek(t->vsize, t->vfd, t->bytes); + + return SUCCESS; +} + status_e gioop_getdents(gwriter_s *w, gtask_s *t, generate_s *g) { if (!t->has_fd) { diff --git a/ioriot/src/generate/gioop.h b/ioriot/src/generate/gioop.h index ad49713..1df57c1 100644 --- a/ioriot/src/generate/gioop.h +++ b/ioriot/src/generate/gioop.h @@ -79,6 +79,7 @@ status_e gioop_readlinkat(gwriter_s *w, gtask_s *t, generate_s *g); status_e gioop_write(gwriter_s *w, gtask_s *t, generate_s *g); status_e gioop_writev(gwriter_s *w, gtask_s *t, generate_s *g); status_e gioop_lseek(gwriter_s *w, gtask_s *t, generate_s *g); +status_e gioop_llseek(gwriter_s *w, gtask_s *t, generate_s *g); status_e gioop_getdents(gwriter_s *w, gtask_s *t, generate_s *g); status_e gioop_mkdir(gwriter_s *w, gtask_s *t, generate_s *g); status_e gioop_rmdir(gwriter_s *w, gtask_s *t, generate_s *g); diff --git a/ioriot/src/generate/vsize.c b/ioriot/src/generate/vsize.c index f2d56ba..4bf8433 100644 --- a/ioriot/src/generate/vsize.c +++ b/ioriot/src/generate/vsize.c @@ -17,7 +17,6 @@ #include "generate.h" // Helper macros - #define _Set_file(v) v->is_file = true; v->unsure = v->is_dir = false #define _Set_dir(v) v->is_dir = true; v->unsure = v->is_file = false #define _Set_unsure(v) v->unsure = true @@ -35,14 +34,14 @@ vsize_s* vsize_new(char *file_path, const unsigned long id, v->inserted = false; v->is_dir = false; v->is_file = false; - v->offset = -1; v->path = Clone(file_path); v->renamed = false; v->required = false; v->unsure = false; v->updates = 0; - v->vsize = 0; - v->vsize_deficit = 0; + v->bytes = 0; + v->read_ranges = NULL; + v->write_ranges = NULL; return v; } @@ -52,6 +51,11 @@ void vsize_destroy(vsize_s *v) if (!v) return; + if (v->read_ranges) + btree_destroy(v->read_ranges); + if (v->write_ranges) + btree_destroy(v->write_ranges); + free(v->path); free(v); } @@ -91,9 +95,9 @@ void init_parent_dir(vsize_s *v, const char *path) void vsize_open(vsize_s *v, void *vfd, const char *path, const int flags) { - // v->first_encounter == false means, that this is the first occurance of + // v->updates == 0 means, that this is the first occurance of // this path and we didn't initialise it (means we didn't ensure that - // we want to create all parent directories etc. + // we want to create all parent directories etc.) if (v->updates == 0) { // We may use a recycled vfd object! When opening a file we always @@ -161,56 +165,87 @@ void vsize_rename(vsize_s *v, vsize_s *v2, // We are not 100% sure that this is really a file, // the path might be still a directory though! _Set_unsure(v2); + v2->updates++; // For debugging purposes only _Set_renamed(v2); - v2->updates++; } } -void vsize_adjust(vsize_s *v, vfd_s* vfd) +void vsize_ensure_data_range(vsize_s *v, btree_s **ranges, const long offset, const long bytes) { - if (v->vsize >= vfd->offset) - return; + if (*ranges == NULL) { + if (offset == 0) { + if (v->bytes + IGNORE_FILE_HOLE_BYTES < bytes) { + // No file hole, just set the new (larger) vsize + v->bytes = bytes; + } else { + // Nothing to do, vsize is already sufficient + } + + } else { // if (offset > 0) + if (offset <= v->bytes) { + // We won't add a hole to the file here either + if (v->bytes < bytes) { + // No file hole, just set the new (larger) bytes + v->bytes = bytes; + } else { + // Nothing to do, bytes is already sufficient + } + } else { // if (offset > v->bytes) + // From offset larger than bytes, we have a hole in the file! + *ranges = btree_new(); + + // Insert root data range + btree_insert(*ranges, 0, (void*)v->bytes); + + // This value is not used anymore, we use the btree instead from now + // to store all used data ranges of a file. + v->bytes = -1; + + // Rerun this function with a data range btree initialised + vsize_ensure_data_range(v, ranges, offset, bytes); + } + } - long deficit = v->vsize - vfd->offset; - if (deficit < v->vsize_deficit) { - v->vsize_deficit = deficit; - _Set_required(v); - _Set_file(v); + } else { // if (*ranges != NULL) + btree_ensure_range_l(*ranges, offset, offset+bytes, + IGNORE_FILE_HOLE_BYTES); } } void vsize_read(vsize_s *v, void *vfd, const char *path, const int bytes) { vfd_s *vfd_ = vfd; + + if (v->write_ranges == NULL || + !btree_has_range_l(v->write_ranges, vfd_->offset, vfd_->offset+bytes)) { + vsize_ensure_data_range(v, &v->read_ranges, vfd_->offset, bytes); + _Set_required(v); + _Set_file(v); + } + vfd_->offset += bytes; - vsize_adjust(v, vfd_); v->updates++; } -void vsize_seek(vsize_s *v, void *vfd, const long new_offset) +void vsize_write(vsize_s *v, void *vfd, const char *path, const int bytes) { - //vfd_s *vfd_ = vfd; - - // The file's offset can be greater than the file's current size, in which - // case the next write to the file will extend the file. This is referred - // to as creating a hole in a file and is allowed. However, this behaviour - // does not suit the estimation of the file size before we want to run the - // test. - - // TODO: Implement file hole support! - //v->updates++; + vfd_s *vfd_ = vfd; + vsize_ensure_data_range(v, &v->write_ranges, vfd_->offset, bytes); + vfd_->offset += bytes; + v->updates++; } -void vsize_write(vsize_s *v, void *vfd, const char *path, const int bytes) +void vsize_seek(vsize_s *v, void *vfd, const long new_offset) { vfd_s *vfd_ = vfd; - vfd_->offset += bytes; - if (v->vsize < vfd_->offset) - v->vsize = vfd_->offset; + // The file's offset can be greater than the file's current size, in which + // case the next write to the file will extend the file. This is referred + // to as creating a hole in a file. + vfd_->offset = new_offset; v->updates++; } diff --git a/ioriot/src/generate/vsize.h b/ioriot/src/generate/vsize.h index 8556ec0..ffda9e5 100644 --- a/ioriot/src/generate/vsize.h +++ b/ioriot/src/generate/vsize.h @@ -16,7 +16,7 @@ #define VSIZE_H #include "../utils/utils.h" -#include "../datas/hmap.h" +#include "../datas/btree.h" #include "../vfd.h" /** @@ -30,11 +30,11 @@ */ typedef struct vsize_s_ { char *path; /**< The path to the file/directory */ - off_t offset; /**< The current file offset */ + long bytes; /**< The virtual size */ + btree_s *read_ranges; /**< Used to store used data ranges in a file with holes */ + btree_s *write_ranges; /**< Used to store used data ranges in a file with holes */ unsigned long id; /**< The vsize id */ void *generate; /**< A pointer to the generate object */ - long vsize; /**< The virtual size */ - long vsize_deficit; /**< Size to use for file creating during init mode */ bool renamed; /**< True if file/dir has been renamed */ bool required; /**< True if init mode will create this file/dir */ bool is_dir; /**< True if this file/dir is a directory */ @@ -72,19 +72,18 @@ void vsize_destroy(vsize_s *v); void init_parent_dir(vsize_s *v, const char *path); /** - * @brief Adjusts the vsize + * @brief Ensure that we have a data range in the virtual file * * Compares the virtual file size of the file in the vsize - * object to the the offset in the virtual file descriptor. - * In case the offset is higher we have a size deficit and - * we need to mark it. That way ioriot can ensure that - * during init mode it will create a file with the correct - * size prior of running the test! + * object to the the given offsets. This is required just in case + * we have holes in the file to be replayed. * * @param v The virtual size object - * @param vfd The virtual file descriptor object + * @param ranges The ranges object to operaet on + * @param offset The start offset + * @param bytes The amount of bytes */ -void vsize_adjust(vsize_s *v, vfd_s* vfd); +void vsize_ensure_data_range(vsize_s *v, btree_s **ranges, const long offset, const long bytes); /** * @brief Adjust vsize on open diff --git a/ioriot/src/init/init.c b/ioriot/src/init/init.c index e375379..3f9d8a0 100644 --- a/ioriot/src/init/init.c +++ b/ioriot/src/init/init.c @@ -21,7 +21,6 @@ #include "../mounts.h" #include "../utils/futils.h" - init_s *init_new(options_s *opts) { init_s *i = Malloc(init_s); @@ -118,7 +117,8 @@ status_e init_run(options_s *opts) fseeko(i->replay_fd, init_offset, SEEK_SET); bool is_file = false, is_dir = false; - long vsize = 0; + long offset = 0; + long bytes = 0; char *path; // Stats @@ -136,6 +136,7 @@ status_e init_run(options_s *opts) // Process the INIT section of the .replay file line by line. while ((read = getline(&line, &len, i->replay_fd)) != -1) { + Debug(line); char *tok = strtok_r(line, "|", &saveptr); for (int ntok = 0; tok; ntok++) { @@ -147,12 +148,18 @@ status_e init_run(options_s *opts) is_file = atoi(tok) == 1; break; case 2: - vsize = atol(tok); - if (vsize < 0) { - Error("Size overflow"); + offset = atol(tok); + if (offset < 0) { + Error("Offset overflow: '%ld'", offset); } break; case 3: + bytes = atol(tok); + if (bytes < 0) { + Error("Size overflow: '%ld'", bytes); + } + break; + case 4: path = tok; break; default: @@ -178,7 +185,8 @@ status_e init_run(options_s *opts) } else if (is_file) { task->is_file = true; - task->vsize = vsize; + task->bytes = bytes; + task->offset = offset; } task->path = Clone(path); diff --git a/ioriot/src/init/itask.c b/ioriot/src/init/itask.c index f04ce33..de7c551 100644 --- a/ioriot/src/init/itask.c +++ b/ioriot/src/init/itask.c @@ -35,7 +35,7 @@ void itask_destroy(itask_s *task) void itask_reset_stats(itask_s *task) { task->is_dir = task->is_file = false; - task->sizes_created = task->vsize = 0; + task->sizes_created = task->offset = task->bytes = 0; task->dirs_created = task->files_created = 0; if (task->path) { @@ -60,7 +60,7 @@ void itask_extract_stats(itask_s *task, long* dirs_created, long *files_created, void itask_print(itask_s *task) { - Put("itask(%p): is_dir:%d is_file:%d vsize:%ld path:%s", + Put("itask(%p): is_dir:%d is_file:%d offset:%ld bytes:%ld path:%s", (void*)task, task->is_dir, task->is_file, - task->vsize, task->path); + task->offset, task->bytes, task->path); } diff --git a/ioriot/src/init/itask.h b/ioriot/src/init/itask.h index b10d515..21afba4 100644 --- a/ioriot/src/init/itask.h +++ b/ioriot/src/init/itask.h @@ -23,7 +23,8 @@ typedef struct itask_s_ { bool is_dir; bool is_file; - long vsize; + long offset; + long bytes; char *path; long dirs_created; long files_created; diff --git a/ioriot/src/init/ithread.c b/ioriot/src/init/ithread.c index a580e70..bcc31f3 100644 --- a/ioriot/src/init/ithread.c +++ b/ioriot/src/init/ithread.c @@ -90,9 +90,13 @@ void ithread_run_task(ithread_s *t, itask_s *task) } else if (task->is_file) { if (!ensure_file_exists(task->path, &task->dirs_created)) { task->files_created++; - if (task->vsize > 0) { - append_random_to_file(task->path, task->vsize); - task->sizes_created += task->vsize; + if (task->bytes > 0) { + if (task->offset > 0) { + write_random_to_file(task->path, task->bytes, task->offset); + } else { + append_random_to_file(task->path, task->bytes); + } + task->sizes_created += task->bytes; } } } diff --git a/ioriot/src/opcodes.h b/ioriot/src/opcodes.h index 3d5c114..0dd060c 100644 --- a/ioriot/src/opcodes.h +++ b/ioriot/src/opcodes.h @@ -69,6 +69,7 @@ typedef enum { FCNTL = 70, GETDENTS, LSEEK, + LLSEEK, // mmap syscalls MMAP2 = 80, diff --git a/ioriot/src/replay/rioop.c b/ioriot/src/replay/rioop.c index 2e16c94..0ce19c5 100644 --- a/ioriot/src/replay/rioop.c +++ b/ioriot/src/replay/rioop.c @@ -151,6 +151,7 @@ void rioop_run(rprocess_s *p, rthread_s *t, rtask_s *task) rioop_getdents(p, t, task); break; case LSEEK: + case LLSEEK: rioop_lseek(p, t, task); break; diff --git a/ioriot/src/utests.c b/ioriot/src/utests.c index 0fc53c3..7cae7e8 100644 --- a/ioriot/src/utests.c +++ b/ioriot |
