diff --git a/kernel/mars.h b/kernel/mars.h index 451f7749..4fe55658 100644 --- a/kernel/mars.h +++ b/kernel/mars.h @@ -195,6 +195,7 @@ struct mars_info { struct list_head dent_brick_link; \ const char *brick_path; \ struct mars_global *global; \ + void **kill_ptr; \ int kill_round; \ bool killme; \ void (*show_status)(struct mars_brick *brick, bool shutdown); \ diff --git a/kernel/sy_old/mars_light.c b/kernel/sy_old/mars_light.c index 765837e2..6037c27a 100644 --- a/kernel/sy_old/mars_light.c +++ b/kernel/sy_old/mars_light.c @@ -293,6 +293,7 @@ struct mars_rotate { int split_brain_round; int copy_next_is_available; int relevant_serial; + bool has_symlinks; bool has_error; bool allow_update; bool forbid_replay; @@ -2269,6 +2270,7 @@ int make_log_init(void *buf, struct mars_dent *dent) rot->split_brain_serial = 0; rot->copy_next_serial = 0; rot->has_error = false; + rot->has_symlinks = true; if (dent->new_link) sscanf(dent->new_link, "%lld", &rot->dev_size); @@ -2415,6 +2417,7 @@ int make_log_init(void *buf, struct mars_dent *dent) if (!trans_brick) { goto done; } + rot->trans_brick->kill_ptr = (void**)&rot->trans_brick; rot->trans_brick->replay_limiter = &rot->replay_limiter; /* For safety, default is to try an (unnecessary) replay in case * something goes wrong later. @@ -3020,6 +3023,7 @@ int make_log_finalize(struct mars_global *global, struct mars_dent *dent) if (!rot) goto err; CHECK_PTR(rot, err); + rot->has_symlinks = true; trans_brick = rot->trans_brick; status = 0; if (!trans_brick) { @@ -3174,7 +3178,9 @@ done: } rot->copy_next_is_available = 0; rot->copy_brick = copy_brick; - if (!copy_brick) { + if (copy_brick) { + copy_brick->kill_ptr = (void**)&rot->copy_brick; + } else { rot->copy_serial = 0; } @@ -3223,6 +3229,8 @@ int make_primary(void *buf, struct mars_dent *dent) goto done; CHECK_PTR(rot, done); + rot->has_symlinks = true; + rot->todo_primary = global->global_power.button && dent->new_link && !strcmp(dent->new_link, my_id()); MARS_DBG("todo_primary = %d is_primary = %d\n", rot->todo_primary, rot->is_primary); @@ -3248,6 +3256,8 @@ int make_bio(void *buf, struct mars_dent *dent) if (!rot) goto done; + rot->has_symlinks = true; + switch_on = _check_allow(global, dent->d_parent, "attach"); brick = @@ -3339,6 +3349,7 @@ int make_dev(void *buf, struct mars_dent *dent) MARS_DBG("nothing to do\n"); goto err; } + rot->has_symlinks = true; if (!rot->trans_brick) { MARS_DBG("transaction logger does not exist\n"); goto done; @@ -3393,6 +3404,7 @@ int make_dev(void *buf, struct mars_dent *dent) MARS_DBG("setting killme on if_brick\n"); dev_brick->killme = true; } + dev_brick->kill_ptr = (void**)&rot->if_brick; dev_brick->show_status = _show_brick_status; _dev_brick = (void*)dev_brick; open_count = atomic_read(&_dev_brick->open_count); @@ -3628,6 +3640,7 @@ static int make_sync(void *buf, struct mars_dent *dent) rot = dent->d_parent->d_private; if (rot) { rot->forbid_replay = false; + rot->has_symlinks = true; rot->allow_update = true; rot->syncstatus_dent = dent; } @@ -3733,8 +3746,10 @@ static int make_sync(void *buf, struct mars_dent *dent) { const char *argv[2] = { src, dst }; status = __make_copy(global, dent, do_start ? switch_path : "", copy_path, dent->d_parent->d_path, argv, start_pos, end_pos, mars_fast_fullsync > 0, true, ©); - if (copy) + if (copy) { + copy->kill_ptr = (void**)&rot->sync_brick; copy->copy_limiter = &rot->sync_limiter; + } rot->sync_brick = copy; } @@ -3869,6 +3884,83 @@ static int check_deleted(void *buf, struct mars_dent *dent) return 0; } +static +int make_res(void *buf, struct mars_dent *dent) +{ + struct mars_rotate *rot = dent->d_private; + + if (!rot) { + MARS_DBG("nothing to do\n"); + goto done; + } + + rot->has_symlinks = false; + + done: + return 0; +} + +static +int kill_res(void *buf, struct mars_dent *dent) +{ + struct mars_rotate *rot = dent->d_private; + + if (!rot || !rot->parent_path || !rot->global || !rot->global->global_power.button) { + MARS_DBG("nothing to do\n"); + goto done; + } + if (rot->has_symlinks) { + MARS_DBG("symlinks were present, nothing to kill.\n"); + goto done; + } + // this code is only executed in case of forced deletion of symlinks + + if (rot->if_brick) { + if (atomic_read(&rot->if_brick->open_count) > 0) { + MARS_ERR("cannot destroy resource '%s': device is is use!\n", rot->parent_path); + goto done; + } + rot->if_brick->killme = true; + if (!rot->if_brick->power.led_off) { + int status = mars_power_button((void*)rot->if_brick, false, false); + MARS_INF("switching off resource '%s', device status = %d\n", rot->parent_path, status); + } else { + mars_kill_brick((void*)rot->if_brick); + rot->if_brick = NULL; + } + } + if (rot->sync_brick) { + rot->sync_brick->killme = true; + if (!rot->sync_brick->power.led_off) { + int status = mars_power_button((void*)rot->sync_brick, false, false); + MARS_INF("switching off resource '%s', sync status = %d\n", rot->parent_path, status); + } + } + if (rot->copy_brick) { + rot->copy_brick->killme = true; + if (!rot->copy_brick->power.led_off) { + int status = mars_power_button((void*)rot->copy_brick, false, false); + MARS_INF("switching off resource '%s', fetch status = %d\n", rot->parent_path, status); + } + } + if (rot->trans_brick) { + struct trans_logger_output *output = rot->trans_brick->outputs[0]; + if (!output || output->nr_connected) { + MARS_ERR("cannot destroy resource '%s': trans_logger is is use!\n", rot->parent_path); + goto done; + } + rot->trans_brick->killme = true; + if (!rot->trans_brick->power.led_off) { + int status = mars_power_button((void*)rot->trans_brick, false, false); + MARS_INF("switching off resource '%s', logger status = %d\n", rot->parent_path, status); + } + } + + + done: + return 0; +} + /////////////////////////////////////////////////////////////////////// // the order is important! @@ -4053,6 +4145,8 @@ static const struct light_class light_classes[] = { .cl_type = 'd', .cl_use_channel = true, .cl_father = CL_ROOT, + .cl_forward = make_res, + .cl_backward = kill_res, }, /* Subdirectory for resource-specific userspace items... diff --git a/kernel/sy_old/sy_generic.c b/kernel/sy_old/sy_generic.c index 6e53a855..805e8167 100644 --- a/kernel/sy_old/sy_generic.c +++ b/kernel/sy_old/sy_generic.c @@ -1263,6 +1263,9 @@ int mars_kill_brick(struct mars_brick *brick) MARS_DBG("---> freeing '%s' '%s'\n", SAFE_STR(brick->brick_name), SAFE_STR(brick->brick_path)); + if (brick->kill_ptr) + *brick->kill_ptr = NULL; + for (i = 0; i < max_inputs; i++) { struct generic_input *input = (void*)brick->inputs[i]; if (!input)