summaryrefslogtreecommitdiff
path: root/firmware/common/file.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2017-01-08 17:14:10 -0500
committerMichael Sevakis <jethead71@rockbox.org>2017-01-17 14:35:36 -0500
commita931c76b3a46d1884e985a3bfc82b947521dab97 (patch)
tree1141cf9a9a8c123bde3d76d147ee1e910c7c6045 /firmware/common/file.c
parent0056ea8a256af0e2daaf451af43c00708a31d4df (diff)
downloadrockbox-a931c76b3a46d1884e985a3bfc82b947521dab97.tar.gz
rockbox-a931c76b3a46d1884e985a3bfc82b947521dab97.zip
Do some debug and preparatory work for ramcache and playlist
The file system rework introduced incompatibility between dircache and the tagcache ramcache and playlist dircache path caching. This update makes changes to filesystem code to reintegrate all that. It also fixes a couple bugs that were found when vetting all the code. The filestream cache was being reset without regard to the stream even if it was shared in write mode (made work of .playlist_control). Better handling of unmounting gives files a better go at force-closing them without risk to disk integrity. Did some miscellaneous pedantic changes. Improved efficiency of testing a file's existence (a little) since the path parser will be shared between file code and parsing for the sake of finding dircache references, not duplicated as before. This commit doesn't reenable said items just for the sake of keeping changes separate and related. Plan for the next is to enable dircache again for the playlists (easy peasy) and reenable tagcache ramcache but *without* the dircache path caching because it's rather substantial to change in itself. The ramcache will still function without dircache. Change-Id: I7e2a9910b866251fa8333e1275f72fcfc8425d2d
Diffstat (limited to 'firmware/common/file.c')
-rw-r--r--firmware/common/file.c57
1 files changed, 33 insertions, 24 deletions
diff --git a/firmware/common/file.c b/firmware/common/file.c
index 6444918f1b..1f93824dc8 100644
--- a/firmware/common/file.c
+++ b/firmware/common/file.c
@@ -54,7 +54,7 @@ static struct filestr_desc * get_filestr(int fildes)
54 return file; 54 return file;
55 55
56 DEBUGF("fildes %d: bad file number\n", fildes); 56 DEBUGF("fildes %d: bad file number\n", fildes);
57 errno = (file && file->stream.flags == FV_NONEXIST) ? ENXIO : EBADF; 57 errno = (file && (file->stream.flags & FD_NONEXIST)) ? ENXIO : EBADF;
58 return NULL; 58 return NULL;
59} 59}
60 60
@@ -187,24 +187,28 @@ file_error:
187 return rc; 187 return rc;
188} 188}
189 189
190/* callback for each file stream to make sure all data is in sync with new 190/* Handle syncing all file's streams to the truncation */
191 size */ 191static void handle_truncate(struct filestr_desc * const file, file_size_t size)
192void ftruncate_internal_callback(struct filestr_base *stream,
193 struct filestr_base *s)
194{ 192{
195 struct filestr_desc *file = (struct filestr_desc *)s; 193 unsigned long filesectors = filesize_sectors(size);
196 file_size_t size = *file->sizep;
197
198 /* caches with data beyond new extents are invalid */
199 unsigned long sector = file->stream.cachep->sector;
200 if (sector != INVALID_SECNUM && sector >= filesize_sectors(size))
201 filestr_discard_cache(&file->stream);
202 194
203 /* keep all positions within bounds */ 195 struct filestr_base *s = NULL;
204 if (file->offset > size) 196 while ((s = fileobj_get_next_stream(&file->stream, s)))
205 file->offset = size; 197 {
206 198 /* caches with data beyond new extents are invalid */
207 (void)stream; 199 unsigned long sector = s->cachep->sector;
200 if (sector != INVALID_SECNUM && sector >= filesectors)
201 filestr_discard_cache(s);
202
203 /* files outside bounds must be rewound */
204 if (fat_query_sectornum(&s->fatstr) > filesectors)
205 fat_seek_to_stream(&s->fatstr, &file->stream.fatstr);
206
207 /* clip file offset too if needed */
208 struct filestr_desc *f = (struct filestr_desc *)s;
209 if (f->offset > size)
210 f->offset = size;
211 }
208} 212}
209 213
210/* truncate the file to the specified length */ 214/* truncate the file to the specified length */
@@ -246,13 +250,17 @@ static int ftruncate_internal(struct filestr_desc *file, file_size_t size,
246 rc2 = fat_truncate(&file->stream.fatstr); 250 rc2 = fat_truncate(&file->stream.fatstr);
247 if (rc2 < 0) 251 if (rc2 < 0)
248 FILE_ERROR(EIO, rc2 * 10 - 3); 252 FILE_ERROR(EIO, rc2 * 10 - 3);
253
254 /* never needs to be done this way again since any data beyond the
255 cached size is now gone */
256 fileobj_change_flags(&file->stream, 0, FO_TRUNC);
249 } 257 }
250 /* else just change the cached file size */ 258 /* else just change the cached file size */
251 259
252 if (truncsize < cursize) 260 if (truncsize < cursize)
253 { 261 {
254 *file->sizep = truncsize; 262 *file->sizep = truncsize;
255 fileop_ontruncate_internal(&file->stream); 263 handle_truncate(file, truncsize);
256 } 264 }
257 265
258 /* if truncation was partially successful, it effectively destroyed 266 /* if truncation was partially successful, it effectively destroyed
@@ -299,10 +307,6 @@ static int fsync_internal(struct filestr_desc *file)
299 int rc2 = ftruncate_internal(file, size, rc == 0); 307 int rc2 = ftruncate_internal(file, size, rc == 0);
300 if (rc2 < 0) 308 if (rc2 < 0)
301 FILE_ERROR(ERRNO, rc2 * 10 - 2); 309 FILE_ERROR(ERRNO, rc2 * 10 - 2);
302
303 /* never needs to be done this way again since any data beyond the
304 cached size is now gone */
305 fileobj_change_flags(&file->stream, 0, FO_TRUNC);
306 } 310 }
307 311
308file_error:; 312file_error:;
@@ -327,8 +331,7 @@ static int close_internal(struct filestr_desc *file)
327 /* call only when holding WRITER lock (updates directory entries) */ 331 /* call only when holding WRITER lock (updates directory entries) */
328 int rc; 332 int rc;
329 333
330 if ((file->stream.flags & FD_WRITE) && 334 if ((file->stream.flags & (FD_WRITE|FD_NONEXIST)) == FD_WRITE)
331 !(fileobj_get_flags(&file->stream) & FO_REMOVED))
332 { 335 {
333 rc = fsync_internal(file); 336 rc = fsync_internal(file);
334 if (rc < 0) 337 if (rc < 0)
@@ -786,6 +789,12 @@ int open_noiso_internal(const char *path, int oflag)
786 return open_internal_locked(path, oflag, FF_ANYTYPE | FF_NOISO); 789 return open_internal_locked(path, oflag, FF_ANYTYPE | FF_NOISO);
787} 790}
788 791
792void force_close_writer_internal(struct filestr_base *stream)
793{
794 /* only we do writers so we know this is our guy */
795 close_internal((struct filestr_desc *)stream);
796}
797
789 798
790/** POSIX **/ 799/** POSIX **/
791 800