mirror of https://github.com/schoebel/mars
import mars-20.tgz
This commit is contained in:
parent
807cd30eb9
commit
251ccafdb1
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@
|
|||
# Makefile for MARS
|
||||
#
|
||||
|
||||
obj-$(CONFIG_MARS) += brick.o mars_generic.o
|
||||
obj-$(CONFIG_MARS) += brick.o mars_generic.o mars_check.o
|
||||
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
|
||||
|
|
1
mars.h
1
mars.h
|
@ -52,6 +52,7 @@ struct mars_io_object_layout {
|
|||
GENERIC_OBJECT(PREFIX); \
|
||||
struct bio *orig_bio; \
|
||||
int (*mars_endio)(struct mars_io_object *mio, int error); \
|
||||
void *cb_private; \
|
||||
|
||||
struct mars_io_object {
|
||||
MARS_IO_OBJECT(mars_io);
|
||||
|
|
62
mars_buf.c
62
mars_buf.c
|
@ -230,6 +230,7 @@ static int buf_buf_get(struct buf_output *output, struct mars_buf_object *mbuf)
|
|||
unsigned long flags;
|
||||
int status = -EILSEQ;
|
||||
|
||||
might_sleep();
|
||||
|
||||
buf_count = atomic_read(&mbuf->buf_count);
|
||||
if (unlikely(buf_count != 0)) {
|
||||
|
@ -239,7 +240,7 @@ static int buf_buf_get(struct buf_output *output, struct mars_buf_object *mbuf)
|
|||
|
||||
mbuf_a = buf_mars_buf_get_aspect(output, mbuf);
|
||||
if (unlikely(!mbuf_a))
|
||||
goto err_free;
|
||||
goto done;
|
||||
|
||||
base_pos = mbuf->buf_pos & ~(loff_t)(brick->backing_size - 1);
|
||||
base_offset = (mbuf->buf_pos - base_pos);
|
||||
|
@ -264,11 +265,11 @@ static int buf_buf_get(struct buf_output *output, struct mars_buf_object *mbuf)
|
|||
status = -ENOMEM;
|
||||
bf = kzalloc(sizeof(struct buf_head), GFP_KERNEL);
|
||||
if (!bf)
|
||||
goto err_free;
|
||||
goto done;
|
||||
|
||||
bf->bf_data = (void*)__get_free_pages(GFP_KERNEL, brick->backing_order);
|
||||
if (!bf->bf_data)
|
||||
goto err_free2;
|
||||
goto err_free;
|
||||
|
||||
bf->bf_brick = brick;
|
||||
atomic_set(&bf->bf_bio_count, 0);
|
||||
|
@ -279,6 +280,7 @@ static int buf_buf_get(struct buf_output *output, struct mars_buf_object *mbuf)
|
|||
INIT_LIST_HEAD(&bf->bf_again_write_pending_anchor);
|
||||
|
||||
traced_lock(&brick->buf_lock, flags);
|
||||
|
||||
brick->alloc_count++;
|
||||
/* during the open lock, somebody might have raced
|
||||
* against us at the same base_pos...
|
||||
|
@ -313,9 +315,9 @@ static int buf_buf_get(struct buf_output *output, struct mars_buf_object *mbuf)
|
|||
|
||||
return mbuf->buf_len;
|
||||
|
||||
err_free2:
|
||||
kfree(bf);
|
||||
err_free:
|
||||
kfree(bf);
|
||||
done:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -341,12 +343,20 @@ static void _buf_buf_put(struct buf_head *bf)
|
|||
* So this race is ok.
|
||||
*/
|
||||
bf_count = atomic_read(&bf->bf_count);
|
||||
if (bf_count <= 0) {
|
||||
if (likely(bf_count <= 0)) {
|
||||
struct list_head *where = &brick->lru_anchor;
|
||||
if (unlikely(bf_count < 0)) {
|
||||
atomic_set(&bf->bf_count, 0);
|
||||
MARS_ERR("bf_count UNDERRUN %d\n", bf_count);
|
||||
}
|
||||
#if 1
|
||||
if (unlikely(!list_empty(&bf->bf_io_pending_anchor))) {
|
||||
MARS_ERR("bf_io_pending_anchor is not empty!\n");
|
||||
}
|
||||
if (unlikely(!list_empty(&bf->bf_again_write_pending_anchor))) {
|
||||
MARS_ERR("bf_again_write_pending_anchor is not empty!\n");
|
||||
}
|
||||
#endif
|
||||
if (unlikely(!(bf->bf_flags & MARS_BUF_UPTODATE))) {
|
||||
list_del_init(&bf->bf_hash_head);
|
||||
brick->current_count--;
|
||||
|
@ -354,7 +364,7 @@ static void _buf_buf_put(struct buf_head *bf)
|
|||
}
|
||||
list_del(&bf->bf_lru_head);
|
||||
list_add(&bf->bf_lru_head, where);
|
||||
}
|
||||
} // else no harm can happen
|
||||
|
||||
// lru freeing (this is completeley independent from bf)
|
||||
__lru_free(brick);
|
||||
|
@ -503,6 +513,8 @@ static int _buf_make_bios(struct buf_brick *brick, struct buf_head *bf, void *st
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Remember the number of bios we are submitting.
|
||||
*/
|
||||
atomic_inc(&bf->bf_bio_count);
|
||||
|
||||
MARS_DBG("starting buf IO mio=%p bio=%p bf=%p bf_count=%d bf_bio_count=%d\n", mio, mio->orig_bio, bf, atomic_read(&bf->bf_count), atomic_read(&bf->bf_bio_count));
|
||||
|
@ -541,6 +553,9 @@ static void _buf_bio_callback(struct bio *bio, int code)
|
|||
int old_flags;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(tmp);
|
||||
#if 1
|
||||
int count = 0;
|
||||
#endif
|
||||
|
||||
mio_a = bio->bi_private;
|
||||
bf = mio_a->mia_bf;
|
||||
|
@ -603,6 +618,11 @@ static void _buf_bio_callback(struct bio *bio, int code)
|
|||
if (mbuf_a->bfa_bf != bf) {
|
||||
MARS_ERR("bad pointers %p != %p\n", mbuf_a->bfa_bf, bf);
|
||||
}
|
||||
#if 1
|
||||
if (!(++count % 100)) {
|
||||
MARS_ERR("endless loop 1\n");
|
||||
}
|
||||
#endif
|
||||
list_del_init(&mbuf_a->bfc_pending_head);
|
||||
list_add_tail(&mbuf_a->bfc_pending_head, &bf->bf_io_pending_anchor);
|
||||
|
||||
|
@ -638,6 +658,11 @@ static void _buf_bio_callback(struct bio *bio, int code)
|
|||
if (mbuf_a->bfa_bf != bf) {
|
||||
MARS_ERR("bad pointers %p != %p\n", mbuf_a->bfa_bf, bf);
|
||||
}
|
||||
#if 1
|
||||
if (!(++count % 100)) {
|
||||
MARS_ERR("endless loop 2\n");
|
||||
}
|
||||
#endif
|
||||
buf_count = atomic_read(&mbuf->buf_count);
|
||||
if (buf_count <= 0) {
|
||||
MARS_ERR("bad buf_count %d\n", buf_count);
|
||||
|
@ -648,7 +673,6 @@ static void _buf_bio_callback(struct bio *bio, int code)
|
|||
mbuf->buf_flags = bf->bf_flags;
|
||||
mbuf->cb_error = bf->bf_bio_status;
|
||||
mbuf_a->nr_io_pending--;
|
||||
//traced_unlock(&brick->buf_lock, flags);
|
||||
|
||||
mbuf->cb_buf_endio(mbuf);
|
||||
|
||||
|
@ -657,21 +681,12 @@ static void _buf_bio_callback(struct bio *bio, int code)
|
|||
_buf_buf_put(bf);
|
||||
buf_free_mars_buf(mbuf);
|
||||
}
|
||||
|
||||
//traced_lock(&brick->buf_lock, flags);
|
||||
}
|
||||
|
||||
if (start_len) {
|
||||
MARS_DBG("ATTENTION %d\n", start_len);
|
||||
_buf_make_bios(brick, bf, start_data, start_pos, start_len, WRITE);
|
||||
}
|
||||
#if 0
|
||||
// drop extra refcounts for pending IO
|
||||
if (old_flags & MARS_BUF_READING)
|
||||
_buf_buf_put(bf);
|
||||
if (old_flags & MARS_BUF_WRITING)
|
||||
_buf_buf_put(bf);
|
||||
#endif
|
||||
// drop the extra reference from above
|
||||
_buf_buf_put(bf);
|
||||
}
|
||||
|
@ -764,7 +779,7 @@ static void buf_buf_io(struct buf_output *output, struct mars_buf_object *mbuf,
|
|||
bf->bf_flags |= MARS_BUF_READING;
|
||||
bf->bf_bio_status = 0;
|
||||
|
||||
// always read the whole buffer
|
||||
// always read the whole buffer.
|
||||
start_data = (void*)((unsigned long)mbuf->buf_data & ~(unsigned long)(brick->backing_size - 1));
|
||||
start_pos = mbuf->buf_pos & ~(loff_t)(brick->backing_size - 1);
|
||||
start_len = brick->backing_size;
|
||||
|
@ -775,20 +790,23 @@ static void buf_buf_io(struct buf_output *output, struct mars_buf_object *mbuf,
|
|||
mbuf->buf_flags = bf->bf_flags;
|
||||
mbuf->cb_error = bf->bf_bio_status;
|
||||
|
||||
// grab an extra reference.
|
||||
/* Grab an extra reference.
|
||||
* This will be released later in _buf_bio_callback() after
|
||||
* calling the callbacks.
|
||||
*/
|
||||
atomic_inc(&mbuf->buf_count);
|
||||
|
||||
traced_unlock(&brick->buf_lock, flags);
|
||||
|
||||
if (!start_len) {
|
||||
// nothing to start
|
||||
// nothing to start, IO is already started.
|
||||
return;
|
||||
}
|
||||
|
||||
status = _buf_make_bios(brick, bf, start_data, start_pos, start_len, rw);
|
||||
if (likely(status >= 0)) {
|
||||
/* no callback, this time.
|
||||
* they will be called from _buf_bio_callback().
|
||||
/* No immediate callback, this time.
|
||||
* Callbacks will be called later from _buf_bio_callback().
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,302 @@
|
|||
// (c) 2010 Thomas Schoebel-Theuer / 1&1 Internet AG
|
||||
|
||||
/* Check brick
|
||||
* checks various semantic properties, uses watchdog to find lost callbacks.
|
||||
*/
|
||||
|
||||
//#define BRICK_DEBUGGING
|
||||
//#define MARS_DEBUGGING
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
///////////////////////// own type definitions ////////////////////////
|
||||
|
||||
#include "mars_check.h"
|
||||
|
||||
///////////////////////// own helper functions ////////////////////////
|
||||
|
||||
static int check_mars_endio(struct mars_io_object *mio, int error)
|
||||
{
|
||||
struct check_output *output = mio->cb_private;
|
||||
struct check_mars_io_aspect *mio_a = NULL;
|
||||
int status;
|
||||
unsigned long flags;
|
||||
|
||||
if (!output) {
|
||||
MARS_ERR("bad private on mio %p\n", mio);
|
||||
goto regenerate;
|
||||
}
|
||||
mio_a = check_mars_io_get_aspect(output, mio);
|
||||
|
||||
traced_lock(&output->lock, flags);
|
||||
if (list_empty(&mio_a->mio_head)) {
|
||||
MARS_ERR("mio callback called twice on %p\n", mio);
|
||||
}
|
||||
list_del_init(&mio_a->mio_head);
|
||||
//mio->cb_private = mio_a->old_private;
|
||||
traced_unlock(&output->lock, flags);
|
||||
|
||||
mio_a->last_jiffies = jiffies;
|
||||
regenerate:
|
||||
status = mio_a->old_mars_endio(mio, error);
|
||||
mio->cb_private = output;
|
||||
return status;
|
||||
}
|
||||
|
||||
static void check_buf_endio(struct mars_buf_object *mbuf)
|
||||
{
|
||||
struct check_output *output = mbuf->cb_private;
|
||||
struct check_mars_buf_aspect *mbuf_a = check_mars_buf_get_aspect(output, mbuf);
|
||||
unsigned long flags;
|
||||
|
||||
traced_lock(&output->lock, flags);
|
||||
if (list_empty(&mbuf_a->mbuf_head)) {
|
||||
MARS_ERR("mbuf callback called twice on %p\n", mbuf);
|
||||
}
|
||||
list_del_init(&mbuf_a->mbuf_head);
|
||||
traced_unlock(&output->lock, flags);
|
||||
|
||||
mbuf->cb_private = mbuf_a->old_private;
|
||||
mbuf_a->last_jiffies = jiffies;
|
||||
mbuf_a->old_buf_endio(mbuf);
|
||||
mbuf->cb_private = output;
|
||||
}
|
||||
|
||||
static int check_watchdog(void *data)
|
||||
{
|
||||
struct check_output *output = data;
|
||||
MARS_INF("watchdog has started.\n");
|
||||
while (!kthread_should_stop()) {
|
||||
struct list_head *h;
|
||||
unsigned long flags;
|
||||
unsigned long now;
|
||||
|
||||
msleep_interruptible(5000);
|
||||
|
||||
traced_lock(&output->lock, flags);
|
||||
|
||||
now = jiffies;
|
||||
for (h = output->mio_anchor.next; h != &output->mio_anchor; h = h->next) {
|
||||
struct check_mars_io_aspect *mio_a;
|
||||
struct mars_io_object *mio;
|
||||
unsigned long elapsed;
|
||||
|
||||
mio_a = container_of(h, struct check_mars_io_aspect, mio_head);
|
||||
mio = mio_a->object;
|
||||
elapsed = now - mio_a->last_jiffies;
|
||||
if (elapsed > 10 * HZ) {
|
||||
mio_a->last_jiffies = now;
|
||||
MARS_ERR("instance %d: mio %p callback is missing for more than 10 seconds.\n", output->instance_nr, mio);
|
||||
}
|
||||
}
|
||||
for (h = output->mbuf_anchor.next; h != &output->mbuf_anchor; h = h->next) {
|
||||
struct check_mars_buf_aspect *mbuf_a;
|
||||
struct mars_buf_object *mbuf;
|
||||
unsigned long elapsed;
|
||||
|
||||
mbuf_a = container_of(h, struct check_mars_buf_aspect, mbuf_head);
|
||||
mbuf = mbuf_a->object;
|
||||
elapsed = now - mbuf_a->last_jiffies;
|
||||
if (elapsed > 10 * HZ) {
|
||||
mbuf_a->last_jiffies = now;
|
||||
MARS_ERR("instance %d: mbuf %p callback is missing for more than 10 seconds.\n", output->instance_nr, mbuf);
|
||||
}
|
||||
}
|
||||
traced_unlock(&output->lock, flags);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////// own brick / input / output operations //////////////////
|
||||
|
||||
static int check_io(struct check_output *output, struct mars_io_object *mio)
|
||||
{
|
||||
struct check_input *input = output->brick->inputs[0];
|
||||
int status;
|
||||
#if 0
|
||||
struct check_mars_io_aspect *mio_a = check_mars_io_get_aspect(output, mio);
|
||||
unsigned long flags;
|
||||
|
||||
traced_lock(&output->lock, flags);
|
||||
if (!list_empty(&mio_a->mio_head)) {
|
||||
MARS_ERR("multiple mars_endio() in parallel on %p\n", mio);
|
||||
}
|
||||
list_add_tail(&mio_a->mio_head, &output->mio_anchor);
|
||||
if (mio->mars_endio != check_mars_endio) {
|
||||
mio_a->old_mars_endio = mio->mars_endio;
|
||||
mio->mars_endio = check_mars_endio;
|
||||
}
|
||||
mio_a->old_private = mio->cb_private;
|
||||
mio->cb_private = output;
|
||||
mio_a->last_jiffies = jiffies;
|
||||
traced_unlock(&output->lock, flags);
|
||||
|
||||
#endif
|
||||
status = GENERIC_INPUT_CALL(input, mars_io, mio);
|
||||
#if 0
|
||||
if (status < 0) { // revert. TODO: change semantics to callback _always_
|
||||
traced_lock(&output->lock, flags);
|
||||
list_del_init(&mio_a->mio_head);
|
||||
traced_unlock(&output->lock, flags);
|
||||
}
|
||||
#endif
|
||||
//mio->cb_private = mio_a->old_private;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int check_get_info(struct check_output *output, struct mars_info *info)
|
||||
{
|
||||
struct check_input *input = output->brick->inputs[0];
|
||||
return GENERIC_INPUT_CALL(input, mars_get_info, info);
|
||||
}
|
||||
|
||||
static int check_buf_get(struct check_output *output, struct mars_buf_object *mbuf)
|
||||
{
|
||||
struct check_input *input = output->brick->inputs[0];
|
||||
return GENERIC_INPUT_CALL(input, mars_buf_get, mbuf);
|
||||
}
|
||||
|
||||
static void check_buf_put(struct check_output *output, struct mars_buf_object *mbuf)
|
||||
{
|
||||
struct check_input *input = output->brick->inputs[0];
|
||||
GENERIC_INPUT_CALL(input, mars_buf_put, mbuf);
|
||||
}
|
||||
|
||||
static void check_buf_io(struct check_output *output, struct mars_buf_object *mbuf, int rw)
|
||||
{
|
||||
struct check_input *input = output->brick->inputs[0];
|
||||
struct check_mars_buf_aspect *mbuf_a = check_mars_buf_get_aspect(output, mbuf);
|
||||
unsigned long flags;
|
||||
traced_lock(&output->lock, flags);
|
||||
if (!list_empty(&mbuf_a->mbuf_head)) {
|
||||
MARS_ERR("instance %d: multiple buf_endio() in parallel on %p\n", output->instance_nr, mbuf);
|
||||
}
|
||||
list_add_tail(&mbuf_a->mbuf_head, &output->mbuf_anchor);
|
||||
if (mbuf->cb_buf_endio != check_buf_endio) {
|
||||
mbuf_a->old_buf_endio = mbuf->cb_buf_endio;
|
||||
mbuf->cb_buf_endio = check_buf_endio;
|
||||
mbuf_a->old_private = mbuf->cb_private;
|
||||
mbuf->cb_private = output;
|
||||
}
|
||||
mbuf_a->last_jiffies = jiffies;
|
||||
traced_unlock(&output->lock, flags);
|
||||
GENERIC_INPUT_CALL(input, mars_buf_io, mbuf, rw);
|
||||
}
|
||||
|
||||
//////////////// object / aspect constructors / destructors ///////////////
|
||||
|
||||
static int check_mars_io_aspect_init_fn(struct generic_aspect *_ini, void *_init_data)
|
||||
{
|
||||
struct check_mars_io_aspect *ini = (void*)_ini;
|
||||
INIT_LIST_HEAD(&ini->mio_head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_mars_buf_aspect_init_fn(struct generic_aspect *_ini, void *_init_data)
|
||||
{
|
||||
struct check_mars_buf_aspect *ini = (void*)_ini;
|
||||
INIT_LIST_HEAD(&ini->mbuf_head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MARS_MAKE_STATICS(check);
|
||||
|
||||
////////////////////// brick constructors / destructors ////////////////////
|
||||
|
||||
static int check_brick_construct(struct check_brick *brick)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_output_construct(struct check_output *output)
|
||||
{
|
||||
static int count = 0;
|
||||
struct task_struct *watchdog;
|
||||
spin_lock_init(&output->lock);
|
||||
INIT_LIST_HEAD(&output->mio_anchor);
|
||||
INIT_LIST_HEAD(&output->mbuf_anchor);
|
||||
output->instance_nr = ++count;
|
||||
watchdog = kthread_create(check_watchdog, output, "check_watchdog%d", output->instance_nr);
|
||||
if (!IS_ERR(watchdog)) {
|
||||
output->watchdog = watchdog;
|
||||
wake_up_process(watchdog);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////// static structs ////////////////////////
|
||||
|
||||
static struct check_brick_ops check_brick_ops = {
|
||||
};
|
||||
|
||||
static struct check_output_ops check_output_ops = {
|
||||
.make_object_layout = check_make_object_layout,
|
||||
.mars_io = check_io,
|
||||
.mars_get_info = check_get_info,
|
||||
.mars_buf_get = check_buf_get,
|
||||
.mars_buf_put = check_buf_put,
|
||||
.mars_buf_io = check_buf_io,
|
||||
};
|
||||
|
||||
static const struct check_input_type check_input_type = {
|
||||
.type_name = "check_input",
|
||||
.input_size = sizeof(struct check_input),
|
||||
};
|
||||
|
||||
static const struct check_input_type *check_input_types[] = {
|
||||
&check_input_type,
|
||||
};
|
||||
|
||||
static const struct check_output_type check_output_type = {
|
||||
.type_name = "check_output",
|
||||
.output_size = sizeof(struct check_output),
|
||||
.master_ops = &check_output_ops,
|
||||
.output_construct = &check_output_construct,
|
||||
.aspect_types = check_aspect_types,
|
||||
.layout_code = {
|
||||
[BRICK_OBJ_MARS_IO] = LAYOUT_ALL,
|
||||
[BRICK_OBJ_MARS_BUF] = LAYOUT_ALL,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct check_output_type *check_output_types[] = {
|
||||
&check_output_type,
|
||||
};
|
||||
|
||||
const struct check_brick_type check_brick_type = {
|
||||
.type_name = "check_brick",
|
||||
.brick_size = sizeof(struct check_brick),
|
||||
.max_inputs = 1,
|
||||
.max_outputs = 1,
|
||||
.master_ops = &check_brick_ops,
|
||||
.default_input_types = check_input_types,
|
||||
.default_output_types = check_output_types,
|
||||
.brick_construct = &check_brick_construct,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(check_brick_type);
|
||||
|
||||
////////////////// module init stuff /////////////////////////
|
||||
|
||||
static int __init init_check(void)
|
||||
{
|
||||
printk(MARS_INFO "init_check()\n");
|
||||
return check_register_brick_type();
|
||||
}
|
||||
|
||||
static void __exit exit_check(void)
|
||||
{
|
||||
printk(MARS_INFO "exit_check()\n");
|
||||
check_unregister_brick_type();
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("MARS check brick");
|
||||
MODULE_AUTHOR("Thomas Schoebel-Theuer <tst@1und1.de>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(init_check);
|
||||
module_exit(exit_check);
|
|
@ -0,0 +1,40 @@
|
|||
// (c) 2010 Thomas Schoebel-Theuer / 1&1 Internet AG
|
||||
#ifndef MARS_CHECK_H
|
||||
#define MARS_CHECK_H
|
||||
|
||||
struct check_mars_io_aspect {
|
||||
GENERIC_ASPECT(mars_io);
|
||||
struct list_head mio_head;
|
||||
int (*old_mars_endio)(struct mars_io_object *mio, int error);
|
||||
void *old_private;
|
||||
unsigned long last_jiffies;
|
||||
};
|
||||
|
||||
struct check_mars_buf_aspect {
|
||||
GENERIC_ASPECT(mars_buf);
|
||||
struct list_head mbuf_head;
|
||||
void (*old_buf_endio)(struct mars_buf_object *mbuf);
|
||||
void *old_private;
|
||||
unsigned long last_jiffies;
|
||||
};
|
||||
|
||||
struct check_brick {
|
||||
MARS_BRICK(check);
|
||||
};
|
||||
|
||||
struct check_input {
|
||||
MARS_INPUT(check);
|
||||
};
|
||||
|
||||
struct check_output {
|
||||
MARS_OUTPUT(check);
|
||||
spinlock_t lock;
|
||||
int instance_nr;
|
||||
struct task_struct *watchdog;
|
||||
struct list_head mio_anchor;
|
||||
struct list_head mbuf_anchor;
|
||||
};
|
||||
|
||||
MARS_TYPES(check);
|
||||
|
||||
#endif
|
|
@ -265,17 +265,10 @@ static int device_sio_mars_io(struct device_sio_output *output, struct mars_io_o
|
|||
}
|
||||
|
||||
done:
|
||||
if (!ret) {
|
||||
bio->bi_size = 0;
|
||||
if (direction == WRITE && barrier) {
|
||||
sync_file(output);
|
||||
}
|
||||
}
|
||||
mio->mars_endio(mio, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WITH_THREAD
|
||||
static int device_sio_mars_queue(struct device_sio_output *output, struct mars_io_object *mio)
|
||||
{
|
||||
int index = 0;
|
||||
|
@ -311,23 +304,30 @@ static int device_sio_thread(void *data)
|
|||
//set_user_nice(current, -20);
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
struct list_head *tmp;
|
||||
struct list_head *tmp = NULL;
|
||||
struct device_sio_mars_io_aspect *aspect;
|
||||
struct mars_io_object *mio;
|
||||
unsigned long flags;
|
||||
|
||||
wait_event_interruptible(tinfo->event,
|
||||
!list_empty(&tinfo->mio_list) ||
|
||||
kthread_should_stop());
|
||||
wait_event_interruptible_timeout(
|
||||
tinfo->event,
|
||||
!list_empty(&tinfo->mio_list) || kthread_should_stop(),
|
||||
HZ);
|
||||
|
||||
if (list_empty(&tinfo->mio_list))
|
||||
continue;
|
||||
tinfo->last_jiffies = jiffies;
|
||||
|
||||
traced_lock(&tinfo->lock, flags);
|
||||
tmp = tinfo->mio_list.next;
|
||||
list_del_init(tmp);
|
||||
|
||||
if (!list_empty(&tinfo->mio_list)) {
|
||||
tmp = tinfo->mio_list.next;
|
||||
list_del_init(tmp);
|
||||
}
|
||||
|
||||
traced_unlock(&tinfo->lock, flags);
|
||||
|
||||
if (!tmp)
|
||||
continue;
|
||||
|
||||
aspect = container_of(tmp, struct device_sio_mars_io_aspect, io_head);
|
||||
mio = aspect->object;
|
||||
MARS_DBG("got %p %p\n", aspect, mio);
|
||||
|
@ -337,7 +337,28 @@ static int device_sio_thread(void *data)
|
|||
MARS_INF("kthread has stopped.\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int device_sio_watchdog(void *data)
|
||||
{
|
||||
struct device_sio_output *output = data;
|
||||
MARS_INF("watchdog has started.\n");
|
||||
while (!kthread_should_stop()) {
|
||||
int i;
|
||||
|
||||
msleep_interruptible(5000);
|
||||
|
||||
for (i = 0; i <= WITH_THREAD; i++) {
|
||||
struct sio_threadinfo *tinfo = &output->tinfo[i];
|
||||
unsigned long now = jiffies;
|
||||
unsigned long elapsed = now - tinfo->last_jiffies;
|
||||
if (elapsed > 10 * HZ) {
|
||||
tinfo->last_jiffies = now;
|
||||
MARS_ERR("thread %d is dead for more than 10 seconds.\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int device_sio_get_info(struct device_sio_output *output, struct mars_info *info)
|
||||
{
|
||||
|
@ -365,22 +386,6 @@ static int device_sio_mars_buf_aspect_init_fn(struct generic_aspect *_ini, void
|
|||
|
||||
MARS_MAKE_STATICS(device_sio);
|
||||
|
||||
#if 0
|
||||
static int device_sio_make_object_layout(struct device_sio_output *output, struct generic_object_layout *object_layout)
|
||||
{
|
||||
const struct generic_object_type *object_type = object_layout->object_type;
|
||||
int slot;
|
||||
if (object_type != &mars_io_type)
|
||||
return 0;
|
||||
|
||||
slot = device_sio_mars_io_add_aspect(output, object_layout, &device_sio_mars_io_aspect_type);
|
||||
if (slot < 0)
|
||||
return slot;
|
||||
|
||||
return sizeof(struct device_sio_mars_io_aspect);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////// brick constructors / destructors ////////////////////
|
||||
|
||||
static int device_sio_brick_construct(struct device_sio_brick *brick)
|
||||
|
@ -394,6 +399,7 @@ static int device_sio_output_construct(struct device_sio_output *output)
|
|||
int flags = O_CREAT | O_RDWR | O_LARGEFILE;
|
||||
int prot = 0600;
|
||||
char *path = "/tmp/testfile.img";
|
||||
struct task_struct *watchdog;
|
||||
int index;
|
||||
|
||||
oldfs = get_fs();
|
||||
|
@ -416,7 +422,6 @@ static int device_sio_output_construct(struct device_sio_output *output)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_THREAD
|
||||
spin_lock_init(&output->g_lock);
|
||||
output->index = 0;
|
||||
for (index = 0; index <= WITH_THREAD; index++) {
|
||||
|
@ -425,6 +430,7 @@ static int device_sio_output_construct(struct device_sio_output *output)
|
|||
spin_lock_init(&tinfo->lock);
|
||||
init_waitqueue_head(&tinfo->event);
|
||||
INIT_LIST_HEAD(&tinfo->mio_list);
|
||||
tinfo->last_jiffies = jiffies;
|
||||
tinfo->thread = kthread_create(device_sio_thread, tinfo, "mars_sio%d", index);
|
||||
if (IS_ERR(tinfo->thread)) {
|
||||
int error = PTR_ERR(tinfo->thread);
|
||||
|
@ -434,20 +440,22 @@ static int device_sio_output_construct(struct device_sio_output *output)
|
|||
}
|
||||
wake_up_process(tinfo->thread);
|
||||
}
|
||||
#endif
|
||||
|
||||
watchdog = kthread_create(device_sio_watchdog, output, "mars_watchdog%d", 0);
|
||||
if (!IS_ERR(watchdog)) {
|
||||
wake_up_process(watchdog);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int device_sio_output_destruct(struct device_sio_output *output)
|
||||
{
|
||||
#ifdef WITH_THREAD
|
||||
int index;
|
||||
for (index = 0; index <= WITH_THREAD; index++) {
|
||||
kthread_stop(output->tinfo[index].thread);
|
||||
output->tinfo[index].thread = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (output->filp) {
|
||||
filp_close(output->filp, NULL);
|
||||
output->filp = NULL;
|
||||
|
@ -463,11 +471,7 @@ static struct device_sio_brick_ops device_sio_brick_ops = {
|
|||
|
||||
static struct device_sio_output_ops device_sio_output_ops = {
|
||||
.make_object_layout = device_sio_make_object_layout,
|
||||
#ifdef WITH_THREAD
|
||||
.mars_io = device_sio_mars_queue,
|
||||
#else
|
||||
.mars_io = device_sio_mars_io,
|
||||
#endif
|
||||
.mars_get_info = device_sio_get_info,
|
||||
};
|
||||
|
||||
|
|
|
@ -21,24 +21,21 @@ struct device_sio_input {
|
|||
MARS_INPUT(device_sio);
|
||||
};
|
||||
|
||||
#ifdef WITH_THREAD
|
||||
struct sio_threadinfo {
|
||||
struct device_sio_output *output;
|
||||
struct list_head mio_list;
|
||||
struct task_struct *thread;
|
||||
wait_queue_head_t event;
|
||||
spinlock_t lock;
|
||||
unsigned long last_jiffies;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct device_sio_output {
|
||||
MARS_OUTPUT(device_sio);
|
||||
struct file *filp;
|
||||
#ifdef WITH_THREAD
|
||||
struct sio_threadinfo tinfo[WITH_THREAD+1];
|
||||
spinlock_t g_lock;
|
||||
int index;
|
||||
#endif
|
||||
};
|
||||
|
||||
MARS_TYPES(device_sio);
|
||||
|
|
54
mars_test.c
54
mars_test.c
|
@ -15,22 +15,24 @@
|
|||
#include "mars.h"
|
||||
|
||||
#include "mars_if_device.h"
|
||||
#include "mars_dummy.h"
|
||||
#include "mars_check.h"
|
||||
#include "mars_device_sio.h"
|
||||
#include "mars_buf.h"
|
||||
#include "mars_usebuf.h"
|
||||
|
||||
GENERIC_MAKE_CONNECT(if_device, device_sio);
|
||||
GENERIC_MAKE_CONNECT(if_device, buf);
|
||||
GENERIC_MAKE_CONNECT(if_device, dummy);
|
||||
GENERIC_MAKE_CONNECT(if_device, check);
|
||||
GENERIC_MAKE_CONNECT(if_device, usebuf);
|
||||
GENERIC_MAKE_CONNECT(usebuf, dummy);
|
||||
GENERIC_MAKE_CONNECT(check, usebuf);
|
||||
GENERIC_MAKE_CONNECT(usebuf, check);
|
||||
GENERIC_MAKE_CONNECT(buf, device_sio);
|
||||
GENERIC_MAKE_CONNECT(dummy, buf);
|
||||
GENERIC_MAKE_CONNECT(check, buf);
|
||||
|
||||
static struct if_device_brick *if_brick = NULL;
|
||||
static struct usebuf_brick *usebuf_brick = NULL;
|
||||
static struct dummy_brick *dummy_brick = NULL;
|
||||
static struct check_brick *check_brick = NULL;
|
||||
static struct check_brick *check_brick0 = NULL;
|
||||
static struct buf_brick *buf_brick = NULL;
|
||||
static struct device_sio_brick *device_brick = NULL;
|
||||
|
||||
|
@ -47,14 +49,13 @@ void make_test_instance(void)
|
|||
int status;
|
||||
void *mem;
|
||||
|
||||
MARS_DBG("starting....\n");
|
||||
|
||||
mem = kzalloc(size, GFP_KERNEL);
|
||||
if (!mem) {
|
||||
MARS_ERR("cannot grab test memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
MARS_DBG("starting....\n");
|
||||
|
||||
status = device_sio_brick_init_full(mem, size, &device_sio_brick_type, NULL, NULL, names);
|
||||
MARS_DBG("done (status=%d)\n", status);
|
||||
if (status) {
|
||||
|
@ -68,7 +69,6 @@ void make_test_instance(void)
|
|||
MARS_ERR("cannot grab test memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = if_device_brick_init_full(mem, size, &if_device_brick_type, NULL, NULL, names);
|
||||
MARS_DBG("done (status=%d)\n", status);
|
||||
if (status) {
|
||||
|
@ -82,14 +82,13 @@ void make_test_instance(void)
|
|||
MARS_ERR("cannot grab test memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = dummy_brick_init_full(mem, size, &dummy_brick_type, NULL, NULL, names);
|
||||
status = check_brick_init_full(mem, size, &check_brick_type, NULL, NULL, names);
|
||||
MARS_DBG("done (status=%d)\n", status);
|
||||
if (status) {
|
||||
MARS_ERR("cannot init brick dummy\n");
|
||||
MARS_ERR("cannot init brick check\n");
|
||||
return;
|
||||
}
|
||||
dummy_brick = mem;
|
||||
check_brick = mem;
|
||||
|
||||
#if 1 // usebuf zwischenschalten
|
||||
mem = kzalloc(size, GFP_KERNEL);
|
||||
|
@ -97,7 +96,6 @@ void make_test_instance(void)
|
|||
MARS_ERR("cannot grab test memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = usebuf_brick_init_full(mem, size, &usebuf_brick_type, NULL, NULL, names);
|
||||
MARS_DBG("done (status=%d)\n", status);
|
||||
if (status) {
|
||||
|
@ -106,13 +104,29 @@ void make_test_instance(void)
|
|||
}
|
||||
usebuf_brick = mem;
|
||||
|
||||
status = if_device_usebuf_connect(if_brick->inputs[0], usebuf_brick->outputs[0]);
|
||||
mem = kzalloc(size, GFP_KERNEL);
|
||||
if (!mem) {
|
||||
MARS_ERR("cannot grab test memory\n");
|
||||
return;
|
||||
}
|
||||
status = check_brick_init_full(mem, size, &check_brick_type, NULL, NULL, names);
|
||||
MARS_DBG("done (status=%d)\n", status);
|
||||
if (status) {
|
||||
MARS_ERR("cannot init brick check\n");
|
||||
return;
|
||||
}
|
||||
check_brick0 = mem;
|
||||
|
||||
status = if_device_check_connect(if_brick->inputs[0], check_brick0->outputs[0]);
|
||||
MARS_DBG("connect (status=%d)\n", status);
|
||||
status = usebuf_dummy_connect(usebuf_brick->inputs[0], dummy_brick->outputs[0]);
|
||||
|
||||
status = check_usebuf_connect(check_brick0->inputs[0], usebuf_brick->outputs[0]);
|
||||
MARS_DBG("connect (status=%d)\n", status);
|
||||
status = usebuf_check_connect(usebuf_brick->inputs[0], check_brick->outputs[0]);
|
||||
MARS_DBG("connect (status=%d)\n", status);
|
||||
#else
|
||||
(void)usebuf_brick;
|
||||
status = if_device_dummy_connect(if_brick->inputs[0], dummy_brick->outputs[0]);
|
||||
status = if_device_check_connect(if_brick->inputs[0], check_brick->outputs[0]);
|
||||
MARS_DBG("connect (status=%d)\n", status);
|
||||
#endif
|
||||
|
||||
|
@ -130,14 +144,14 @@ void make_test_instance(void)
|
|||
return;
|
||||
}
|
||||
buf_brick = mem;
|
||||
buf_brick->backing_order = 0;
|
||||
buf_brick->backing_order = 4;
|
||||
buf_brick->backing_size = PAGE_SIZE << buf_brick->backing_order;
|
||||
buf_brick->max_count = 512;
|
||||
|
||||
status = buf_device_sio_connect(buf_brick->inputs[0], device_brick->outputs[0]);
|
||||
MARS_DBG("connect (status=%d)\n", status);
|
||||
|
||||
status = dummy_buf_connect(dummy_brick->inputs[0], buf_brick->outputs[0]);
|
||||
status = check_buf_connect(check_brick->inputs[0], buf_brick->outputs[0]);
|
||||
MARS_DBG("connect (status=%d)\n", status);
|
||||
|
||||
if (true) {
|
||||
|
@ -166,7 +180,7 @@ void make_test_instance(void)
|
|||
}
|
||||
#else
|
||||
|
||||
status = dummy_device_sio_connect(dummy_brick->inputs[0], device_brick->outputs[0]);
|
||||
status = check_device_sio_connect(check_brick->inputs[0], device_brick->outputs[0]);
|
||||
MARS_DBG("connect (status=%d)\n", status);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -29,14 +29,12 @@ static void _usebuf_copy(struct usebuf_mars_buf_aspect *mbuf_a, int rw)
|
|||
void *bio_data = bio_base + mbuf_a->bvec_offset;
|
||||
int len = mbuf_a->bvec_len;
|
||||
|
||||
#if 1
|
||||
if (rw == READ) {
|
||||
memcpy(bio_data, buf_data, len);
|
||||
//memset(bio_data, 0, len);
|
||||
} else {
|
||||
memcpy(buf_data, bio_data, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
kunmap_atomic(bio_base, KM_USER0);
|
||||
}
|
||||
|
||||
|
@ -47,7 +45,7 @@ static int _usebuf_mio_endio(struct usebuf_output *output, struct mars_io_object
|
|||
|
||||
mio_a = usebuf_mars_io_get_aspect(output, mio);
|
||||
if (unlikely(!mio_a)) {
|
||||
MARS_ERR("cannot get mio_a\n");
|
||||
MARS_FAT("cannot get mio_a from mio %p\n", mio);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -89,17 +87,17 @@ static void _usebuf_mbuf_endio(struct mars_buf_object *mbuf)
|
|||
output = mbuf->cb_private;
|
||||
if (unlikely(!output)) {
|
||||
MARS_ERR("bad argument output\n");
|
||||
goto out_err2;
|
||||
goto out_err;
|
||||
}
|
||||
mbuf_a = usebuf_mars_buf_get_aspect(output, mbuf);
|
||||
if (unlikely(!mbuf_a)) {
|
||||
MARS_ERR("cannot get aspect\n");
|
||||
goto out_err2;
|
||||
goto out_err;
|
||||
}
|
||||
mio = mbuf_a->mio;
|
||||
if (unlikely(!mio)) {
|
||||
MARS_ERR("cannot get mio\n");
|
||||
goto out_err1;
|
||||
goto out_err;
|
||||
}
|
||||
MARS_DBG("mio=%p\n", mio);
|
||||
mio_a = usebuf_mars_io_get_aspect(output, mio);
|
||||
|
@ -158,8 +156,7 @@ out_nocheck:
|
|||
if (!status)
|
||||
status = ignore;
|
||||
|
||||
out_err1:
|
||||
out_err2:
|
||||
out_err:
|
||||
mbuf->cb_error = status;
|
||||
}
|
||||
|
||||
|
@ -294,9 +291,7 @@ static int usebuf_io(struct usebuf_output *output, struct mars_io_object *mio)
|
|||
|
||||
done_drop:
|
||||
// drop initial refcount
|
||||
if (!status) {
|
||||
(void)_usebuf_mio_endio(output, mio, 0);
|
||||
}
|
||||
(void)_usebuf_mio_endio(output, mio, status);
|
||||
|
||||
done:
|
||||
MARS_DBG("status=%d\n", status);
|
||||
|
|
Loading…
Reference in New Issue