diff options
Diffstat (limited to 'firmware/common/dircache.c')
-rw-r--r-- | firmware/common/dircache.c | 92 |
1 files changed, 32 insertions, 60 deletions
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 3b880d3382..c274b6c62c 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c @@ -249,7 +249,6 @@ static struct dircache_runinfo /* cache buffer info */ int handle; /* buflib buffer handle */ size_t bufsize; /* size of buflib allocation - 1 */ - int buflocked; /* don't move due to other allocs */ union { void *p; /* address of buffer - ENTRYSIZE */ struct dircache_entry *pentry; /* alias of .p to assist entry resolution */ @@ -329,29 +328,9 @@ static inline void dumpster_clean_buffer(void *p, size_t size) */ static int move_callback(int handle, void *current, void *new) { - if (dircache_runinfo.buflocked) - return BUFLIB_CB_CANNOT_MOVE; - + (void)handle; (void)current; dircache_runinfo.p = new - ENTRYSIZE; - return BUFLIB_CB_OK; - (void)handle; (void)current; -} - -/** - * add a "don't move" lock count - */ -static inline void buffer_lock(void) -{ - dircache_runinfo.buflocked++; -} - -/** - * remove a "don't move" lock count - */ -static inline void buffer_unlock(void) -{ - dircache_runinfo.buflocked--; } @@ -500,7 +479,7 @@ static void binding_dissolve_volume(struct dircache_runinfo_volume *dcrivolp) static int alloc_cache(size_t size) { /* pad with one extra-- see alloc_name() and free_name() */ - return core_alloc_ex("dircache", size + 1, &dircache_runinfo.ops); + return core_alloc_ex(size + 1, &dircache_runinfo.ops); } /** @@ -530,14 +509,14 @@ static void set_buffer(int handle, size_t size) /** * remove the allocation from dircache control and return the handle + * Note that dircache must not be using the buffer! */ static int reset_buffer(void) { int handle = dircache_runinfo.handle; if (handle > 0) { - /* don't mind .p; it might get changed by the callback even after - this call; buffer presence is determined by the following: */ + /* don't mind .p; buffer presence is determined by the following: */ dircache_runinfo.handle = 0; dircache_runinfo.bufsize = 0; } @@ -1473,7 +1452,7 @@ static void sab_process_volume(struct dircache_volume *dcvolp) */ int dircache_readdir_dirent(struct filestr_base *stream, struct dirscan_info *scanp, - struct dirent *entry) + struct DIRENT *entry) { struct file_base_info *dirinfop = stream->infop; @@ -1728,8 +1707,8 @@ static int sab_process_dir(struct dircache_entry *ce) /* save current paths size */ int pathpos = strlen(sab_path); /* append entry */ - strlcpy(&sab_path[pathpos], "/", sizeof(sab_path) - pathpos); - strlcpy(&sab_path[pathpos+1], entry->d_name, sizeof(sab_path) - pathpos - 1); + strmemccpy(&sab_path[pathpos], "/", sizeof(sab_path) - pathpos); + strmemccpy(&sab_path[pathpos+1], entry->d_name, sizeof(sab_path) - pathpos - 1); int rc = sab_process_dir(ce->down); /* restore path */ @@ -1756,11 +1735,11 @@ static int sab_process_dir(struct dircache_entry *ce) static int sab_process_volume(IF_MV(int volume,) struct dircache_entry *ce) { memset(ce, 0, sizeof(struct dircache_entry)); - strlcpy(sab_path, "/", sizeof sab_path); + strmemccpy(sab_path, "/", sizeof sab_path); return sab_process_dir(ce); } -int dircache_readdir_r(struct dircache_dirscan *dir, struct dirent *result) +int dircache_readdir_r(struct dircache_dirscan *dir, struct DIRENT *result) { if (dircache_state != DIRCACHE_READY) return readdir_r(dir->###########3, result, &result); @@ -1776,7 +1755,7 @@ int dircache_readdir_r(struct dircache_dirscan *dir, struct dirent *result) dir->scanidx = ce - dircache_root; - strlcpy(result->d_name, ce->d_name, sizeof (result->d_name)); + strmemccpy(result->d_name, ce->d_name, sizeof (result->d_name)); result->info = ce->dirinfo; return 1; @@ -1857,7 +1836,7 @@ static void reset_cache(void) */ static void build_volumes(void) { - buffer_lock(); + core_pin(dircache_runinfo.handle); for (int i = 0; i < NUM_VOLUMES; i++) { @@ -1903,12 +1882,15 @@ static void build_volumes(void) logf("Done, %ld KiB used", dircache.size / 1024); - buffer_unlock(); + if (dircache_runinfo.handle > 0) /* dircache may have been disabled */ + core_unpin(dircache_runinfo.handle); } /** * allocate buffer and return whether or not a synchronous build should take * place; if 'realloced' is NULL, it's just a query about what will happen + * + * Note this must be called with the dircache_lock() active. */ static int prepare_build(bool *realloced) { @@ -1958,17 +1940,14 @@ static int prepare_build(bool *realloced) *realloced = true; reset_cache(); - buffer_lock(); - int handle = reset_buffer(); - dircache_unlock(); + dircache_unlock(); /* release lock held by caller */ - if (handle > 0) - core_free(handle); + core_free(handle); handle = alloc_cache(size); - dircache_lock(); + dircache_lock(); /* reacquire lock */ if (dircache_runinfo.suspended && handle > 0) { @@ -1980,13 +1959,9 @@ static int prepare_build(bool *realloced) } if (handle <= 0) - { - buffer_unlock(); return -1; - } set_buffer(handle, size); - buffer_unlock(); return syncbuild; } @@ -2164,8 +2139,7 @@ static void dircache_suspend_internal(bool freeit) dircache_unlock(); - if (handle > 0) - core_free(handle); + core_free(handle); thread_wait(thread_id); @@ -2386,9 +2360,9 @@ void dircache_fileop_create(struct file_base_info *dirinfop, if ((dinp->attr & ATTR_DIRECTORY) && !is_dotdir_name(basename)) { /* scan-in the contents of the new directory at this level only */ - buffer_lock(); + core_pin(dircache_runinfo.handle); sab_process_dir(infop, false); - buffer_unlock(); + core_unpin(dircache_runinfo.handle); } } @@ -2541,13 +2515,10 @@ static ssize_t get_path_sub(int idx, struct get_path_sub_data *data) cename = ""; #ifdef HAVE_MULTIVOLUME + /* prepend the volume specifier */ int volume = IF_MV_VOL(-idx - 1); - if (volume > 0) - { - /* prepend the volume specifier for volumes > 0 */ - cename = alloca(VOL_MAX_LEN+1); - get_volume_name(volume, cename); - } + cename = alloca(VOL_MAX_LEN+1); + get_volume_name(volume, cename); #endif /* HAVE_MULTIVOLUME */ data->serialhash = dc_hash_serialnum(get_idx_dcvolp(idx)->serialnum, @@ -2920,7 +2891,7 @@ void dircache_dump(void) if (dircache_runinfo.handle) { - buffer_lock(); + core_pin(dircache_runinfo.handle); /* bin */ write(fdbin, dircache_runinfo.p + ENTRYSIZE, @@ -2990,7 +2961,7 @@ void dircache_dump(void) tm.tm_hour, tm.tm_min, tm.tm_sec); } - buffer_unlock(); + core_unpin(dircache_runinfo.handle); } dircache_unlock(); @@ -3109,7 +3080,6 @@ int dircache_load(void) } dircache_lock(); - buffer_lock(); if (!dircache_is_clean(false)) goto error; @@ -3118,6 +3088,7 @@ int dircache_load(void) dircache = maindata.dircache; set_buffer(handle, bufsize); + core_pin(handle); hasbuffer = true; /* convert back to in-RAM representation */ @@ -3172,17 +3143,17 @@ int dircache_load(void) dircache_enable_internal(false); /* cache successfully loaded */ + core_unpin(handle); logf("Done, %ld KiB used", dircache.size / 1024); rc = 0; error: if (rc < 0 && hasbuffer) reset_buffer(); - buffer_unlock(); dircache_unlock(); error_nolock: - if (rc < 0 && handle > 0) + if (rc < 0) core_free(handle); if (fd >= 0) @@ -3204,8 +3175,9 @@ int dircache_save(void) if (fd < 0) return -1; + /* it seems the handle *must* exist if this function is called */ dircache_lock(); - buffer_lock(); + core_pin(dircache_runinfo.handle); int rc = -1; @@ -3274,7 +3246,7 @@ int dircache_save(void) that makes what was saved completely invalid */ rc = 0; error: - buffer_unlock(); + core_unpin(dircache_runinfo.handle); dircache_unlock(); if (rc < 0) |