import mars-63.tgz

This commit is contained in:
Thomas Schoebel-Theuer 2011-02-28 19:00:32 +01:00
parent db2dfebcb1
commit a92db584bb
10 changed files with 456 additions and 307 deletions

50
brick.c
View File

@ -629,11 +629,13 @@ void set_button_wait(struct generic_switch *sw, bool val, bool force, int timeou
}
EXPORT_SYMBOL_GPL(set_button_wait);
int set_recursive_button(struct generic_brick *orig_brick, bool val, bool force, int timeout)
int set_recursive_button(struct generic_brick *orig_brick, brick_switch_t mode, int timeout)
{
struct generic_brick **table = NULL;
int max = PAGE_SIZE / sizeof(void*) / 2;
int stack;
bool val = (mode == BR_ON_ONE || mode == BR_ON_ALL);
bool force = (mode != BR_OFF_ONE && mode != BR_OFF_ALL);
int status;
restart:
@ -662,26 +664,26 @@ int set_recursive_button(struct generic_brick *orig_brick, bool val, bool force,
status = -EDEADLK;
goto done;
}
for (i = 0; i < brick->nr_inputs; i++) {
struct generic_input *input = brick->inputs[i];
struct generic_output *output;
struct generic_brick *next;
if (!input)
continue;
output = input->connect;
if (!output)
continue;
next = output->brick;
if (!next)
continue;
if (next->power.led_on)
continue;
table[stack++] = next;
if (unlikely(stack > max)) {
goto restart;
if (mode >= BR_ON_ALL) {
for (i = 0; i < brick->nr_inputs; i++) {
struct generic_input *input = brick->inputs[i];
struct generic_output *output;
struct generic_brick *next;
if (!input)
continue;
output = input->connect;
if (!output)
continue;
next = output->brick;
if (!next)
continue;
table[stack++] = next;
if (unlikely(stack > max)) {
goto restart;
}
}
}
} else {
} else if (mode >= BR_ON_ALL) {
int i;
for (i = 0; i < brick->nr_outputs; i++) {
struct generic_output *output = brick->outputs[i];
@ -693,8 +695,6 @@ int set_recursive_button(struct generic_brick *orig_brick, bool val, bool force,
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;
if (next->power.led_off)
continue;
table[stack++] = next;
if (unlikely(stack > max)) {
goto restart;
@ -713,6 +713,14 @@ int set_recursive_button(struct generic_brick *orig_brick, bool val, bool force,
goto done;
}
if (force && !val && (mode == BR_FREE_ONE || mode == BR_FREE_ALL) && brick->free) {
status = brick->free(brick);
if (status < 0) {
BRICK_DBG("freeing brick '%s' (%s) failed, status = %d\n", brick->brick_name, orig_brick->brick_name, status);
goto done;
}
}
}
status = 0;

20
brick.h
View File

@ -142,6 +142,7 @@ struct generic_switch {
struct BRICK##_input **inputs; \
struct BRICK##_output **outputs; \
struct generic_switch power; \
int (*free)(struct BRICK##_brick *del); \
struct list_head tmp_head; \
struct generic_brick {
@ -684,7 +685,9 @@ extern void set_lamport(struct timespec *old);
#endif
/* Generic interface to simple brick status changes
/* Generic interface to simple brick status changes.
*
* "Forced switch off" means that it cannot be switched on again.
*/
extern void set_button(struct generic_switch *sw, bool val, bool force);
extern void set_button_wait(struct generic_switch *sw, bool val, bool force, int timeout);
@ -701,7 +704,20 @@ extern void set_led_off(struct generic_switch *sw, bool val);
* There is one exception: when @force is set, only the direction to
* "off" remains possible. This is useful for emergency shutdowns.
*/
extern int set_recursive_button(struct generic_brick *brick, bool val, bool force, int timeout);
typedef enum {
// only one brick instance
BR_ON_ONE, // switch on one brick instance
BR_OFF_ONE, // just switch off (may be switched on again)
BR_KILL_ONE, // forced switch off => may be never switched on again
BR_FREE_ONE, // forced switch off + deallocation (when possible)
// dito, but operating on the whole graph
BR_ON_ALL,
BR_OFF_ALL,
BR_KILL_ALL,
BR_FREE_ALL,
} brick_switch_t;
extern int set_recursive_button(struct generic_brick *brick, brick_switch_t mode, int timeout);
/////////////////////////////////////////////////////////////////////////

35
mars.h
View File

@ -248,11 +248,11 @@ extern const struct meta mars_mref_meta[];
extern struct mars_global *mars_global;
extern void mars_trigger(void);
extern int mars_power_button(struct mars_brick *brick, bool val, bool force);
extern int mars_power_button(struct mars_brick *brick, bool val);
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, bool force, int timeout);
extern int mars_power_button_recursive(struct mars_brick *brick, bool val, int timeout);
/////////////////////////////////////////////////////////////////////////
@ -295,11 +295,13 @@ extern const struct meta mars_timespec_meta[];
extern const struct meta mars_kstat_meta[];
extern const struct meta mars_dent_meta[];
extern struct generic_brick_type *_client_brick_type; // for avoidance of cyclic references
struct mars_global {
struct semaphore mutex;
struct generic_switch global_power;
struct list_head dent_anchor;
struct list_head brick_anchor;
struct generic_switch global_power;
struct semaphore mutex;
volatile bool main_trigger;
wait_queue_head_t main_event;
//void *private;
@ -314,8 +316,33 @@ extern struct mars_dent *mars_find_dent(struct mars_global *global, const char *
extern void mars_dent_free(struct mars_dent *dent);
extern void mars_dent_free_all(struct list_head *anchor);
// lowe-level brick instantiation
extern struct mars_brick *mars_find_brick(struct mars_global *global, const void *brick_type, const char *path);
extern struct mars_brick *mars_make_brick(struct mars_global *global, const void *_brick_type, const char *path, const char *name);
extern int mars_free_brick(struct mars_brick *brick);
extern int mars_kill_brick(struct mars_brick *brick);
// mid-level brick instantiation (identity is based on path strings)
extern char *vpath_make(struct mars_dent *father, const char *fmt, va_list *args);
extern char *path_make(struct mars_dent *father, const char *fmt, ...);
extern struct mars_brick *path_find_brick(struct mars_global *global, const void *brick_type, struct mars_dent *father, const char *fmt, ...);
extern struct mars_brick *make_brick_all(
struct mars_global *global,
struct mars_dent *father,
struct generic_brick_type *new_brick_type,
const char *new_name,
int timeout,
const char *new_fmt,
const char *prev_fmt[],
int prev_count,
...
);
// general MARS infrastructure
#define MARS_ERR_ONCE(dent, args...) if (!dent->d_once_error++) MARS_ERR(args)

View File

@ -11,6 +11,7 @@
#include <linux/string.h>
#include <linux/kthread.h>
#define _STRATEGY // only for _client_brick_type
#include "mars.h"
///////////////////////// own type definitions ////////////////////////
@ -493,6 +494,7 @@ EXPORT_SYMBOL_GPL(client_brick_type);
static int __init init_client(void)
{
MARS_INF("init_client()\n");
_client_brick_type = (void*)&client_brick_type;
return client_register_brick_type();
}

View File

@ -410,7 +410,7 @@ static int device_aio_switch(struct device_aio_brick *brick)
{
static int index = 0;
struct device_aio_output *output = brick->outputs[0];
const char *path = output->output_name;
const char *path = output->brick->brick_name;
int flags = O_CREAT | O_RDWR | O_LARGEFILE;
int prot = 0600;
mm_segment_t oldfs;
@ -533,7 +533,7 @@ static int device_aio_output_construct(struct device_aio_output *output)
static int device_aio_output_destruct(struct device_aio_output *output)
{
return mars_power_button((void*)output->brick, false, true);
return mars_power_button((void*)output->brick, false);
}
///////////////////////// static structs ////////////////////////

View File

@ -18,6 +18,73 @@
#include <linux/namei.h>
#include <linux/kthread.h>
/////////////////////////////////////////////////////////////////////
// meta descriptions
const struct meta mars_info_meta[] = {
META_INI(current_size, struct mars_info, FIELD_INT),
META_INI(transfer_order, struct mars_info, FIELD_INT),
META_INI(transfer_size, struct mars_info, FIELD_INT),
{}
};
EXPORT_SYMBOL_GPL(mars_info_meta);
const struct meta mars_mref_meta[] = {
META_INI(ref_pos, struct mref_object, FIELD_INT),
META_INI(ref_len, struct mref_object, FIELD_INT),
META_INI(ref_may_write, struct mref_object, FIELD_INT),
META_INI(ref_flags, struct mref_object, FIELD_INT),
META_INI(ref_rw, struct mref_object, FIELD_INT),
META_INI(ref_id, struct mref_object, FIELD_INT),
META_INI(_ref_cb.cb_error, struct mref_object, FIELD_INT),
{}
};
EXPORT_SYMBOL_GPL(mars_mref_meta);
const struct meta mars_timespec_meta[] = {
META_INI(tv_sec, struct timespec, FIELD_INT),
META_INI(tv_nsec, struct timespec, FIELD_INT),
{}
};
EXPORT_SYMBOL_GPL(mars_timespec_meta);
const struct meta mars_kstat_meta[] = {
META_INI(ino, struct kstat, FIELD_INT),
META_INI(mode, struct kstat, FIELD_INT),
META_INI(size, struct kstat, FIELD_INT),
META_INI_SUB(atime, struct kstat, mars_timespec_meta),
META_INI_SUB(mtime, struct kstat, mars_timespec_meta),
META_INI_SUB(ctime, struct kstat, mars_timespec_meta),
META_INI(blksize, struct kstat, FIELD_INT),
{}
};
EXPORT_SYMBOL_GPL(mars_kstat_meta);
const struct meta mars_dent_meta[] = {
META_INI(d_name, struct mars_dent, FIELD_STRING),
META_INI(d_rest, struct mars_dent, FIELD_STRING),
META_INI(d_path, struct mars_dent, FIELD_STRING),
META_INI(d_namelen, struct mars_dent, FIELD_INT),
META_INI(d_pathlen, struct mars_dent, FIELD_INT),
META_INI(d_type, struct mars_dent, FIELD_INT),
META_INI(d_class, struct mars_dent, FIELD_INT),
META_INI(d_version, struct mars_dent, FIELD_INT),
META_INI_SUB(new_stat,struct mars_dent, mars_kstat_meta),
META_INI_SUB(old_stat,struct mars_dent, mars_kstat_meta),
META_INI(new_link, struct mars_dent, FIELD_STRING),
META_INI(old_link, struct mars_dent, FIELD_STRING),
META_INI(d_args, struct mars_dent, FIELD_STRING),
META_INI(d_argv[0], struct mars_dent, FIELD_STRING),
META_INI(d_argv[1], struct mars_dent, FIELD_STRING),
META_INI(d_argv[2], struct mars_dent, FIELD_STRING),
META_INI(d_argv[3], struct mars_dent, FIELD_STRING),
{}
};
EXPORT_SYMBOL_GPL(mars_dent_meta);
/////////////////////////////////////////////////////////////////////
// some helpers
int mars_lstat(const char *path, struct kstat *stat)
@ -178,7 +245,7 @@ void mars_trigger(void)
}
EXPORT_SYMBOL_GPL(mars_trigger);
int mars_power_button(struct mars_brick *brick, bool val, bool force)
int mars_power_button(struct mars_brick *brick, bool val)
{
int status = 0;
bool oldval = brick->power.button;
@ -186,10 +253,10 @@ int mars_power_button(struct mars_brick *brick, bool val, bool force)
if (brick->power.force_off)
val = false;
if (val != oldval || force) {
if (val != oldval) {
MARS_DBG("brick '%s' type '%s' power button %d -> %d\n", brick->brick_path, brick->type->type_name, oldval, val);
set_button(&brick->power, val, force);
set_button(&brick->power, val, false);
if (brick->ops)
status = brick->ops->brick_switch(brick);
@ -200,7 +267,7 @@ int mars_power_button(struct mars_brick *brick, bool val, bool force)
}
EXPORT_SYMBOL_GPL(mars_power_button);
int mars_power_button_recursive(struct mars_brick *brick, bool val, bool force, int timeout)
int mars_power_button_recursive(struct mars_brick *brick, bool val, int timeout)
{
int status = 0;
bool oldval = brick->power.button;
@ -208,15 +275,13 @@ int mars_power_button_recursive(struct mars_brick *brick, bool val, bool force,
if (brick->power.force_off)
val = false;
if (val != oldval || force) {
MARS_DBG("brick '%s' type '%s' power button %d -> %d\n", brick->brick_path, brick->type->type_name, oldval, val);
if (val != oldval) {
brick_switch_t mode;
mode = (val ? BR_ON_ALL : BR_OFF_ALL);
status = set_recursive_button((void*)brick, val, force, timeout);
if (status >= 0)
status = brick->ops->brick_switch(brick);
MARS_DBG("brick '%s' type '%s' power button %d -> %d (mode = %d)\n", brick->brick_path, brick->type->type_name, oldval, val, mode);
mars_trigger();
status = set_recursive_button((void*)brick, mode, timeout);
}
return status;
}
@ -619,6 +684,10 @@ void mars_dent_free_all(struct list_head *anchor)
EXPORT_SYMBOL_GPL(mars_dent_free_all);
/////////////////////////////////////////////////////////////////////
// low-level brick instantiation
struct mars_brick *mars_find_brick(struct mars_global *global, const void *brick_type, const char *path)
{
struct list_head *tmp;
@ -646,6 +715,53 @@ struct mars_brick *mars_find_brick(struct mars_global *global, const void *brick
}
EXPORT_SYMBOL_GPL(mars_find_brick);
int mars_free_brick(struct mars_brick *brick)
{
int i;
int status;
if (!brick) {
MARS_ERR("bad brick parameter\n");
status = -EINVAL;
goto done;
}
if (!brick->power.force_off || !brick->power.led_off) {
MARS_DBG("brick '%s' is not freeable\n", brick->brick_name);
status = -ETXTBSY;
goto done;
}
// first check whether the brick is in use somewhere
for (i = 0; i < brick->nr_outputs; i++) {
if (brick->outputs[i]->nr_connected > 0) {
MARS_DBG("brick '%s' not freeable, output %i is used\n", brick->brick_name, i);
status = -EEXIST;
goto done;
}
}
MARS_DBG("===> freeing brick name = '%s'\n", brick->brick_name);
#if 1 // TODO: debug locking crash
(void)generic_brick_exit_full((void*)brick);
#endif
if (brick->brick_name)
kfree(brick->brick_name);
if (brick->brick_path)
kfree(brick->brick_path);
kfree(brick);
mars_trigger();
status = 0;
done:
return status;
}
EXPORT_SYMBOL_GPL(mars_free_brick);
struct mars_brick *mars_make_brick(struct mars_global *global, const void *_brick_type, const char *path, const char *_name)
{
const char *name = kstrdup(_name, GFP_MARS);
@ -702,6 +818,7 @@ struct mars_brick *mars_make_brick(struct mars_global *global, const void *_bric
MARS_ERR("cannot init brick %s\n", brick_type->type_name);
goto err_path;
}
res->free = mars_free_brick;
/* Immediately make it visible, regardless of internal state.
* Switching on / etc must be done separately.
@ -710,6 +827,8 @@ struct mars_brick *mars_make_brick(struct mars_global *global, const void *_bric
list_add(&res->brick_link, &global->brick_anchor);
up(&global->mutex);
mars_trigger();
return res;
err_path:
@ -722,71 +841,192 @@ err_name:
}
EXPORT_SYMBOL_GPL(mars_make_brick);
int mars_kill_brick(struct mars_brick *brick)
{
struct mars_global *global;
int status = -EINVAL;
CHECK_PTR(brick, done);
global = brick->global;
CHECK_PTR(global, done);
MARS_DBG("===> killing brick path = '%s' name = '%s'\n", brick->brick_path, brick->brick_name);
down(&global->mutex);
list_del_init(&brick->brick_link);
up(&global->mutex);
// start shutdown
status = set_recursive_button((void*)brick, BR_FREE_ALL, 10 * HZ);
done:
return status;
}
EXPORT_SYMBOL_GPL(mars_kill_brick);
/////////////////////////////////////////////////////////////////////
// meta descriptions
// mid-level brick instantiation (identity is based on path strings)
const struct meta mars_info_meta[] = {
META_INI(current_size, struct mars_info, FIELD_INT),
META_INI(transfer_order, struct mars_info, FIELD_INT),
META_INI(transfer_size, struct mars_info, FIELD_INT),
{}
};
EXPORT_SYMBOL_GPL(mars_info_meta);
char *vpath_make(struct mars_dent *father, const char *fmt, va_list *args)
{
int len = father->d_pathlen;
char *res = kmalloc(len + MARS_PATH_MAX, GFP_MARS);
const struct meta mars_mref_meta[] = {
META_INI(ref_pos, struct mref_object, FIELD_INT),
META_INI(ref_len, struct mref_object, FIELD_INT),
META_INI(ref_may_write, struct mref_object, FIELD_INT),
META_INI(ref_flags, struct mref_object, FIELD_INT),
META_INI(ref_rw, struct mref_object, FIELD_INT),
META_INI(ref_id, struct mref_object, FIELD_INT),
META_INI(_ref_cb.cb_error, struct mref_object, FIELD_INT),
{}
};
EXPORT_SYMBOL_GPL(mars_mref_meta);
if (likely(res)) {
memcpy(res, father->d_path, len);
vsnprintf(res + len, MARS_PATH_MAX, fmt, *args);
}
return res;
}
EXPORT_SYMBOL_GPL(vpath_make);
const struct meta mars_timespec_meta[] = {
META_INI(tv_sec, struct timespec, FIELD_INT),
META_INI(tv_nsec, struct timespec, FIELD_INT),
{}
};
EXPORT_SYMBOL_GPL(mars_timespec_meta);
char *path_make(struct mars_dent *father, const char *fmt, ...)
{
va_list args;
char *res;
va_start(args, fmt);
res = vpath_make(father, fmt, &args);
va_end(args);
return res;
}
EXPORT_SYMBOL_GPL(path_make);
const struct meta mars_kstat_meta[] = {
META_INI(ino, struct kstat, FIELD_INT),
META_INI(mode, struct kstat, FIELD_INT),
META_INI(size, struct kstat, FIELD_INT),
META_INI_SUB(atime, struct kstat, mars_timespec_meta),
META_INI_SUB(mtime, struct kstat, mars_timespec_meta),
META_INI_SUB(ctime, struct kstat, mars_timespec_meta),
META_INI(blksize, struct kstat, FIELD_INT),
{}
};
EXPORT_SYMBOL_GPL(mars_kstat_meta);
struct mars_brick *path_find_brick(struct mars_global *global, const void *brick_type, struct mars_dent *father, const char *fmt, ...)
{
va_list args;
char *fullpath;
struct mars_brick *res;
const struct meta mars_dent_meta[] = {
META_INI(d_name, struct mars_dent, FIELD_STRING),
META_INI(d_rest, struct mars_dent, FIELD_STRING),
META_INI(d_path, struct mars_dent, FIELD_STRING),
META_INI(d_namelen, struct mars_dent, FIELD_INT),
META_INI(d_pathlen, struct mars_dent, FIELD_INT),
META_INI(d_type, struct mars_dent, FIELD_INT),
META_INI(d_class, struct mars_dent, FIELD_INT),
META_INI(d_version, struct mars_dent, FIELD_INT),
META_INI_SUB(new_stat,struct mars_dent, mars_kstat_meta),
META_INI_SUB(old_stat,struct mars_dent, mars_kstat_meta),
META_INI(new_link, struct mars_dent, FIELD_STRING),
META_INI(old_link, struct mars_dent, FIELD_STRING),
META_INI(d_args, struct mars_dent, FIELD_STRING),
META_INI(d_argv[0], struct mars_dent, FIELD_STRING),
META_INI(d_argv[1], struct mars_dent, FIELD_STRING),
META_INI(d_argv[2], struct mars_dent, FIELD_STRING),
META_INI(d_argv[3], struct mars_dent, FIELD_STRING),
{}
};
EXPORT_SYMBOL_GPL(mars_dent_meta);
va_start(args, fmt);
fullpath = vpath_make(father, fmt, &args);
va_end(args);
if (!fullpath) {
return NULL;
}
res = mars_find_brick(global, brick_type, fullpath);
kfree(fullpath);
MARS_DBG("search for '%s' found = %p\n", fullpath, res);
return res;
}
EXPORT_SYMBOL_GPL(path_find_brick);
struct generic_brick_type *_client_brick_type = NULL;
EXPORT_SYMBOL_GPL(_client_brick_type);
struct mars_brick *make_brick_all(
struct mars_global *global,
struct mars_dent *father,
struct generic_brick_type *new_brick_type,
const char *new_name,
int timeout,
const char *new_fmt,
const char *prev_fmt[],
int prev_count,
...
)
{
va_list args;
char *new_path;
struct mars_brick *brick = NULL;
char *paths[prev_count];
struct mars_brick *prev[prev_count];
int i;
// treat variable arguments
va_start(args, prev_count);
new_path = vpath_make(father, new_fmt, &args);
for (i = 0; i < prev_count; i++) {
paths[i] = vpath_make(father, prev_fmt[i], &args);
}
va_end(args);
if (!new_path) {
MARS_ERR("could not create new path\n");
goto err;
}
// don't do anything if brick already exists
brick = mars_find_brick(global, new_brick_type, new_path);
if (brick) {
MARS_DBG("found brick '%s'\n", new_path);
goto done;
}
MARS_DBG("----> new brick '%s'\n", new_path);
// get all predecessor bricks
for (i = 0; i < prev_count; i++) {
char *path = paths[i];
if (!path) {
MARS_ERR("could not create path %d\n", i);
goto err;
}
prev[i] = mars_find_brick(global, NULL, path);
if (!prev[i] && _client_brick_type) {
char *remote = strchr(path, '@');
if (remote) {
remote++;
prev[i] = mars_make_brick(global, _client_brick_type, path, remote);
}
}
if (!prev[i]) {
MARS_ERR("prev brick '%s' does not exist\n", path);
goto err;
}
MARS_DBG("------> predecessor %d '%s'\n", i, path);
}
// create it...
brick = mars_make_brick(global, new_brick_type, new_path, new_name);
if (unlikely(!brick)) {
MARS_DBG("creation failed '%s' '%s'\n", new_path, new_name);
goto err;
}
if (unlikely(brick->nr_inputs < prev_count)) {
MARS_ERR("wrong number of arguments: %d < %d\n", brick->nr_inputs, prev_count);
goto err;
}
// connect the wires
for (i = 0; i < prev_count; i++) {
int status;
status = generic_connect((void*)brick->inputs[i], (void*)prev[i]->outputs[0]);
if (unlikely(status < 0)) {
MARS_ERR("'%s' '%s' cannot connect input %d\n", new_path, new_name, i);
goto err;
}
}
// switch on (may fail silently, but responsibility is at the workers)
if (timeout > 0) {
int status;
status = mars_power_button_recursive((void*)brick, true, timeout);
MARS_DBG("switch on status = %d\n", status);
}
return brick;
err:
if (brick)
mars_kill_brick(brick);
brick = NULL;
done:
for (i = 0; i < prev_count; i++) {
if (paths[i]) {
kfree(paths[i]);
}
}
if (new_path)
kfree(new_path);
return brick;
}
EXPORT_SYMBOL_GPL(make_brick_all);
/////////////////////////////////////////////////////////////////////

View File

@ -31,11 +31,7 @@
static struct task_struct *main_thread = NULL;
struct light_dent {
MARS_DENT(light_dent);
};
typedef int (*light_worker_fn)(void *buf, struct light_dent *dent);
typedef int (*light_worker_fn)(void *buf, struct mars_dent *dent);
struct light_class {
char *cl_name;
@ -48,104 +44,12 @@ struct light_class {
light_worker_fn cl_backward;
};
static
struct mars_brick *make_brick(struct mars_global *global, const void *_brick_type, const char *path, const char *name)
{
struct mars_brick *res;
MARS_DBG("type = '%s' path = '%s' name = '%s'\n", ((struct generic_brick_type*)_brick_type)->type_name, path, name);
res = mars_make_brick(global, _brick_type, path, name);
MARS_DBG("brick = %p\n", res);
if (res) {
mars_trigger();
}
return res;
}
static
int kill_brick(struct mars_brick *brick, int max_level)
{
int i;
int status;
if (!brick) {
MARS_ERR("bad brick parameter\n");
return -EINVAL;
}
// first check whether the brick is in use somewhere
for (i = 0; i < brick->nr_outputs; i++) {
if (brick->outputs[i]->nr_connected > 0) {
MARS_DBG("brick '%s' not killable, output %i is used\n", brick->brick_name, i);
return -EEXIST;
}
}
MARS_DBG("===> killing brick name = '%s'\n", brick->brick_name);
// start shutdown
#if 1
status = mars_power_button_recursive((void*)brick, false, true, 5 * HZ);
#else
status = mars_power_button((void*)brick, false, true);
MARS_DBG("kill '%s' status = %d led_off = %d\n", brick->brick_name, status, brick->power.led_off);
// wait until clean shutdown
if (status >= 0 && brick->power.led_off) {
int count = 0;
struct mars_brick *prev[brick->nr_inputs];
// remove from the global list => no longer visible
down(&brick->global->mutex);
list_del_init(&brick->brick_link);
up(&brick->global->mutex);
/* Disconnect all inputs.
* This must not start earlier, because during shutdown
* the inputs could be needed for cleanup operations etc.
*/
for (i = 0; i < brick->nr_inputs; i++) {
if (brick->inputs[i]->connect) {
prev[count++] = brick->inputs[i]->connect->brick;
(void)generic_disconnect((void*)brick->inputs[i]);
}
}
/* recursively kill predecessors
*/
if (max_level > 0) {
struct mars_brick *old = NULL;
for (i = 0; i < count; i++) {
if (!prev[i] || prev[i] == old || list_empty(&prev[i]->brick_link))
continue;
old = prev[i];
status |= kill_brick(prev[i], max_level - 1);
#if 1
msleep(500);
#endif
}
}
/* This runs unchecked and may therefore leave memory remains,
* but we currently have no separate list for "zombies".
* TODO: do better.
*/
#if 0 // TODO: debug locking crash
(void)generic_brick_exit_full((void*)brick);
#endif
mars_trigger();
}
#endif
return status;
}
///////////////////////////////////////////////////////////////////////
// internal helpers
static
void _normalized_path(char *res, int maxlen, struct light_dent *father, const char *prefix, const char *suffix)
void _normalized_path(char *res, int maxlen, struct mars_dent *father, const char *prefix, const char *suffix)
{
char *test;
int prelen;
@ -189,8 +93,7 @@ done:
*res = '\0';
}
static
struct mars_brick *find_other(struct mars_global *global, const void *brick_type, struct light_dent *father, const char *prefix, const char *suffix)
struct mars_brick *find_other(struct mars_global *global, const void *brick_type, struct mars_dent *father, const char *prefix, const char *suffix)
{
int len = (father ? father->d_pathlen : 0)
+ strlen(prefix)
@ -206,12 +109,11 @@ struct mars_brick *find_other(struct mars_global *global, const void *brick_type
/* Create a new brick and connect its inputs to a set of predecessors.
* Before starting that, check whether all predecessors exist and are healthy.
*/
static
struct mars_brick *make_all(struct mars_global *global,
const void *new_brick_type,
const char *new_path,
const char *new_name,
struct light_dent *father,
struct mars_dent *father,
const void *brick_type[],
const char *prefix[],
const char *suffix[],
@ -242,30 +144,13 @@ struct mars_brick *make_all(struct mars_global *global,
}
}
// special case for client brick: treat network indirection
if (new_brick_type == &client_brick_type) {
struct mars_dent *test;
char path[256];
snprintf(path, sizeof(path), "/mars/ips/ip-%s", new_name);
test = mars_find_dent(global, path);
if (test && test->new_link) {
MARS_DBG("translation '%s' => '%s'\n", new_name, test->new_link);
new_name = test->new_link;
}
}
// create it...
brick = make_brick(global, new_brick_type, fullpath, new_name);
brick = mars_make_brick(global, new_brick_type, fullpath, new_name);
if (unlikely(!brick)) {
MARS_DBG("creation failed '%s' '%s'\n", fullpath, new_name);
return NULL;
}
// special case for aio: file name is treated different IMPROVEME!
if (new_brick_type == &device_aio_brick_type) {
brick->outputs[0]->output_name = brick->brick_name;
}
// connect the wires
for (i = 0; i < count; i++) {
status = generic_connect((void*)brick->inputs[i], (void*)prev[i]->outputs[0]);
@ -281,13 +166,13 @@ struct mars_brick *make_all(struct mars_global *global,
// switch on (may fail silently, but responsibility is at the workers)
if (switch_on) {
status = mars_power_button((void*)brick, true, false);
status = mars_power_button((void*)brick, true);
MARS_DBG("switch on status = %d\n", status);
}
return brick;
err:
status = kill_brick(brick, 0);
status = mars_kill_brick(brick);
if (status >= 0) {
brick = NULL;
}
@ -296,7 +181,7 @@ err:
#define MARS_DELIM ','
static int _parse_args(struct light_dent *dent, char *str, int count)
static int _parse_args(struct mars_dent *dent, char *str, int count)
{
int i;
int status = -EINVAL;
@ -350,7 +235,7 @@ done:
///////////////////////////////////////////////////////////////////////
static
int __make_copy(struct mars_global *global, struct light_dent *parent, const char *path, const char *argv[], loff_t start_pos, struct copy_brick **__copy)
int __make_copy(struct mars_global *global, struct mars_dent *parent, const char *path, const char *argv[], loff_t start_pos, struct copy_brick **__copy)
{
const char *new_argv[4];
struct mars_brick *copy;
@ -464,7 +349,7 @@ int __make_copy(struct mars_global *global, struct light_dent *parent, const cha
_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((void*)copy, true, false);
status = mars_power_button((void*)copy, true);
MARS_DBG("copy switch status = %d\n", status);
}
}
@ -491,7 +376,7 @@ struct mars_peerinfo {
};
static
int _update_file(struct mars_global *global, struct light_dent *parent, const char *peer, const char *path)
int _update_file(struct mars_global *global, struct mars_dent *parent, const char *peer, const char *path)
{
char tmp[MARS_PATH_MAX] = {};
const char *argv[2] = { tmp, path};
@ -526,7 +411,7 @@ int _is_peer_logfile(const char *name, const char *id)
}
static
int run_bones(void *buf, struct light_dent *dent)
int run_bones(void *buf, struct mars_dent *dent)
{
int status = 0;
struct mars_peerinfo *peer = buf;
@ -697,7 +582,7 @@ int remote_thread(void *data)
{
struct list_head *tmp;
for (tmp = tmp_list.next; tmp != &tmp_list; tmp = tmp->next) {
struct light_dent *dent = container_of(tmp, struct light_dent, sub_link);
struct mars_dent *dent = container_of(tmp, struct mars_dent, sub_link);
if (!dent->d_path) {
MARS_DBG("NULL\n");
continue;
@ -732,7 +617,7 @@ done:
// helpers for worker functions
static int _kill_peer(void *buf, struct light_dent *dent)
static int _kill_peer(void *buf, struct mars_dent *dent)
{
struct mars_global *global = buf;
struct mars_peerinfo *peer = dent->d_private;
@ -755,7 +640,7 @@ static int _kill_peer(void *buf, struct light_dent *dent)
return 0;
}
static int _make_peer(void *buf, struct light_dent *dent, char *mypeer, char *path, light_worker_fn worker)
static int _make_peer(void *buf, struct mars_dent *dent, char *mypeer, char *path, light_worker_fn worker)
{
static int serial = 0;
struct mars_global *global = buf;
@ -804,22 +689,22 @@ done:
return status;
}
static int _kill_remote(void *buf, struct light_dent *dent)
static int _kill_remote(void *buf, struct mars_dent *dent)
{
return _kill_peer(buf, dent);
}
static int _make_remote(void *buf, struct light_dent *dent)
static int _make_remote(void *buf, struct mars_dent *dent)
{
return _make_peer(buf, dent, NULL, "/mars", NULL);
}
static int kill_scan(void *buf, struct light_dent *dent)
static int kill_scan(void *buf, struct mars_dent *dent)
{
return _kill_peer(buf, dent);
}
static int make_scan(void *buf, struct light_dent *dent)
static int make_scan(void *buf, struct mars_dent *dent)
{
MARS_DBG("path = '%s' peer = '%s'\n", dent->d_path, dent->d_rest);
if (!strcmp(dent->d_rest, my_id())) {
@ -830,7 +715,7 @@ static int make_scan(void *buf, struct light_dent *dent)
static
int _kill_default(void *buf, struct light_dent *dent, int maxlevel)
int kill_all(void *buf, struct mars_dent *dent)
{
struct mars_global *global = buf;
struct mars_brick *brick;
@ -843,37 +728,23 @@ int _kill_default(void *buf, struct light_dent *dent, int maxlevel)
if (!brick) {
return 0;
}
return kill_brick(brick, maxlevel);
return mars_kill_brick(brick);
}
static
int kill_default(void *buf, struct light_dent *dent)
{
return _kill_default(buf, dent, 0);
}
static
int kill_all(void *buf, struct light_dent *dent)
{
return _kill_default(buf, dent, 999);
}
///////////////////////////////////////////////////////////////////////
// handlers / helpers for logfile rotation
struct mars_rotate {
struct light_dent *replay_link;
struct light_dent *aio_dent;
struct mars_dent *replay_link;
struct mars_dent *aio_dent;
struct device_aio_brick *aio_brick;
struct mars_info aio_info;
struct trans_logger_brick *trans_brick;
struct light_dent *relevant_log;
struct light_dent *current_log;
struct light_dent *prev_log;
struct light_dent *next_log;
struct mars_dent *relevant_log;
struct mars_dent *current_log;
struct mars_dent *prev_log;
struct mars_dent *next_log;
long long last_jiffies;
loff_t start_pos;
loff_t end_pos;
@ -904,7 +775,7 @@ void _create_new_logfile(char *path)
}
static
int _update_link(struct mars_rotate *rot, struct light_dent *parent, int sequence, loff_t pos)
int _update_link(struct mars_rotate *rot, struct mars_dent *parent, int sequence, loff_t pos)
{
struct timespec now = {};
char old[MARS_PATH_MAX] = {};
@ -931,14 +802,14 @@ int _update_link(struct mars_rotate *rot, struct light_dent *parent, int sequenc
/* This must be called once at every round of logfile checking.
*/
static
int make_log_init(void *buf, struct light_dent *parent)
int make_log_init(void *buf, struct mars_dent *parent)
{
struct mars_global *global = buf;
struct mars_brick *aio_brick;
struct mars_brick *trans_brick;
struct mars_rotate *rot = parent->d_private;
struct light_dent *replay_link;
struct light_dent *aio_dent;
struct mars_dent *replay_link;
struct mars_dent *aio_dent;
struct mars_output *output;
char tmp[MARS_PATH_MAX] = {};
int status;
@ -1074,9 +945,9 @@ done:
* ret == 3 : relevant for appending
*/
static
int _check_logging_status(struct mars_global *global, struct light_dent *dent, long long *oldpos, long long *newpos)
int _check_logging_status(struct mars_global *global, struct mars_dent *dent, long long *oldpos, long long *newpos)
{
struct light_dent *parent = dent->d_parent;
struct mars_dent *parent = dent->d_parent;
struct mars_rotate *rot = parent->d_private;
int status = -EINVAL;
@ -1130,13 +1001,13 @@ done:
* This is important!
*/
static
int make_log(void *buf, struct light_dent *dent)
int make_log(void *buf, struct mars_dent *dent)
{
struct mars_global *global = buf;
struct light_dent *parent = dent->d_parent;
struct mars_dent *parent = dent->d_parent;
struct mars_rotate *rot = parent->d_private;
struct trans_logger_brick *trans_brick;
struct light_dent *prev_log;
struct mars_dent *prev_log;
loff_t start_pos = 0;
loff_t end_pos = 0;
int status = -EINVAL;
@ -1272,7 +1143,7 @@ int _start_trans(struct mars_rotate *rot)
/* Switch on....
*/
status = mars_power_button((void*)trans_brick, true, false);
status = mars_power_button((void*)trans_brick, true);
MARS_DBG("status = %d\n", status);
done:
@ -1291,7 +1162,7 @@ int _stop_trans(struct mars_rotate *rot)
/* Switch off....
*/
status = mars_power_button((void*)trans_brick, false, false);
status = mars_power_button((void*)trans_brick, false);
MARS_DBG("status = %d\n", status);
if (status < 0) {
goto done;
@ -1308,7 +1179,7 @@ done:
}
static
int make_log_finalize(struct mars_global *global, struct light_dent *parent)
int make_log_finalize(struct mars_global *global, struct mars_dent *parent)
{
struct mars_rotate *rot = parent->d_private;
struct trans_logger_brick *trans_brick;
@ -1382,9 +1253,9 @@ done:
// specific handlers
static
int make_primary(void *buf, struct light_dent *dent)
int make_primary(void *buf, struct mars_dent *dent)
{
struct light_dent *parent;
struct mars_dent *parent;
struct mars_rotate *rot;
int status = -EINVAL;
@ -1401,7 +1272,7 @@ done:
}
static
int make_aio(void *buf, struct light_dent *dent)
int make_aio(void *buf, struct mars_dent *dent)
{
struct mars_global *global = buf;
struct mars_brick *brick;
@ -1415,7 +1286,7 @@ int make_aio(void *buf, struct light_dent *dent)
goto done;
}
dent->d_kill_inactive = true;
brick = make_brick(global, &device_aio_brick_type, dent->d_path, dent->d_path);
brick = mars_make_brick(global, &device_aio_brick_type, dent->d_path, dent->d_path);
if (unlikely(!brick)) {
status = -ENXIO;
goto done;
@ -1423,18 +1294,18 @@ int make_aio(void *buf, struct light_dent *dent)
brick->outputs[0]->output_name = dent->d_path;
_brick = (void*)brick;
_brick->outputs[0]->o_fdsync = true;
status = mars_power_button((void*)brick, true, false);
status = mars_power_button((void*)brick, true);
if (status < 0) {
kill_default(buf, dent);
kill_all(buf, dent);
}
done:
return status;
}
static int make_dev(void *buf, struct light_dent *dent)
static int make_dev(void *buf, struct mars_dent *dent)
{
struct mars_global *global = buf;
struct light_dent *parent = dent->d_parent;
struct mars_dent *parent = dent->d_parent;
struct mars_rotate *rot = parent->d_private;
struct mars_brick *dev_brick;
int status = 0;
@ -1493,7 +1364,7 @@ done:
return status;
}
static int _make_direct(void *buf, struct light_dent *dent)
static int _make_direct(void *buf, struct mars_dent *dent)
{
struct mars_global *global = buf;
struct mars_brick *brick;
@ -1546,7 +1417,7 @@ done:
return status;
}
static int _make_copy(void *buf, struct light_dent *dent)
static int _make_copy(void *buf, struct mars_dent *dent)
{
struct mars_global *global = buf;
int status;
@ -1566,11 +1437,11 @@ done:
return status;
}
static int make_sync(void *buf, struct light_dent *dent)
static int make_sync(void *buf, struct mars_dent *dent)
{
struct mars_global *global = buf;
loff_t start_pos = 0;
struct light_dent *connect_dent;
struct mars_dent *connect_dent;
char *peer;
struct copy_brick *copy = NULL;
char src[MARS_PATH_MAX];
@ -1624,7 +1495,7 @@ static int make_sync(void *buf, struct light_dent *dent)
snprintf(dst, sizeof(dst), "%s/syncstatus-%s", dent->d_parent->d_path, my_id());
status = mars_symlink(src, dst, NULL, 0);
if (status >= 0 && copy->copy_last == copy->copy_end) {
status = mars_power_button((void*)copy, false, false);
status = mars_power_button((void*)copy, false);
MARS_DBG("copy switch status = %d\n", status);
}
}
@ -1725,7 +1596,7 @@ static const struct light_class light_classes[] = {
.cl_hostcontext = true,
.cl_father = CL_RESOURCE,
.cl_forward = make_aio,
.cl_backward = kill_default,
.cl_backward = kill_all,
},
/* Symlink pointing to the name of the primary node
*/
@ -1748,7 +1619,7 @@ static const struct light_class light_classes[] = {
.cl_hostcontext = true,
.cl_father = CL_RESOURCE,
.cl_forward = make_aio,
.cl_backward = kill_default,
.cl_backward = kill_all,
},
/* symlink indicating the current status / end
* of initial data sync.
@ -1761,7 +1632,7 @@ static const struct light_class light_classes[] = {
.cl_father = CL_RESOURCE,
#if 1
.cl_forward = make_sync,
.cl_backward = kill_default,
.cl_backward = kill_all,
#endif
},
/* Only for testing: make a copy instance
@ -1839,7 +1710,7 @@ static const struct light_class light_classes[] = {
.cl_hostcontext = true,
.cl_father = CL_RESOURCE,
.cl_forward = make_dev,
.cl_backward = kill_default,
.cl_backward = kill_all,
},
{}
};
@ -1989,7 +1860,7 @@ static int light_thread(void *data)
int status;
global.global_power.button = !kthread_should_stop();
status = mars_dent_work(&global, "/mars", sizeof(struct light_dent), light_checker, light_worker, &global, 3);
status = mars_dent_work(&global, "/mars", sizeof(struct mars_dent), light_checker, light_worker, &global, 3);
MARS_DBG("worker status = %d\n", status);
{

View File

@ -42,7 +42,7 @@ char *mars_translate_hostname(struct mars_global *global, const char *name)
{
const char *res = name;
if (global) {
if (likely(global)) {
char tmp[MARS_PATH_MAX];
struct mars_dent *test;

View File

@ -75,7 +75,6 @@ static int handler_thread(void *data)
struct server_brick *brick = data;
struct socket **sock = &brick->handler_socket;
int max_round = 300;
int timeout;
int status = 0;
brick->handler_thread = NULL;
@ -221,31 +220,17 @@ static int handler_thread(void *data)
done:
MARS_DBG("handler_thread terminating, status = %d\n", status);
mars_power_button((void*)brick, false, true);
do {
int status;
status = brick->ops->brick_switch(brick);
if (status < 0) {
MARS_ERR("server shutdown failed, status = %d\n", status);
} else if (max_round-- < 0)
int status = mars_kill_brick((void*)brick);
if (status >= 0)
break;
if (status >= 0 || max_round-- < 0) {
MARS_INF("not dead, giving up....\n");
break;
}
msleep(1000);
} while (!brick->power.led_off);
if (brick->inputs[0] && brick->inputs[0]->connect) {
MARS_DBG("disconnecting input %p\n", brick->inputs[0]->connect);
(void)generic_disconnect((void*)brick->inputs[0]);
}
timeout = 60 * 1000;
while (atomic_read(&brick->in_flight) || !brick->power.led_off) {
MARS_ERR("server brick has resources allocated - cannot terminate thread\n");
msleep(timeout);
if (timeout < 3600 * 1000)
timeout += 30 * 1000;
}
(void)generic_brick_exit_full((void*)brick);
MARS_DBG("done\n");
return 0;
}

View File

@ -154,7 +154,7 @@ void make_test_instance(void)
#ifdef CONF_FDSYNC
_device_brick->outputs[0]->o_fdsync = true;
#endif
mars_power_button((void*)device_brick, true, false);
mars_power_button((void*)device_brick, true);
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, false);
mars_power_button((void*)if_brick, true);
//_if_brick->is_active = true;
msleep(2000);