diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-19 09:48:59 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-19 09:48:59 +0200 |
| commit | 3ad5fbe368771a5023bf36fecd45586bcbb94b93 (patch) | |
| tree | 4b0acc9da6a7aac4e99b1a811c0eb3e55051958d | |
| parent | 8db49370807f2a3e4ebed8422047b69dde395a22 (diff) | |
refactor: table-drive syscall dispatchers (task 466)
| -rw-r--r-- | ioriot/src/generate/gioop.c | 276 | ||||
| -rw-r--r-- | ioriot/src/generate/gioop.h | 1 | ||||
| -rw-r--r-- | ioriot/src/replay/rioop.c | 225 | ||||
| -rw-r--r-- | ioriot/src/replay/rioop.h | 1 | ||||
| -rw-r--r-- | ioriot/src/utests.c | 8 |
5 files changed, 236 insertions, 275 deletions
diff --git a/ioriot/src/generate/gioop.c b/ioriot/src/generate/gioop.c index b16f893..fb1b7a1 100644 --- a/ioriot/src/generate/gioop.c +++ b/ioriot/src/generate/gioop.c @@ -14,9 +14,118 @@ #include "gioop.h" +typedef status_e (*gioop_handler_f)(gwriter_s *w, gtask_s *t, generate_s *g); + +typedef struct { + const char *op; + gioop_handler_f handler; +} gioop_entry_s; + +#define _GIOOP_ENTRY_COUNT(entries) \ + (sizeof(entries) / sizeof((entries)[0])) + +static status_e +_gioop_ignore(gwriter_s *w, gtask_s *t, generate_s *g) +{ + (void)w; + (void)t; + (void)g; + + return SUCCESS; +} + +static gioop_handler_f +_gioop_find_handler(const gioop_entry_s *entries, const size_t num_entries, + const char *op) +{ + if (op == NULL) + return NULL; + + for (size_t i = 0; i < num_entries; ++i) { + if (Eq(entries[i].op, op)) + return entries[i].handler; + } + + return NULL; +} + +static const gioop_entry_s _GIOOP_PREOPEN[] = { + {"open", gioop_open}, + {"openat", gioop_openat}, + {"creat", gioop_creat}, +}; + +static const gioop_entry_s _GIOOP_DISPATCH[] = { + {"close", gioop_close}, + {"stat", gioop_stat}, + {"statfs", gioop_statfs}, + {"statfs64", gioop_statfs64}, + {"fstat", gioop_fstat}, + {"fstatat", gioop_fstatat}, + {"fstatfs", gioop_fstatfs}, + {"fstatfs64", gioop_fstatfs64}, + {"rename", gioop_rename}, + {"renameat", gioop_renameat}, + {"renameat2", gioop_renameat2}, + {"read", gioop_read}, + {"readv", gioop_readv}, + {"readahead", gioop_readahead}, + {"readdir", gioop_readdir}, + {"readlink", gioop_readlink}, + {"readlinkat", gioop_readlinkat}, + {"write", gioop_write}, + {"writev", gioop_writev}, + {"lseek", gioop_lseek}, + {"llseek", gioop_llseek}, + {"getdents", gioop_getdents}, + {"mkdir", gioop_mkdir}, + {"rmdir", gioop_rmdir}, + {"mkdirat", gioop_mkdirat}, + {"unlink", gioop_unlink}, + {"unlinkat", gioop_unlinkat}, + {"lstat", gioop_lstat}, + {"fsync", gioop_fsync}, + {"fdatasync", gioop_fdatasync}, + {"sync", gioop_sync}, + {"syncfs", gioop_syncfs}, + {"sync_file_range", gioop_sync_file_range}, + {"fcntl", gioop_fcntl}, + {"mmap2", _gioop_ignore}, + {"munmap", _gioop_ignore}, + {"mremap", _gioop_ignore}, + {"msync", _gioop_ignore}, + {"chmod", gioop_chmod}, + {"fchmodat", gioop_chmod}, + {"fchmod", gioop_fchmod}, + {"chown", gioop_chown}, + {"chown16", gioop_chown}, + {"lchown", gioop_lchown}, + {"lchown16", gioop_lchown}, + {"fchown", gioop_fchown}, + {"fchownat", gioop_chown}, + {"exit_group", gioop_exit_group}, +}; + +void gioop_test(void) +{ + const size_t preopen_count = _GIOOP_ENTRY_COUNT(_GIOOP_PREOPEN); + const size_t dispatch_count = _GIOOP_ENTRY_COUNT(_GIOOP_DISPATCH); + + assert(_gioop_find_handler(_GIOOP_PREOPEN, preopen_count, "open") == + gioop_open); + assert(_gioop_find_handler(_GIOOP_DISPATCH, dispatch_count, "close") == + gioop_close); + assert(_gioop_find_handler(_GIOOP_DISPATCH, dispatch_count, "msync") == + _gioop_ignore); + assert(_gioop_find_handler(_GIOOP_DISPATCH, dispatch_count, NULL) == NULL); + assert(_gioop_find_handler(_GIOOP_DISPATCH, dispatch_count, + "definitely_unknown") == NULL); +} + status_e gioop_run(gwriter_s *w, gtask_s *t) { status_e ret = SUCCESS; + gioop_handler_f handler = NULL; // There was already an error in the parser (parser.c) processing this // task! Don't process it futher. @@ -31,14 +140,11 @@ status_e gioop_run(gwriter_s *w, gtask_s *t) generate_gprocess_by_realpid(g, t); // One of the open syscalls may openes a file handle succesfully - if (Eq(t->op, "open")) { - Cleanup(gioop_open(w, t, g)); - - } else if (Eq(t->op, "openat")) { - Cleanup(gioop_openat(w, t, g)); - - } else if (Eq(t->op, "creat")) { - Cleanup(gioop_creat(w, t, g)); + handler = _gioop_find_handler(_GIOOP_PREOPEN, + _GIOOP_ENTRY_COUNT(_GIOOP_PREOPEN), + t->op); + if (handler != NULL) { + Cleanup(handler(w, t, g)); } // Get the virtual file descriptor of a given real fd and store a pointer @@ -48,155 +154,15 @@ status_e gioop_run(gwriter_s *w, gtask_s *t) Cleanup_unless(SUCCESS, ret); } - - if (Eq(t->op, "close")) { - Cleanup(gioop_close(w, t, g)); - - } else if (Eq(t->op, "stat")) { - Cleanup(gioop_stat(w, t, g)); - - } else if (Eq(t->op, "statfs")) { - Cleanup(gioop_statfs(w, t, g)); - - } else if (Eq(t->op, "statfs64")) { - Cleanup(gioop_statfs64(w, t, g)); - - } else if (Eq(t->op, "fstat")) { - Cleanup(gioop_fstat(w, t, g)); - - } else if (Eq(t->op, "fstatat")) { - Cleanup(gioop_fstatat(w, t, g)); - - } else if (Eq(t->op, "fstatfs")) { - Cleanup(gioop_fstatfs(w, t, g)); - - } else if (Eq(t->op, "fstatfs64")) { - Cleanup(gioop_fstatfs64(w, t, g)); - - } else if (Eq(t->op, "rename")) { - Cleanup(gioop_rename(w, t, g)); - - } else if (Eq(t->op, "renameat")) { - Cleanup(gioop_renameat(w, t, g)); - - } else if (Eq(t->op, "renameat2")) { - Cleanup(gioop_renameat2(w, t, g)); - - } else if (Eq(t->op, "read")) { - Cleanup(gioop_read(w, t, g)); - - } else if (Eq(t->op, "readv")) { - Cleanup(gioop_readv(w, t, g)); - - } else if (Eq(t->op, "readahead")) { - Cleanup(gioop_readahead(w, t, g)); - - } else if (Eq(t->op, "readdir")) { - Cleanup(gioop_readdir(w, t, g)); - - } else if (Eq(t->op, "readlink")) { - Cleanup(gioop_readlink(w, t, g)); - - } else if (Eq(t->op, "readlinkat")) { - Cleanup(gioop_readlinkat(w, t, g)); - - } else if (Eq(t->op, "write")) { - Cleanup(gioop_write(w, t, g)); - - } else if (Eq(t->op, "writev")) { - Cleanup(gioop_writev(w, t, g)); - - } 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)); - - } else if (Eq(t->op, "mkdir")) { - Cleanup(gioop_mkdir(w, t, g)); - - } else if (Eq(t->op, "rmdir")) { - Cleanup(gioop_rmdir(w, t, g)); - - } else if (Eq(t->op, "mkdirat")) { - Cleanup(gioop_mkdirat(w, t, g)); - - } else if (Eq(t->op, "unlink")) { - Cleanup(gioop_unlink(w, t, g)); - - } else if (Eq(t->op, "unlinkat")) { - Cleanup(gioop_unlinkat(w, t, g)); - - } else if (Eq(t->op, "lstat")) { - Cleanup(gioop_lstat(w, t, g)); - - } else if (Eq(t->op, "fsync")) { - Cleanup(gioop_fsync(w, t, g)); - - } else if (Eq(t->op, "fdatasync")) { - Cleanup(gioop_fdatasync(w, t, g)); - - } else if (Eq(t->op, "sync")) { - Cleanup(gioop_sync(w, t, g)); - - } else if (Eq(t->op, "syncfs")) { - Cleanup(gioop_syncfs(w, t, g)); - - } else if (Eq(t->op, "sync_file_range")) { - Cleanup(gioop_sync_file_range(w, t, g)); - - } else if (Eq(t->op, "fcntl")) { - Cleanup(gioop_fcntl(w, t, g)); - - } else if (Eq(t->op, "mmap2")) { - // Support for mmap added later - - } else if (Eq(t->op, "munmap")) { - // Support for mmap added later - - } else if (Eq(t->op, "mremap")) { - // Support for mmap added later - - } else if (Eq(t->op, "msync")) { - // Support for mmap added later - - } else if (Eq(t->op, "chmod")) { - Cleanup(gioop_chmod(w, t, g)); - - } else if (Eq(t->op, "fchmodat")) { - Cleanup(gioop_chmod(w, t, g)); - - } else if (Eq(t->op, "fchmod")) { - Cleanup(gioop_fchmod(w, t, g)); - - } else if (Eq(t->op, "chown")) { - Cleanup(gioop_chown(w, t, g)); - - } else if (Eq(t->op, "chown16")) { - Cleanup(gioop_chown(w, t, g)); - - } else if (Eq(t->op, "lchown")) { - Cleanup(gioop_lchown(w, t, g)); - - } else if (Eq(t->op, "lchown16")) { - Cleanup(gioop_lchown(w, t, g)); - - } else if (Eq(t->op, "fchown")) { - Cleanup(gioop_fchown(w, t, g)); - - } else if (Eq(t->op, "fchownat")) { - Cleanup(gioop_chown(w, t, g)); - - } else if (Eq(t->op, "exit_group")) { - Cleanup(gioop_exit_group(w, t, g)); - - } else { - Cleanup(ERROR;); + handler = _gioop_find_handler(_GIOOP_DISPATCH, + _GIOOP_ENTRY_COUNT(_GIOOP_DISPATCH), + t->op); + if (handler != NULL) { + Cleanup(handler(w, t, g)); } + Cleanup(ERROR); + cleanup: #ifdef LOG_FILTERED diff --git a/ioriot/src/generate/gioop.h b/ioriot/src/generate/gioop.h index 1df57c1..2266e09 100644 --- a/ioriot/src/generate/gioop.h +++ b/ioriot/src/generate/gioop.h @@ -55,6 +55,7 @@ void gioop_close_all_vfd_cb(void *data, void *data2); * @return SUCCESS if everything went fine */ status_e gioop_run(gwriter_s *w, gtask_s *t); +void gioop_test(void); status_e gioop_open(gwriter_s *w, gtask_s *t, generate_s *g); status_e gioop_openat(gwriter_s *w, gtask_s *t, generate_s *g); diff --git a/ioriot/src/replay/rioop.c b/ioriot/src/replay/rioop.c index 5ec64b5..2b3d98c 100644 --- a/ioriot/src/replay/rioop.c +++ b/ioriot/src/replay/rioop.c @@ -17,6 +17,16 @@ #include "../vfd.h" #include "rworker.h" +typedef void (*rioop_handler_f)(rprocess_s *p, rthread_s *t, rtask_s *task); + +typedef struct { + int op; + rioop_handler_f handler; +} rioop_entry_s; + +#define _RIOOP_ENTRY_COUNT(entries) \ + (sizeof(entries) / sizeof((entries)[0])) + // Printing error messages #define _Error(...) \ fprintf(stderr, "%s:%d ERROR: ", __FILE__, __LINE__); \ @@ -70,136 +80,111 @@ _rioop_get_pwd(const char *user, struct passwd *pwd, char *buf, return result; } -void rioop_run(rprocess_s *p, rthread_s *t, rtask_s *task) +static void +_rioop_noop(rprocess_s *p, rthread_s *t, rtask_s *task) { - _Init_op(2); - - switch (op) { - // stat() syscalls - case FSTAT: - rioop_fstat(p, t, task); - break; - case FSTATFS: - case FSTATFS64: - //Error("op(%d) not implemented", op); - break; - case FSTAT_AT: - case LSTAT: - case STAT: - rioop_stat(p, t, task); - break; - case STATFS: - case STATFS64: - //Error("op(%d) not implemented", op); - break; - - // read() syscalls - case READ: - case READV: - rioop_read(p, t, task); - break; - case READAHEAD: - //Error("op(%d) not implemented", op); - break; - case READLINK: - case READLINK_AT: - //Error("op(%d) not implemented", op); - break; - - // write() syscalls - case WRITE: - case WRITEV: - rioop_write(p, t, task); - break; - - // open() and other syscalls which may creat - case OPEN: - case OPEN_AT: - rioop_open(p, t, task, -1); - break; - case CREAT: - // A call to crat() is equivalent to calling open() with flags.. - rioop_open(p, t, task, O_CREAT|O_WRONLY|O_TRUNC); - break; - case MKDIR: - case MKDIR_AT: - rioop_mkdir(p, t, task); - break; - - // rename() syscalls - case RENAME: - case RENAME_AT: - case RENAME_AT2: - rioop_rename(p, t, task); - break; + (void)p; + (void)t; + (void)task; +} - // close() and unlink() syscalls - case CLOSE: - rioop_close(p, t, task); - break; - case UNLINK: - case UNLINK_AT: - rioop_unlink(p, t, task); - break; - case RMDIR: - rioop_rmdir(p, t, task); - break; +static void +_rioop_open_default(rprocess_s *p, rthread_s *t, rtask_s *task) +{ + rioop_open(p, t, task, -1); +} - // sync() syscalls - case FSYNC: - rioop_fsync(p, t, task); - break; - case FDATASYNC: - rioop_fdatasync(p, t, task); - break; - case SYNC: - case SYNCFS: - case SYNC_FILE_RANGE: - //Error("op(%d) not implemented", op); - break; +static void +_rioop_open_creat(rprocess_s *p, rthread_s *t, rtask_s *task) +{ + rioop_open(p, t, task, O_CREAT|O_WRONLY|O_TRUNC); +} - // Other syscalls - case FCNTL: - rioop_fcntl(p, t, task); - break; - case GETDENTS: - rioop_getdents(p, t, task); - break; - case LSEEK: - case LLSEEK: - rioop_lseek(p, t, task); - break; +static rioop_handler_f +_rioop_find_handler(const rioop_entry_s *entries, const size_t num_entries, + const int op) +{ + for (size_t i = 0; i < num_entries; ++i) { + if (entries[i].op == op) + return entries[i].handler; + } - // chmod() syscalls - case CHMOD: - rioop_chmod(p, t, task); - break; - case FCHMOD: - rioop_fchmod(p, t, task); - break; + return NULL; +} - // chown() syscalls - case CHOWN: - rioop_chown(p, t, task); - break; - case FCHOWN: - case FCHOWNAT: - rioop_fchown(p, t, task); - break; - case LCHOWN: - rioop_lchown(p, t, task); - break; +static const rioop_entry_s _RIOOP_HANDLERS[] = { + {FSTAT, rioop_fstat}, + {FSTATFS, _rioop_noop}, + {FSTATFS64, _rioop_noop}, + {FSTAT_AT, rioop_stat}, + {LSTAT, rioop_stat}, + {STAT, rioop_stat}, + {STATFS, _rioop_noop}, + {STATFS64, _rioop_noop}, + {READ, rioop_read}, + {READV, rioop_read}, + {READAHEAD, _rioop_noop}, + {READLINK, _rioop_noop}, + {READLINK_AT, _rioop_noop}, + {WRITE, rioop_write}, + {WRITEV, rioop_write}, + {OPEN, _rioop_open_default}, + {OPEN_AT, _rioop_open_default}, + {CREAT, _rioop_open_creat}, + {MKDIR, rioop_mkdir}, + {MKDIR_AT, rioop_mkdir}, + {RENAME, rioop_rename}, + {RENAME_AT, rioop_rename}, + {RENAME_AT2, rioop_rename}, + {CLOSE, rioop_close}, + {UNLINK, rioop_unlink}, + {UNLINK_AT, rioop_unlink}, + {RMDIR, rioop_rmdir}, + {FSYNC, rioop_fsync}, + {FDATASYNC, rioop_fdatasync}, + {SYNC, _rioop_noop}, + {SYNCFS, _rioop_noop}, + {SYNC_FILE_RANGE, _rioop_noop}, + {FCNTL, rioop_fcntl}, + {GETDENTS, rioop_getdents}, + {LSEEK, rioop_lseek}, + {LLSEEK, rioop_lseek}, + {CHMOD, rioop_chmod}, + {FCHMOD, rioop_fchmod}, + {CHOWN, rioop_chown}, + {FCHOWN, rioop_fchown}, + {FCHOWNAT, rioop_fchown}, + {LCHOWN, rioop_lchown}, + {META_EXIT_GROUP, _rioop_noop}, + {META_TIMELINE, _rioop_noop}, +}; + +void rioop_test(void) +{ + const size_t handler_count = _RIOOP_ENTRY_COUNT(_RIOOP_HANDLERS); + + assert(_rioop_find_handler(_RIOOP_HANDLERS, handler_count, OPEN) == + _rioop_open_default); + assert(_rioop_find_handler(_RIOOP_HANDLERS, handler_count, CREAT) == + _rioop_open_creat); + assert(_rioop_find_handler(_RIOOP_HANDLERS, handler_count, READAHEAD) == + _rioop_noop); + assert(_rioop_find_handler(_RIOOP_HANDLERS, handler_count, -1) == NULL); +} - // Meta operations (I/O replay internal use only). - case META_EXIT_GROUP: - break; - case META_TIMELINE: - break; +void rioop_run(rprocess_s *p, rthread_s *t, rtask_s *task) +{ + _Init_op(2); + rioop_handler_f handler = _rioop_find_handler(_RIOOP_HANDLERS, + _RIOOP_ENTRY_COUNT( + _RIOOP_HANDLERS), + op); - default: + if (handler == NULL) { Error("op(%d) not implemented", op); - break; } + + handler(p, t, task); } void rioop_stat(rprocess_s *p, rthread_s *t, rtask_s *task) diff --git a/ioriot/src/replay/rioop.h b/ioriot/src/replay/rioop.h index 4db4284..aff2a21 100644 --- a/ioriot/src/replay/rioop.h +++ b/ioriot/src/replay/rioop.h @@ -29,6 +29,7 @@ * @param task The replay task object */ void rioop_run(rprocess_s *p, rthread_s *t, rtask_s *task); +void rioop_test(void); void rioop_close(rprocess_s *p, rthread_s *t, rtask_s *task); void rioop_fcntl(rprocess_s *p, rthread_s *t, rtask_s *task); diff --git a/ioriot/src/utests.c b/ioriot/src/utests.c index 1e332f9..3f573e1 100644 --- a/ioriot/src/utests.c +++ b/ioriot/src/utests.c @@ -19,6 +19,8 @@ #include "datas/hmap.h" #include "datas/list.h" #include "datas/rbuffer.h" +#include "generate/gioop.h" +#include "replay/rioop.h" #include "replay/replay.h" #include "utils/utils.h" @@ -39,6 +41,12 @@ void utests_run() fprintf(stderr, "Running utils_test()\n"); utils_test(); + fprintf(stderr, "Running gioop_test()\n"); + gioop_test(); + + fprintf(stderr, "Running rioop_test()\n"); + rioop_test(); + fprintf(stderr, "Running replay_test()\n"); replay_test(); |
