From 57a366a8e1a2768de90e36bb044295b7eef777dd Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Fri, 15 Feb 2013 16:39:27 +0000 Subject: [PATCH] Fix #1605 - timeshift: correct mistake in file refcounting. (cherry picked from commit c33880290202d7181b51da968cd6247328225c92) --- src/timeshift/private.h | 6 ++++-- src/timeshift/timeshift_filemgr.c | 35 ++++++++++++++++++++++++------- src/timeshift/timeshift_reader.c | 19 +++++++++++++---- src/timeshift/timeshift_writer.c | 1 + 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/timeshift/private.h b/src/timeshift/private.h index 0a7f5b86..435eb4f8 100644 --- a/src/timeshift/private.h +++ b/src/timeshift/private.h @@ -137,10 +137,12 @@ void timeshift_filemgr_init ( void ); void timeshift_filemgr_term ( void ); int timeshift_filemgr_makedirs ( int ts_index, char *buf, size_t len ); -timeshift_file_t *timeshift_filemgr_last - ( timeshift_t *ts ); timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create ); +timeshift_file_t *timeshift_filemgr_oldest + ( timeshift_t *ts ); +timeshift_file_t *timeshift_filemgr_newest + ( timeshift_t *ts ); timeshift_file_t *timeshift_filemgr_prev ( timeshift_file_t *ts, int *end, int keep ); timeshift_file_t *timeshift_filemgr_next diff --git a/src/timeshift/timeshift_filemgr.c b/src/timeshift/timeshift_filemgr.c index 19bc6b43..cf6906e2 100644 --- a/src/timeshift/timeshift_filemgr.c +++ b/src/timeshift/timeshift_filemgr.c @@ -161,6 +161,7 @@ void timeshift_filemgr_remove { if (tsf->fd != -1) close(tsf->fd); + tvhlog(LOG_DEBUG, "timeshift", "ts %d remove %s\n", ts->id, tsf->path); TAILQ_REMOVE(&ts->files, tsf, link); atomic_add_u64(×hift_total_size, -tsf->size); timeshift_reaper_remove(tsf); @@ -192,7 +193,7 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create ) /* Return last file */ if (!create) - return TAILQ_LAST(&ts->files, timeshift_file_list); + return timeshift_filemgr_newest(ts); /* No space */ if (ts->full) @@ -216,9 +217,7 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create ) if (!tsf_hd->refcount) { timeshift_filemgr_remove(ts, tsf_hd, 0); } else { -#ifdef TSHFT_TRACE tvhlog(LOG_DEBUG, "timeshift", "ts %d buffer full", ts->id); -#endif ts->full = 1; } } @@ -227,8 +226,16 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create ) /* Check size */ if (!timeshift_unlimited_size && atomic_pre_add_u64(×hift_total_size, 0) >= timeshift_max_size) { - tvhlog(LOG_DEBUG, "timshift", "ts %d buffer full", ts->id); - ts->full = 1; + + /* Remove the last file (if we can) */ + if (!tsf_hd->refcount) { + timeshift_filemgr_remove(ts, tsf_hd, 0); + + /* Full */ + } else { + tvhlog(LOG_DEBUG, "timshift", "ts %d buffer full", ts->id); + ts->full = 1; + } } /* Create new file */ @@ -273,6 +280,7 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create ) tsf_tl = tsf_tmp; } + tsf_tl->refcount++; return tsf_tl; } @@ -303,11 +311,24 @@ timeshift_file_t *timeshift_filemgr_prev /* * Get the oldest file */ -timeshift_file_t *timeshift_filemgr_last ( timeshift_t *ts ) +timeshift_file_t *timeshift_filemgr_oldest ( timeshift_t *ts ) { - return TAILQ_FIRST(&ts->files); + timeshift_file_t *tsf = TAILQ_FIRST(&ts->files); + if (tsf) + tsf->refcount++; + return tsf; } +/* + * Get the newest file + */ +timeshift_file_t *timeshift_filemgr_newest ( timeshift_t *ts ) +{ + timeshift_file_t *tsf = TAILQ_LAST(&ts->files, timeshift_file_list); + if (tsf) + tsf->refcount++; + return tsf; +} /* ************************************************************************** * Setup / Teardown diff --git a/src/timeshift/timeshift_reader.c b/src/timeshift/timeshift_reader.c index 70bd9d0a..e2d4437e 100644 --- a/src/timeshift/timeshift_reader.c +++ b/src/timeshift/timeshift_reader.c @@ -192,10 +192,11 @@ static timeshift_index_iframe_t *_timeshift_first_frame { int end; timeshift_index_iframe_t *tsi = NULL; - timeshift_file_t *tsf = timeshift_filemgr_last(ts); + timeshift_file_t *tsf = timeshift_filemgr_oldest(ts); while (tsf && !tsi) { - if (!(tsi = TAILQ_FIRST(&tsf->iframes))) + if (!(tsi = TAILQ_FIRST(&tsf->iframes))) { tsf = timeshift_filemgr_next(tsf, &end, 0); + } } if (tsf) tsf->refcount--; @@ -209,8 +210,9 @@ static timeshift_index_iframe_t *_timeshift_last_frame timeshift_index_iframe_t *tsi = NULL; timeshift_file_t *tsf = timeshift_filemgr_get(ts, 0); while (tsf && !tsi) { - if (!(tsi = TAILQ_LAST(&tsf->iframes, timeshift_index_iframe_list))) + if (!(tsi = TAILQ_LAST(&tsf->iframes, timeshift_index_iframe_list))) { tsf = timeshift_filemgr_prev(tsf, &end, 0); + } } if (tsf) tsf->refcount--; @@ -227,6 +229,10 @@ static int _timeshift_skip int64_t sec = req_time / (1000000 * TIMESHIFT_FILE_PERIOD); int back = (req_time < cur_time) ? 1 : 0; int end = 0; + + /* Hold local ref */ + if (cur_file) + cur_file->refcount++; /* Coarse search */ if (!tsi) { @@ -272,7 +278,7 @@ static int _timeshift_skip /* Find start/end of buffer */ if (end) { if (back) { - tsf = timeshift_filemgr_last(ts); + tsf = timeshift_filemgr_oldest(ts); tsi = NULL; while (tsf && !tsi) { if (!(tsi = TAILQ_FIRST(&tsf->iframes))) @@ -290,6 +296,9 @@ static int _timeshift_skip } } + if (cur_file) + cur_file->refcount--; + /* Done */ *new_file = tsf; *iframe = tsi; @@ -667,6 +676,8 @@ void *timeshift_reader ( void *p ) } /* Position */ + if (cur_file) + cur_file->refcount--; cur_file = tsf; if (tsi) cur_off = tsi->pos; diff --git a/src/timeshift/timeshift_writer.c b/src/timeshift/timeshift_writer.c index 06810a86..0e2f50ae 100644 --- a/src/timeshift/timeshift_writer.c +++ b/src/timeshift/timeshift_writer.c @@ -271,6 +271,7 @@ static void _process_msg tsf->bad = 1; ts->full = 1; ///< Stop any more writing } + tsf->refcount--; } pthread_mutex_unlock(&ts->rdwr_mutex); break;