diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2017-04-01 10:19:52 -0400 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2017-04-01 13:01:20 -0400 |
commit | b3de64e7c11db0d7b0a37827be36e8749d36d942 (patch) | |
tree | 1fbf253d1380036d7a9ed850cb9d2ef1ddf3df35 | |
parent | 4f03c566cc4074bd8bbc35b212d0d0ce839c5c24 (diff) | |
download | rockbox-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.c | 73 |
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; | |||
209 | 209 | ||
210 | #ifdef HAVE_TC_RAMCACHE | 210 | #ifdef HAVE_TC_RAMCACHE |
211 | 211 | ||
212 | #define TC_ALIGN_PTR(p, gap_out_p) \ | 212 | #define TC_ALIGN_PTR(p, type, gap_out_p) \ |
213 | ({ typeof (p) __p = (p); \ | 213 | ({ typeof (p) __p = (p); \ |
214 | typeof (p) __palgn = ALIGN_UP(__p, sizeof (intptr_t)); \ | 214 | typeof (p) __palgn = ALIGN_UP(__p, __alignof__(type)); \ |
215 | *(gap_out_p) = __palgn - __p; \ | 215 | *(gap_out_p) = (char *)__palgn - (char *)__p; \ |
216 | __palgn; }) | 216 | __palgn; }) |
217 | 217 | ||
218 | #define IF_TCRCDC(...) IF_DIRCACHE(__VA_ARGS__) | 218 | #define IF_TCRCDC(...) IF_DIRCACHE(__VA_ARGS__) |
@@ -3872,14 +3872,15 @@ static struct buflib_callbacks ops = { | |||
3872 | 3872 | ||
3873 | static bool allocate_tagcache(void) | 3873 | static bool allocate_tagcache(void) |
3874 | { | 3874 | { |
3875 | tc_stat.ramcache_allocated = 0; | ||
3876 | tcramcache.handle = 0; | ||
3877 | tcramcache.hdr = NULL; | ||
3878 | |||
3875 | /* Load the header. */ | 3879 | /* Load the header. */ |
3876 | struct master_header tcmh; | 3880 | struct master_header tcmh; |
3877 | int fd = open_master_fd(&tcmh, false); | 3881 | int fd = open_master_fd(&tcmh, false); |
3878 | if (fd < 0) | 3882 | if (fd < 0) |
3879 | { | ||
3880 | tcramcache.hdr = NULL; | ||
3881 | return false; | 3883 | return false; |
3882 | } | ||
3883 | 3884 | ||
3884 | close(fd); | 3885 | close(fd); |
3885 | 3886 | ||
@@ -3887,8 +3888,6 @@ static bool allocate_tagcache(void) | |||
3887 | * Now calculate the required cache size plus | 3888 | * Now calculate the required cache size plus |
3888 | * some extra space for alignment fixes. | 3889 | * some extra space for alignment fixes. |
3889 | */ | 3890 | */ |
3890 | tc_stat.ramcache_allocated = 0; | ||
3891 | |||
3892 | size_t alloc_size = tcmh.tch.datasize + 256 + TAGCACHE_RESERVE + | 3891 | size_t alloc_size = tcmh.tch.datasize + 256 + TAGCACHE_RESERVE + |
3893 | sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *); | 3892 | sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *); |
3894 | #ifdef HAVE_DIRCACHE | 3893 | #ifdef HAVE_DIRCACHE |
@@ -3899,14 +3898,13 @@ static bool allocate_tagcache(void) | |||
3899 | if (handle <= 0) | 3898 | if (handle <= 0) |
3900 | return false; | 3899 | return false; |
3901 | 3900 | ||
3902 | void *data = core_get_data(handle); | 3901 | tcramcache.handle = handle; |
3903 | 3902 | tcramcache.hdr = core_get_data(handle); | |
3904 | tcramcache.hdr = data; | ||
3905 | tc_stat.ramcache_allocated = alloc_size; | 3903 | tc_stat.ramcache_allocated = alloc_size; |
3906 | 3904 | ||
3907 | memset(tcramcache.hdr, 0, sizeof(struct ramcache_header)); | 3905 | memset(tcramcache.hdr, 0, sizeof(struct ramcache_header)); |
3908 | memcpy(¤t_tcmh, &tcmh, sizeof current_tcmh); | 3906 | memcpy(¤t_tcmh, &tcmh, sizeof current_tcmh); |
3909 | logf("tagcache: %lu bytes allocated.", tc_stat.ramcache_allocated); | 3907 | logf("tagcache: %d bytes allocated.", tc_stat.ramcache_allocated); |
3910 | 3908 | ||
3911 | return true; | 3909 | return true; |
3912 | } | 3910 | } |
@@ -3917,6 +3915,7 @@ static bool tagcache_dumpload(void) | |||
3917 | struct statefile_header shdr; | 3915 | struct statefile_header shdr; |
3918 | int fd, rc, handle; | 3916 | int fd, rc, handle; |
3919 | 3917 | ||
3918 | tcramcache.handle = 0; | ||
3920 | tcramcache.hdr = NULL; | 3919 | tcramcache.hdr = NULL; |
3921 | 3920 | ||
3922 | fd = open(TAGCACHE_STATEFILE, O_RDONLY); | 3921 | fd = open(TAGCACHE_STATEFILE, O_RDONLY); |
@@ -3946,6 +3945,7 @@ static bool tagcache_dumpload(void) | |||
3946 | } | 3945 | } |
3947 | 3946 | ||
3948 | tcrc_buffer_lock(); | 3947 | tcrc_buffer_lock(); |
3948 | tcramcache.handle = handle; | ||
3949 | tcramcache.hdr = core_get_data(handle); | 3949 | tcramcache.hdr = core_get_data(handle); |
3950 | rc = read(fd, tcramcache.hdr, shdr.tc_stat.ramcache_allocated); | 3950 | rc = read(fd, tcramcache.hdr, shdr.tc_stat.ramcache_allocated); |
3951 | tcrc_buffer_unlock(); | 3951 | tcrc_buffer_unlock(); |
@@ -4019,6 +4019,8 @@ static bool load_tagcache(void) | |||
4019 | #endif /* HAVE_DIRCACHE */ | 4019 | #endif /* HAVE_DIRCACHE */ |
4020 | 4020 | ||
4021 | logf("loading tagcache to ram..."); | 4021 | logf("loading tagcache to ram..."); |
4022 | |||
4023 | tcrc_buffer_lock(); /* lock for the rest of the scan, simpler to handle */ | ||
4022 | 4024 | ||
4023 | fd = open(TAGCACHE_FILE_MASTER, O_RDONLY); | 4025 | fd = open(TAGCACHE_FILE_MASTER, O_RDONLY); |
4024 | if (fd < 0) | 4026 | if (fd < 0) |
@@ -4027,8 +4029,6 @@ static bool load_tagcache(void) | |||
4027 | goto failure; | 4029 | goto failure; |
4028 | } | 4030 | } |
4029 | 4031 | ||
4030 | tcrc_buffer_lock(); /* lock for the rest of the scan, simpler to handle */ | ||
4031 | |||
4032 | struct master_header tcmh; | 4032 | struct master_header tcmh; |
4033 | if (ecread(fd, &tcmh, 1, master_header_ec, tc_stat.econ) | 4033 | if (ecread(fd, &tcmh, 1, master_header_ec, tc_stat.econ) |
4034 | != sizeof(struct master_header) | 4034 | != sizeof(struct master_header) |
@@ -4072,7 +4072,7 @@ static bool load_tagcache(void) | |||
4072 | if (TAGCACHE_IS_NUMERIC(tag)) | 4072 | if (TAGCACHE_IS_NUMERIC(tag)) |
4073 | continue; | 4073 | continue; |
4074 | 4074 | ||
4075 | p = TC_ALIGN_PTR(p, &rc); | 4075 | p = TC_ALIGN_PTR(p, struct tagcache_header, &rc); |
4076 | bytesleft -= rc; | 4076 | bytesleft -= rc; |
4077 | if (bytesleft < (ssize_t)sizeof(struct tagcache_header)) | 4077 | if (bytesleft < (ssize_t)sizeof(struct tagcache_header)) |
4078 | { | 4078 | { |
@@ -4100,7 +4100,7 @@ static bool load_tagcache(void) | |||
4100 | if (do_timed_yield() && check_event_queue()) | 4100 | if (do_timed_yield() && check_event_queue()) |
4101 | goto failure; | 4101 | goto failure; |
4102 | 4102 | ||
4103 | p = TC_ALIGN_PTR(p, &rc); | 4103 | p = TC_ALIGN_PTR(p, struct tagfile_entry, &rc); |
4104 | bytesleft -= rc; | 4104 | bytesleft -= rc; |
4105 | if (bytesleft < (ssize_t)sizeof(struct tagfile_entry)) | 4105 | if (bytesleft < (ssize_t)sizeof(struct tagfile_entry)) |
4106 | { | 4106 | { |
@@ -4119,20 +4119,31 @@ static bool load_tagcache(void) | |||
4119 | goto failure; | 4119 | goto failure; |
4120 | } | 4120 | } |
4121 | 4121 | ||
4122 | /* We have a special handling for the filename tags; neither the | 4122 | int idx_id = fe->idx_id; /* dircache reference clobbers *fe */ |
4123 | paths nor the entry headers are stored; only the tagcache header | 4123 | struct index_entry *idx = &tcramcache.hdr->indices[idx_id]; |
4124 | and dircache references are. */ | 4124 | |
4125 | if (tag == tag_filename) | 4125 | if (idx_id != -1 || tag == tag_filename) /* filename NOT optional */ |
4126 | { | 4126 | { |
4127 | int idx_id = fe->idx_id; /* gonna clobber tagfile entry */ | ||
4128 | if (idx_id < 0 || idx_id >= tcmh.tch.entry_count) | 4127 | if (idx_id < 0 || idx_id >= tcmh.tch.entry_count) |
4129 | { | 4128 | { |
4130 | logf("corrupt tagfile entry (tag: %d)", tag); | 4129 | logf("corrupt tagfile entry:tag=%d:idxid=%d", tag, idx_id); |
4131 | goto failure; | 4130 | goto failure; |
4132 | } | 4131 | } |
4133 | 4132 | ||
4134 | struct index_entry *idx = &tcramcache.hdr->indices[idx_id]; | 4133 | if (idx->tag_seek[tag] != pos) |
4134 | { | ||
4135 | logf("corrupt data structures!:"); | ||
4136 | logf(" tag_seek[%d]=%ld:pos=%ld", tag, | ||
4137 | idx->tag_seek[tag], pos); | ||
4138 | goto failure; | ||
4139 | } | ||
4140 | } | ||
4135 | 4141 | ||
4142 | /* We have a special handling for the filename tags; neither the | ||
4143 | paths nor the entry headers are stored; only the tagcache header | ||
4144 | and dircache references are. */ | ||
4145 | if (tag == tag_filename) | ||
4146 | { | ||
4136 | #ifdef HAVE_DIRCACHE | 4147 | #ifdef HAVE_DIRCACHE |
4137 | if (idx->flag & FLAG_DIRCACHE) | 4148 | if (idx->flag & FLAG_DIRCACHE) |
4138 | { | 4149 | { |
@@ -4145,12 +4156,6 @@ static bool load_tagcache(void) | |||
4145 | bytesleft -= sizeof (struct dircache_fileref); | 4156 | bytesleft -= sizeof (struct dircache_fileref); |
4146 | #endif /* HAVE_DIRCACHE */ | 4157 | #endif /* HAVE_DIRCACHE */ |
4147 | 4158 | ||
4148 | if (idx->tag_seek[tag] != pos) | ||
4149 | { | ||
4150 | logf("corrupt data structures!"); | ||
4151 | goto failure; | ||
4152 | } | ||
4153 | |||
4154 | char filename[TAG_MAXLEN+32]; | 4159 | char filename[TAG_MAXLEN+32]; |
4155 | if (fe->tag_length >= (long)sizeof(filename)-1) | 4160 | if (fe->tag_length >= (long)sizeof(filename)-1) |
4156 | { | 4161 | { |
@@ -4163,11 +4168,14 @@ static bool load_tagcache(void) | |||
4163 | 4168 | ||
4164 | if ((idx->flag & FLAG_DELETED) IFN_DIRCACHE( || !auto_update )) | 4169 | if ((idx->flag & FLAG_DELETED) IFN_DIRCACHE( || !auto_update )) |
4165 | { | 4170 | { |
4171 | /* seek over tag data instead of reading */ | ||
4166 | if (lseek(fd, fe->tag_length, SEEK_CUR) < 0) | 4172 | if (lseek(fd, fe->tag_length, SEEK_CUR) < 0) |
4167 | { | 4173 | { |
4168 | logf("read error #11.5"); | 4174 | logf("read error #11.5"); |
4169 | goto failure; | 4175 | goto failure; |
4170 | } | 4176 | } |
4177 | |||
4178 | continue; | ||
4171 | } | 4179 | } |
4172 | 4180 | ||
4173 | if (read(fd, filename, fe->tag_length) != fe->tag_length) | 4181 | if (read(fd, filename, fe->tag_length) != fe->tag_length) |
@@ -4191,7 +4199,7 @@ static bool load_tagcache(void) | |||
4191 | else if (auto_update) | 4199 | else if (auto_update) |
4192 | #else /* ndef HAVE_DIRCACHE */ | 4200 | #else /* ndef HAVE_DIRCACHE */ |
4193 | /* Check if path is no longer valid */ | 4201 | /* Check if path is no longer valid */ |
4194 | if (auto_update && !file_exists(filename)) | 4202 | if (!file_exists(filename)) |
4195 | #endif /* HAVE_DIRCACHE */ | 4203 | #endif /* HAVE_DIRCACHE */ |
4196 | { | 4204 | { |
4197 | logf("Entry no longer valid."); | 4205 | logf("Entry no longer valid."); |
@@ -4218,7 +4226,7 @@ static bool load_tagcache(void) | |||
4218 | if (rc != fe->tag_length) | 4226 | if (rc != fe->tag_length) |
4219 | { | 4227 | { |
4220 | logf("read error #13"); | 4228 | logf("read error #13"); |
4221 | logf("rc=0x%04x", rc); // 0x431 | 4229 | logf("rc=0x%04x", (unsigned int)rc); // 0x431 |
4222 | logf("len=0x%04lx", fe->tag_length); // 0x4000 | 4230 | logf("len=0x%04lx", fe->tag_length); // 0x4000 |
4223 | logf("pos=0x%04lx", lseek(fd, 0, SEEK_CUR)); // 0x433 | 4231 | logf("pos=0x%04lx", lseek(fd, 0, SEEK_CUR)); // 0x433 |
4224 | logf("tag=0x%02x", tag); // 0x00 | 4232 | logf("tag=0x%02x", tag); // 0x00 |
@@ -4661,6 +4669,9 @@ static void load_ramcache(void) | |||
4661 | * so disable it entirely to prevent further issues. */ | 4669 | * so disable it entirely to prevent further issues. */ |
4662 | tc_stat.ready = false; | 4670 | tc_stat.ready = false; |
4663 | tcramcache.hdr = NULL; | 4671 | tcramcache.hdr = NULL; |
4672 | int handle = tcramcache.handle; | ||
4673 | tcramcache.handle = 0; | ||
4674 | core_free(handle); | ||
4664 | } | 4675 | } |
4665 | 4676 | ||
4666 | cpu_boost(false); | 4677 | cpu_boost(false); |