summaryrefslogtreecommitdiffstats
path: root/firmware/common/dircache.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common/dircache.c')
-rw-r--r--firmware/common/dircache.c92
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)