Skip to content

Commit

Permalink
Make magic dependent on fs length, if needed. (see #59 & #66)
Browse files Browse the repository at this point in the history
This will also add possibility to probe the filesystems length
beforehand to fully mounting it.

Thanks @hreintke.

Added API funcs:
  SPIFFS_probe_nbr_of_blocks

Added config:
  SPIFFS_USE_MAGIC_LENGTH
  • Loading branch information
pellepl committed Jan 24, 2016
1 parent 5183bf4 commit ac33a75
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 5 deletions.
12 changes: 11 additions & 1 deletion src/default/spiffs_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@
#define SPIFFS_USE_MAGIC (0)
#endif

#if SPIFFS_USE_MAGIC
// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is
// enabled, the magic will also be dependent on the length of the filesystem.
// For example, a filesystem configured and formatted for 4 megabytes will not
// be accepted for mounting with a configuration defining the filesystem as 2
// megabytes.
#ifndef SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_USE_MAGIC_LENGTH (0)
#endif
#endif

// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
// These should be defined on a multithreaded system

Expand All @@ -131,7 +142,6 @@
#define SPIFFS_UNLOCK(fs)
#endif


// Enable if only one spiffs instance with constant configuration will exist
// on the target. This will reduce calculations, flash and memory accesses.
// Parts of configuration must be defined below instead of at time of mount.
Expand Down
27 changes: 27 additions & 0 deletions src/spiffs.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,33 @@ typedef struct {

// functions

#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
/**
* Special function. This takes a spiffs config struct and returns
* the number of blocks this file system was formatted with.
* This function relies on following in the passed config struct:
* hal_read_f, phys_addr, and log_page_size.
*
* Do note, that caution should be taken with the value returned here.
*
* There is no check whatsoever that the flash actually contains a file
* system - meaning that just any number could be returned.
*
* There is neither any check that the configuration is set correctly.
* The block size may for instance differ.
*
* One must be sure of the page size and the physical address when
* calling this function.
*
* The resulting value can then be used to set the config structs
* phys_size by multiplying it with the known block size.
*
* @param config essential parts of the physical and logical
* configuration of the file system
*/
s32_t SPIFFS_probe_nbr_of_blocks(spiffs_config *config);
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH

/**
* Initializes the file system dynamic parameters and mounts the filesystem.
* If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS
Expand Down
11 changes: 11 additions & 0 deletions src/spiffs_hydrogen.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ s32_t SPIFFS_format(spiffs *fs) {
return 0;
}

#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH

s32_t SPIFFS_probe_nbr_of_blocks(spiffs_config *config) {
SPIFFS_LOCK(fs);
s32_t block_count = spiffs_probe(config);
SPIFFS_UNLOCK(fs);
return block_count;
}

#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH

s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
u8_t *fd_space, u32_t fd_space_size,
void *cache, u32_t cache_size,
Expand Down
28 changes: 26 additions & 2 deletions src/spiffs_nucleus.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ s32_t spiffs_erase_block(

#if SPIFFS_USE_MAGIC
// finally, write magic
spiffs_obj_id magic = SPIFFS_MAGIC(fs);
spiffs_obj_id magic = SPIFFS_MAGIC(fs, bix);
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
SPIFFS_MAGIC_PADDR(fs, bix),
sizeof(spiffs_obj_id), (u8_t *)&magic);
Expand All @@ -259,6 +259,30 @@ s32_t spiffs_erase_block(
}


#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
s32_t spiffs_probe(
spiffs_config *cfg) {
s32_t res;
spiffs dummy_fs; // create a dummy fs struct just to be able to use macros
memcpy(&dummy_fs.cfg, cfg, sizeof(spiffs_config));
spiffs_obj_id magic;
u32_t paddr = SPIFFS_MAGIC_PADDR(&dummy_fs, (spiffs_block_ix)0);
#if SPIFFS_HAL_CALLBACK_EXTRA
// not any proper fs to report here, so callback with null
// (cross fingers that no-one gets angry)
res = cfg->hal_read_f((void *)0, paddr, sizeof(spiffs_obj_id), (u8_t *)&magic);
#else
res = cfg->hal_read_f(paddr, sizeof(spiffs_obj_id), (u8_t *)&magic);
#endif
SPIFFS_CHECK_RES(res);

// unwind the magic crap to get nbr of blocks
dummy_fs.block_count = 0;
return SPIFFS_MAGIC(&dummy_fs, 0) ^ magic;
}
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH


static s32_t spiffs_obj_lu_scan_v(
spiffs *fs,
spiffs_obj_id obj_id,
Expand Down Expand Up @@ -311,7 +335,7 @@ s32_t spiffs_obj_lu_scan(
sizeof(spiffs_obj_id), (u8_t *)&magic);

SPIFFS_CHECK_RES(res);
if (magic != SPIFFS_MAGIC(fs)) {
if (magic != SPIFFS_MAGIC(fs, bix)) {
if (unerased_bix == (spiffs_block_ix)-1) {
// allow one unerased block as it might be powered down during an erase
unerased_bix = bix;
Expand Down
15 changes: 14 additions & 1 deletion src/spiffs_nucleus.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,15 @@
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)

#define SPIFFS_MAGIC(fs) ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
#if SPIFFS_USE_MAGIC
#if !SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_MAGIC(fs, bix) \
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
#else // SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_MAGIC(fs, bix) \
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
#endif // SPIFFS_USE_MAGIC_LENGTH
#endif // SPIFFS_USE_MAGIC

#define SPIFFS_CONFIG_MAGIC (0x20090315)

Expand Down Expand Up @@ -530,6 +538,11 @@ s32_t spiffs_erase_block(
spiffs *fs,
spiffs_block_ix bix);

#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
s32_t spiffs_probe(
spiffs_config *cfg);
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH

// ---------------

s32_t spiffs_obj_lu_scan(
Expand Down
4 changes: 3 additions & 1 deletion src/test/params_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
#define SPIFFS_PHYS_ADDR (4*1024*1024)

// test using filesystem magic
//#define SPIFFS_USE_MAGIC 1
#define SPIFFS_USE_MAGIC 1
// test using filesystem magic length
#define SPIFFS_USE_MAGIC_LENGTH 1

#define SECTOR_SIZE 65536
#define LOG_BLOCK (SECTOR_SIZE*2)
Expand Down
70 changes: 70 additions & 0 deletions src/test/test_hydrogen.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,76 @@ TEST(info)
}
TEST_END(info)

#if SPIFFS_USE_MAGIC
TEST(magic)
{
fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256);
SPIFFS_unmount(FS);

TEST_CHECK_EQ(fs_mount_specific(0, 65536*16, 65536, 65536, 256), SPIFFS_OK);
SPIFFS_unmount(FS);

TEST_CHECK_NEQ(fs_mount_specific(0, 65536*16, 65536, 65536, 128), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);

TEST_CHECK_NEQ(fs_mount_specific(4, 65536*16, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);

return TEST_RES_OK;
}
TEST_END(magic)


#if SPIFFS_USE_MAGIC_LENGTH
TEST(magic_length)
{
fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256);
SPIFFS_unmount(FS);

TEST_CHECK_EQ(fs_mount_specific(0, 65536*16, 65536, 65536, 256), SPIFFS_OK);
SPIFFS_unmount(FS);

TEST_CHECK_NEQ(fs_mount_specific(0, 65536*8, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);

TEST_CHECK_NEQ(fs_mount_specific(0, 65536*15, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);

TEST_CHECK_NEQ(fs_mount_specific(0, 65536*17, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);

TEST_CHECK_NEQ(fs_mount_specific(0, 65536*256, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);

return TEST_RES_OK;
}
TEST_END(magic_length)


TEST(magic_length_probe)
{
fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 16);

fs_reset_specific(0, 0, 65536*24, 65536, 65536, 256);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 24);

fs_reset_specific(0, 0, 32768*16, 32768, 32768, 128);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 16);

fs_reset_specific(0, 0, 16384*37, 16384, 16384, 128);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 37);

fs_reset_specific(0, 0, 4096*11, 4096, 4096, 256);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 11);

return TEST_RES_OK;
}
TEST_END(magic_length_probe)

#endif // SPIFFS_USE_MAGIC_LENGTH

#endif // SPIFFS_USE_MAGIC

TEST(missing_file)
{
Expand Down

0 comments on commit ac33a75

Please sign in to comment.