diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/common/dircache.c | 51 | ||||
-rw-r--r-- | firmware/include/dircache.h | 6 |
2 files changed, 51 insertions, 6 deletions
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 873e0f9cf4..efab37b5c4 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c | |||
@@ -52,6 +52,7 @@ static struct dircache_entry *fd_bindings[MAX_OPEN_FILES]; | |||
52 | static struct dircache_entry *dircache_root; | 52 | static struct dircache_entry *dircache_root; |
53 | 53 | ||
54 | static bool dircache_initialized = false; | 54 | static bool dircache_initialized = false; |
55 | static bool dircache_initializing = false; | ||
55 | static bool thread_enabled = false; | 56 | static bool thread_enabled = false; |
56 | static unsigned long allocated_size = DIRCACHE_LIMIT; | 57 | static unsigned long allocated_size = DIRCACHE_LIMIT; |
57 | static unsigned long dircache_size = 0; | 58 | static unsigned long dircache_size = 0; |
@@ -64,6 +65,9 @@ static struct event_queue dircache_queue; | |||
64 | static long dircache_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)]; | 65 | static long dircache_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)]; |
65 | static const char dircache_thread_name[] = "dircache"; | 66 | static const char dircache_thread_name[] = "dircache"; |
66 | 67 | ||
68 | static struct fdbind_queue fdbind_cache[MAX_PENDING_BINDINGS]; | ||
69 | static int fdbind_idx = 0; | ||
70 | |||
67 | /* --- Internal cache structure control functions --- */ | 71 | /* --- Internal cache structure control functions --- */ |
68 | 72 | ||
69 | /** | 73 | /** |
@@ -446,12 +450,15 @@ static int dircache_do_rebuild(void) | |||
446 | { | 450 | { |
447 | struct fat_dir dir; | 451 | struct fat_dir dir; |
448 | unsigned int start_tick; | 452 | unsigned int start_tick; |
453 | int i; | ||
449 | 454 | ||
450 | /* Measure how long it takes build the cache. */ | 455 | /* Measure how long it takes build the cache. */ |
451 | start_tick = current_tick; | 456 | start_tick = current_tick; |
457 | dircache_initializing = true; | ||
452 | 458 | ||
453 | if ( fat_opendir(IF_MV2(volume,) &dir, 0, NULL) < 0 ) { | 459 | if ( fat_opendir(IF_MV2(volume,) &dir, 0, NULL) < 0 ) { |
454 | logf("Failed opening root dir"); | 460 | logf("Failed opening root dir"); |
461 | dircache_initializing = false; | ||
455 | return -3; | 462 | return -3; |
456 | } | 463 | } |
457 | 464 | ||
@@ -472,14 +479,22 @@ static int dircache_do_rebuild(void) | |||
472 | logf("dircache_travel failed"); | 479 | logf("dircache_travel failed"); |
473 | cpu_boost(false); | 480 | cpu_boost(false); |
474 | dircache_size = 0; | 481 | dircache_size = 0; |
482 | dircache_initializing = false; | ||
475 | return -2; | 483 | return -2; |
476 | } | 484 | } |
477 | cpu_boost(false); | 485 | cpu_boost(false); |
478 | 486 | ||
479 | logf("Done, %d KiB used", dircache_size / 1024); | 487 | logf("Done, %d KiB used", dircache_size / 1024); |
488 | |||
480 | dircache_initialized = true; | 489 | dircache_initialized = true; |
490 | dircache_initializing = false; | ||
481 | cache_build_ticks = current_tick - start_tick; | 491 | cache_build_ticks = current_tick - start_tick; |
482 | 492 | ||
493 | /* Initialized fd bindings. */ | ||
494 | memset(fd_bindings, 0, sizeof(fd_bindings)); | ||
495 | for (i = 0; i < fdbind_idx; i++) | ||
496 | dircache_bind(fdbind_cache[i].fd, fdbind_cache[i].path); | ||
497 | |||
483 | if (thread_enabled) | 498 | if (thread_enabled) |
484 | { | 499 | { |
485 | if (allocated_size - dircache_size < DIRCACHE_RESERVE) | 500 | if (allocated_size - dircache_size < DIRCACHE_RESERVE) |
@@ -710,6 +725,18 @@ void dircache_copy_path(const struct dircache_entry *entry, char *buf, int size) | |||
710 | } | 725 | } |
711 | 726 | ||
712 | /* --- Directory cache live updating functions --- */ | 727 | /* --- Directory cache live updating functions --- */ |
728 | static int block_until_ready(void) | ||
729 | { | ||
730 | /* Block until dircache has been built. */ | ||
731 | while (!dircache_initialized && dircache_initializing) | ||
732 | sleep(1); | ||
733 | |||
734 | if (!dircache_initialized) | ||
735 | return -1; | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
713 | static struct dircache_entry* dircache_new_entry(const char *path, int attribute) | 740 | static struct dircache_entry* dircache_new_entry(const char *path, int attribute) |
714 | { | 741 | { |
715 | struct dircache_entry *entry; | 742 | struct dircache_entry *entry; |
@@ -783,6 +810,18 @@ void dircache_bind(int fd, const char *path) | |||
783 | { | 810 | { |
784 | struct dircache_entry *entry; | 811 | struct dircache_entry *entry; |
785 | 812 | ||
813 | /* Queue requests until dircache has been built. */ | ||
814 | if (!dircache_initialized && dircache_initializing) | ||
815 | { | ||
816 | if (fdbind_idx >= MAX_PENDING_BINDINGS) | ||
817 | return ; | ||
818 | strncpy(fdbind_cache[fdbind_idx].path, path, | ||
819 | sizeof(fdbind_cache[fdbind_idx].path)-1); | ||
820 | fdbind_cache[fdbind_idx].fd = fd; | ||
821 | fdbind_idx++; | ||
822 | return ; | ||
823 | } | ||
824 | |||
786 | if (!dircache_initialized) | 825 | if (!dircache_initialized) |
787 | return ; | 826 | return ; |
788 | 827 | ||
@@ -816,7 +855,7 @@ void dircache_update_filesize(int fd, long newsize, long startcluster) | |||
816 | 855 | ||
817 | void dircache_mkdir(const char *path) | 856 | void dircache_mkdir(const char *path) |
818 | { /* Test ok. */ | 857 | { /* Test ok. */ |
819 | if (!dircache_initialized) | 858 | if (block_until_ready()) |
820 | return ; | 859 | return ; |
821 | 860 | ||
822 | logf("mkdir: %s", path); | 861 | logf("mkdir: %s", path); |
@@ -827,7 +866,7 @@ void dircache_rmdir(const char *path) | |||
827 | { /* Test ok. */ | 866 | { /* Test ok. */ |
828 | struct dircache_entry *entry; | 867 | struct dircache_entry *entry; |
829 | 868 | ||
830 | if (!dircache_initialized) | 869 | if (block_until_ready()) |
831 | return ; | 870 | return ; |
832 | 871 | ||
833 | logf("rmdir: %s", path); | 872 | logf("rmdir: %s", path); |
@@ -848,7 +887,7 @@ void dircache_remove(const char *name) | |||
848 | { /* Test ok. */ | 887 | { /* Test ok. */ |
849 | struct dircache_entry *entry; | 888 | struct dircache_entry *entry; |
850 | 889 | ||
851 | if (!dircache_initialized) | 890 | if (block_until_ready()) |
852 | return ; | 891 | return ; |
853 | 892 | ||
854 | logf("remove: %s", name); | 893 | logf("remove: %s", name); |
@@ -872,7 +911,7 @@ void dircache_rename(const char *oldpath, const char *newpath) | |||
872 | char absolute_path[MAX_PATH]; | 911 | char absolute_path[MAX_PATH]; |
873 | char *p; | 912 | char *p; |
874 | 913 | ||
875 | if (!dircache_initialized) | 914 | if (block_until_ready()) |
876 | return ; | 915 | return ; |
877 | 916 | ||
878 | logf("rename: %s->%s", oldpath, newpath); | 917 | logf("rename: %s->%s", oldpath, newpath); |
@@ -927,9 +966,9 @@ void dircache_add_file(const char *path, long startcluster) | |||
927 | { | 966 | { |
928 | struct dircache_entry *entry; | 967 | struct dircache_entry *entry; |
929 | 968 | ||
930 | if (!dircache_initialized) | 969 | if (block_until_ready()) |
931 | return ; | 970 | return ; |
932 | 971 | ||
933 | logf("add file: %s", path); | 972 | logf("add file: %s", path); |
934 | entry = dircache_new_entry(path, 0); | 973 | entry = dircache_new_entry(path, 0); |
935 | if (entry == NULL) | 974 | if (entry == NULL) |
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h index 48f29806e3..4141254de6 100644 --- a/firmware/include/dircache.h +++ b/firmware/include/dircache.h | |||
@@ -46,6 +46,12 @@ struct dircache_maindata { | |||
46 | struct dircache_entry *root_entry; | 46 | struct dircache_entry *root_entry; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | #define MAX_PENDING_BINDINGS 2 | ||
50 | struct fdbind_queue { | ||
51 | char path[MAX_PATH]; | ||
52 | int fd; | ||
53 | }; | ||
54 | |||
49 | /* Exported structures. */ | 55 | /* Exported structures. */ |
50 | struct dircache_entry { | 56 | struct dircache_entry { |
51 | struct dircache_entry *next; | 57 | struct dircache_entry *next; |