From 52d6fadfe9fa8e443d554ef55fd3f5021160da2e Mon Sep 17 00:00:00 2001 From: Thomas Schoebel-Theuer Date: Sun, 8 Aug 2010 21:51:20 +0100 Subject: [PATCH] import mars-32.tgz --- Makefile | 2 +- mars_buf.c | 6 +- mars_test.c | 4 +- mars_trans_logger.c | 279 ++++++++++++++++++++++++++++++++++++++++++++ mars_trans_logger.h | 34 ++++++ 5 files changed, 319 insertions(+), 6 deletions(-) create mode 100644 mars_trans_logger.c create mode 100644 mars_trans_logger.h diff --git a/Makefile b/Makefile index d5086b04..6a84576f 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_MARS_DUMMY) += mars_dummy.o obj-$(CONFIG_MARS_IF_DEVICE) += mars_if_device.o obj-$(CONFIG_MARS_DEVICE_SIO) += mars_device_sio.o obj-$(CONFIG_MARS_BUF) += mars_buf.o mars_usebuf.o -#obj-$(CONFIG_MARS_TRANS_LOGGER) += mars_trans_logger.o +obj-$(CONFIG_MARS_TRANS_LOGGER) += mars_trans_logger.o obj-$(CONFIG_MARS_TEST) += mars_test.o diff --git a/mars_buf.c b/mars_buf.c index f813754b..ab593c89 100644 --- a/mars_buf.c +++ b/mars_buf.c @@ -22,7 +22,7 @@ ///////////////////////// own helper functions //////////////////////// -static inline int buf_hash_fn(struct buf_brick *brick, unsigned int base_index) +static inline int buf_hash_fn(unsigned int base_index) { // simple and stupid unsigned int tmp; @@ -35,7 +35,7 @@ static inline int buf_hash_fn(struct buf_brick *brick, unsigned int base_index) static struct buf_head *hash_find(struct buf_brick *brick, unsigned int base_index) { - int hash = buf_hash_fn(brick, base_index); + int hash = buf_hash_fn(base_index); struct list_head *start = &brick->cache_anchors[hash]; struct list_head *tmp; struct buf_head *res; @@ -64,7 +64,7 @@ static struct buf_head *hash_find(struct buf_brick *brick, unsigned int base_ind static inline void hash_insert(struct buf_brick *brick, struct buf_head *elem) { - int hash = buf_hash_fn(brick, elem->bf_base_index); + int hash = buf_hash_fn(elem->bf_base_index); struct list_head *start = &brick->cache_anchors[hash]; list_add(&elem->bf_hash_head, start); } diff --git a/mars_test.c b/mars_test.c index 365b3a6e..28e6831b 100644 --- a/mars_test.c +++ b/mars_test.c @@ -121,8 +121,8 @@ void make_test_instance(void) buf_brick = brick(&buf_brick_type); _buf_brick = (void*)buf_brick; _buf_brick->backing_order = 0; - //_buf_brick->backing_order = 4; - //_buf_brick->backing_order = 7; + _buf_brick->backing_order = 4; + _buf_brick->backing_order = 7; _buf_brick->backing_size = PAGE_SIZE << _buf_brick->backing_order; _buf_brick->max_count = MEM >> _buf_brick->backing_order; diff --git a/mars_trans_logger.c b/mars_trans_logger.c new file mode 100644 index 00000000..a32b63dc --- /dev/null +++ b/mars_trans_logger.c @@ -0,0 +1,279 @@ +// (c) 2010 Thomas Schoebel-Theuer / 1&1 Internet AG + +// Trans_Logger brick (just for demonstration) + +//#define BRICK_DEBUGGING +//#define MARS_DEBUGGING + +#include +#include +#include +#include + +#include "mars.h" + +///////////////////////// own type definitions //////////////////////// + +#include "mars_trans_logger.h" + +///////////////////////// own helper functions //////////////////////// + + +static inline int hash_fn(unsigned int base_index) +{ + // simple and stupid + unsigned int tmp; + tmp = base_index ^ (base_index / TRANS_HASH_MAX); + tmp += tmp / 13; + tmp ^= tmp / (TRANS_HASH_MAX * TRANS_HASH_MAX); + return tmp % TRANS_HASH_MAX; +} + +static struct trans_logger_mars_ref_aspect *hash_find(struct hash_anchor *table, loff_t pos, int len) +{ + unsigned int base_index = ((unsigned int)pos) >> REGION_SIZE_BITS; + int hash = hash_fn(base_index); + struct hash_anchor *start = &table[hash]; + struct list_head *tmp; + struct trans_logger_mars_ref_aspect *res = NULL; + struct trans_logger_mars_ref_aspect *test_a; + struct mars_ref_object *test; + loff_t min_pos = -1; + int count = 0; + unsigned int flags; + + traced_readlock(&start->hash_lock, flags); + + /* Caution: there may be duplicates in the list, some of them + * overlapping in many different ways. + * Always find the both _newest_ and _lowest_ overlapping element! + */ + for (tmp = start->hash_anchor.next; tmp != &start->hash_anchor; tmp = tmp->next) { +#if 1 + static int max = 0; + if (++count > max) { + max = count; + if (!(max % 10)) { + MARS_INF("hash maxlen=%d hash=%d base_index=%u\n", max, hash, base_index); + } + } +#endif + test_a = container_of(tmp, struct trans_logger_mars_ref_aspect, hash_head); + test = test_a->object; + if (pos < test->ref_pos + test->ref_len && pos + len > test->ref_pos) { + if (test->ref_pos >= pos) { + // always prefer the lowest distance, even if elder + if (test->ref_pos < min_pos || min_pos < 0) { + min_pos = test->ref_pos; + res = test_a; + } + } else { + // always take the newest one, distance does not matter + if (min_pos < 0) { + min_pos = test->ref_pos; + res = test_a; + } + } + } + } + + traced_readunlock(&start->hash_lock, flags); + + return res; +} + +static inline void hash_insert(struct hash_anchor *table, struct trans_logger_mars_ref_aspect *elem) +{ + unsigned int base_index = ((unsigned int)elem->object->ref_pos) >> REGION_SIZE_BITS; + int hash = hash_fn(base_index); + struct hash_anchor *start = &table[hash]; + unsigned int flags; + + traced_writelock(&start->hash_lock, flags); + + list_add(&elem->hash_head, &start->hash_anchor); + + traced_writeunlock(&start->hash_lock, flags); +} + +static inline void hash_delete(struct hash_anchor *table, struct trans_logger_mars_ref_aspect *elem) +{ + unsigned int base_index = ((unsigned int)elem->object->ref_pos) >> REGION_SIZE_BITS; + int hash = hash_fn(base_index); + struct hash_anchor *start = &table[hash]; + unsigned int flags; + + traced_writelock(&start->hash_lock, flags); + + list_del_init(&elem->hash_head); + + traced_writeunlock(&start->hash_lock, flags); +} + +////////////////// own brick / input / output operations ////////////////// + +static int trans_logger_get_info(struct trans_logger_output *output, struct mars_info *info) +{ + struct trans_logger_input *input = output->brick->inputs[0]; + return GENERIC_INPUT_CALL(input, mars_get_info, info); +} + +static int trans_logger_ref_get(struct trans_logger_output *output, struct mars_ref_object *mref) +{ + struct trans_logger_input *input = output->brick->inputs[0]; + unsigned int base_offset = ((unsigned int)mref->ref_pos) & (REGION_SIZE - 1); + struct trans_logger_mars_ref_aspect *shadow_a; + + if (base_offset + mref->ref_len > REGION_SIZE) + mref->ref_len = REGION_SIZE - base_offset; + + if (mref->ref_rw == READ) { + /* Look if the is a newer version on the fly which shadows + * the old one. + * When a shadow is found, use it as buffer for the mref. + */ + shadow_a = hash_find(output->hash_table, mref->ref_pos, mref->ref_len); + if (shadow_a) { + struct mars_ref_object *shadow = shadow_a->object; + int diff = shadow->ref_pos - mref->ref_pos; + int restlen; + if (diff > 0) { + /* Although the shadow is overlapping, the + * region before its start is _not_ shadowed. + * Thus we return this (smaller) unshadowed + * region. + */ + mref->ref_len = diff; + goto call; + } + restlen = shadow->ref_len + diff; + if (mref->ref_len > restlen) + mref->ref_len = restlen; + //... + return -ENOSYS; + } + call: + return GENERIC_INPUT_CALL(input, mars_ref_get, mref); + } + //... + return -ENOSYS; +} + +static void trans_logger_ref_put(struct trans_logger_output *output, struct mars_ref_object *mref) +{ + struct trans_logger_input *input = output->brick->inputs[0]; + GENERIC_INPUT_CALL(input, mars_ref_put, mref); +} + +static void trans_logger_ref_io(struct trans_logger_output *output, struct mars_ref_object *mref, int rw) +{ + struct trans_logger_input *input = output->brick->inputs[0]; + GENERIC_INPUT_CALL(input, mars_ref_io, mref, rw); +} + +//////////////// object / aspect constructors / destructors /////////////// + +static int trans_logger_mars_ref_aspect_init_fn(struct generic_aspect *_ini, void *_init_data) +{ + struct trans_logger_mars_ref_aspect *ini = (void*)_ini; + INIT_LIST_HEAD(&ini->hash_head); + (void)ini; + return 0; +} + +static void trans_logger_mars_ref_aspect_exit_fn(struct generic_aspect *_ini, void *_init_data) +{ + struct trans_logger_mars_ref_aspect *ini = (void*)_ini; + CHECK_HEAD_EMPTY(&ini->hash_head); + (void)ini; +} + +MARS_MAKE_STATICS(trans_logger); + +////////////////////// brick constructors / destructors //////////////////// + +static int trans_logger_brick_construct(struct trans_logger_brick *brick) +{ + return 0; +} + +static int trans_logger_output_construct(struct trans_logger_output *output) +{ + int i; + for (i = 0; i < TRANS_HASH_MAX; i++) { + struct hash_anchor *start = &output->hash_table[i]; + rwlock_init(&start->hash_lock); + INIT_LIST_HEAD(&start->hash_anchor); + } + return 0; +} + +///////////////////////// static structs //////////////////////// + +static struct trans_logger_brick_ops trans_logger_brick_ops = { +}; + +static struct trans_logger_output_ops trans_logger_output_ops = { + .make_object_layout = trans_logger_make_object_layout, + .mars_get_info = trans_logger_get_info, + .mars_ref_get = trans_logger_ref_get, + .mars_ref_put = trans_logger_ref_put, + .mars_ref_io = trans_logger_ref_io, +}; + +static const struct trans_logger_input_type trans_logger_input_type = { + .type_name = "trans_logger_input", + .input_size = sizeof(struct trans_logger_input), +}; + +static const struct trans_logger_input_type *trans_logger_input_types[] = { + &trans_logger_input_type, +}; + +static const struct trans_logger_output_type trans_logger_output_type = { + .type_name = "trans_logger_output", + .output_size = sizeof(struct trans_logger_output), + .master_ops = &trans_logger_output_ops, + .output_construct = &trans_logger_output_construct, + .aspect_types = trans_logger_aspect_types, + .layout_code = { + [BRICK_OBJ_MARS_REF] = LAYOUT_ALL, + } +}; + +static const struct trans_logger_output_type *trans_logger_output_types[] = { + &trans_logger_output_type, +}; + +const struct trans_logger_brick_type trans_logger_brick_type = { + .type_name = "trans_logger_brick", + .brick_size = sizeof(struct trans_logger_brick), + .max_inputs = 1, + .max_outputs = 1, + .master_ops = &trans_logger_brick_ops, + .default_input_types = trans_logger_input_types, + .default_output_types = trans_logger_output_types, + .brick_construct = &trans_logger_brick_construct, +}; +EXPORT_SYMBOL_GPL(trans_logger_brick_type); + +////////////////// module init stuff ///////////////////////// + +static int __init init_trans_logger(void) +{ + printk(MARS_INFO "init_trans_logger()\n"); + return trans_logger_register_brick_type(); +} + +static void __exit exit_trans_logger(void) +{ + printk(MARS_INFO "exit_trans_logger()\n"); + trans_logger_unregister_brick_type(); +} + +MODULE_DESCRIPTION("MARS trans_logger brick"); +MODULE_AUTHOR("Thomas Schoebel-Theuer "); +MODULE_LICENSE("GPL"); + +module_init(init_trans_logger); +module_exit(exit_trans_logger); diff --git a/mars_trans_logger.h b/mars_trans_logger.h new file mode 100644 index 00000000..507b1a22 --- /dev/null +++ b/mars_trans_logger.h @@ -0,0 +1,34 @@ +// (c) 2010 Thomas Schoebel-Theuer / 1&1 Internet AG +#ifndef MARS_TRANS_LOGGER_H +#define MARS_TRANS_LOGGER_H + +#define REGION_SIZE_BITS 22 +#define REGION_SIZE (1 << REGION_SIZE_BITS) +#define TRANS_HASH_MAX 32 + +struct trans_logger_mars_ref_aspect { + GENERIC_ASPECT(mars_ref); + struct list_head hash_head; +}; + +struct trans_logger_brick { + MARS_BRICK(trans_logger); +}; + +struct trans_logger_input { + MARS_INPUT(trans_logger); +}; + +struct hash_anchor { + rwlock_t hash_lock; + struct list_head hash_anchor; +}; + +struct trans_logger_output { + MARS_OUTPUT(trans_logger); + struct hash_anchor hash_table[TRANS_HASH_MAX]; +}; + +MARS_TYPES(trans_logger); + +#endif