summaryrefslogtreecommitdiff
path: root/firmware/include
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/include
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/include')
-rw-r--r--firmware/include/dircache.h40
-rw-r--r--firmware/include/dircache_redirect.h19
-rw-r--r--firmware/include/file_internal.h91
-rw-r--r--firmware/include/fileobj_mgr.h5
4 files changed, 104 insertions, 51 deletions
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index 7e8c764e7f..d73c6f6e81 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -57,6 +57,15 @@
57 figure pessimistic */ 57 figure pessimistic */
58typedef uint32_t dc_serial_t; 58typedef uint32_t dc_serial_t;
59 59
60/* these should agree with size of dc_serial_t */
61#define DC_SERHASH_START 0xffffffff
62
63/* I was originally using FNV hash but decided this is probably okay
64 (for now) */
65#define dc_hash_serialnum(s, h) \
66 ({ dc_serial_t __x = (s); crc_32(&(__x), sizeof(dc_serial_t), (h)); })
67#define DC_SERIAL_FMT "0x%08lX"
68
60/** 69/**
61 ****************************************************************************/ 70 ****************************************************************************/
62 71
@@ -132,10 +141,33 @@ void dircache_fileop_sync(struct file_base_binding *infop,
132 const struct dirinfo_native *dinp); 141 const struct dirinfo_native *dinp);
133 142
134 143
135/** Dircache paths and files **/ 144/** Dircache paths, files and shortcuts **/
136ssize_t dircache_get_path(const struct dircache_file *dcfilep, char *buf, 145struct dircache_fileref
137 size_t size); 146{
138int dircache_get_file(const char *path, struct dircache_file *dcfilep); 147 struct dircache_file dcfile;
148 dc_serial_t serialhash; /* Hash of serialnumbers to root */
149};
150
151void dircache_fileref_init(struct dircache_fileref *dcfrefp);
152ssize_t dircache_get_fileref_path(const struct dircache_fileref *dcfrefp,
153 char *buf, size_t size);
154
155/* Bitflags for dircache_search() */
156enum dircache_search_flags
157{
158 DCS_FILEREF = 0x01, /* Check fileref existence and serial number */
159 _DCS_VERIFY_FLAG = 0x02, /* Internal: Only valid with DCS_FILEREF */
160 DCS_FILEREF_VERIFY = 0x03, /* Do DCS_FILEREF check + verify serial hash */
161 DCS_CACHED_PATH = 0x04, /* Check only cache for provided path */
162 _DCS_STORAGE_FLAG = 0x08, /* Internal: Only valid with DCS_CACHED_PATH */
163 DCS_STORAGE_PATH = 0x0c, /* Read-through if needed for provided path */
164 DCS_UPDATE_FILEREF = 0x10, /* If fileref is not valid but path is found or
165 searching a path, update the reference
166 information */
167};
168
169int dircache_search(unsigned int flags, struct dircache_fileref *dcfrefp,
170 const char *path);
139 171
140 172
141/** Debug screen/info stuff **/ 173/** Debug screen/info stuff **/
diff --git a/firmware/include/dircache_redirect.h b/firmware/include/dircache_redirect.h
index 15fb4bc38d..9fae16b551 100644
--- a/firmware/include/dircache_redirect.h
+++ b/firmware/include/dircache_redirect.h
@@ -24,6 +24,8 @@
24 24
25/*** 25/***
26 ** Internal redirects that depend upon whether or not dircache is made 26 ** Internal redirects that depend upon whether or not dircache is made
27 **
28 ** Some stuff deals with it, some doesn't right now. This is a nexus point..
27 **/ 29 **/
28 30
29/** File binding **/ 31/** File binding **/
@@ -119,11 +121,6 @@ static inline void fileop_onsync_internal(struct filestr_base *stream)
119#endif 121#endif
120} 122}
121 123
122static inline void fileop_ontruncate_internal(struct filestr_base *stream)
123{
124 fileobj_fileop_truncate(stream);
125}
126
127static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) 124static inline void volume_onmount_internal(IF_MV_NONVOID(int volume))
128{ 125{
129#ifdef HAVE_DIRCACHE 126#ifdef HAVE_DIRCACHE
@@ -134,10 +131,20 @@ static inline void volume_onmount_internal(IF_MV_NONVOID(int volume))
134 131
135static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume)) 132static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume))
136{ 133{
137 fileobj_mgr_unmount(IF_MV(volume));
138#ifdef HAVE_DIRCACHE 134#ifdef HAVE_DIRCACHE
135 /* First, to avoid update of something about to be destroyed anyway */
139 dircache_unmount(IF_MV(volume)); 136 dircache_unmount(IF_MV(volume));
140#endif 137#endif
138 fileobj_mgr_unmount(IF_MV(volume));
139}
140
141static inline void fileop_onunmount_internal(struct filestr_base *stream)
142{
143
144 if (stream->flags & FD_WRITE)
145 force_close_writer_internal(stream); /* try to save stuff */
146 else
147 fileop_onclose_internal(stream); /* just readers, bye */
141} 148}
142 149
143 150
diff --git a/firmware/include/file_internal.h b/firmware/include/file_internal.h
index d1bb67406a..acec81206e 100644
--- a/firmware/include/file_internal.h
+++ b/firmware/include/file_internal.h
@@ -81,6 +81,7 @@
81#define ATTR_NEW_FILE (ATTR_ARCHIVE) 81#define ATTR_NEW_FILE (ATTR_ARCHIVE)
82#define ATTR_NEW_DIRECTORY (ATTR_DIRECTORY) 82#define ATTR_NEW_DIRECTORY (ATTR_DIRECTORY)
83 83
84#define ATTR_SYSTEM_ROOT (ATTR_SYSROOT | ATTR_DIRECTORY)
84#define ATTR_MOUNT_POINT (ATTR_VOLUME | ATTR_DIRECTORY) 85#define ATTR_MOUNT_POINT (ATTR_VOLUME | ATTR_DIRECTORY)
85 86
86/** File sector cache **/ 87/** File sector cache **/
@@ -110,33 +111,35 @@ void file_cache_free(struct filestr_cache *cachep);
110enum fildes_and_obj_flags 111enum fildes_and_obj_flags
111{ 112{
112 /* used in descriptor and common */ 113 /* used in descriptor and common */
113 FDO_BUSY = 0x0001, /* descriptor/object is in use */ 114 FDO_BUSY = 0x0001, /* descriptor/object is in use */
114 /* only used in individual stream descriptor */ 115 /* only used in individual stream descriptor */
115 FD_WRITE = 0x0002, /* descriptor has write mode */ 116 FD_WRITE = 0x0002, /* descriptor has write mode */
116 FD_WRONLY = 0x0004, /* descriptor is write mode only */ 117 FD_WRONLY = 0x0004, /* descriptor is write mode only */
117 FD_APPEND = 0x0008, /* descriptor is append mode */ 118 FD_APPEND = 0x0008, /* descriptor is append mode */
119 FD_NONEXIST = 0x8000, /* closed but not freed (uncombined) */
118 /* only used as common flags */ 120 /* only used as common flags */
119 FO_DIRECTORY = 0x0010, /* fileobj is a directory */ 121 FO_DIRECTORY = 0x0010, /* fileobj is a directory */
120 FO_TRUNC = 0x0020, /* fileobj is opened to be truncated */ 122 FO_TRUNC = 0x0020, /* fileobj is opened to be truncated */
121 FO_REMOVED = 0x0040, /* fileobj was deleted while open */ 123 FO_REMOVED = 0x0040, /* fileobj was deleted while open */
122 FO_SINGLE = 0x0080, /* fileobj has only one stream open */ 124 FO_SINGLE = 0x0080, /* fileobj has only one stream open */
123 FDO_MASK = 0x00ff, 125 FDO_MASK = 0x00ff,
124 /* bitflags that instruct various 'open' functions how to behave */ 126 FDO_CHG_MASK = FO_TRUNC, /* fileobj permitted external change */
125 FF_FILE = 0x0000, /* expect file; accept file only */ 127 /* bitflags that instruct various 'open' functions how to behave;
126 FF_DIR = 0x0100, /* expect dir; accept dir only */ 128 * saved in stream flags (only) but not used by manager */
127 FF_ANYTYPE = 0x0200, /* succeed if either file or dir */ 129 FF_FILE = 0x00000000, /* expect file; accept file only */
128 FF_TYPEMASK = 0x0300, /* mask of typeflags */ 130 FF_DIR = 0x00010000, /* expect dir; accept dir only */
129 FF_CREAT = 0x0400, /* create if file doesn't exist */ 131 FF_ANYTYPE = 0x00020000, /* succeed if either file or dir */
130 FF_EXCL = 0x0800, /* fail if creating and file exists */ 132 FF_TYPEMASK = 0x00030000, /* mask of typeflags */
131 FF_CHECKPREFIX = 0x1000, /* detect if file is prefix of path */ 133 FF_CREAT = 0x00040000, /* create if file doesn't exist */
132 FF_NOISO = 0x2000, /* do not decode ISO filenames to UTF-8 */ 134 FF_EXCL = 0x00080000, /* fail if creating and file exists */
133 FF_MASK = 0x3f00, 135 FF_CHECKPREFIX = 0x00100000, /* detect if file is prefix of path */
134 /* special values used in isolation */ 136 FF_NOISO = 0x00200000, /* do not decode ISO filenames to UTF-8 */
135 FV_NONEXIST = 0x8000, /* closed but not freed (unmounted) */ 137 FF_PROBE = 0x00400000, /* only test existence; don't open */
136 FV_OPENSYSROOT = 0xc001, /* open sysroot, volume 0 not mounted */ 138 FF_CACHEONLY = 0x00800000, /* succeed only if in dircache */
139 FF_SELFINFO = 0x01000000, /* return info on self as well */
140 FF_MASK = 0x01ff0000,
137}; 141};
138 142
139
140/** Common data structures used throughout **/ 143/** Common data structures used throughout **/
141 144
142/* basic file information about its location */ 145/* basic file information about its location */
@@ -183,8 +186,7 @@ struct dirscan_info
183struct filestr_base 186struct filestr_base
184{ 187{
185 struct ll_node node; /* list item node (first!) */ 188 struct ll_node node; /* list item node (first!) */
186 uint16_t flags; /* FD_* bits of this stream */ 189 uint32_t flags; /* F[DF]_* bits of this stream */
187 uint16_t unused; /* not used */
188 struct filestr_cache cache; /* stream-local cache */ 190 struct filestr_cache cache; /* stream-local cache */
189 struct filestr_cache *cachep; /* the cache in use (local or shared) */ 191 struct filestr_cache *cachep; /* the cache in use (local or shared) */
190 struct file_base_info *infop; /* base file information */ 192 struct file_base_info *infop; /* base file information */
@@ -235,17 +237,25 @@ static inline void filestr_unlock(struct filestr_base *stream)
235#define FILESTR_UNLOCK(type, stream) \ 237#define FILESTR_UNLOCK(type, stream) \
236 ({ if (FILESTR_##type) filestr_unlock(stream); }) 238 ({ if (FILESTR_##type) filestr_unlock(stream); })
237 239
238#define ATTR_PREFIX (0x8000) /* out of the way of all ATTR_* bits */ 240/* auxilliary attributes - out of the way of regular ATTR_* bits */
241#define ATTR_SYSROOT (0x8000)
242#define ATTR_PREFIX (0x4000)
239 243
240/* structure to return detailed information about what you opened */ 244/* structure to return detailed information about what you opened */
241struct path_component_info 245struct path_component_info
242{ 246{
243 const char *name; /* pointer to name within 'path' */ 247 const char *name; /* pointer to name within 'path' (OUT) */
244 size_t length; /* length of component within 'path' */ 248 size_t length; /* length of component within 'path' */
245 file_size_t filesize; /* size of the opened file (0 if dir) */ 249 file_size_t filesize; /* size of the opened file (0 if dir) */
246 unsigned int attr; /* attributes of this component */ 250 unsigned int attr; /* attributes of this component */
247 struct file_base_info *prefixp; /* base info to check as prefix (IN) */ 251 struct file_base_info *prefixp; /* base info to check as prefix
248 struct file_base_info parentinfo; /* parent directory info of file */ 252 (IN if FF_CHECKPREFIX) */
253 union {
254 struct file_base_info parentinfo; /* parent directory base info of file
255 (if not FF_SELFINFO) */
256 struct file_base_info info; /* base info of file itself
257 (if FF_SELFINFO) */
258 };
249}; 259};
250 260
251int open_stream_internal(const char *path, unsigned int callflags, 261int open_stream_internal(const char *path, unsigned int callflags,
@@ -261,6 +271,7 @@ int remove_stream_internal(const char *path, struct filestr_base *stream,
261int test_stream_exists_internal(const char *path, unsigned int callflags); 271int test_stream_exists_internal(const char *path, unsigned int callflags);
262 272
263int open_noiso_internal(const char *path, int oflag); /* file.c */ 273int open_noiso_internal(const char *path, int oflag); /* file.c */
274void force_close_writer_internal(struct filestr_base *stream); /* file.c */
264 275
265struct dirent; 276struct dirent;
266int uncached_readdir_dirent(struct filestr_base *stream, 277int uncached_readdir_dirent(struct filestr_base *stream,
@@ -326,22 +337,26 @@ static inline void file_internal_unlock_WRITER(void)
326 * not in the macro 337 * not in the macro
327 */ 338 */
328 339
340#define FILE_SET_CODE(_name, _keepcode, _value) \
341 ({ __builtin_constant_p(_value) ? \
342 ({ if ((_value) != (_keepcode)) _name = (_value); }) : \
343 ({ _name = (_value); }); })
344
329/* set errno and rc and proceed to the "file_error:" label */ 345/* set errno and rc and proceed to the "file_error:" label */
330#define FILE_ERROR(_errno, _rc) \ 346#define FILE_ERROR(_errno, _rc) \
331 ({ __builtin_constant_p(_errno) ? \ 347 ({ FILE_SET_CODE(errno, ERRNO, (_errno)); \
332 ({ if ((_errno) != ERRNO) errno = (_errno); }) : \ 348 FILE_SET_CODE(rc, RC, (_rc)); \
333 ({ errno = (_errno); }); \
334 __builtin_constant_p(_rc) ? \
335 ({ if ((_rc) != RC) rc = (_rc); }) : \
336 ({ rc = (_rc); }); \
337 goto file_error; }) 349 goto file_error; })
338 350
339/* set errno and return a value at the point of invocation */ 351/* set errno and return a value at the point of invocation */
340#define FILE_ERROR_RETURN(_errno, _rc...) \ 352#define FILE_ERROR_RETURN(_errno, _rc...) \
341 ({ __builtin_constant_p(_errno) ? \ 353 ({ FILE_SET_CODE(errno, ERRNO, _errno); \
342 ({ if ((_errno) != ERRNO) errno = (_errno); }) : \ 354 return _rc; })
343 ({ errno = (_errno); }); \ 355
344 return _rc; }) 356/* set errno and return code, no branching */
357#define FILE_ERROR_SET(_errno, _rc) \
358 ({ FILE_SET_CODE(errno, ERRNO, (_errno)); \
359 FILE_SET_CODE(rc, RC, (_rc)); })
345 360
346 361
347/** Misc. stuff **/ 362/** Misc. stuff **/
diff --git a/firmware/include/fileobj_mgr.h b/firmware/include/fileobj_mgr.h
index c90a59bea0..627d2df341 100644
--- a/firmware/include/fileobj_mgr.h
+++ b/firmware/include/fileobj_mgr.h
@@ -41,12 +41,11 @@ void fileobj_fileop_rename(struct filestr_base *stream,
41void fileobj_fileop_remove(struct filestr_base *stream, 41void fileobj_fileop_remove(struct filestr_base *stream,
42 const struct file_base_info *oldinfop); 42 const struct file_base_info *oldinfop);
43void fileobj_fileop_sync(struct filestr_base *stream); 43void fileobj_fileop_sync(struct filestr_base *stream);
44void fileobj_fileop_truncate(struct filestr_base *stream);
45extern void ftruncate_internal_callback(struct filestr_base *stream,
46 struct filestr_base *s);
47 44
48file_size_t * fileobj_get_sizep(const struct filestr_base *stream); 45file_size_t * fileobj_get_sizep(const struct filestr_base *stream);
49unsigned int fileobj_get_flags(const struct filestr_base *stream); 46unsigned int fileobj_get_flags(const struct filestr_base *stream);
47struct filestr_base * fileobj_get_next_stream(const struct filestr_base *stream,
48 const struct filestr_base *s);
50void fileobj_change_flags(struct filestr_base *stream, 49void fileobj_change_flags(struct filestr_base *stream,
51 unsigned int flags, unsigned int mask); 50 unsigned int flags, unsigned int mask);
52void fileobj_mgr_unmount(IF_MV_NONVOID(int volume)); 51void fileobj_mgr_unmount(IF_MV_NONVOID(int volume));