I have been going though various sources and your hints and came eventually to a working prototype.
What I adopted is a kind of LRU cache mechanism which uses a fixed buffer of n blocks which is allocated at startup of the SD card driver.
Fixed buffers allow to avoid memory fragmentation and slowness due to malloc/free operations.
When a cache block is accessed or modified, an internal timestamp keeps track of the age of each entry. I do not use some internal real time clock but simply a counter which increments by 1 each time I get a new timestamp. Eviction of old cache items is done automatically by choosing the oldest one for new items. I avoided the use of linked lists as I keep only around 32 blocks in memory.
WB cache is implemented as well and it can occupy at most n % of the total available cache memory (n blocks). Write cache is flushed to disk by a separate task either after 200ms or when the maximum threshold is reached.
The additional layer of code is noticeable when doing I/O performance tests on single files as results are worse than without caching.
Anyhow the big advantage is that now access to the FAT or RMW operations (done quite often by the OS when calling fwrite with few data) are much faster and the overall system performance is a lot better.
Thanks for your help and incitations

Now I have to test, tune and improve my code