fix disconnect of bricks, better copy statistics, various improvements

This commit is contained in:
schoebel 2011-11-04 16:43:23 +01:00 committed by Thomas Schoebel-Theuer
parent c5a9ad16ff
commit 4525d28aed
8 changed files with 67 additions and 24 deletions

26
brick.c
View File

@ -789,16 +789,30 @@ int set_recursive_button(struct generic_brick *orig_brick, brick_switch_t mode,
BRICK_DBG("--> switch '%s' stack = %d\n", SAFE_STR(brick->brick_name), stack); BRICK_DBG("--> switch '%s' stack = %d\n", SAFE_STR(brick->brick_name), stack);
set_button_wait(brick, val, force, timeout); set_button_wait(brick, val, force, timeout);
if (val ? !brick->power.led_on : !brick->power.led_off) { if (val ? !brick->power.led_on : !brick->power.led_off) {
BRICK_DBG("switching to %d: brick '%s' not ready (%s)\n", val, SAFE_STR(brick->brick_name), SAFE_STR(orig_brick->brick_name)); BRICK_ERR("switching '%s' to %d: brick not ready (%s)\n", SAFE_STR(brick->brick_name), val, SAFE_STR(orig_brick->brick_name));
goto done; goto done;
} }
if (force && !val && (mode == BR_FREE_ONE || mode == BR_FREE_ALL) && brick->free) { if (force && !val && (mode == BR_FREE_ONE || mode == BR_FREE_ALL)) {
int i;
BRICK_DBG("---> freeing '%s'\n", SAFE_STR(brick->brick_name)); BRICK_DBG("---> freeing '%s'\n", SAFE_STR(brick->brick_name));
status = brick->free(brick); for (i = 0; i < brick->type->max_inputs; i++) {
if (status < 0) { struct generic_input *input = brick->inputs[i];
BRICK_DBG("freeing failed, status = %d\n", status); BRICK_DBG("---> i = %d\n", i);
goto done; if (!input)
continue;
status = generic_disconnect(input);
if (status < 0) {
BRICK_ERR("disconnect %d failed, status = %d\n", i, status);
goto done;
}
}
if (brick->free) {
status = brick->free(brick);
if (status < 0) {
BRICK_ERR("freeing failed, status = %d\n", status);
goto done;
}
} }
} }

4
mars.h
View File

@ -266,8 +266,8 @@ extern const struct meta mars_timespec_meta[];
#include "sy_old/strategy.h" #include "sy_old/strategy.h"
#endif #endif
extern void mars_power_led_on(struct generic_brick *brick, bool val); extern void mars_power_led_on(struct mars_brick *brick, bool val);
extern void mars_power_led_off(struct generic_brick *brick, bool val); extern void mars_power_led_off(struct mars_brick *brick, bool val);
/* this should disappear! /* this should disappear!
*/ */
extern void (*_mars_trigger)(void); extern void (*_mars_trigger)(void);

View File

@ -313,7 +313,7 @@ int receiver_thread(void *data)
status = mars_recv_cb(output->socket, mref); status = mars_recv_cb(output->socket, mref);
MARS_IO("new status = %d, pos = %lld len = %d rw = %d\n", status, mref->ref_pos, mref->ref_len, mref->ref_rw); MARS_IO("new status = %d, pos = %lld len = %d rw = %d\n", status, mref->ref_pos, mref->ref_len, mref->ref_rw);
if (status < 0) { if (status < 0) {
MARS_ERR("interrupted data transfer during callback, status = %d\n", status); MARS_WRN("interrupted data transfer during callback, status = %d\n", status);
traced_lock(&output->hash_lock[hash_index], flags); traced_lock(&output->hash_lock[hash_index], flags);
list_add_tail(&mref_a->hash_head, &output->hash_table[hash_index]); list_add_tail(&mref_a->hash_head, &output->hash_table[hash_index]);
traced_unlock(&output->hash_lock[hash_index], flags); traced_unlock(&output->hash_lock[hash_index], flags);
@ -325,7 +325,6 @@ int receiver_thread(void *data)
traced_unlock(&output->lock, flags); traced_unlock(&output->lock, flags);
atomic_dec(&output->fly_count); atomic_dec(&output->fly_count);
SIMPLE_CALLBACK(mref, 0); SIMPLE_CALLBACK(mref, 0);
client_ref_put(output, mref); client_ref_put(output, mref);
break; break;
@ -333,7 +332,7 @@ int receiver_thread(void *data)
case CMD_GETINFO: case CMD_GETINFO:
status = mars_recv_struct(output->socket, &output->info, mars_info_meta); status = mars_recv_struct(output->socket, &output->info, mars_info_meta);
if (status < 0) { if (status < 0) {
MARS_ERR("got bad info from remote side, status = %d\n", status); MARS_WRN("got bad info from remote side, status = %d\n", status);
goto done; goto done;
} }
output->got_info = true; output->got_info = true;
@ -488,6 +487,28 @@ done:
} }
//////////////// informational / statistics ///////////////
static
char *client_statistics(struct client_brick *brick, int verbose)
{
struct client_output *output = brick->outputs[0];
char *res = brick_string_alloc(0);
if (!res)
return NULL;
snprintf(res, 512, "socket = %p fly_count = %d\n",
output->socket,
atomic_read(&output->fly_count));
return res;
}
static
void client_reset_statistics(struct client_brick *brick)
{
}
//////////////// object / aspect constructors / destructors /////////////// //////////////// object / aspect constructors / destructors ///////////////
static int client_mref_aspect_init_fn(struct generic_aspect *_ini) static int client_mref_aspect_init_fn(struct generic_aspect *_ini)
@ -546,6 +567,8 @@ static int client_output_destruct(struct client_output *output)
static struct client_brick_ops client_brick_ops = { static struct client_brick_ops client_brick_ops = {
.brick_switch = client_switch, .brick_switch = client_switch,
.brick_statistics = client_statistics,
.reset_statistics = client_reset_statistics,
}; };
static struct client_output_ops client_output_ops = { static struct client_output_ops client_output_ops = {

View File

@ -130,14 +130,14 @@ void copy_endio(struct generic_callback *cb)
goto exit; goto exit;
} }
if (unlikely(cb->cb_error < 0)) { if (unlikely(cb->cb_error < 0)) {
MARS_ERR("IO error %d on index %d, old state = %d\n", cb->cb_error, index, st->state); MARS_DBG("IO error %d on index %d, old state = %d\n", cb->cb_error, index, st->state);
error = cb->cb_error; error = cb->cb_error;
} else if (likely(!st->error)) { } else if (likely(!st->error)) {
st->table[queue] = mref; st->table[queue] = mref;
} }
exit: exit:
if (unlikely(error)) { if (unlikely(error < 0)) {
st->error = error; st->error = error;
_clash(brick); _clash(brick);
} }

View File

@ -196,7 +196,7 @@ EXPORT_SYMBOL_GPL(mars_log_trace);
// power led handling // power led handling
void mars_power_led_on(struct generic_brick *brick, bool val) void mars_power_led_on(struct mars_brick *brick, bool val)
{ {
bool oldval = brick->power.led_on; bool oldval = brick->power.led_on;
if (val != oldval) { if (val != oldval) {
@ -207,7 +207,7 @@ void mars_power_led_on(struct generic_brick *brick, bool val)
} }
EXPORT_SYMBOL_GPL(mars_power_led_on); EXPORT_SYMBOL_GPL(mars_power_led_on);
void mars_power_led_off(struct generic_brick *brick, bool val) void mars_power_led_off(struct mars_brick *brick, bool val)
{ {
bool oldval = brick->power.led_off; bool oldval = brick->power.led_off;
if (val != oldval) { if (val != oldval) {

View File

@ -3186,11 +3186,12 @@ static int light_thread(void *data)
MARS_DBG("worker status = %d\n", status); MARS_DBG("worker status = %d\n", status);
if (!_global.global_power.button) { if (!_global.global_power.button) {
status = mars_kill_brick_when_possible(&_global, &_global.brick_anchor, false, (void*)&copy_brick_type); status = mars_kill_brick_when_possible(&_global, &_global.brick_anchor, false, (void*)&copy_brick_type, false);
MARS_DBG("kill copy bricks (when possible) = %d\n", status);
} }
status = mars_kill_brick_when_possible(&_global, &_global.brick_anchor, false, (void*)&client_brick_type); status = mars_kill_brick_when_possible(&_global, &_global.brick_anchor, false, (void*)&client_brick_type, false);
MARS_DBG("kill client bricks (when possible) = %d\n", status); MARS_DBG("kill client bricks (when possible) = %d\n", status);
status = mars_kill_brick_when_possible(&_global, &_global.brick_anchor, false, (void*)&aio_brick_type); status = mars_kill_brick_when_possible(&_global, &_global.brick_anchor, false, (void*)&aio_brick_type, false);
MARS_DBG("kill aio bricks (when possible) = %d\n", status); MARS_DBG("kill aio bricks (when possible) = %d\n", status);
_show_status_all(&_global); _show_status_all(&_global);

View File

@ -75,7 +75,7 @@ extern struct mars_brick *mars_make_brick(struct mars_global *global, struct mar
extern int mars_free_brick(struct mars_brick *brick); extern int mars_free_brick(struct mars_brick *brick);
extern int mars_kill_brick(struct mars_brick *brick); extern int mars_kill_brick(struct mars_brick *brick);
extern int mars_kill_brick_all(struct mars_global *global, struct list_head *anchor, bool use_dent_link); extern int mars_kill_brick_all(struct mars_global *global, struct list_head *anchor, bool use_dent_link);
extern int mars_kill_brick_when_possible(struct mars_global *global, struct list_head *anchor, bool use_dent_link, const struct mars_brick_type *type); extern int mars_kill_brick_when_possible(struct mars_global *global, struct list_head *anchor, bool use_dent_link, const struct mars_brick_type *type, bool only_off);
// mid-level brick instantiation (identity is based on path strings) // mid-level brick instantiation (identity is based on path strings)

View File

@ -954,7 +954,7 @@ int mars_kill_brick(struct mars_brick *brick)
CHECK_PTR(brick, done); CHECK_PTR(brick, done);
global = brick->global; global = brick->global;
MARS_DBG("===> killing brick path = '%s' name = '%s'\n", SAFE_STR(brick->brick_path), SAFE_STR(brick->brick_name)); MARS_DBG("===> killing brick %s path = '%s' name = '%s'\n", SAFE_STR(brick->type->type_name), SAFE_STR(brick->brick_path), SAFE_STR(brick->brick_name));
if (global) { if (global) {
down_write(&global->brick_mutex); down_write(&global->brick_mutex);
@ -1011,7 +1011,7 @@ int mars_kill_brick_all(struct mars_global *global, struct list_head *anchor, bo
} }
EXPORT_SYMBOL_GPL(mars_kill_brick_all); EXPORT_SYMBOL_GPL(mars_kill_brick_all);
int mars_kill_brick_when_possible(struct mars_global *global, struct list_head *anchor, bool use_dent_link, const struct mars_brick_type *type) int mars_kill_brick_when_possible(struct mars_global *global, struct list_head *anchor, bool use_dent_link, const struct mars_brick_type *type, bool only_off)
{ {
int return_status = 0; int return_status = 0;
struct list_head *tmp; struct list_head *tmp;
@ -1032,15 +1032,18 @@ int mars_kill_brick_when_possible(struct mars_global *global, struct list_head *
continue; continue;
} }
// only kill unconnected bricks // only kill unconnected bricks
if (brick->outputs[0]->nr_connected > 0) { if (brick->outputs[0] && brick->outputs[0]->nr_connected > 0) {
continue; continue;
} }
#if 1 if (only_off) {
MARS_DBG("POWER OFF '%s'\n", brick->brick_name);
status = mars_power_button(brick, false, false);
goto success;
}
/* optimization: /* optimization:
* only kill bricks which have not been touched during the current mars_dent_work() round. * only kill bricks which have not been touched during the current mars_dent_work() round.
* disable this for stress-testing the allocation/deallocation logic. * disable this for stress-testing the allocation/deallocation logic.
*/ */
#endif
if (global && global->global_version == brick->brick_version) { if (global && global->global_version == brick->brick_version) {
continue; continue;
} }
@ -1048,10 +1051,12 @@ int mars_kill_brick_when_possible(struct mars_global *global, struct list_head *
if (global) { if (global) {
up_write(&global->brick_mutex); up_write(&global->brick_mutex);
} }
MARS_DBG("KILLING '%s'\n", brick->brick_name);
status = mars_kill_brick(brick); status = mars_kill_brick(brick);
if (global) { if (global) {
down_write(&global->brick_mutex); down_write(&global->brick_mutex);
} }
success:
if (status >= 0) { if (status >= 0) {
return_status++; return_status++;
} else { } else {