-/*
- * Copyright (C) 2008-2011 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* SPDX-License-Identifier: GPL-2.0 */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
static struct timeval next_removal_check;
/** Creation time of the snapshot currently being created. */
static int64_t current_snapshot_creation_time;
-/** The snapshot currently being removed. */
+/* Set by the pre-rm hook, cleared by handle_remove_exit(). */
struct snapshot *snapshot_currently_being_removed;
/** Needed by the post-create hook. */
static char *path_to_last_complete_snapshot;
fprintf(log, "\n*** internal state ***\n\n");
fprintf(log,
"pid: %d\n"
- "logile: %s\n"
+ "logfile: %s\n"
"snapshot_currently_being_removed: %s\n"
"path_to_last_complete_snapshot: %s\n"
"reference_snapshot: %s\n"
return config_file;
}
-static int send_signal(int sig)
+static int send_signal(int sig, bool wait)
{
pid_t pid;
char *config_file = get_config_file_name();
int ret = get_dss_pid(config_file, &pid);
+ unsigned ms = 32;
+ struct timespec ts;
free(config_file);
if (ret < 0)
ret = kill(pid, sig);
if (ret < 0)
return -ERRNO_TO_DSS_ERROR(errno);
- return 1;
+ if (!wait)
+ return 1;
+ while (ms < 5000) {
+ ts.tv_sec = ms / 1000;
+ ts.tv_nsec = (ms % 1000) * 1000 * 1000;
+ ret = nanosleep(&ts, NULL);
+ if (ret < 0)
+ return -ERRNO_TO_DSS_ERROR(errno);
+ ret = kill(pid, 0);
+ if (ret < 0) {
+ if (errno != ESRCH)
+ return -ERRNO_TO_DSS_ERROR(errno);
+ return 1;
+ }
+ ms *= 2;
+ }
+ return -E_KILL_TIMEOUT;
}
struct signal_info {
static int com_kill(void)
{
+ bool w_given = OPT_GIVEN(KILL, WAIT);
const char *arg = OPT_STRING_VAL(KILL, SIGNAL);
int ret, i;
return ret;
if (val < 0 || val > SIGRTMAX)
return -ERRNO_TO_DSS_ERROR(EINVAL);
- return send_signal(val);
+ return send_signal(val, w_given);
}
if (strncasecmp(arg, "sig", 3) == 0)
arg += 3;
if (strcasecmp(arg, "CLD") == 0)
- return send_signal(SIGCHLD);
+ return send_signal(SIGCHLD, w_given);
if (strcasecmp(arg, "IOT") == 0)
- return send_signal(SIGABRT);
+ return send_signal(SIGABRT, w_given);
for (i = 0; i < SIGNAL_TABLE_SIZE; i++)
if (strcasecmp(arg, signal_table[i].name) == 0)
- return send_signal(signal_table[i].num);
+ return send_signal(signal_table[i].num, w_given);
DSS_ERROR_LOG(("invalid sigspec: %s\n", arg));
return -ERRNO_TO_DSS_ERROR(EINVAL);
}
static int64_t compute_next_snapshot_time(void)
{
int64_t x = 0, now = get_current_time(), unit_interval
- = 24 * 3600 * OPT_UINT32_VAL(DSS, UNIT_INTERVAL), ret;
+ = 24 * 3600 * OPT_UINT32_VAL(DSS, UNIT_INTERVAL), ret,
+ last_completion_time;
unsigned wanted = desired_number_of_snapshots(0,
OPT_UINT32_VAL(DSS, NUM_INTERVALS)),
num_complete = 0;
continue;
num_complete++;
x += s->completion_time - s->creation_time;
+ last_completion_time = s->completion_time;
}
assert(x >= 0);
x /= num_complete; /* avg time to create one snapshot */
if (unit_interval < x * wanted) /* oops, no sleep at all */
goto out;
- ret = s->completion_time + unit_interval / wanted - x;
+ ret = last_completion_time + unit_interval / wanted - x;
out:
free_snapshot_list(&sl);
return ret;
return strcmp(s->name, name_of_reference_snapshot)? 0 : 1;
}
-/*
- * return: 0: no redundant snapshots, 1: rm process started, negative: error
- */
static struct snapshot *find_redundant_snapshot(struct snapshot_list *sl)
{
int i, interval;
switch (sig) {
case SIGINT:
case SIGTERM:
- kill_children();
- ret = -E_SIGNAL;
- break;
+ return -E_SIGNAL;
case SIGHUP:
ret = handle_sighup();
break;
{
int ret;
+ assert(argv);
ret = rename_resume_snap(current_snapshot_creation_time);
if (ret < 0)
return ret;
ret = -E_BUG;
kill_children();
exit_hook(ret);
+ while (wait(NULL) >= 0 || errno != ECHILD)
+ ; /* still have children to wait for */
return ret;
}
EXPORT_CMD_HANDLER(run);
else if (OPT_GIVEN(DSS, HELP))
txt = lls_short_help(CMD_PTR(DSS));
else if (OPT_GIVEN(DSS, VERSION))
- txt = dss_strdup(VERSION_STRING);
+ txt = make_message("%s\n", VERSION_STRING);
else
return;
printf("%s", txt);