Fix #1605 - timeshift: correct mistake in file refcounting.

(cherry picked from commit c338802902)
This commit is contained in:
Adam Sutton 2013-02-15 16:39:27 +00:00
parent 86f7e8ab1b
commit 57a366a8e1
4 changed files with 48 additions and 13 deletions

View file

@ -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

View file

@ -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(&timeshift_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(&timeshift_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

View file

@ -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;

View file

@ -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;