1
0
mirror of https://github.com/schoebel/mars synced 2025-03-25 04:26:49 +00:00

import mars-91.tgz

This commit is contained in:
Thomas Schoebel-Theuer 2011-04-08 10:52:46 +01:00
parent 4565ba8fc7
commit bf7489cb64
10 changed files with 1207 additions and 411 deletions

View File

@ -988,7 +988,6 @@ void free_meta(void *data, const struct meta *meta)
}
EXPORT_SYMBOL_GPL(free_meta);
/////////////////////////////////////////////////////////////////////////
// module init stuff

55
brick.h
View File

@ -7,6 +7,13 @@
#include <linux/sched.h>
#include <linux/wait.h>
#ifdef CONFIG_DEBUG_KERNEL
#define INLINE inline
//#define INLINE __attribute__((__noinline__))
#else
#define INLINE inline
#endif
#ifdef _STRATEGY
#define _STRATEGY_CODE(X) X
#define _NORMAL_CODE(X) /**/
@ -284,7 +291,7 @@ struct generic_output_type {
int generic_register_brick_type(const struct generic_brick_type *new_type);
int generic_unregister_brick_type(const struct generic_brick_type *old_type);
inline void _generic_output_init(struct generic_brick *brick, const struct generic_output_type *type, struct generic_output *output, const char *output_name)
INLINE void _generic_output_init(struct generic_brick *brick, const struct generic_output_type *type, struct generic_output *output, const char *output_name)
{
output->output_name = output_name;
output->brick = brick;
@ -295,7 +302,7 @@ inline void _generic_output_init(struct generic_brick *brick, const struct gener
INIT_LIST_HEAD(&output->output_head);
}
inline void _generic_output_exit(struct generic_output *output)
INLINE void _generic_output_exit(struct generic_output *output)
{
list_del_init(&output->output_head);
output->output_name = NULL;
@ -309,7 +316,7 @@ inline void _generic_output_exit(struct generic_output *output)
#ifdef _STRATEGY // call this only in strategy bricks, never in ordinary bricks
// you need this only if you circumvent generic_brick_init_full()
inline int generic_brick_init(const struct generic_brick_type *type, struct generic_brick *brick, const char *brick_name)
INLINE int generic_brick_init(const struct generic_brick_type *type, struct generic_brick *brick, const char *brick_name)
{
brick->brick_name = brick_name;
brick->type = type;
@ -322,7 +329,7 @@ inline int generic_brick_init(const struct generic_brick_type *type, struct gene
return 0;
}
inline void generic_brick_exit(struct generic_brick *brick)
INLINE void generic_brick_exit(struct generic_brick *brick)
{
list_del_init(&brick->tmp_head);
brick->brick_name = NULL;
@ -332,7 +339,7 @@ inline void generic_brick_exit(struct generic_brick *brick)
brick->nr_outputs = 0;
}
inline int generic_input_init(struct generic_brick *brick, int index, const struct generic_input_type *type, struct generic_input *input, const char *input_name)
INLINE int generic_input_init(struct generic_brick *brick, int index, const struct generic_input_type *type, struct generic_input *input, const char *input_name)
{
if (index < 0 || index >= brick->type->max_inputs)
return -EINVAL;
@ -348,7 +355,7 @@ inline int generic_input_init(struct generic_brick *brick, int index, const stru
return 0;
}
inline void generic_input_exit(struct generic_input *input)
INLINE void generic_input_exit(struct generic_input *input)
{
list_del_init(&input->input_head);
input->input_name = NULL;
@ -357,7 +364,7 @@ inline void generic_input_exit(struct generic_input *input)
input->connect = NULL;
}
inline int generic_output_init(struct generic_brick *brick, int index, const struct generic_output_type *type, struct generic_output *output, const char *output_name)
INLINE int generic_output_init(struct generic_brick *brick, int index, const struct generic_output_type *type, struct generic_output *output, const char *output_name)
{
if (index < 0 || index >= brick->type->max_outputs)
return -ENOMEM;
@ -369,7 +376,7 @@ inline int generic_output_init(struct generic_brick *brick, int index, const str
return 0;
}
inline int generic_size(const struct generic_brick_type *brick_type)
INLINE int generic_size(const struct generic_brick_type *brick_type)
{
int size = brick_type->brick_size;
int i;
@ -398,7 +405,7 @@ int generic_brick_init_full(
int generic_brick_exit_full(
struct generic_brick *brick);
inline int generic_connect(struct generic_input *input, struct generic_output *output)
INLINE int generic_connect(struct generic_input *input, struct generic_output *output)
{
BRICK_DBG("generic_connect(input=%p, output=%p)\n", input, output);
if (unlikely(!input || !output))
@ -421,7 +428,7 @@ inline int generic_connect(struct generic_input *input, struct generic_output *o
return 0;
}
inline int generic_disconnect(struct generic_input *input)
INLINE int generic_disconnect(struct generic_input *input)
{
BRICK_DBG("generic_disconnect(input=%p)\n", input);
if (!input)
@ -467,7 +474,7 @@ extern const struct BRICK##_brick_type BRICK##_brick_type; \
extern const struct BRICK##_input_type BRICK##_input_type; \
extern const struct BRICK##_output_type BRICK##_output_type; \
\
static inline void _##BRICK##_output_init(struct BRICK##_brick *brick, struct BRICK##_output *output, char *output_name) \
static INLINE void _##BRICK##_output_init(struct BRICK##_brick *brick, struct BRICK##_output *output, char *output_name) \
{ \
_generic_output_init( \
(struct generic_brick*)brick, \
@ -477,12 +484,12 @@ static inline void _##BRICK##_output_init(struct BRICK##_brick *brick, struct BR
} \
\
_STRATEGY_CODE( \
static inline int BRICK##_brick_init(struct BRICK##_brick *brick, char *brick_name) \
static INLINE int BRICK##_brick_init(struct BRICK##_brick *brick, char *brick_name) \
{ \
return generic_brick_init((const struct generic_brick_type*)&BRICK##_brick_type, (struct generic_brick*)brick, brick_name); \
} \
\
static inline int BRICK##_input_init(struct BRICK##_brick *brick, int index, struct BRICK##_input *input, char *input_name) \
static INLINE int BRICK##_input_init(struct BRICK##_brick *brick, int index, struct BRICK##_input *input, char *input_name) \
{ \
return generic_input_init( \
(struct generic_brick*)brick, \
@ -492,7 +499,7 @@ static inline int BRICK##_input_init(struct BRICK##_brick *brick, int index, str
input_name); \
} \
\
static inline int BRICK##_output_init(struct BRICK##_brick *brick, int index, struct BRICK##_output *output, char *output_name) \
static INLINE int BRICK##_output_init(struct BRICK##_brick *brick, int index, struct BRICK##_output *output, char *output_name) \
{ \
return generic_output_init( \
(struct generic_brick*)brick, \
@ -515,14 +522,14 @@ static inline int BRICK##_output_init(struct BRICK##_brick *brick, int index, st
\
_STRATEGY_CODE( \
\
inline int INPUT_BRICK##_##OUTPUT_BRICK##_connect( \
INLINE int INPUT_BRICK##_##OUTPUT_BRICK##_connect( \
struct INPUT_BRICK##_input *input, \
struct OUTPUT_BRICK##_output *output) \
{ \
return generic_connect((struct generic_input*)input, (struct generic_output*)output); \
} \
\
inline int INPUT_BRICK##_##OUTPUT_BRICK####_disconnect( \
INLINE int INPUT_BRICK##_##OUTPUT_BRICK####_disconnect( \
struct INPUT_BRICK##_input *input) \
{ \
return generic_disconnect((struct generic_input*)input); \
@ -545,7 +552,7 @@ extern void free_generic(struct generic_object *object);
#define GENERIC_OBJECT_LAYOUT_FUNCTIONS(BRICK) \
\
inline int BRICK##_init_object_layout(struct BRICK##_output *output, struct generic_object_layout *object_layout, int aspect_max, const struct generic_object_type *object_type) \
INLINE int BRICK##_init_object_layout(struct BRICK##_output *output, struct generic_object_layout *object_layout, int aspect_max, const struct generic_object_type *object_type) \
{ \
if (likely(object_layout->aspect_layouts_table && object_layout->aspect_layouts && object_layout->object_layout_generation == brick_layout_generation)) \
return 0; \
@ -554,7 +561,7 @@ inline int BRICK##_init_object_layout(struct BRICK##_output *output, struct gene
#define GENERIC_ASPECT_LAYOUT_FUNCTIONS(BRICK,TYPE) \
\
inline int BRICK##_##TYPE##_add_aspect(struct BRICK##_output *output, struct TYPE##_object_layout *object_layout, const struct generic_aspect_type *aspect_type) \
INLINE int BRICK##_##TYPE##_add_aspect(struct BRICK##_output *output, struct TYPE##_object_layout *object_layout, const struct generic_aspect_type *aspect_type) \
{ \
int res = generic_add_aspect((struct generic_output*)output, (struct generic_object_layout *)object_layout, aspect_type); \
BRICK_DBG(#BRICK " " #TYPE "added aspect_type %p (%s) to object_layout %p (type %s) on output %p (type %s), status=%d\n", aspect_type, aspect_type->aspect_type_name, object_layout, object_layout->object_type->object_type_name, output, output->type->type_name, res); \
@ -563,7 +570,7 @@ inline int BRICK##_##TYPE##_add_aspect(struct BRICK##_output *output, struct TYP
#define GENERIC_OBJECT_FUNCTIONS(TYPE) \
\
inline struct TYPE##_object *TYPE##_construct(void *data, struct TYPE##_object_layout *object_layout) \
INLINE struct TYPE##_object *TYPE##_construct(void *data, struct TYPE##_object_layout *object_layout) \
{ \
struct TYPE##_object *obj = data; \
int i; \
@ -596,7 +603,7 @@ inline struct TYPE##_object *TYPE##_construct(void *data, struct TYPE##_object_l
return obj; \
} \
\
inline void TYPE##_destruct(struct TYPE##_object *obj) \
INLINE void TYPE##_destruct(struct TYPE##_object *obj) \
{ \
struct TYPE##_object_layout *object_layout = obj->object_layout; \
int i; \
@ -627,7 +634,7 @@ inline void TYPE##_destruct(struct TYPE##_object *obj) \
#define GENERIC_ASPECT_FUNCTIONS(BRICK,TYPE) \
\
inline struct BRICK##_##TYPE##_aspect *BRICK##_##TYPE##_get_aspect(struct BRICK##_output *output, struct TYPE##_object *obj) \
INLINE struct BRICK##_##TYPE##_aspect *BRICK##_##TYPE##_get_aspect(struct BRICK##_output *output, struct TYPE##_object *obj) \
{ \
struct generic_object_layout *object_layout; \
struct generic_aspect_layout *aspect_layout; \
@ -648,7 +655,7 @@ inline struct BRICK##_##TYPE##_aspect *BRICK##_##TYPE##_get_aspect(struct BRICK#
return (void*)obj + aspect_layout->aspect_offset; \
} \
\
inline struct TYPE##_object *BRICK##_alloc_##TYPE(struct BRICK##_output *output, struct generic_object_layout *object_layout) \
INLINE struct TYPE##_object *BRICK##_alloc_##TYPE(struct BRICK##_output *output, struct generic_object_layout *object_layout) \
{ \
if (unlikely(!object_layout->aspect_layouts_table || !object_layout->aspect_layouts || object_layout->object_layout_generation != brick_layout_generation)) { \
int status = default_init_object_layout((struct generic_output*)output, object_layout, BRICK_DEPTH_MAX, &TYPE##_type, #BRICK); \
@ -658,12 +665,12 @@ inline struct TYPE##_object *BRICK##_alloc_##TYPE(struct BRICK##_output *output,
return (struct TYPE##_object*)alloc_generic(object_layout); \
} \
\
inline struct TYPE##_object *BRICK##_alloc_##TYPE##_pure(struct generic_object_layout *object_layout) \
INLINE struct TYPE##_object *BRICK##_alloc_##TYPE##_pure(struct generic_object_layout *object_layout) \
{ \
return (struct TYPE##_object*)alloc_generic(object_layout); \
} \
\
inline void BRICK##_free_##TYPE(struct TYPE##_object *object) \
INLINE void BRICK##_free_##TYPE(struct TYPE##_object *object) \
{ \
free_generic((struct generic_object*)object); \
} \

View File

@ -16,7 +16,7 @@ void init_logst(struct log_status *logst, struct mars_input *input, struct mars_
}
EXPORT_SYMBOL_GPL(init_logst);
#define MARS_LOG_CB_MAX 16
#define MARS_LOG_CB_MAX 32
struct log_cb_info {
struct mref_object *mref;
@ -26,7 +26,7 @@ struct log_cb_info {
};
static
void log_endio(struct generic_callback *cb)
void log_write_endio(struct generic_callback *cb)
{
struct log_cb_info *cb_info = cb->cb_private;
int i;
@ -38,6 +38,8 @@ void log_endio(struct generic_callback *cb)
mars_log_trace(cb_info->mref);
}
MARS_IO("nr_endio = %d\n", cb_info->nr_endio);
for (i = 0; i < cb_info->nr_endio; i++) {
cb_info->endios[i](cb_info->privates[i], cb->cb_error);
}
@ -78,7 +80,7 @@ void log_flush(struct log_status *logst)
logst->log_pos += logst->offset;
cb = &mref->_ref_cb;
cb->cb_fn = log_endio;
cb->cb_fn = log_write_endio;
cb->cb_private = logst->private;
logst->private = NULL;
cb->cb_error = 0;
@ -194,6 +196,7 @@ put:
err_free:
mars_free_mref(mref);
if (logst->private) {
// TODO: if callbacks are already registered, call them here with some error code
kfree(logst->private);
logst->private = NULL;
}
@ -282,6 +285,7 @@ int log_scan(void *buf, int len, struct log_header *lh, void **payload, int *pay
int offset;
int i;
*payload = NULL;
*payload_len = 0;
for (i = 0; i < len; i += sizeof(long)) {
@ -293,6 +297,7 @@ int log_scan(void *buf, int len, struct log_header *lh, void **payload, int *pay
char valid_copy;
int restlen;
int found_offset;
offset = i;
DATA_GET(buf, offset, start_magic);
@ -333,8 +338,7 @@ int log_scan(void *buf, int len, struct log_header *lh, void **payload, int *pay
DATA_GET(buf, offset, lh->l_code);
DATA_GET(buf, offset, lh->l_extra);
*payload = buf + offset;
*payload_len = lh->l_len;
found_offset = offset;
offset += lh->l_len;
restlen = len - offset;
@ -364,6 +368,10 @@ int log_scan(void *buf, int len, struct log_header *lh, void **payload, int *pay
MARS_WRN("size mismatch at offset %d: %d != %d\n", i, total_len, offset - i);
// just warn, but no consequences: better use the data, it has been checked by lots of magics
}
// Success...
*payload = buf + found_offset;
*payload_len = lh->l_len;
goto done;
}
offset = i;
@ -377,7 +385,7 @@ done:
}
static
void read_endio(struct generic_callback *cb)
void log_read_endio(struct generic_callback *cb)
{
struct log_status *logst = cb->cb_private;
@ -394,13 +402,24 @@ err:
int log_read(struct log_status *logst, struct log_header *lh, void **payload, int *payload_len)
{
struct mref_object *mref = logst->read_mref;
int status = 0;
if (!mref) {
struct mref_object *mref;
int status;
restart:
status = 0;
mref = logst->read_mref;
if (!mref || logst->do_free) {
struct generic_callback *cb;
int chunk_offset;
int chunk_rest;
if (mref) {
logst->log_pos += logst->offset;
GENERIC_INPUT_CALL(logst->input, mref_put, mref);
logst->read_mref = NULL;
logst->offset = 0;
}
mref = mars_alloc_mref(logst->output, &logst->ref_object_layout);
if (unlikely(!mref)) {
MARS_ERR("no mref\n");
@ -409,36 +428,39 @@ int log_read(struct log_status *logst, struct log_header *lh, void **payload, in
mref->ref_pos = logst->log_pos;
chunk_offset = logst->log_pos & (loff_t)(logst->chunk_size - 1);
chunk_rest = logst->chunk_size - chunk_offset;
mref->ref_len = chunk_rest + logst->chunk_size;
mref->ref_len = chunk_rest + logst->chunk_size * 8;
#if 0
mref->ref_prio = MARS_PRIO_LOW;
#endif
status = GENERIC_INPUT_CALL(logst->input, mref_get, mref);
if (unlikely(status < 0)) {
MARS_ERR("mref_get() failed, status = %d\n", status);
if (status != -ENODATA) {
MARS_ERR("mref_get() failed, status = %d\n", status);
}
goto done_free;
}
cb = &mref->_ref_cb;
cb->cb_fn = read_endio;
cb->cb_fn = log_read_endio;
cb->cb_private = logst;
cb->cb_error = 0;
cb->cb_prev = NULL;
mref->ref_cb = cb;
mref->ref_rw = 0;
mref->ref_rw = READ;
logst->offset = 0;
logst->got = false;
logst->do_free = false;
GENERIC_INPUT_CALL(logst->input, mref_io, mref);
wait_event_interruptible_timeout(logst->event, logst->got, 60 * HZ);
status = -EIO;
if (!logst->got)
goto done_free;
goto done_put;
status = logst->error_code;
if (status < 0)
goto done_free;
goto done_put;
logst->read_mref = mref;
}
@ -448,24 +470,40 @@ int log_read(struct log_status *logst, struct log_header *lh, void **payload, in
status = -EINVAL;
}
if (unlikely(status < 0)) {
goto done_free;
goto done_put;
}
// memorize success
logst->offset += status;
if (logst->offset < mref->ref_len - logst->chunk_size) {
goto done;
if (logst->offset > mref->ref_len - logst->chunk_size) {
logst->do_free = true;
}
done:
if (status == -ENODATA) {
status = 0; // indicates EOF
}
return status;
done_put:
if (mref) {
logst->log_pos += logst->offset;
GENERIC_INPUT_CALL(logst->input, mref_put, mref);
logst->read_mref = NULL;
logst->offset = 0;
}
if (status == -EAGAIN && logst->offset > 0) {
goto restart;
}
goto done;
done_free:
if (mref) {
if (status >= 0) {
logst->log_pos += logst->offset;
}
GENERIC_INPUT_CALL(logst->input, mref_put, mref);
logst->read_mref = NULL;
mars_free_mref(mref);
}
done:
return status;
logst->read_mref = NULL;
goto done;
}
EXPORT_SYMBOL_GPL(log_read);

View File

@ -109,6 +109,7 @@ struct log_status {
wait_queue_head_t event;
int error_code;
bool got;
bool do_free;
void *private;
};

View File

@ -403,7 +403,7 @@ static int bio_thread(void *data)
LIST_HEAD(tmp_list);
unsigned long flags;
wait_event_interruptible_timeout(brick->event, !list_empty(&brick->completed_list), HZ);
wait_event_interruptible_timeout(brick->event, !list_empty(&brick->completed_list), 10 * HZ);
spin_lock_irqsave(&brick->lock, flags);
list_replace_init(&brick->completed_list, &tmp_list);

View File

@ -8,7 +8,8 @@
//#define MARS_DEBUGGING
//#define IO_DEBUGGING
#define REQUEST_MERGING
//#define REQUEST_MERGING
//#define PREFETCH_LEN PAGE_SIZE // TODO: make this work
// low-level device parameters
//#define USE_MAX_SECTORS (MARS_MAX_SEGMENT_SIZE >> 9)
@ -75,7 +76,7 @@ void if_endio(struct generic_callback *cb)
if (!atomic_dec_and_test(&bio->bi_comp_cnt)) {
continue;
}
#if 0
#if 1
if (mref_a->object->ref_is_kmapped) {
struct bio_vec *bvec;
int i;
@ -161,6 +162,7 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
const bool barrier = ((bio->bi_rw & 1) != READ && bio_rw_flagged(bio, BIO_RW_BARRIER));
loff_t pos = ((loff_t)bio->bi_sector) << 9; // TODO: make dynamic
int rw = bio_data_dir(bio);
int total_len = bio->bi_size;
int error = -ENOSYS;
MARS_IO("bio %p size = %d\n", bio, bio->bi_size);
@ -214,6 +216,10 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
data = kmap(page);
MARS_IO("page = %p data = %p\n", page, data);
error = -EINVAL;
if (unlikely(!data))
break;
data += offset;
while (bv_len > 0) {
@ -238,13 +244,13 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
tmp_a = container_of(tmp, struct if_mref_aspect, hash_head);
tmp_mref = tmp_a->object;
if (tmp_mref->ref_page != page || tmp_mref->ref_rw != rw || tmp_a->bio_count >= MAX_BIO) {
if (tmp_mref->ref_page != page || tmp_mref->ref_rw != rw || tmp_a->bio_count >= MAX_BIO || tmp_mref->ref_len + bv_len > tmp_a->max_len) {
continue;
}
if (tmp_mref->ref_data + tmp_mref->ref_len == data) {
goto merge_end;
#if 1
#if 0
} else if (data + bv_len == tmp_mref->ref_data) {
goto merge_front;
#endif
@ -258,6 +264,9 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
mref = tmp_mref;
mref_a = tmp_a;
this_len = bv_len;
if (barrier) {
mref->ref_skip_sync = false;
}
for (i = 0; i < mref_a->bio_count; i++) {
if (mref_a->orig_bio[i] == bio) {
@ -269,9 +278,6 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
atomic_inc(&bio->bi_comp_cnt);
mref_a->orig_bio[mref_a->bio_count++] = bio;
assigned = true;
if (barrier) {
mref->ref_skip_sync = false;
}
goto unlock;
} // foreach hash collision list member
@ -279,6 +285,7 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
traced_unlock(&input->hash_lock[hash_index], flags);
#endif
if (!mref) {
int prefetch_len;
error = -ENOMEM;
mref = if_alloc_mref(&brick->hidden_output, &input->mref_object_layout);
if (unlikely(!mref)) {
@ -290,6 +297,15 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
up(&input->kick_sem);
goto err;
}
#ifdef PREFETCH_LEN
prefetch_len = PREFETCH_LEN - offset;
if (prefetch_len < bv_len)
prefetch_len = bv_len;
#else
prefetch_len = bv_len;
#endif
cb = &mref_a->cb;
cb->cb_fn = if_endio;
cb->cb_private = mref_a;
@ -299,7 +315,7 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
mref_a->input = input;
mref->ref_rw = mref->ref_may_write = rw;
mref->ref_pos = pos;
mref->ref_len = bv_len;
mref->ref_len = prefetch_len;
mref->ref_data = data; // direct IO
mref->ref_page = page;
mref->ref_is_kmapped = true;
@ -311,6 +327,11 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
}
mars_trace(mref, "if_start");
mref_a->max_len = this_len = mref->ref_len; // now may be shorter than originally requested.
if (this_len > bv_len) {
mref->ref_len = this_len = bv_len;
}
if (rw) {
atomic_inc(&input->mref_write_count);
} else {
@ -337,19 +358,22 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
traced_lock(&input->req_lock, flags);
list_add_tail(&mref_a->plug_head, &input->plug_anchor);
traced_unlock(&input->req_lock, flags);
this_len = mref->ref_len; // now may be shorter than originally requested.
} // !mref
pos += this_len;
data += this_len;
bv_len -= this_len;
total_len -= this_len;
} // while bv_len > 0
} // foreach bvec
up(&input->kick_sem);
error = 0;
if (likely(!total_len)) {
error = 0;
} else {
MARS_ERR("bad rest len = %d\n", total_len);
}
err:

View File

@ -18,6 +18,7 @@ struct if_mref_aspect {
struct list_head hash_head;
int hash_index;
int bio_count;
int max_len;
struct bio *orig_bio[MAX_BIO];
struct generic_callback cb;
struct if_input *input;

View File

@ -64,8 +64,10 @@ struct light_class {
#define CONF_TRANS_FLYING 4
#define CONF_TRANS_PRIO MARS_PRIO_HIGH
#define CONF_ALL_BATCHLEN 2
#define CONF_ALL_FLYING 4
//#define CONF_ALL_BATCHLEN 2
#define CONF_ALL_BATCHLEN 1
//#define CONF_ALL_FLYING 4
#define CONF_ALL_FLYING 1
#define CONF_ALL_CONTENTION 0
#define CONF_ALL_PRESSURE 0
#define CONF_ALL_PRIO MARS_PRIO_LOW
@ -929,7 +931,7 @@ void _create_new_logfile(const char *path)
}
static
int _update_replaylink(struct mars_rotate *rot, struct mars_dent *parent, int sequence, loff_t pos, bool check_exist)
int _update_replaylink(struct mars_dent *parent, int sequence, loff_t pos, bool check_exist)
{
struct timespec now = {};
char *old;
@ -965,10 +967,7 @@ int _update_replaylink(struct mars_rotate *rot, struct mars_dent *parent, int se
if (status < 0) {
MARS_ERR("cannot create symlink '%s' -> '%s' status = %d\n", old, new, status);
} else {
MARS_DBG("make symlink '%s' -> '%s' status = %d\n", old, new, status);
}
if (status >= 0) {
rot->last_jiffies = jiffies;
MARS_DBG("make replay symlink '%s' -> '%s' status = %d\n", old, new, status);
}
kfree(new);
@ -1265,11 +1264,13 @@ int make_log(void *buf, struct mars_dent *dent)
switch (status) {
case 0: // not relevant
goto ok;
case 1: /* Relevant, but transaction replay already finished.
case 1: /* Relevant, and transaction replay already finished.
* When primary, switch over to a new logfile.
*/
if (!trans_brick->power.button && !trans_brick->power.led_on && trans_brick->power.led_off) {
_update_replaylink(rot, dent->d_parent, dent->d_serial + 1, 0, !rot->is_primary);
_update_replaylink(dent->d_parent, dent->d_serial + 1, 0, !rot->is_primary);
trans_brick->current_pos = 0;
rot->last_jiffies = jiffies;
mars_trigger();
}
status = -EAGAIN;
@ -1367,10 +1368,12 @@ int _start_trans(struct mars_rotate *rot)
/* Supply all relevant parameters
*/
trans_brick->sequence = rot->relevant_log->d_serial;
trans_brick->do_replay = rot->do_replay;
trans_brick->current_pos = rot->start_pos;
trans_brick->start_pos = rot->start_pos;
trans_brick->end_pos = rot->end_pos;
if ((trans_brick->do_replay = rot->do_replay)) {
trans_brick->replay_start_pos = rot->start_pos;
trans_brick->replay_end_pos = rot->end_pos;
} else {
trans_brick->log_start_pos = rot->start_pos;
}
/* Switch on....
*/
@ -1429,12 +1432,13 @@ int make_log_finalize(struct mars_global *global, struct mars_dent *parent)
if (trans_brick->power.button && trans_brick->power.led_on && !trans_brick->power.led_off) {
bool do_stop =
trans_brick->do_replay ?
(trans_brick->replay_pos == trans_brick->end_pos) :
(trans_brick->replay_pos == trans_brick->replay_end_pos || trans_brick->replay_code != -EAGAIN) :
(rot->relevant_log && rot->relevant_log != rot->current_log);
MARS_DBG("do_stop = %d\n", (int)do_stop);
if (do_stop || (long long)jiffies > rot->last_jiffies + 5 * HZ) {
status = _update_replaylink(rot, parent, trans_brick->sequence, trans_brick->replay_pos, true);
status = _update_replaylink(parent, trans_brick->sequence, trans_brick->replay_pos, true);
rot->last_jiffies = jiffies;
}
if (do_stop) {
status = _stop_trans(rot);

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,11 @@
#define REGION_SIZE (1 << REGION_SIZE_BITS)
#define TRANS_HASH_MAX 512
//#define BITMAP_CHECKS
#ifdef BITMAP_CHECKS
#include <linux/bitmap.h>
#endif
#include <linux/time.h>
#include "log_format.h"
#include "pairing_heap.h"
@ -20,11 +25,13 @@ struct logger_queue {
struct list_head q_anchor;
struct pairing_heap_mref *heap_high;
struct pairing_heap_mref *heap_low;
loff_t heap_border;
long long q_last_action; // jiffies
loff_t heap_margin;
loff_t last_pos;
long long q_last_insert; // jiffies
spinlock_t q_lock;
atomic_t q_queued;
atomic_t q_flying;
atomic_t q_total;
const char *q_insert_info;
const char *q_pushback_info;
const char *q_fetch_info;
@ -46,22 +53,54 @@ struct hash_anchor {
struct list_head hash_anchor;
};
struct writeback_info {
loff_t w_pos;
int w_len;
struct list_head w_collect_list; // list of collected orig requests
struct list_head w_sub_read_list; // for saving the old data before overwrite
struct list_head w_sub_write_list; // for overwriting
};
struct trans_logger_mref_aspect {
GENERIC_ASPECT(mref);
struct trans_logger_output *output;
struct list_head hash_head;
struct list_head q_head;
struct list_head pos_head;
struct list_head replay_head;
struct list_head collect_head;
struct pairing_heap_mref ph;
struct trans_logger_mref_aspect *shadow_ref;
void *shadow_data;
bool do_dealloc;
bool do_buffered;
bool is_hashed;
bool is_valid;
bool is_outdated;
bool is_dirty;
bool ignore_this;
struct timespec stamp;
loff_t log_pos;
loff_t fetch_margin;
struct generic_callback cb;
struct trans_logger_mref_aspect *orig_mref_a;
struct list_head sub_list;
struct list_head sub_head;
int total_sub_count;
atomic_t current_sub_count;
int collect_generation;
#ifdef BITMAP_CHECKS
int shadow_offset;
int bitmap_write;
int bitmap_write_slave;
int bitmap_read;
int start_phase1;
int end_phase1;
int start_phase2;
int sub_count;
unsigned long dirty_bitmap[4];
unsigned long touch_bitmap[4];
unsigned long slave_bitmap[4];
unsigned long work_bitmap[4];
#endif
};
struct trans_logger_brick {
@ -73,17 +112,23 @@ struct trans_logger_brick {
int chunk_size; // must be at least 8K (better 64k)
int flush_delay; // delayed firing of incomplete chunks
bool do_replay; // mode of operation
bool do_continuous_replay; // mode of operation
bool log_reads; // additionally log pre-images
bool debug_shortcut; // only for testing! never use in production!
loff_t start_pos; // where to start replay
loff_t end_pos; // end of replay
loff_t replay_start_pos; // where to start replay
loff_t replay_end_pos; // end of replay
loff_t log_start_pos; // where to start logging
// readonly from outside
loff_t current_pos; // current logging position
loff_t replay_pos; // current replay position
loff_t replay_pos; // current replay position (both in replay mode and in logging mode)
loff_t current_pos; // current logging position (usually ahead of replay_pos)
int replay_code; // replay errors (if any)
// private
loff_t old_margin;
struct log_status logst;
struct list_head pos_list;
spinlock_t pos_lock;
spinlock_t replay_lock;
struct list_head pos_list;
struct list_head replay_list;
};
struct trans_logger_output {