summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2017-04-01 10:19:52 -0400
committerMichael Sevakis <jethead71@rockbox.org>2017-04-01 13:01:20 -0400
commitb3de64e7c11db0d7b0a37827be36e8749d36d942 (patch)
tree1fbf253d1380036d7a9ed850cb9d2ef1ddf3df35
parent4f03c566cc4074bd8bbc35b212d0d0ce839c5c24 (diff)
downloadrockbox-b3de64e7c11db0d7b0a37827be36e8749d36d942.tar.gz
rockbox-b3de64e7c11db0d7b0a37827be36e8749d36d942.zip
Database: Fix destabilization if ramcache fails to load + misc.
It seems to like not having any idea any attempt was made to load it so just try to put it back like the option was never on. Integrity check other tags besides the filename. Fix a few logfs that spat out warnings and add a bit more detail to a couple. Move a buffer lock to the right spot. Better aligning macro. Add a "continue" that should have been there when filename is seeked over during load. Change-Id: Ib0c517a7b77d3ba0dd6530ddef19bed62116e4a8
-rw-r--r--apps/tagcache.c73
1 files changed, 42 insertions, 31 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 6b6e4839d5..e1b99bd3a7 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -209,10 +209,10 @@ static struct master_header current_tcmh;
#ifdef HAVE_TC_RAMCACHE
-#define TC_ALIGN_PTR(p, gap_out_p) \
+#define TC_ALIGN_PTR(p, type, gap_out_p) \
({ typeof (p) __p = (p); \
- typeof (p) __palgn = ALIGN_UP(__p, sizeof (intptr_t)); \
- *(gap_out_p) = __palgn - __p; \
+ typeof (p) __palgn = ALIGN_UP(__p, __alignof__(type)); \
+ *(gap_out_p) = (char *)__palgn - (char *)__p; \
__palgn; })
#define IF_TCRCDC(...) IF_DIRCACHE(__VA_ARGS__)
@@ -3872,14 +3872,15 @@ static struct buflib_callbacks ops = {
static bool allocate_tagcache(void)
{
+ tc_stat.ramcache_allocated = 0;
+ tcramcache.handle = 0;
+ tcramcache.hdr = NULL;
+
/* Load the header. */
struct master_header tcmh;
int fd = open_master_fd(&tcmh, false);
if (fd < 0)
- {
- tcramcache.hdr = NULL;
return false;
- }
close(fd);
@@ -3887,8 +3888,6 @@ static bool allocate_tagcache(void)
* Now calculate the required cache size plus
* some extra space for alignment fixes.
*/
- tc_stat.ramcache_allocated = 0;
-
size_t alloc_size = tcmh.tch.datasize + 256 + TAGCACHE_RESERVE +
sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *);
#ifdef HAVE_DIRCACHE
@@ -3899,14 +3898,13 @@ static bool allocate_tagcache(void)
if (handle <= 0)
return false;
- void *data = core_get_data(handle);
-
- tcramcache.hdr = data;
+ tcramcache.handle = handle;
+ tcramcache.hdr = core_get_data(handle);
tc_stat.ramcache_allocated = alloc_size;
memset(tcramcache.hdr, 0, sizeof(struct ramcache_header));
memcpy(&current_tcmh, &tcmh, sizeof current_tcmh);
- logf("tagcache: %lu bytes allocated.", tc_stat.ramcache_allocated);
+ logf("tagcache: %d bytes allocated.", tc_stat.ramcache_allocated);
return true;
}
@@ -3917,6 +3915,7 @@ static bool tagcache_dumpload(void)
struct statefile_header shdr;
int fd, rc, handle;
+ tcramcache.handle = 0;
tcramcache.hdr = NULL;
fd = open(TAGCACHE_STATEFILE, O_RDONLY);
@@ -3946,6 +3945,7 @@ static bool tagcache_dumpload(void)
}
tcrc_buffer_lock();
+ tcramcache.handle = handle;
tcramcache.hdr = core_get_data(handle);
rc = read(fd, tcramcache.hdr, shdr.tc_stat.ramcache_allocated);
tcrc_buffer_unlock();
@@ -4019,6 +4019,8 @@ static bool load_tagcache(void)
#endif /* HAVE_DIRCACHE */
logf("loading tagcache to ram...");
+
+ tcrc_buffer_lock(); /* lock for the rest of the scan, simpler to handle */
fd = open(TAGCACHE_FILE_MASTER, O_RDONLY);
if (fd < 0)
@@ -4027,8 +4029,6 @@ static bool load_tagcache(void)
goto failure;
}
- tcrc_buffer_lock(); /* lock for the rest of the scan, simpler to handle */
-
struct master_header tcmh;
if (ecread(fd, &tcmh, 1, master_header_ec, tc_stat.econ)
!= sizeof(struct master_header)
@@ -4072,7 +4072,7 @@ static bool load_tagcache(void)
if (TAGCACHE_IS_NUMERIC(tag))
continue;
- p = TC_ALIGN_PTR(p, &rc);
+ p = TC_ALIGN_PTR(p, struct tagcache_header, &rc);
bytesleft -= rc;
if (bytesleft < (ssize_t)sizeof(struct tagcache_header))
{
@@ -4100,7 +4100,7 @@ static bool load_tagcache(void)
if (do_timed_yield() && check_event_queue())
goto failure;
- p = TC_ALIGN_PTR(p, &rc);
+ p = TC_ALIGN_PTR(p, struct tagfile_entry, &rc);
bytesleft -= rc;
if (bytesleft < (ssize_t)sizeof(struct tagfile_entry))
{
@@ -4119,20 +4119,31 @@ static bool load_tagcache(void)
goto failure;
}
- /* We have a special handling for the filename tags; neither the
- paths nor the entry headers are stored; only the tagcache header
- and dircache references are. */
- if (tag == tag_filename)
+ int idx_id = fe->idx_id; /* dircache reference clobbers *fe */
+ struct index_entry *idx = &tcramcache.hdr->indices[idx_id];
+
+ if (idx_id != -1 || tag == tag_filename) /* filename NOT optional */
{
- int idx_id = fe->idx_id; /* gonna clobber tagfile entry */
if (idx_id < 0 || idx_id >= tcmh.tch.entry_count)
{
- logf("corrupt tagfile entry (tag: %d)", tag);
+ logf("corrupt tagfile entry:tag=%d:idxid=%d", tag, idx_id);
goto failure;
}
- struct index_entry *idx = &tcramcache.hdr->indices[idx_id];
+ if (idx->tag_seek[tag] != pos)
+ {
+ logf("corrupt data structures!:");
+ logf(" tag_seek[%d]=%ld:pos=%ld", tag,
+ idx->tag_seek[tag], pos);
+ goto failure;
+ }
+ }
+ /* We have a special handling for the filename tags; neither the
+ paths nor the entry headers are stored; only the tagcache header
+ and dircache references are. */
+ if (tag == tag_filename)
+ {
#ifdef HAVE_DIRCACHE
if (idx->flag & FLAG_DIRCACHE)
{
@@ -4145,12 +4156,6 @@ static bool load_tagcache(void)
bytesleft -= sizeof (struct dircache_fileref);
#endif /* HAVE_DIRCACHE */
- if (idx->tag_seek[tag] != pos)
- {
- logf("corrupt data structures!");
- goto failure;
- }
-
char filename[TAG_MAXLEN+32];
if (fe->tag_length >= (long)sizeof(filename)-1)
{
@@ -4163,11 +4168,14 @@ static bool load_tagcache(void)
if ((idx->flag & FLAG_DELETED) IFN_DIRCACHE( || !auto_update ))
{
+ /* seek over tag data instead of reading */
if (lseek(fd, fe->tag_length, SEEK_CUR) < 0)
{
logf("read error #11.5");
goto failure;
}
+
+ continue;
}
if (read(fd, filename, fe->tag_length) != fe->tag_length)
@@ -4191,7 +4199,7 @@ static bool load_tagcache(void)
else if (auto_update)
#else /* ndef HAVE_DIRCACHE */
/* Check if path is no longer valid */
- if (auto_update && !file_exists(filename))
+ if (!file_exists(filename))
#endif /* HAVE_DIRCACHE */
{
logf("Entry no longer valid.");
@@ -4218,7 +4226,7 @@ static bool load_tagcache(void)
if (rc != fe->tag_length)
{
logf("read error #13");
- logf("rc=0x%04x", rc); // 0x431
+ logf("rc=0x%04x", (unsigned int)rc); // 0x431
logf("len=0x%04lx", fe->tag_length); // 0x4000
logf("pos=0x%04lx", lseek(fd, 0, SEEK_CUR)); // 0x433
logf("tag=0x%02x", tag); // 0x00
@@ -4661,6 +4669,9 @@ static void load_ramcache(void)
* so disable it entirely to prevent further issues. */
tc_stat.ready = false;
tcramcache.hdr = NULL;
+ int handle = tcramcache.handle;
+ tcramcache.handle = 0;
+ core_free(handle);
}
cpu_boost(false);