import mars-82.tgz

This commit is contained in:
Thomas Schoebel-Theuer 2011-03-23 18:58:02 +01:00
parent ee9a1d47ff
commit 9b1410c0ef
12 changed files with 337 additions and 240 deletions

155
brick.c
View File

@ -94,52 +94,62 @@ int generic_brick_init_full(
BRICK_DBG("generic_brick_init_full: switch to default input_types\n");
input_types = brick_type->default_input_types;
names = brick_type->default_input_names;
if (unlikely(!input_types)) {
BRICK_ERR("no input types specified\n");
return -EINVAL;
}
}
if (input_types) {
BRICK_DBG("generic_brick_init_full: input_types\n");
brick->inputs = data;
data += sizeof(void*) * brick_type->max_inputs;
size -= sizeof(void*) * brick_type->max_inputs;
if (size < 0) {
BRICK_DBG("generic_brick_init_full: input_types\n");
brick->inputs = data;
data += sizeof(void*) * brick_type->max_inputs;
size -= sizeof(void*) * brick_type->max_inputs;
if (size < 0) {
return -ENOMEM;
}
for (i = 0; i < brick_type->max_inputs; i++) {
struct generic_input *input = data;
const struct generic_input_type *type = *input_types++;
if (!type || type->input_size <= 0) {
return -EINVAL;
}
BRICK_DBG("generic_brick_init_full: calling generic_input_init()\n");
status = generic_input_init(brick, i, type, input, (names && *names) ? *names++ : type->type_name);
if (status < 0)
return status;
data += type->input_size;
size -= type->input_size;
if (size < 0)
return -ENOMEM;
}
for (i = 0; i < brick_type->max_inputs; i++) {
struct generic_input *input = data;
const struct generic_input_type *type = *input_types++;
BRICK_DBG("generic_brick_init_full: calling generic_input_init()\n");
status = generic_input_init(brick, i, type, input, (names && *names) ? *names++ : type->type_name);
if (status)
return status;
data += type->input_size;
size -= type->input_size;
if (size < 0)
return -ENOMEM;
}
}
if (!output_types) {
BRICK_DBG("generic_brick_init_full: switch to default output_types\n");
output_types = brick_type->default_output_types;
names = brick_type->default_output_names;
if (unlikely(!output_types)) {
BRICK_ERR("no output types specified\n");
return -EINVAL;
}
}
if (output_types) {
BRICK_DBG("generic_brick_init_full: output_types\n");
brick->outputs = data;
data += sizeof(void*) * brick_type->max_outputs;
size -= sizeof(void*) * brick_type->max_outputs;
BRICK_DBG("generic_brick_init_full: output_types\n");
brick->outputs = data;
data += sizeof(void*) * brick_type->max_outputs;
size -= sizeof(void*) * brick_type->max_outputs;
if (size < 0)
return -ENOMEM;
for (i = 0; i < brick_type->max_outputs; i++) {
struct generic_output *output = data;
const struct generic_output_type *type = *output_types++;
if (!type || type->output_size <= 0) {
return -EINVAL;
}
BRICK_DBG("generic_brick_init_full: calling generic_output_init()\n");
generic_output_init(brick, i, type, output, (names && *names) ? *names++ : type->type_name);
if (status < 0)
return status;
data += type->output_size;
size -= type->output_size;
if (size < 0)
return -ENOMEM;
for (i = 0; i < brick_type->max_outputs; i++) {
struct generic_output *output = data;
const struct generic_output_type *type = *output_types++;
BRICK_DBG("generic_brick_init_full: calling generic_output_init()\n");
generic_output_init(brick, i, type, output, (names && *names) ? *names++ : type->type_name);
if (status)
return status;
data += type->output_size;
size -= type->output_size;
if (size < 0)
return -ENOMEM;
}
}
// call the specific constructors
@ -147,7 +157,7 @@ int generic_brick_init_full(
if (brick_type->brick_construct) {
BRICK_DBG("generic_brick_init_full: calling brick_construct()\n");
status = brick_type->brick_construct(brick);
if (status)
if (status < 0)
return status;
}
for (i = 0; i < brick_type->max_inputs; i++) {
@ -161,7 +171,7 @@ int generic_brick_init_full(
if (input->type->input_construct) {
BRICK_DBG("generic_brick_init_full: calling input_construct()\n");
status = input->type->input_construct(input);
if (status)
if (status < 0)
return status;
}
}
@ -176,7 +186,7 @@ int generic_brick_init_full(
if (output->type->output_construct) {
BRICK_DBG("generic_brick_init_full: calling output_construct()\n");
status = output->type->output_construct(output);
if (status)
if (status < 0)
return status;
}
}
@ -189,7 +199,7 @@ int generic_brick_exit_full(struct generic_brick *brick)
int i;
int status;
// first, check all outputs
for (i = 0; i < brick->nr_outputs; i++) {
for (i = 0; i < brick->type->max_outputs; i++) {
struct generic_output *output = brick->outputs[i];
if (!output)
continue;
@ -260,13 +270,13 @@ int generic_brick_exit_recursively(struct generic_brick *brick, bool destroy_inp
int postpone = 0;
brick = container_of(tmp.next, struct generic_brick, tmp_head);
list_del_init(&brick->tmp_head);
for (i = 0; i < brick->nr_outputs; i++) {
for (i = 0; i < brick->type->max_outputs; i++) {
struct generic_output *output = brick->outputs[i];
if (output && output->nr_connected) {
postpone += output->nr_connected;
}
}
for (i = 0; i < brick->nr_inputs; i++) {
for (i = 0; i < brick->type->max_inputs; i++) {
struct generic_input *input = brick->inputs[i];
if (input && input->connect) {
struct generic_brick *other = input->connect->brick;
@ -301,7 +311,14 @@ int generic_add_aspect(struct generic_output *output, struct generic_object_layo
return -EINVAL;
}
#if 0
nr = object_layout->object_type->brick_obj_nr;
if (nr < 0 || nr >= BRICK_OBJ_NR) {
return -EINVAL;
}
#else
nr = 0;
#endif
aspect_layout = (void*)&output->output_aspect_layouts[nr];
if (aspect_layout->aspect_type && aspect_layout->aspect_layout_generation == object_layout->object_layout_generation) {
/* aspect_layout is already initialized.
@ -682,24 +699,26 @@ int set_recursive_button(struct generic_brick *orig_brick, brick_switch_t mode,
int stack;
bool val = (mode == BR_ON_ONE || mode == BR_ON_ALL);
bool force = (mode != BR_OFF_ONE && mode != BR_OFF_ALL);
int oldstack = 0;
int pos;
int status;
#define PUSH_STACK(next) \
{ \
int j; \
bool found = false; \
/* eliminate duplicates */ \
for (j = 0; j < stack; j++) { \
if (table[j] == next) { \
BRICK_DBG(" double entry %d '%s' stack = %d\n", i, next->brick_name, stack); \
if (table[j] == (next)) { \
BRICK_DBG(" double entry %d '%s' stack = %d\n", i, (next)->brick_name, stack); \
found = true; \
break; \
} \
} \
if (!found) { \
BRICK_DBG(" push %d '%s' stack = %d\n", i, next->brick_name, stack); \
table[stack++] = next; \
BRICK_DBG(" push '%s' stack = %d\n", (next)->brick_name, stack); \
table[stack++] = (next); \
if (unlikely(stack > max)) { \
BRICK_ERR("---- max = %d overflow, restarting...\n", max); \
goto restart; \
} \
} \
@ -719,15 +738,10 @@ int set_recursive_button(struct generic_brick *orig_brick, brick_switch_t mode,
table[stack++] = orig_brick;
status = -EAGAIN;
while (stack > oldstack) {
int i;
struct generic_brick *brick;
for (pos = 0; pos < stack; pos++) {
struct generic_brick *brick = table[pos];
oldstack = stack;
brick = table[stack - 1];
BRICK_DBG("--> brick = '%s' inputs = %d stack = %d\n", brick->brick_name, brick->nr_inputs, stack);
msleep(1000);
BRICK_DBG("--> pos = %d stack = %d brick = '%s' inputs = %d/%d outputs = %d/%d\n", pos, stack, brick->brick_name, brick->nr_inputs, brick->type->max_inputs, brick->nr_outputs, brick->type->max_outputs);
if (val) {
force = false;
@ -736,10 +750,13 @@ int set_recursive_button(struct generic_brick *orig_brick, brick_switch_t mode,
goto done;
}
if (mode >= BR_ON_ALL) {
for (i = 0; i < brick->nr_inputs; i++) {
int i;
for (i = 0; i < brick->type->max_inputs; i++) {
struct generic_input *input = brick->inputs[i];
struct generic_output *output;
struct generic_brick *next;
BRICK_DBG("---> i = %d\n", i);
msleep(1000);
if (!input)
continue;
output = input->connect;
@ -753,22 +770,32 @@ int set_recursive_button(struct generic_brick *orig_brick, brick_switch_t mode,
}
}
} else if (mode >= BR_ON_ALL) {
for (i = 0; i < brick->nr_outputs; i++) {
int i;
for (i = 0; i < brick->type->max_outputs; i++) {
struct generic_output *output = brick->outputs[i];
struct list_head *tmp;
struct generic_input *input;
struct generic_brick *next;
BRICK_DBG("---> i = %d output = %p\n", i, output);
msleep(1000);
if (!output)
continue;
for (tmp = output->output_head.next; tmp && tmp != &output->output_head; tmp = tmp->next) {
input = container_of(tmp, struct generic_input, input_head);
next = input->brick;
struct generic_input *input = container_of(tmp, struct generic_input, input_head);
struct generic_brick *next = input->brick;
BRICK_DBG("----> tmp = %p input = %p next = %p\n", tmp, input, next);
msleep(1000);
if (unlikely(!next)) {
BRICK_ERR("oops, bad brick pointer\n");
status = -EINVAL;
goto done;
}
PUSH_STACK(next);
}
}
}
}
BRICK_DBG("-> stack = %d\n", stack);
while (stack > 0) {
struct generic_brick *brick = table[--stack];
BRICK_DBG("--> switch '%s' stack = %d\n", brick->brick_name, stack);
@ -779,7 +806,9 @@ int set_recursive_button(struct generic_brick *orig_brick, brick_switch_t mode,
}
if (force && !val && (mode == BR_FREE_ONE || mode == BR_FREE_ALL) && brick->free) {
BRICK_DBG("---> freeing '%s'\n", brick->brick_name);
status = brick->free(brick);
BRICK_DBG("---> freeing '%s' status = %d\n", brick->brick_name, status);
if (status < 0) {
BRICK_DBG("freeing brick '%s' (%s) failed, status = %d\n", brick->brick_name, orig_brick->brick_name, status);
goto done;
@ -789,10 +818,10 @@ int set_recursive_button(struct generic_brick *orig_brick, brick_switch_t mode,
}
status = 0;
done:
done:
BRICK_DBG("-> done '%s' status = %d\n", orig_brick->brick_name, status);
if (table)
kfree(table);
BRICK_DBG("-> done '%s' status = %d\n", orig_brick->brick_name, status);
return status;
}
EXPORT_SYMBOL_GPL(set_recursive_button);

11
brick.h
View File

@ -183,7 +183,7 @@ struct generic_input {
struct BRICK##_output_ops *ops; \
struct list_head output_head; \
int nr_connected; \
/* _must_ be the last member */ \
/* _must_ be the last member (may expand to open array) */ \
struct generic_aspect_layout output_aspect_layouts[BRICK_OBJ_MAX]; \
struct generic_output {
@ -365,16 +365,19 @@ inline int generic_connect(struct generic_input *input, struct generic_output *o
return -EINVAL;
if (unlikely(input->connect))
return -EEXIST;
if (unlikely(!list_empty(&input->input_head)))
return -EINVAL;
// helps only against the most common errors
if (unlikely(input->brick == output->brick))
return -EDEADLK;
input->connect = output;
output->nr_connected++;
list_add(&input->input_head, &output->output_head);
BRICK_DBG("now nr_connected=%d\n", output->nr_connected);
/* no atomic_t necessary (_any_ change is sufficient)
*/
brick_layout_generation++;
list_add(&input->input_head, &output->output_head);
BRICK_DBG("now nr_connected=%d\n", output->nr_connected);
return 0;
}
@ -384,8 +387,8 @@ inline int generic_disconnect(struct generic_input *input)
if (!input)
return -EINVAL;
if (input->connect) {
BRICK_DBG("now nr_connected=%d\n", input->connect->nr_connected);
input->connect->nr_connected--;
BRICK_DBG("now nr_connected=%d\n", input->connect->nr_connected);
input->connect = NULL;
list_del_init(&input->input_head);
//brick_layout_generation++;

View File

@ -243,12 +243,6 @@ bool log_finalize(struct log_status *logst, int len, void (*endio)(void *private
ok = true;
#if 0
if (logst->restlen < PAGE_SIZE + OVERHEAD) {
log_flush(logst);
}
#endif
err:
return ok;
}

14
mars.h
View File

@ -10,7 +10,11 @@
/////////////////////////////////////////////////////////////////////////
// include the brick infrastucture
// include the generic brick infrastucture
#ifdef BRICK_H
#error "brick.h must not be already included - please reorganize your includes"
#endif
#define BRICK_OBJ_MREF 0
#define BRICK_OBJ_MAX 1
@ -22,7 +26,7 @@
/////////////////////////////////////////////////////////////////////////
// MARS-specific debugging helper
// MARS-specific debugging helpers
#define MARS_DELAY /**/
//#define MARS_DELAY msleep(20000)
@ -277,11 +281,11 @@ extern struct mars_global *mars_global;
extern void _mars_trigger(void);
#define mars_trigger() do { MARS_INF("trigger...\n"); _mars_trigger(); } while (0)
extern int mars_power_button(struct mars_brick *brick, bool val);
extern int mars_power_button(struct mars_brick *brick, bool val, bool force_off);
extern void mars_power_led_on(struct mars_brick *brick, bool val);
extern void mars_power_led_off(struct mars_brick *brick, bool val);
extern int mars_power_button_recursive(struct mars_brick *brick, bool val, int timeout);
extern int mars_power_button_recursive(struct mars_brick *brick, bool val, bool force_off, int timeout);
/////////////////////////////////////////////////////////////////////////
@ -335,7 +339,7 @@ struct mars_global {
//void *private;
};
typedef int (*mars_dent_checker)(const char *path, const char *name, int namlen, unsigned int d_type, int *prefix, int *serial);
typedef int (*mars_dent_checker)(struct mars_dent *parent, const char *name, int namlen, unsigned int d_type, int *prefix, int *serial);
typedef int (*mars_dent_worker)(struct mars_global *global, struct mars_dent *dent, bool direction);
extern int mars_dent_work(struct mars_global *global, char *dirname, int allocsize, mars_dent_checker checker, mars_dent_worker worker, void *buf, int maxdepth);

View File

@ -628,7 +628,7 @@ static int aio_output_construct(struct aio_output *output)
static int aio_output_destruct(struct aio_output *output)
{
return mars_power_button((void*)output->brick, false);
return 0;
}
///////////////////////// static structs ////////////////////////
@ -645,6 +645,15 @@ static struct aio_output_ops aio_output_ops = {
.mars_get_info = aio_get_info,
};
const struct aio_input_type aio_input_type = {
.type_name = "aio_input",
.input_size = sizeof(struct aio_input),
};
static const struct aio_input_type *aio_input_types[] = {
&aio_input_type,
};
const struct aio_output_type aio_output_type = {
.type_name = "aio_output",
.output_size = sizeof(struct aio_output),
@ -667,6 +676,7 @@ const struct aio_brick_type aio_brick_type = {
.max_inputs = 0,
.max_outputs = 1,
.master_ops = &aio_brick_ops,
.default_input_types = aio_input_types,
.default_output_types = aio_output_types,
.brick_construct = &aio_brick_construct,
};

View File

@ -256,11 +256,14 @@ void _mars_trigger(void)
}
EXPORT_SYMBOL_GPL(_mars_trigger);
int mars_power_button(struct mars_brick *brick, bool val)
int mars_power_button(struct mars_brick *brick, bool val, bool force_off)
{
int status = 0;
bool oldval = brick->power.button;
if (force_off && !val)
brick->power.force_off = true;
if (brick->power.force_off)
val = false;
@ -278,17 +281,20 @@ int mars_power_button(struct mars_brick *brick, bool val)
}
EXPORT_SYMBOL_GPL(mars_power_button);
int mars_power_button_recursive(struct mars_brick *brick, bool val, int timeout)
int mars_power_button_recursive(struct mars_brick *brick, bool val, bool force_off, int timeout)
{
int status = 0;
bool oldval = brick->power.button;
if (force_off && !val)
brick->power.force_off = true;
if (brick->power.force_off)
val = false;
if (val != oldval) {
brick_switch_t mode;
mode = (val ? BR_ON_ALL : BR_OFF_ALL);
mode = (val ? BR_ON_ALL : (force_off ? BR_FREE_ALL : BR_OFF_ALL));
MARS_DBG("brick '%s' type '%s' power button %d -> %d (mode = %d)\n", brick->brick_path, brick->type->type_name, oldval, val, mode);
@ -329,7 +335,7 @@ struct mars_cookie {
struct mars_global *global;
mars_dent_checker checker;
char *path;
void *parent;
struct mars_dent *parent;
int pathlen;
int allocsize;
int depth;
@ -425,7 +431,7 @@ int mars_filler(void *__buf, const char *name, int namlen, loff_t offset,
return 0;
}
class = cookie->checker(cookie->path, name, namlen, d_type, &prefix, &serial);
class = cookie->checker(cookie->parent, name, namlen, d_type, &prefix, &serial);
if (class < 0)
return 0;
@ -761,6 +767,7 @@ EXPORT_SYMBOL_GPL(mars_find_brick);
int mars_free_brick(struct mars_brick *brick)
{
struct mars_global *global;
int i;
int status;
@ -787,19 +794,28 @@ int mars_free_brick(struct mars_brick *brick)
MARS_DBG("===> freeing brick name = '%s'\n", brick->brick_name);
#if 1 // TODO: debug locking crash
(void)generic_brick_exit_full((void*)brick);
global = brick->global;
if (global) {
down(&global->mutex);
list_del_init(&brick->global_brick_link);
list_del_init(&brick->dent_brick_link);
up(&global->mutex);
}
status = generic_brick_exit_full((void*)brick);
if (status >= 0) {
#if 0 // TODO: check whether crash remains possible
if (brick->brick_name)
kfree(brick->brick_name);
if (brick->brick_path)
kfree(brick->brick_path);
kfree(brick);
#endif
if (brick->brick_name)
kfree(brick->brick_name);
if (brick->brick_path)
kfree(brick->brick_path);
kfree(brick);
mars_trigger();
status = 0;
mars_trigger();
} else {
MARS_ERR("error freeing brick, status = %d\n", status);
}
done:
return status;
@ -832,6 +848,10 @@ struct mars_brick *mars_make_brick(struct mars_global *global, struct mars_dent
MARS_ERR("input_type %d is missing\n", i);
goto err_name;
}
if (unlikely(type->input_size <= 0)) {
MARS_ERR("bad input_size at %d\n", i);
goto err_name;
}
size += type->input_size;
}
output_types = brick_type->default_output_types;
@ -841,6 +861,10 @@ struct mars_brick *mars_make_brick(struct mars_global *global, struct mars_dent
MARS_ERR("output_type %d is missing\n", i);
goto err_name;
}
if (unlikely(type->output_size <= 0)) {
MARS_ERR("bad output_size at %d\n", i);
goto err_name;
}
size += type->output_size;
}
@ -898,11 +922,6 @@ int mars_kill_brick(struct mars_brick *brick)
MARS_DBG("===> killing brick path = '%s' name = '%s'\n", brick->brick_path, brick->brick_name);
down(&global->mutex);
list_del_init(&brick->global_brick_link);
list_del_init(&brick->dent_brick_link);
up(&global->mutex);
// start shutdown
status = set_recursive_button((void*)brick, BR_FREE_ALL, 10 * HZ);
@ -1021,12 +1040,14 @@ struct mars_brick *make_brick_all(
struct mars_brick *brick = NULL;
char *paths[prev_count];
struct mars_brick *prev[prev_count];
int switch_state = true;
int i;
// treat variable arguments
va_start(args, prev_count);
if (switch_fmt) {
switch_path = vpath_make(switch_fmt, &args);
switch_state = false;
}
if (new_fmt) {
new_path = _new_path = vpath_make(new_fmt, &args);
@ -1042,11 +1063,21 @@ struct mars_brick *make_brick_all(
MARS_ERR("could not create new path\n");
goto err;
}
if (switch_path) {
struct mars_dent *test = mars_find_dent(global, switch_path);
if (test && test->new_link) {
sscanf(test->new_link, "%d", &switch_state);
}
}
// don't do anything if brick already exists
// brick already existing?
brick = mars_find_brick(global, new_brick_type != _aio_brick_type && new_brick_type != _bio_brick_type ? new_brick_type : NULL, new_path);
if (brick) {
// just switch the power state
MARS_IO("found brick '%s'\n", new_path);
goto do_switch;
}
if (!switch_state) { // don't start => also don't create
goto done;
}
if (!new_name)
@ -1120,11 +1151,17 @@ struct mars_brick *make_brick_all(
setup_fn(brick, private);
}
// switch on (may fail silently, but responsibility is at the workers)
if (timeout > 0) {
do_switch:
// switch on/off (may fail silently, but responsibility is at the workers)
if (timeout > 0 || !switch_state) {
int status;
status = mars_power_button_recursive((void*)brick, true, timeout);
status = mars_power_button_recursive((void*)brick, switch_state, !switch_state, timeout);
MARS_DBG("switch on status = %d\n", status);
#if 1 // TODO: need cleanup_fn() here
if (!switch_state && status >= 0 && !brick->power.button && brick->power.led_off) {
mars_kill_brick(brick);
}
#endif
}
return brick;

View File

@ -487,7 +487,15 @@ static int if_switch(struct if_brick *brick)
mars_power_led_on((void*)brick, false);
disk = input->disk;
if (!disk)
goto down;
goto is_down;
#if 0
q = disk->queue;
if (q) {
blk_cleanup_queue(q);
input->q = NULL;
}
#endif
if (atomic_read(&input->open_count) > 0) {
MARS_INF("device '%s' is open %d times, cannot shutdown\n", disk->disk_name, atomic_read(&input->open_count));
return -EBUSY;
@ -496,17 +504,10 @@ static int if_switch(struct if_brick *brick)
bdput(input->bdev);
input->bdev = NULL;
}
if (disk) {
q = disk->queue;
del_gendisk(input->disk);
put_disk(input->disk);
input->disk = NULL;
if (q) {
blk_cleanup_queue(q);
}
}
//........
down:
del_gendisk(input->disk);
put_disk(input->disk);
input->disk = NULL;
is_down:
mars_power_led_off((void*)brick, true);
}
return 0;
@ -560,14 +561,6 @@ static int if_input_construct(struct if_input *input)
static int if_input_destruct(struct if_input *input)
{
if (input->bdev)
bdput(input->bdev);
if (input->disk) {
del_gendisk(input->disk);
//put_disk(input->disk);
}
if (input->q)
blk_cleanup_queue(input->q);
return 0;
}
@ -607,6 +600,12 @@ const struct if_output_type if_output_type = {
[BRICK_OBJ_MREF] = LAYOUT_ALL,
}
};
static const struct if_output_type *if_output_types[] = {
&if_output_type,
};
const struct if_brick_type if_brick_type = {
.type_name = "if_brick",
.brick_size = sizeof(struct if_brick),
@ -614,6 +613,7 @@ const struct if_brick_type if_brick_type = {
.max_outputs = 0,
.master_ops = &if_brick_ops,
.default_input_types = if_input_types,
.default_output_types = if_output_types,
.brick_construct = &if_brick_construct,
.brick_destruct = &if_brick_destruct,
};

View File

@ -228,35 +228,6 @@ done:
return status;
}
#if 0
static
char *_backskip_replace(const char *path, char delim, bool insert, const char *fmt, ...)
{
int path_len = strlen(path);
int total_len = strlen(fmt) + path_len + MARS_PATH_MAX;
char *res = kmalloc(total_len, GFP_MARS);
if (likely(res)) {
va_list args;
int pos = path_len;
int plus;
while (pos > 0 && path[pos] != delim) {
pos--;
}
memcpy(res, path, pos);
va_start(args, fmt);
plus = vsnprintf(res + pos, total_len - pos, fmt, args);
va_end(args);
if (insert) {
strncpy(res + pos + plus, path + pos + 1, total_len - pos - plus);
}
}
return res;
}
#endif
///////////////////////////////////////////////////////////////////////
static
@ -276,7 +247,11 @@ int __make_copy(
struct mars_output *output[2] = {};
struct mars_info info[2] = {};
int i;
int status = -1;
int status = -EINVAL;
if (!switch_path) {
goto done;
}
for (i = 0; i < 2; i++) {
struct mars_brick *aio;
@ -368,7 +343,7 @@ int __make_copy(
_copy->copy_end = info[0].current_size;
MARS_DBG("copy_end = %lld\n", _copy->copy_end);
if (_copy->copy_start < _copy->copy_end) {
status = mars_power_button_recursive((void*)copy, true, 10 * HZ);
status = mars_power_button_recursive((void*)copy, true, false, 10 * HZ);
MARS_DBG("copy switch status = %d\n", status);
}
}
@ -465,9 +440,7 @@ int check_logfile(struct mars_peerinfo *peer, struct mars_dent *dent, struct mar
loff_t src_size = dent->new_stat.size;
const char *switch_path = NULL;
const char *copy_path = NULL;
const char *connect_path = NULL;
const char *alias_path = NULL;
struct kstat connect_stat = {};
struct mars_dent *local_alias;
struct copy_brick *copy_brick;
int status = 0;
@ -508,23 +481,9 @@ int check_logfile(struct mars_peerinfo *peer, struct mars_dent *dent, struct mar
}
// check whether connection is allowed
connect_path = backskip_replace(dent->d_path, '/', false, "/connect-%s", my_id());
if (unlikely(!connect_path)) {
status = -ENOMEM;
goto done;
}
status = mars_stat(connect_path, &connect_stat, true);
MARS_DBG("connect_path = '%s' stat status = %d uid = %d\n", connect_path, status, connect_stat.uid);
if (status < 0 || connect_stat.uid > 0) {
// stop running copy, if any
if (copy_brick) {
MARS_DBG("stopping copy '%s'\n", copy_brick->brick_name);
mars_kill_brick((void*)copy_brick);
}
goto done;
}
switch_path = path_make("%s/switch-%s/connect", parent->d_path, my_id());
// start copy
// start / treat copy brick instance
status = _update_file(peer->global, switch_path, copy_path, dent->d_path, peer->peer, src_size);
MARS_DBG("update '%s' from peer '%s' status = %d\n", dent->d_path, peer->peer, status);
if (status < 0) {
@ -550,10 +509,10 @@ int check_logfile(struct mars_peerinfo *peer, struct mars_dent *dent, struct mar
done:
if (copy_path)
kfree(copy_path);
if (connect_path)
kfree(connect_path);
if (alias_path)
kfree(alias_path);
if (switch_path)
kfree(switch_path);
return status;
}
@ -917,7 +876,7 @@ struct mars_rotate {
};
static
void _create_new_logfile(char *path)
void _create_new_logfile(const char *path)
{
struct file *f;
const int flags = O_RDWR | O_CREAT | O_EXCL;
@ -999,8 +958,9 @@ int make_log_init(void *buf, struct mars_dent *parent)
struct mars_dent *replay_link;
struct mars_dent *aio_dent;
struct mars_output *output;
char *replay_path = NULL;
char *aio_path = NULL;
const char *replay_path = NULL;
const char *aio_path = NULL;
const char *switch_path = NULL;
int status;
if (!rot) {
@ -1101,6 +1061,9 @@ int make_log_init(void *buf, struct mars_dent *parent)
}
MARS_DBG("logfile '%s' size = %lld\n", aio_path, rot->aio_info.current_size);
// check whether attach is allowed
switch_path = path_make("%s/switch-%s/attach", parent->d_path, my_id());
/* Fetch / make the transaction logger.
* We deliberately "forget" to connect the log input here.
* Will be carried out later in make_log().
@ -1115,7 +1078,7 @@ int make_log_init(void *buf, struct mars_dent *parent)
aio_path,
(const struct generic_brick_type*)&trans_logger_brick_type,
(const struct generic_brick_type*[]){NULL},
NULL,
switch_path,
"%s/logger",
(const char *[]){"%s/data-%s"},
1,
@ -1139,6 +1102,8 @@ done:
kfree(aio_path);
if (replay_path)
kfree(replay_path);
if (switch_path)
kfree(switch_path);
return status;
}
@ -1377,7 +1342,7 @@ int _start_trans(struct mars_rotate *rot)
/* Switch on....
*/
status = mars_power_button((void*)trans_brick, true);
status = mars_power_button((void*)trans_brick, true, false);
MARS_DBG("status = %d\n", status);
done:
@ -1394,9 +1359,9 @@ int _stop_trans(struct mars_rotate *rot)
goto done;
}
/* Switch off....
/* Switch off temporarily....
*/
status = mars_power_button((void*)trans_brick, false);
status = mars_power_button((void*)trans_brick, false, false);
MARS_DBG("status = %d\n", status);
if (status < 0 || !trans_brick->power.led_off) {
goto done;
@ -1536,7 +1501,7 @@ int make_bio(void *buf, struct mars_dent *dent)
goto done;
}
brick->outputs[0]->output_name = dent->d_path;
status = mars_power_button((void*)brick, true);
status = mars_power_button((void*)brick, true, false);
if (status < 0) {
kill_all(buf, dent);
}
@ -1697,6 +1662,8 @@ static int _make_copy(void *buf, struct mars_dent *dent)
status = -ENOMEM;
goto done;
}
// check whether connection is allowed
switch_path = path_make("%s/switch-%s/connect", dent->d_parent->d_path, my_id());
status = __make_copy(global, dent, switch_path, copy_path, dent->d_parent->d_path, (const char**)dent->d_argv, -1, NULL);
@ -1704,6 +1671,8 @@ done:
MARS_DBG("status = %d\n", status);
if (copy_path)
kfree(copy_path);
if (switch_path)
kfree(switch_path);
return status;
}
@ -1757,6 +1726,9 @@ static int make_sync(void *buf, struct mars_dent *dent)
if (unlikely(!src || !dst || !copy_path))
goto done;
// check whether connection is allowed
switch_path = path_make("%s/switch-%s/sync", dent->d_parent->d_path, my_id());
MARS_DBG("starting initial sync '%s' => '%s'\n", src, dst);
{
@ -1787,6 +1759,8 @@ done:
kfree(dst);
if (copy_path)
kfree(copy_path);
if (switch_path)
kfree(switch_path);
return status;
}
@ -1801,6 +1775,8 @@ enum {
CL_PEERS,
// resource definitions
CL_RESOURCE,
CL_SWITCH,
CL_SWITCH_ITEMS,
CL_CONNECT,
CL_DATA,
CL_PRIMARY,
@ -1854,6 +1830,27 @@ static const struct light_class light_classes[] = {
.cl_forward = make_log_init,
.cl_backward = NULL,
},
/* Subdirectory for controlling items...
*/
[CL_SWITCH] = {
.cl_name = "switch-",
.cl_len = 7,
.cl_type = 'd',
.cl_hostcontext = true,
.cl_father = CL_RESOURCE,
.cl_forward = NULL,
.cl_backward = NULL,
},
/* ... and its contents
*/
[CL_SWITCH_ITEMS] = {
.cl_name = "",
.cl_len = 0, // catch any
.cl_type = 'l',
.cl_father = CL_SWITCH,
.cl_forward = NULL,
.cl_backward = NULL,
},
/* Symlink indicating the current peer
*/
[CL_CONNECT] = {
@ -1983,7 +1980,7 @@ static const struct light_class light_classes[] = {
/* Helper routine to pre-determine the relevance of a name from the filesystem.
*/
static int light_checker(const char *path, const char *_name, int namlen, unsigned int d_type, int *prefix, int *serial)
static int light_checker(struct mars_dent *parent, const char *_name, int namlen, unsigned int d_type, int *prefix, int *serial)
{
int class;
int status = -2;
@ -1999,44 +1996,62 @@ static int light_checker(const char *path, const char *_name, int namlen, unsign
for (class = CL_ROOT + 1; ; class++) {
const struct light_class *test = &light_classes[class];
int len = test->cl_len;
if (!len || !test->cl_name)
if (!test->cl_name) { // end of table
break;
}
//MARS_DBG(" testing class '%s'\n", test->cl_name);
#if 0
#ifdef MARS_DEBUGGING
if (len != strlen(test->cl_name)) {
MARS_ERR("internal table '%s': %d != %d\n", test->cl_name, len, (int)strlen(test->cl_name));
MARS_ERR("internal table '%s' mismatch: %d != %d\n", test->cl_name, len, (int)strlen(test->cl_name));
len = strlen(test->cl_name);
}
#endif
if (namlen >= len && !memcmp(name, test->cl_name, len)) {
//MARS_DBG("path '%s/%s' matches class %d '%s'\n", path, name, class, test->cl_name);
// special contexts
if (test->cl_serial) {
int plus = 0;
int count;
count = sscanf(name+len, "%d%n", serial, &plus);
if (count < 1) {
//MARS_DBG("'%s' serial number mismatch at '%s'\n", name, name+len);
status = -1;
goto done;
}
len += plus;
if (name[len] == '-')
len++;
}
*prefix = len;
if (test->cl_hostcontext) {
if (memcmp(name+len, my_id(), namlen-len)) {
//MARS_DBG("context mismatch '%s' at '%s'\n", name, name+len);
status = -1;
goto done;
}
}
status = class;
goto done;
if (test->cl_father &&
(!parent || parent->d_class != test->cl_father)) {
continue;
}
if (len > 0 &&
(namlen < len || memcmp(name, test->cl_name, len))) {
continue;
}
//MARS_DBG("path '%s/%s' matches class %d '%s'\n", path, name, class, test->cl_name);
// check special contexts
if (test->cl_serial) {
int plus = 0;
int count;
count = sscanf(name+len, "%d%n", serial, &plus);
if (count < 1) {
//MARS_DBG("'%s' serial number mismatch at '%s'\n", name, name+len);
status = -1;
goto done;
}
len += plus;
if (name[len] == '-')
len++;
}
if (prefix)
*prefix = len;
if (test->cl_hostcontext) {
if (memcmp(name+len, my_id(), namlen-len)) {
//MARS_DBG("context mismatch '%s' at '%s'\n", name, name+len);
status = -1;
goto done;
}
}
// all ok
status = class;
goto done;
}
//MARS_DBG("no match for '%s' '%s'\n", path, name);
done:
#ifdef MARS_DEBUGGING
if (name)
@ -2167,32 +2182,35 @@ void _show_statist(struct mars_global *global)
int brick_count = 0;
down(&global->mutex);
MARS_STAT("----------- lists:\n");
MARS_STAT("================================== dents:\n");
for (tmp = global->dent_anchor.next; tmp != &global->dent_anchor; tmp = tmp->next) {
struct mars_dent *dent;
dent = container_of(tmp, struct mars_dent, dent_link);
MARS_STAT("dent '%s'\n", dent->d_path);
dent_count++;
}
MARS_STAT("================================== bricks:\n");
for (tmp = global->brick_anchor.next; tmp != &global->brick_anchor; tmp = tmp->next) {
struct mars_brick *test;
int i;
test = container_of(tmp, struct mars_brick, global_brick_link);
if (brick_count)
MARS_STAT("---------\n");
MARS_STAT("brick type = %s path = '%s' name = '%s' level = %d button = %d off = %d on = %d\n", test->type->type_name, test->brick_path, test->brick_name, test->status_level, test->power.button, test->power.led_off, test->power.led_on);
brick_count++;
for (i = 0; i < test->nr_inputs; i++) {
struct mars_input *input = test->inputs[i];
struct mars_output *output = input ? input->connect : NULL;
if (output) {
MARS_STAT(" input %d connected with %s path = '%s' name = '%s'\n", i, output->brick->type->type_name, output->brick->brick_path, output->brick->brick_name);
MARS_STAT(" input %d connected with %s path = '%s' name = '%s'\n", i, output->brick->type->type_name, output->brick->brick_path, output->brick->brick_name);
} else {
MARS_STAT(" input %d not connected\n", i);
MARS_STAT(" input %d not connected\n", i);
}
}
}
up(&global->mutex);
MARS_INF("----------- STATISTICS: %d dents, %d bricks\n", dent_count, brick_count);
MARS_INF("==================== STATISTICS: %d dents, %d bricks\n", dent_count, brick_count);
}
#endif

View File

@ -30,7 +30,7 @@ static struct task_struct *server_thread = NULL;
///////////////////////// own helper functions ////////////////////////
static int server_checker(const char *path, const char *name, int namlen, unsigned int d_type, int *prefix, int *serial)
static int server_checker(struct mars_dent *parent, const char *name, int namlen, unsigned int d_type, int *prefix, int *serial)
{
return 0;
}

View File

@ -511,6 +511,15 @@ static struct sio_output_ops sio_output_ops = {
.mars_get_info = sio_get_info,
};
const struct sio_input_type sio_input_type = {
.type_name = "sio_input",
.input_size = sizeof(struct sio_input),
};
static const struct sio_input_type *sio_input_types[] = {
&sio_input_type,
};
const struct sio_output_type sio_output_type = {
.type_name = "sio_output",
.output_size = sizeof(struct sio_output),
@ -533,6 +542,7 @@ const struct sio_brick_type sio_brick_type = {
.max_inputs = 0,
.max_outputs = 1,
.master_ops = &sio_brick_ops,
.default_input_types = sio_input_types,
.default_output_types = sio_output_types,
.brick_construct = &sio_brick_construct,
};

View File

@ -154,7 +154,7 @@ void make_test_instance(void)
#ifdef CONF_FDSYNC
_device_brick->o_fdsync = true;
#endif
mars_power_button((void*)device_brick, true);
mars_power_button((void*)device_brick, true, false);
first = device_brick->outputs[0];
// last
@ -269,7 +269,7 @@ void make_test_instance(void)
MARS_INF("------------- START GATE --------------\n");
mars_power_button((void*)if_brick, true);
mars_power_button((void*)if_brick, true, false);
//_if_brick->is_active = true;
msleep(2000);

View File

@ -13,7 +13,7 @@ $ip =~ s/\A.*inet +(?!127\.0\.)([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*?\Z/$1/ms or di
chomp $ip;
print "my IP is $ip\n";
umask 0177;
umask 0077;
die "only root may use this tool\n" unless `whoami` eq "root\n"; # getpid() seems to be missing in perlfunc
##################################################################
@ -67,23 +67,11 @@ sub _trigger {
sub _switch {
my ($path, $on) = @_;
# Sadly, there is no system call lchmod().
# It would be better to use the x flag even of symlinks if it were possible.
# As a workaround, we use the owner uid - fortunately this is
# changeable, even by perl (although direct calls to lchown()
# seems to be missing)
if($on) {
system("chown --no-dereference 0 $path");
} else {
system("chown --no-dereference nobody $path");
}
my $oldmode = (lstat $path)[2] & 0700;
my $newmode = $on ? $oldmode | 0100 : $oldmode & ~0100;
print "chmod '$path' $oldmode $newmode";
chmod($newmode, $path) == 1 or die "cannot chmod '$path'\n";
my $tmp = $path;
$tmp =~ s/\/([^\/]+)$/.tmp.$1/;
my $src = $on ? "1" : "0";
symlink($src, $tmp) or die "cannot create switch symlink\n";
rename($tmp, $path) or die "cannot rename switch symlink\n";
}
sub _writable {
@ -222,6 +210,7 @@ sub create_res {
mkdir("$tmp/defaults-$host");
mkdir("$tmp/actual-$host");
mkdir("$tmp/switch-$host");
symlink("1", "$tmp/switch-$host/attach");
symlink("0", "$tmp/switch-$host/connect");
symlink("0", "$tmp/switch-$host/sync");
@ -245,8 +234,9 @@ sub create_res {
sub attach_res {
my ($cmd, $res) = @_;
my $detach = ($cmd eq "detach");
my $path = "$mars/resource-$res/data-$host";
my $path = "$mars/resource-$res/switch-$host/attach";
_switch($path, !$detach);
print "successfully started ${cmd} of resource $res\n"
}
sub connect_res {
@ -254,6 +244,7 @@ sub connect_res {
my $disconnect = ($cmd eq "disconnect");
my $path = "$mars/resource-$res/switch-$host/connect";
_switch($path, !$disconnect);
print "successfully started ${cmd} on resource $res\n"
}
sub pause_res {
@ -261,6 +252,7 @@ sub pause_res {
my $pause = ($cmd eq "pause-sync");
my $path = "$mars/resource-$res/switch-$host/sync";
_switch($path, !$pause);
print "successfully started ${cmd} on resource $res\n"
}
sub up_res {