| | 206 | } |
| | 207 | |
| | 208 | static fs_err_t nx_fs_move_region_backwards(U32 source, U32 dest, U32 len) { |
| | 209 | U32 data[EFC_PAGE_WORDS]; |
| | 210 | |
| | 211 | while (len--) { |
| | 212 | memcpy((void *) data, |
| | 213 | (void *) &(FLASH_BASE_PTR[source*EFC_PAGE_WORDS]), |
| | 214 | EFC_PAGE_BYTES); |
| | 215 | if (!nx__efc_write_page(data, dest)) { |
| | 216 | return FS_ERR_FLASH_ERROR; |
| | 217 | } |
| | 218 | |
| | 219 | if (!nx__efc_erase_page(source, 0)) { |
| | 220 | return FS_ERR_FLASH_ERROR; |
| | 221 | } |
| | 222 | |
| | 223 | source++; |
| | 224 | dest++; |
| | 225 | } |
| | 226 | |
| | 227 | return FS_ERR_NO_ERROR; |
| | 228 | } |
| | 229 | |
| | 230 | static fs_err_t nx_fs_move_region_forwards(U32 source, U32 dest, U32 len) { |
| | 231 | U32 data[EFC_PAGE_WORDS]; |
| | 232 | |
| | 233 | while (len--) { |
| | 234 | memcpy((void *) data, |
| | 235 | (void *) &(FLASH_BASE_PTR[(source+len-1)*EFC_PAGE_WORDS]), |
| | 236 | EFC_PAGE_BYTES); |
| | 237 | if (!nx__efc_write_page(data, dest+len-1)) { |
| | 238 | return FS_ERR_FLASH_ERROR; |
| | 239 | } |
| | 240 | |
| | 241 | if (!nx__efc_erase_page(source, 0)) { |
| | 242 | return FS_ERR_FLASH_ERROR; |
| | 243 | } |
| | 244 | } |
| | 245 | |
| | 246 | return FS_ERR_NO_ERROR; |
| 227 | | /* TODO: allow forward moves ? */ |
| 228 | | NX_ASSERT(dest < source || (dest > source && dest > source + len)); |
| 229 | | |
| 230 | | while (len--) { |
| 231 | | memcpy((void *) data, |
| 232 | | (void *) &(FLASH_BASE_PTR[source*EFC_PAGE_WORDS]), |
| 233 | | EFC_PAGE_BYTES); |
| 234 | | if (!nx__efc_write_page(data, dest)) { |
| 235 | | return FS_ERR_FLASH_ERROR; |
| 236 | | } |
| 237 | | |
| 238 | | if (!nx__efc_erase_page(source, 0)) { |
| 239 | | return FS_ERR_FLASH_ERROR; |
| 240 | | } |
| 241 | | |
| 242 | | source++; |
| 243 | | dest++; |
| 244 | | } |
| 245 | | |
| 246 | | return FS_ERR_NO_ERROR; |
| | 266 | if (source == dest) { |
| | 267 | return FS_ERR_NO_ERROR; |
| | 268 | } else if (dest < source) { |
| | 269 | return nx_fs_move_region_backwards(source, dest, len); |
| | 270 | } else { |
| | 271 | return nx_fs_move_region_forwards(source, dest, len); |
| | 272 | } |
| 911 | | /*Fallback to simple defrag*/ |
| 912 | | nx_fs_defrag_simple(); |
| 913 | | } else { |
| 914 | | while (current_location < FS_PAGE_END) { |
| 915 | | if (nx_fs_page_has_magic(current_location)) { |
| 916 | | /* calculate free space after file */ |
| 917 | | volatile U32 *metadata = &(FLASH_BASE_PTR[current_location*EFC_PAGE_WORDS]); |
| 918 | | hole_start = current_location + nx_fs_get_file_page_count(nx_fs_get_file_size_from_metadata(metadata)); |
| 919 | | nx_fs_find_next_origin(hole_start, &next_origin); |
| 920 | | freeblock_size = next_origin - hole_start; |
| 921 | | |
| 922 | | /* frag operations*/ |
| 923 | | if (freeblock_size > mean_space_per_file) { |
| 924 | | size = nx_fs_get_file_size_from_metadata(metadata); |
| 925 | | nx_fs_move_region(current_location , hole_start + mean_space_per_file, nx_fs_get_file_page_count(size)); |
| 926 | | } else if (freeblock_size < mean_space_per_file) { |
| 927 | | nx_fs_find_next_hole(next_origin, & next_hole); |
| 928 | | /* TODO: fix overlapping on move */ |
| 929 | | nx_fs_move_region(next_origin, hole_start + mean_space_per_file, next_hole -1); |
| 930 | | } |
| 931 | | } |
| 932 | | } |
| 933 | | } |
| 934 | | return FS_ERR_NO_ERROR; |
| 935 | | } |
| 936 | | |
| | 941 | return nx_fs_defrag_simple(); |
| | 942 | } |
| | 943 | |
| | 944 | i = FS_PAGE_START; |
| | 945 | while (i < FS_PAGE_END) { |
| | 946 | if (nx_fs_page_has_magic(i)) { |
| | 947 | /* Calculate free space after file */ |
| | 948 | nx_fs_find_next_hole(i, &hole_start); |
| | 949 | nx_fs_find_next_origin(hole_start, &next_origin); |
| | 950 | freeblock_size = next_origin - hole_start; |
| | 951 | |
| | 952 | /* frag operations */ |
| | 953 | if (freeblock_size > mean_space_per_file) { |
| | 954 | size_t size = nx_fs_get_file_size_from_metadata(metadata); |
| | 955 | nx_fs_move_region(i, hole_start + mean_space_per_file, |
| | 956 | nx_fs_get_file_page_count(size)); |
| | 957 | } else if (freeblock_size < mean_space_per_file) { |
| | 958 | nx_fs_find_next_hole(next_origin, &next_hole); |
| | 959 | nx_fs_move_region(next_origin, hole_start + mean_space_per_file, |
| | 960 | next_hole - next_origin); |
| | 961 | } |
| | 962 | } |
| | 963 | } |
| | 964 | |
| | 965 | return FS_ERR_NO_ERROR; |
| | 966 | } |
| | 967 | |