diff --git a/Makefile b/Makefile index 84501ae..fed9d3c 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC = gcc -CFLAGS = -g `pkg-config fuse --cflags --libs` +CFLAGS = -g `pkg-config fuse --cflags --libs` -L/usr/local/lib -lpcg_random DEPS = noisebox.h -OBJ = fuse.o zeroes.o mersenne.o +OBJ = fuse.o zeroes.o mersenne.o pcg.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/fuse.c b/fuse.c index e37ae59..456087a 100644 --- a/fuse.c +++ b/fuse.c @@ -1,5 +1,5 @@ #define FUSE_USE_VERSION 30 -#define NOISER_COUNT 2 +#define NOISER_COUNT 3 #include #include @@ -12,22 +12,30 @@ #include "noisebox.h" static void* do_init(struct fuse_conn_info *conn) { + struct nb_context *c = malloc(sizeof(struct nb_context)); + Noiser** noisers = malloc(sizeof(Noiser*) * NOISER_COUNT); noisers[0] = zero_init(); noisers[1] = mersenne_init(); + noisers[2] = pcg_init(); + + c->noisers = noisers; + c->state_head = NULL; - return noisers; + return c; } static int getattr_root(struct stat *st) { st->st_mode = S_IFDIR | 0755; st->st_nlink = 2 + NOISER_COUNT; + printf("got attr?\n"); return 0; } static int lookup_path(const char *path, Noiser **n, NoiseFile **nf) { struct fuse_context* c = fuse_get_context(); - Noiser** noisers = c->private_data; + struct nb_context *nbc = c->private_data; + Noiser** noisers = nbc->noisers; char* buf = strdup(path); char *mod = strtok(buf, "/"); @@ -61,7 +69,6 @@ static int lookup_path(const char *path, Noiser **n, NoiseFile **nf) { } } - static int getattr_leaf(const char *path, struct stat *st) { Noiser *n = NULL; NoiseFile *nf = NULL; @@ -107,14 +114,76 @@ static int do_getattr(const char *path, struct stat *st) { if(strcmp(path, "/") == 0) { ret = getattr_root(st); + printf("got attr: root %i\n", ret); } else { ret = getattr_leaf(path, st); }; - return ret; } +static void get_file_state(const char* path, struct fuse_file_info *fi) { + struct fuse_context *c = fuse_get_context(); + struct nb_context *nbc = c->private_data; + struct file_state *fs = nbc->state_head; + if(!fs) { + printf("no state, it's fine.\n"); + fi->fh = (uint64_t)NULL; + return; + } + while(fs->next) { + if(path == fs->name) { + fi->fh = (uint64_t)fs; + return; + } + fs = fs->next; + } + fi->fh = (uint64_t)NULL; + return; +} + +static void append_file_state(struct file_state *add) { + struct fuse_context *c = fuse_get_context(); + struct nb_context *nbc = c->private_data; + struct file_state *fs = nbc->state_head; + if(!fs) { + nbc->state_head = add; + return; + } + while(fs->next) { + fs = fs->next; + } + fs->next = add; + return; +} + +// deletes from list, but does not free. +static void delete_file_state(struct file_state *del) { + struct fuse_context *c = fuse_get_context(); + struct nb_context *nbc = c->private_data; + struct file_state *fs = nbc->state_head; + if(fs == del) { + printf("head = del\n"); + if(del->next) { + fs = del->next; + } else { + fs = NULL; + } + return; + } + while(fs->next) { + if(del == fs->next) { + if(del->next) { + fs->next = del->next; + } else { + fs->next = NULL; + } + return; + } + fs = fs->next; + } +} + static int do_open(const char* path, struct fuse_file_info* fi) { Noiser *n = NULL; NoiseFile *nf = NULL; @@ -122,10 +191,43 @@ static int do_open(const char* path, struct fuse_file_info* fi) { ret = lookup_path(path, &n, &nf); if(ret !=0) { + printf("lookup_path() error"); return ret; } - ret = n->do_open(path, fi); + // check if file is already opened. + get_file_state(path, fi); + if(fi->fh) { + return 0; + } + + if(n->do_open) { + ret = n->do_open(path, fi); + append_file_state((struct file_state *)fi->fh); + } + + return ret; +} + +static int do_release(const char *path, struct fuse_file_info *fi) { + Noiser *n = NULL; + NoiseFile *nf = NULL; + int ret; + + ret = lookup_path(path, &n, &nf); + if(ret !=0) { + printf("lookup_path() error"); + return ret; + } + + if(fi->fh) { + printf("clearing from statelist\n"); + delete_file_state((struct file_state *)fi->fh); + } + if(n->do_release) { + printf("noiser-specific cleanup\n"); + ret = n->do_release(path, fi); + } return ret; } @@ -145,9 +247,11 @@ static int do_read(const char* path, char* buf, size_t sz, off_t offset, static int readdir_root(void *buffer, fuse_fill_dir_t filler) { struct fuse_context* c = fuse_get_context(); - Noiser** noiser = c->private_data; + struct nb_context *nbc = c->private_data; + Noiser** noiser = nbc->noisers; int ret = 0; for(int i=0; iname, NULL, 0); if(ret != 0) { printf("failed to fill %s, dying\n", noiser[i]->name); @@ -178,25 +282,23 @@ static int do_readdir(const char *path, void *buffer, int ret; - if(strcmp(path, "/") == 0) { - ret = readdir_root(buffer, filler); - } else { - // find noiser, generate appropriate files - struct fuse_context* c = fuse_get_context(); - Noiser** noiser = c->private_data; + printf("doing readdir\n"); - char * pathbuf = strdup(path); - char * toplevel = strtok(pathbuf, "/"); - for(int i=0; iname, toplevel) == 0) { - printf("found noiser: %s\n", noiser[i]->name); - ret = do_noiser_readdir(noiser[i], path, buffer, filler, - offset, fi); - } - } + if(strcmp(path, "/") == 0) { + printf("calling readdir_root\n"); + return readdir_root(buffer, filler); } - return ret; + // find noiser, generate appropriate files + Noiser *n = NULL; + NoiseFile *nf = NULL; + + ret = lookup_path(path, &n, &nf); + if(ret !=0) { + printf("lookup_path() error"); + return ret; + } + return do_noiser_readdir(n, path, buffer, filler, offset, fi); } static struct fuse_operations ops = { @@ -225,6 +327,7 @@ static struct fuse_operations ops = { // int (*statfs) (const char *, struct statvfs *); // int (*flush) (const char *, struct fuse_file_info *); // int (*release) (const char *, struct fuse_file_info *); + .release = do_release, // int (*fsync) (const char *, int, struct fuse_file_info *); // int (*setxattr) (const char *, const char *, const char *, size_t, int); // int (*getxattr) (const char *, const char *, char *, size_t); diff --git a/mersenne.c b/mersenne.c index 0eba74a..75bc776 100644 --- a/mersenne.c +++ b/mersenne.c @@ -94,8 +94,9 @@ static uint32_t extract_u32(struct mt_state *state) { static int do_open(const char *path, struct fuse_file_info *fi) { - struct mt_state *state = malloc(sizeof(struct mt_state)); - mt_init(state, 0); + struct file_state *state = malloc(sizeof(struct file_state)); + mt_random_t rng; + mt_init(&rng, 0); fi->fh = (uint64_t)state; return 0; @@ -108,17 +109,23 @@ static int do_getattr(const char *path, struct stat *st) { static int get_noise(size_t n, off_t offset, char* buf, struct fuse_file_info *fi) { printf("getting random bits: %i@%i (%i)\n", n, offset, n*sizeof(char)); + + // FIXME this is wrong. + struct mt_state *state = (struct mt_state *)(fi->fh); + float buf_ratio = (float)sizeof(char)/(float)sizeof(uint32_t); + if(offset != state->consumed * buf_ratio) { + printf("wrong offset, discarding state\n"); + } + // TODO got distracted, never actually did this. + uint32_t *tmp = malloc(n * sizeof(char)); printf("allocated %i\n", sizeof(char) * n); - - struct mt_state *state = (struct mt_state *)(fi->fh); - - float buf_ratio = (float)sizeof(char)/(float)sizeof(uint32_t); int count = n * buf_ratio; printf("calling extract_u32 %i times (%i * %f)\n", count, n, buf_ratio); for(int i=0; iconsumed, count); state->consumed += count; @@ -169,6 +176,5 @@ Noiser* mersenne_init(void) { n->files[7]->name = "200GB"; n->files[7]->size = 200000000000; - return n; } diff --git a/noisebox.h b/noisebox.h index 7325b42..0172d51 100644 --- a/noisebox.h +++ b/noisebox.h @@ -5,6 +5,8 @@ #include #include +#include + #ifndef NOISEBOX_H #define NOISEBOX_H @@ -25,9 +27,31 @@ typedef struct { // int (*do_readdir)(const char *path, void *buffer, fuse_fill_dir_t filler, // off_t offset, struct fuse_file_info *fi); int (*do_open)(const char *, struct fuse_file_info *); + int (*do_release)(const char *, struct fuse_file_info *); } Noiser; +typedef union { + pcg32_random_t *pcg; +} rng_state_t; + +// linked list of open file states +struct file_state { + char *name; + rng_state_t rng; + size_t consumed; + struct file_state *next; + // assume prng output is some integral number of chars. + int char_ratio; +}; + +struct nb_context { + Noiser **noisers; + struct file_state *state_head; +}; + + Noiser* zero_init(void); Noiser* mersenne_init(void); +Noiser* pcg_init(void); #endif diff --git a/pcg.c b/pcg.c new file mode 100644 index 0000000..2cac454 --- /dev/null +++ b/pcg.c @@ -0,0 +1,127 @@ +/* + * pcg.c -- component to provide random numbers from pcg on demand. + */ + +#include +#include +#include +#include + +#include "noisebox.h" + +// static int do_readdir(const char *path, void *buffer, +// fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { +// filler(buffer, ".", NULL, 0); +// filler(buffer, "..", NULL, 0); +// } + +static int do_getattr(const char *path, struct stat *st) { + return 0; +} + +static int get_state(const char *path, struct fuse_file_info *fi) { + return 0; +} + +static int do_open(const char *path, struct fuse_file_info *fi) { + // only called if state isn't already inited. + struct file_state *state = malloc(sizeof(struct file_state)); + pcg32_random_t p; + // fixed constant seed + pcg32_srandom_r(&p, 42u, 54u); + + state->rng.pcg = &p; + state->next = NULL; + state->char_ratio = 4; + + fi->fh = (uint64_t)state; + return 0; +} + +static int do_release(const char *path, struct fuse_file_info *fi) { + free((void *)fi->fh); + return 0; +} + +static int get_noise(size_t n, off_t offset, char* buf, + struct fuse_file_info *fi) { + printf("getting pcg rand: %i:%i\n", n, offset); + printf("sizeof buf = %zu (%zu * %i)\n", n * sizeof(char), n, sizeof(char)); + struct file_state *fh = (struct file_state *)(fi->fh); + + pcg32_random_t *rng = fh->rng.pcg; + + // if offset doesn't match, seek. + if(fh->consumed != offset) { + pcg32_advance_r(rng, offset - fh->consumed); + fh->consumed = offset; + } + + uint32_t *tmp = malloc(n); + + for(int i=0; (i*fh->char_ratio)consumed += n; + memcpy(buf, tmp, n); + + free(tmp); + printf("pcg random numbers obtained\n"); + return n; +} + +Noiser* pcg_init(void) { + Noiser* n = malloc(sizeof(Noiser)); + n->name = "pcg"; + n->state = NULL; + n->get_noise = get_noise; + n->do_open = do_open; + n->do_release = do_release; + + // manually keep track of file count for now. + n->noisefile_count = 10; + n->files = malloc(sizeof(NoiseFile *) * n->noisefile_count); + + n->files[0] = malloc(sizeof(NoiseFile)); + n->files[0]->name = "1M"; + n->files[0]->size = 1ULL<<20; + + n->files[1] = malloc(sizeof(NoiseFile)); + n->files[1]->name = "1G"; + n->files[1]->size = 1ULL<<30; + + n->files[2] = malloc(sizeof(NoiseFile)); + n->files[2]->name = "100G"; + n->files[2]->size = 100 * (1ULL<<30); + + n->files[3] = malloc(sizeof(NoiseFile)); + n->files[3]->name = "200GiB"; + n->files[3]->size = 200 * (1ULL<<30); + + n->files[4] = malloc(sizeof(NoiseFile)); + n->files[4]->name = "400GiB"; + n->files[4]->size = 400 * (1ULL<<30); + + n->files[5] = malloc(sizeof(NoiseFile)); + n->files[5]->name = "1GB"; + n->files[5]->size = 1000000000; + + n->files[6] = malloc(sizeof(NoiseFile)); + n->files[6]->name = "100GB"; + n->files[6]->size = 100000000000; + + n->files[7] = malloc(sizeof(NoiseFile)); + n->files[7]->name = "200GB"; + n->files[7]->size = 200000000000; + + n->files[8] = malloc(sizeof(NoiseFile)); + n->files[8]->name = "400GB"; + n->files[8]->size = 400000000000; + + n->files[9] = malloc(sizeof(NoiseFile)); + n->files[9]->name = "800GB"; + n->files[9]->size = 800000000000; + + return n; +}