static pid_t create_pid;
/** Whether the pre-create-hook/rsync/post-create-hook is currently stopped. */
static int create_process_stopped;
-/** Process id of current rm process. */
-static pid_t rm_pid;
+/** Process id of current pre-remove/rm/post-remove process. */
+static pid_t remove_pid;
/** When the next snapshot is due. */
static struct timeval next_snapshot_time;
/** Creation time of the snapshot currently being created. */
static char *path_to_last_complete_snapshot;
/** \sa \ref snap.h for details. */
static unsigned snapshot_creation_status;
+/** \sa \ref snap.h for details. */
+static unsigned snapshot_removal_status;
DEFINE_DSS_ERRLIST;
static int remove_snapshot(struct snapshot *s, char *why)
{
int fds[3] = {0, 0, 0};
- assert(!rm_pid);
+ assert(!remove_pid);
char *new_name = being_deleted_name(s);
int ret = dss_rename(s->name, new_name);
char *argv[] = {"rm", "-rf", new_name, NULL};
goto out;
DSS_NOTICE_LOG("removing %s snapshot %s (interval = %i)\n",
why, s->name, s->interval);
- ret = dss_exec(&rm_pid, argv[0], argv, fds);
+ ret = dss_exec(&remove_pid, argv[0], argv, fds);
out:
free(new_name);
return ret;
static int handle_rm_exit(int status)
{
- rm_pid = 0;
+ remove_pid = 0;
if (!WIFEXITED(status))
return -E_INVOLUNTARY_EXIT;
if (WEXITSTATUS(status))
static int wait_for_rm_process(void)
{
- int status, ret = wait_for_process(rm_pid, &status);
+ int status, ret = wait_for_process(remove_pid, &status);
if (ret < 0)
return ret;
return -E_BUG;
}
}
- if (pid == rm_pid)
+ if (pid == remove_pid)
return handle_rm_exit(status);
DSS_EMERG_LOG("BUG: unknown process %d died\n", (int)pid);
return -E_BUG;
case SIGTERM:
restart_create_process();
kill_process(create_pid);
- kill_process(rm_pid);
+ kill_process(remove_pid);
ret = -E_SIGNAL;
break;
case SIGHUP:
int low_disk_space;
struct timeval now, *tvp;
- if (rm_pid)
+ if (remove_pid)
tvp = NULL; /* sleep until rm process dies */
else { /* sleep one minute */
tv.tv_sec = 60;
if (ret < 0)
goto out;
}
- if (rm_pid)
+ if (remove_pid)
continue;
ret = disk_space_low();
if (ret < 0)
ret = try_to_free_disk_space(low_disk_space);
if (ret < 0)
goto out;
- if (rm_pid) {
+ if (remove_pid) {
stop_create_process();
continue;
}
store them in a database for further analysis.
"
+option "pre-remove-hook" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~
+"Executed before snapshot removal"
+string typestr="command"
+optional
+details="
+ Execute this command before removing a snapshot. If this
+ command returns with a non-zero exit status, no snapshot is
+ being removed and the operation is retried later.
+
+ For example, one might want to execute a script that checks
+ whether the snapshot to be deleted is currently used by
+ another process, e.g. by a tape-based backup system that runs
+ concurrently to dss.
+
+ Another possible application of this is to record disk-usage
+ patterns before and after snapshot removal.
+"
+
+option "post-remove-hook" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~
+"Executed after snapshot removal"
+string typestr="command"
+optional
+details="
+ Execute this after a snapshot has successfully been
+ removed. The full path of the removed snapshot is
+ passed to the hook as the first argument. The exit code of
+ this hook is ignored.
+"
+
option "exit-hook" e
#~~~~~~~~~~~~~~~~~~~
"Executed if run command exits"
SCS_POST_HOOK_RUNNING,
};
+/** The state of snapshot removal. */
+enum {
+ /** No snapshot is currently being removed. */
+ SRS_READY,
+ /** The pre-removal hook has been started. */
+ SRS_PRE_HOOK_RUNNING,
+ /** The pre-remove hook failed, we're waiting to execute it again. */
+ SRS_PRE_HOOK_FAILURE,
+ /** The rm command is currently executing. */
+ SRS_RM_RUNNING,
+ /** The post-remove hook ist running. */
+ SRS_POST_HOOK_RUNNING,
+};
+
/**
* The status of a snapshot.
*