+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 = dss_exec(&create_pid, argv[0], argv, fds);
+ if (ret < 0)
+ return ret;
+ snapshot_creation_status = HS_RUNNING;
+ return ret;
+}
+
+static int select_loop(void)
+{
+ int ret;
+ /* check every 60 seconds for free disk space */
+ struct timeval tv;
+ char **rsync_argv = NULL;
+
+ for (;;) {
+ fd_set rfds;
+ int low_disk_space;
+ struct timeval *tvp;
+
+ if (remove_pid)
+ tvp = NULL; /* sleep until rm hook/process dies */
+ else { /* sleep one minute */
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+ tvp = &tv;
+ }
+ 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;
+ if (FD_ISSET(signal_pipe, &rfds)) {
+ ret = handle_signal();
+ if (ret < 0)
+ goto out;
+ }
+ if (remove_pid)
+ continue;
+ if (snapshot_removal_status == HS_PRE_SUCCESS) {
+ ret = exec_rm();
+ if (ret < 0)
+ goto out;
+ continue;
+ }
+ if (snapshot_removal_status == HS_SUCCESS) {
+ ret = post_remove_hook();
+ if (ret < 0)
+ goto out;
+ continue;
+ }
+ ret = disk_space_low();
+ if (ret < 0)
+ goto out;
+ low_disk_space = ret;
+ ret = try_to_free_disk_space(low_disk_space);
+ if (ret < 0)
+ goto out;
+ if (snapshot_removal_status != HS_READY) {
+ stop_create_process();
+ continue;
+ }
+ restart_create_process();
+ switch (snapshot_creation_status) {
+ case HS_READY:
+ if (!next_snapshot_is_due())
+ continue;
+ ret = pre_create_hook();
+ if (ret < 0)
+ goto out;
+ continue;
+ case HS_PRE_RUNNING:
+ case HS_RUNNING:
+ 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 */
+ case HS_NEEDS_RESTART:
+ ret = create_snapshot(rsync_argv);
+ if (ret < 0)
+ goto out;
+ continue;
+ case HS_SUCCESS:
+ ret = post_create_hook();
+ if (ret < 0)
+ goto out;
+ continue;
+ }
+ }
+out:
+ return ret;
+}
+
+static void exit_hook(int exit_code)