Hi Stefan,

 

This error does not occur on arm platform as no error reports when flush in case of no write is called in these platforms. You have found the root cause of the error on your platform. The its_flash_fs_ops_t’ flush API does not define the case of empty data to flush as an error. So I am not sure whether the flash driver should support that or not. But what the ITS file system layer can do is avoid flushing in this case. The data block should be switched to the scratch data block even if the calculated remaining data length is 0 after deletion. The reason is that the asset data is not actually erased from the data block yet. It is expected to be erased in its_mblock_erase_scratch_blocks  when calling its_flash_fs_mblock_meta_update_finalize later.

 

An easy fix should be checking the move data into scratch data block. If no data is moved, the skip the flush.

 

I created this patch for the fix. Would you like help review and test it on your board? Thanks.

 

Regards,

Sherry Zhang

 

From: Stefan Krug via TF-M <tf-m@lists.trustedfirmware.org>
Sent: Wednesday, November 16, 2022 10:55 PM
To: TF-M mailing list <tf-m@lists.trustedfirmware.org>
Subject: [TF-M] Deleting last object in a data block in ITS filesystem

 

Hello!

 

Seemingly, there is an issue with file deletion in ITS. I would think it is not

possible to delete the last object in a data block (so that the data

block becomes empty).

 

It’s easiest to reproduce with using large objects (because then the number of

involved objects is small), but would also happen with multiple

smaller objects:

 

With the following flash configuration:

    ITS_MAX_ASSET_SIZE=0x1000

    TFM_HAL_ITS_SECTORS_PER_BLOCK=1

    TFM_HAL_ITS_FLASH_AREA_SIZE=0x20000

    TFM_HAL_ITS_PROGRAM_UNIT=0x100

    ITS_FLASH_NAND_BUF_SIZE=1*0x1000

 

In a sequence of writing and deleting an object like:

 

    const uint8_t big_file[ITS_MAX_ASSET_SIZE] = {0};

    status = psa_its_set(uid, sizeof(big_file), big_file, flags);

    status = psa_its_remove(uid);

 

deleting the file fails with the status of PSA_ERROR_GENERIC_ERROR.

 

 

What I think happens is:

 

Due to the size of the file, it does not fit in the metadata block, and is put a

second (data only) block. The object is written there as expected.

 

When the data block is deleted later, an attempt is being made to compact it

with its_flash_fs_dblock_compact_block(). However, there is no data to keep

before the object to be deleted and also no data to keep after it, this block

will become empty, so no call to its_flash_fs_block_to_block_move() happens,

which causes no call to fs_ctx->ops->write() happens. Now the flash driver in

my case is a buffering its_flash_nand.c. In the write() call it would associate

a buffer for the physical sector to write. But since there is no write() call

the subsequent fs_ctx->ops->flush() fails as it has no buffer to flush out.

 

I believe no compaction of the block should even be attempted - it is known

that the block will be empty beforehand. Perhaps similar to

https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/17578, this is

yet another reason to skip compacting of the block?

 

 

It would be very much appreciated if one of the experts could confirm this

suspicious behavior or point out a mistake I am making.

 

 

Thank you very much, best regards

  Stefan Krug