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:
parent
4565ba8fc7
commit
bf7489cb64
1
brick.c
1
brick.c
@ -988,7 +988,6 @@ void free_meta(void *data, const struct meta *meta)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(free_meta);
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// module init stuff
|
||||
|
55
brick.h
55
brick.h
@ -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); \
|
||||
} \
|
||||
|
88
log_format.c
88
log_format.c
@ -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);
|
||||
|
||||
|
@ -109,6 +109,7 @@ struct log_status {
|
||||
wait_queue_head_t event;
|
||||
int error_code;
|
||||
bool got;
|
||||
bool do_free;
|
||||
void *private;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
46
mars_if.c
46
mars_if.c
@ -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:
|
||||
|
||||
|
@ -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;
|
||||
|
34
mars_light.c
34
mars_light.c
@ -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);
|
||||
|
1327
mars_trans_logger.c
1327
mars_trans_logger.c
File diff suppressed because it is too large
Load Diff
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user