X-Git-Url: http://git.tuebingen.mpg.de/?p=dss.git;a=blobdiff_plain;f=dss.c;h=9f601ceb8365552719b001caad98fdd3efef1b30;hp=93ab802cb123bddde776042a9a9cff266102091c;hb=1a2bfdde95331f8f7262b99c07a5438dae827cdf;hpb=64964f0639b13787a06bea76f922cba18731807c diff --git a/dss.c b/dss.c index 93ab802..9f601ce 100644 --- a/dss.c +++ b/dss.c @@ -161,7 +161,6 @@ static int64_t compute_next_snapshot_time(void) struct snapshot *s = NULL; struct snapshot_list sl; - current_snapshot_creation_time = 0; dss_get_snapshot_list(&sl); FOR_EACH_SNAPSHOT(s, i, &sl) { if (!(s->flags & SS_COMPLETE)) @@ -197,7 +196,6 @@ static int next_snapshot_is_due(void) { int64_t now = get_current_time(); - assert(snapshot_creation_status == HS_READY); if (!next_snapshot_time_is_valid()) next_snapshot_time = compute_next_snapshot_time(); if (next_snapshot_time <= now) { @@ -252,8 +250,7 @@ static int pre_remove_hook(struct snapshot *s, const char *why) cmd = make_message("%s %s/%s", conf.pre_remove_hook_arg, conf.dest_dir_arg, s->name); DSS_DEBUG_LOG("executing %s\n", cmd); - ret = dss_exec_cmdline_pid(&remove_pid, - conf.pre_remove_hook_arg, fds); + ret = dss_exec_cmdline_pid(&remove_pid, cmd, fds); free(cmd); if (ret < 0) return ret; @@ -506,6 +503,7 @@ static int post_create_hook(void) char *cmd; if (!conf.post_create_hook_given) { + create_pid = 0; snapshot_creation_status = HS_READY; return 0; } @@ -543,27 +541,48 @@ static int post_remove_hook(void) return ret; } -static void kill_process(pid_t pid) +static void dss_kill(pid_t pid, int sig, const char *msg) { - if (!pid) + const char *signame, *process_name; + + if (pid == 0) + return; + switch (sig) { + case SIGTERM: signame = "TERM"; break; + case SIGSTOP: signame = "STOP"; break; + case SIGCONT: signame = "CONT"; break; + default: signame = "????"; + } + + if (pid == create_pid) + process_name = "create"; + else if (pid == remove_pid) + process_name = "remove"; + else process_name = "??????"; + + if (msg) + DSS_INFO_LOG("%s\n", msg); + DSS_DEBUG_LOG("sending signal %d (%s) to pid %d (%s process)\n", + sig, signame, (int)pid, process_name); + if (kill(pid, sig) >= 0) return; - DSS_WARNING_LOG("sending SIGTERM to pid %d\n", (int)pid); - kill(pid, SIGTERM); + DSS_INFO_LOG("failed to send signal %d (%s) to pid %d (%s process)\n", + sig, signame, (int)pid, process_name); } static void stop_create_process(void) { - if (!create_pid || create_process_stopped) + if (create_process_stopped) return; - kill(SIGSTOP, create_pid); + dss_kill(create_pid, SIGSTOP, "suspending create process"); create_process_stopped = 1; } static void restart_create_process(void) { - if (!create_pid || !create_process_stopped) + if (!create_process_stopped) return; - kill (SIGCONT, create_pid); + dss_kill(create_pid, SIGCONT, "resuming create process"); create_process_stopped = 0; } @@ -608,8 +627,7 @@ static int wait_for_process(pid_t pid, int *status) } } /* SIGINT or SIGTERM */ - DSS_WARNING_LOG("sending SIGTERM to pid %d\n", (int)pid); - kill(pid, SIGTERM); + dss_kill(pid, SIGTERM, "killing child process"); } if (ret < 0) DSS_ERROR_LOG("failed to wait for process %d\n", (int)pid); @@ -779,18 +797,22 @@ static int handle_sigchld(void) if (pid == create_pid) { switch (snapshot_creation_status) { case HS_PRE_RUNNING: - return handle_pre_create_hook_exit(status); + ret = handle_pre_create_hook_exit(status); + break; case HS_RUNNING: - return handle_rsync_exit(status); + ret = handle_rsync_exit(status); + break; case HS_POST_RUNNING: snapshot_creation_status = HS_READY; - return 1; + ret = 1; + break; default: DSS_EMERG_LOG("BUG: create can't die in status %d\n", snapshot_creation_status); return -E_BUG; } create_pid = 0; + return ret; } if (pid == remove_pid) { ret = handle_remove_exit(status); @@ -934,8 +956,8 @@ static int handle_signal(void) case SIGINT: case SIGTERM: restart_create_process(); - kill_process(create_pid); - kill_process(remove_pid); + dss_kill(create_pid, SIGTERM, NULL); + dss_kill(remove_pid, SIGTERM, NULL); ret = -E_SIGNAL; break; case SIGHUP: @@ -966,6 +988,32 @@ static int use_rsync_locally(char *logname) return 1; } +static int rename_resume_snap(int64_t creation_time) +{ + struct snapshot_list sl = {.num_snapshots = 0}; + struct snapshot *s; + char *new_name = incomplete_name(creation_time); + int ret; + + ret = 0; + if (conf.no_resume_given) + goto out; + dss_get_snapshot_list(&sl); + s = get_newest_snapshot(&sl); + if (!s) + goto out; + if ((s->flags & SS_COMPLETE) != 0) /* complete */ + goto out; + DSS_INFO_LOG("resuming: reusing %s as destination dir\n", s->name); + ret = dss_rename(s->name, new_name); +out: + if (ret >= 0) + DSS_NOTICE_LOG("creating new snapshot %s\n", new_name); + free(new_name); + free_snapshot_list(&sl); + return ret; +} + static void create_rsync_argv(char ***argv, int64_t *num) { char *logname; @@ -1018,11 +1066,10 @@ static void free_rsync_argv(char **argv) static int create_snapshot(char **argv) { int ret, fds[3] = {0, 0, 0}; - char *name; - name = incomplete_name(current_snapshot_creation_time); - DSS_NOTICE_LOG("creating new snapshot %s\n", name); - free(name); + ret = rename_resume_snap(current_snapshot_creation_time); + if (ret < 0) + return ret; ret = dss_exec(&create_pid, argv[0], argv, fds); if (ret < 0) return ret; @@ -1050,7 +1097,6 @@ static int select_loop(void) } FD_ZERO(&rfds); FD_SET(signal_pipe, &rfds); - DSS_DEBUG_LOG("tvp: %p, tv_sec : %lu\n", tvp, (long unsigned) tv.tv_sec); ret = dss_select(signal_pipe + 1, &rfds, NULL, tvp); if (ret < 0) goto out; @@ -1094,10 +1140,17 @@ static int select_loop(void) case HS_POST_RUNNING: continue; case HS_PRE_SUCCESS: - free_rsync_argv(rsync_argv); - create_rsync_argv(&rsync_argv, ¤t_snapshot_creation_time); - /* fall through */ + if (!name_of_reference_snapshot) { + free_rsync_argv(rsync_argv); + create_rsync_argv(&rsync_argv, ¤t_snapshot_creation_time); + } + ret = create_snapshot(rsync_argv); + if (ret < 0) + goto out; + continue; case HS_NEEDS_RESTART: + if (!next_snapshot_is_due()) + continue; ret = create_snapshot(rsync_argv); if (ret < 0) goto out;