diff --git a/brick.c b/brick.c index 28aa47b1..54aa5de4 100644 --- a/brick.c +++ b/brick.c @@ -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); set_button_wait(brick, val, force, timeout); 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; } - 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)); - status = brick->free(brick); - if (status < 0) { - BRICK_DBG("freeing failed, status = %d\n", status); - goto done; + for (i = 0; i < brick->type->max_inputs; i++) { + struct generic_input *input = brick->inputs[i]; + BRICK_DBG("---> i = %d\n", i); + 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; + } } } diff --git a/mars.h b/mars.h index a1833c85..4d54140e 100644 --- a/mars.h +++ b/mars.h @@ -266,8 +266,8 @@ extern const struct meta mars_timespec_meta[]; #include "sy_old/strategy.h" #endif -extern void mars_power_led_on(struct generic_brick *brick, bool val); -extern void mars_power_led_off(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 mars_brick *brick, bool val); /* this should disappear! */ extern void (*_mars_trigger)(void); diff --git a/mars_client.c b/mars_client.c index 3c961052..a5af1954 100644 --- a/mars_client.c +++ b/mars_client.c @@ -313,7 +313,7 @@ int receiver_thread(void *data) 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); 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); list_add_tail(&mref_a->hash_head, &output->hash_table[hash_index]); traced_unlock(&output->hash_lock[hash_index], flags); @@ -325,7 +325,6 @@ int receiver_thread(void *data) traced_unlock(&output->lock, flags); atomic_dec(&output->fly_count); - SIMPLE_CALLBACK(mref, 0); client_ref_put(output, mref); break; @@ -333,7 +332,7 @@ int receiver_thread(void *data) case CMD_GETINFO: status = mars_recv_struct(output->socket, &output->info, mars_info_meta); 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; } 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 /////////////// 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 = { .brick_switch = client_switch, + .brick_statistics = client_statistics, + .reset_statistics = client_reset_statistics, }; static struct client_output_ops client_output_ops = { diff --git a/mars_copy.c b/mars_copy.c index 80abe144..14b824e9 100644 --- a/mars_copy.c +++ b/mars_copy.c @@ -130,14 +130,14 @@ void copy_endio(struct generic_callback *cb) goto exit; } 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; } else if (likely(!st->error)) { st->table[queue] = mref; } exit: - if (unlikely(error)) { + if (unlikely(error < 0)) { st->error = error; _clash(brick); } diff --git a/mars_generic.c b/mars_generic.c index 32b06d3c..3f66bf5c 100644 --- a/mars_generic.c +++ b/mars_generic.c @@ -196,7 +196,7 @@ EXPORT_SYMBOL_GPL(mars_log_trace); // 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; 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); -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; if (val != oldval) { diff --git a/sy_old/mars_light.c b/sy_old/mars_light.c index 53f4fd5c..09c68ca9 100644 --- a/sy_old/mars_light.c +++ b/sy_old/mars_light.c @@ -3186,11 +3186,12 @@ static int light_thread(void *data) MARS_DBG("worker status = %d\n", status); if (!_global.global_power.button) { - status = mars_kill_brick_when_possible(&_global, &_global.brick_anchor, false, (void*)©_brick_type); + status = mars_kill_brick_when_possible(&_global, &_global.brick_anchor, false, (void*)©_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); - 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); _show_status_all(&_global); diff --git a/sy_old/strategy.h b/sy_old/strategy.h index 4ead887b..65402939 100644 --- a/sy_old/strategy.h +++ b/sy_old/strategy.h @@ -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_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_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) diff --git a/sy_old/sy_generic.c b/sy_old/sy_generic.c index 2a5d0c56..14838658 100644 --- a/sy_old/sy_generic.c +++ b/sy_old/sy_generic.c @@ -954,7 +954,7 @@ int mars_kill_brick(struct mars_brick *brick) CHECK_PTR(brick, done); 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) { 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); -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; struct list_head *tmp; @@ -1032,15 +1032,18 @@ int mars_kill_brick_when_possible(struct mars_global *global, struct list_head * continue; } // only kill unconnected bricks - if (brick->outputs[0]->nr_connected > 0) { + if (brick->outputs[0] && brick->outputs[0]->nr_connected > 0) { 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: * only kill bricks which have not been touched during the current mars_dent_work() round. * disable this for stress-testing the allocation/deallocation logic. */ -#endif if (global && global->global_version == brick->brick_version) { continue; } @@ -1048,10 +1051,12 @@ int mars_kill_brick_when_possible(struct mars_global *global, struct list_head * if (global) { up_write(&global->brick_mutex); } + MARS_DBG("KILLING '%s'\n", brick->brick_name); status = mars_kill_brick(brick); if (global) { down_write(&global->brick_mutex); } + success: if (status >= 0) { return_status++; } else {