With the old code, it was possible that dss decided to remove the
snapshot which is currently being used as the hardlink directory for
the current rsync process. This patch changes the behaviour so that
reference snapshots are never removed.
The downside of this approach is of course that it is now easier to
fill up the disk..
static struct timeval next_removal_check;
/** Creation time of the snapshot currently being created. */
static int64_t current_snapshot_creation_time;
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. */
+/** The snapshot currently being removed. */
struct snapshot *snapshot_currently_being_removed;
/** Needed by the post-create hook. */
static char *path_to_last_complete_snapshot;
struct snapshot *snapshot_currently_being_removed;
/** Needed by the post-create hook. */
static char *path_to_last_complete_snapshot;
+static char *name_of_reference_snapshot;
/** \sa \ref snap.h for details. */
enum hook_status snapshot_creation_status;
/** \sa \ref snap.h for details. */
/** \sa \ref snap.h for details. */
enum hook_status snapshot_creation_status;
/** \sa \ref snap.h for details. */
+static int is_reference_snapshot(struct snapshot *s)
+{
+ if (!name_of_reference_snapshot)
+ return 0;
+ return strcmp(s->name, name_of_reference_snapshot)? 0 : 1;
+}
+
/*
* return: 0: no redundant snapshots, 1: rm process started, negative: error
*/
/*
* return: 0: no redundant snapshots, 1: rm process started, negative: error
*/
if (snapshot_is_being_created(s))
continue;
if (snapshot_is_being_created(s))
continue;
+ if (is_reference_snapshot(s))
+ continue;
//DSS_DEBUG_LOG("checking %s\n", s->name);
if (s->interval > interval) {
prev = s;
//DSS_DEBUG_LOG("checking %s\n", s->name);
if (s->interval > interval) {
prev = s;
FOR_EACH_SNAPSHOT(s, i, sl) {
if (snapshot_is_being_created(s))
continue;
FOR_EACH_SNAPSHOT(s, i, sl) {
if (snapshot_is_being_created(s))
continue;
+ if (is_reference_snapshot(s))
+ continue;
if (s->interval <= conf.num_intervals_arg)
continue;
return s;
if (s->interval <= conf.num_intervals_arg)
continue;
return s;
struct snapshot *find_oldest_removable_snapshot(struct snapshot_list *sl)
{
struct snapshot *find_oldest_removable_snapshot(struct snapshot_list *sl)
{
- struct snapshot *s = get_oldest_snapshot(sl);
-
- if (!s) /* no snapshot found */
- return NULL;
- DSS_INFO_LOG("oldest snapshot: %s\n", s->name);
- if (snapshot_is_being_created(s))
- return NULL;
- return s;
+ int i;
+ struct snapshot *s;
+ FOR_EACH_SNAPSHOT(s, i, sl) {
+ if (snapshot_is_being_created(s))
+ continue;
+ if (is_reference_snapshot(s))
+ continue;
+ DSS_INFO_LOG("oldest removable snapshot: %s\n", s->name);
+ return s;
+ }
+ return NULL;
}
static int rename_incomplete_snapshot(int64_t start)
}
static int rename_incomplete_snapshot(int64_t start)
victim = find_oldest_removable_snapshot(&sl);
if (victim)
goto remove;
victim = find_oldest_removable_snapshot(&sl);
if (victim)
goto remove;
- DSS_CRIT_LOG("uhuhu: not enough disk space for a single snapshot\n");
+ DSS_CRIT_LOG("uhuhu: disk space low and nothing to remove\n");
ret = -ERRNO_TO_DSS_ERROR(ENOSPC);
goto out;
remove:
ret = -ERRNO_TO_DSS_ERROR(ENOSPC);
goto out;
remove:
if (ret < 0)
goto out;
snapshot_creation_status = HS_SUCCESS;
if (ret < 0)
goto out;
snapshot_creation_status = HS_SUCCESS;
+ free(name_of_reference_snapshot);
+ name_of_reference_snapshot = NULL;
out:
create_pid = 0;
create_process_stopped = 0;
out:
create_pid = 0;
create_process_stopped = 0;
static void create_rsync_argv(char ***argv, int64_t *num)
{
static void create_rsync_argv(char ***argv, int64_t *num)
{
- char *logname, *newest;
int i = 0, j;
struct snapshot_list sl;
dss_get_snapshot_list(&sl);
int i = 0, j;
struct snapshot_list sl;
dss_get_snapshot_list(&sl);
- newest = name_of_newest_complete_snapshot(&sl);
+ assert(!name_of_reference_snapshot);
+ name_of_reference_snapshot = name_of_newest_complete_snapshot(&sl);
free_snapshot_list(&sl);
*argv = dss_malloc((15 + conf.rsync_option_given) * sizeof(char *));
free_snapshot_list(&sl);
*argv = dss_malloc((15 + conf.rsync_option_given) * sizeof(char *));
(*argv)[i++] = dss_strdup("--delete");
for (j = 0; j < conf.rsync_option_given; j++)
(*argv)[i++] = dss_strdup(conf.rsync_option_arg[j]);
(*argv)[i++] = dss_strdup("--delete");
for (j = 0; j < conf.rsync_option_given; j++)
(*argv)[i++] = dss_strdup(conf.rsync_option_arg[j]);
- if (newest) {
- DSS_INFO_LOG("using %s as reference snapshot\n", newest);
- (*argv)[i++] = make_message("--link-dest=../%s", newest);
- free(newest);
+ if (name_of_reference_snapshot) {
+ DSS_INFO_LOG("using %s as reference\n", name_of_reference_snapshot);
+ (*argv)[i++] = make_message("--link-dest=../%s",
+ name_of_reference_snapshot);
- DSS_INFO_LOG("no previous snapshot found\n");
+ DSS_INFO_LOG("no suitable reference snapshot found\n");
logname = dss_logname();
if (use_rsync_locally(logname))
(*argv)[i++] = dss_strdup(conf.source_dir_arg);
logname = dss_logname();
if (use_rsync_locally(logname))
(*argv)[i++] = dss_strdup(conf.source_dir_arg);
int complete_name(int64_t start, int64_t end, char **result);
__malloc char *name_of_newest_complete_snapshot(struct snapshot_list *sl);
int complete_name(int64_t start, int64_t end, char **result);
__malloc char *name_of_newest_complete_snapshot(struct snapshot_list *sl);
-/**
- * Get the oldest snapshot in a snapshot list.
- */
-_static_inline_ struct snapshot *get_oldest_snapshot(struct snapshot_list *sl)
-{
- if (!sl->num_snapshots)
- return NULL;
- return sl->snapshots[0];
-}
-
/**
* Get the newest snapshot in a snapshot list.
*/
/**
* Get the newest snapshot in a snapshot list.
*/