# FreeRTOS-FAT creates files with same long file name but with different short name

**URL:** <https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585>\
**Category:** Kernel\
**Created:** [March 2, 2022, 7:31am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585 "2022-03-02T07:31:53Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Austin](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/austin/32/242_2.png) [@Austin](https://forums.freertos.org/u/Austin)\
**Post date:** [March 2, 2022, 7:31am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/1 "2022-03-02T07:31:53Z")

</div>

Hi,

We create a FreeRTOS-FAT test to create/write files using FreeRTOS-FAT on SD card. The test is multi-threading. From test result, we get 4 files with same long file name (fstest\_dump\_task\_0x3971\_file\_idx\_0.bin), while the short file names are different.

The sdcard can mount and read/write in Linux and no error message pop-up

Is it a normal or it means there is an issue?

/mnt/tmp$ ls -l  
-rwxr-xr-x 1 root root 10485760 1月 1 2028 fstest\_dump\_task\_0x3971\_file\_idx\_0.bin  
-rwxr-xr-x 1 root root 10485760 1月 1 2028 fstest\_dump\_task\_0x3971\_file\_idx\_0.bin  
-rwxr-xr-x 1 root root 10485760 1月 1 2028 fstest\_dump\_task\_0x3971\_file\_idx\_0.bin  
-rwxr-xr-x 1 root root 10485760 1月 1 2028 fstest\_dump\_task\_0x3971\_file\_idx\_0.bin

Using Linux fatcat, they have different short names:

sudo ./fatcat /dev/sdd -l /  
Listing path /

f 1/1/2028 00:00:00 fstest\_dump\_task\_0x3971\_file\_idx\_0.bin (FSTEST~1.BIN) c=371496 s=10485760 (10M)  
f 0/1/2028 00:00:00 fstest\_dump\_task\_0x3971\_file\_idx\_0.bin (FSTEST~2.BIN) c=371498 s=10485760 (10M)  
f 0/1/2028 00:00:00 fstest\_dump\_task\_0x3971\_file\_idx\_0.bin (FSTEST~3.BIN) c=371497 s=10485760 (10M)  
f 0/1/2028 00:00:00 fstest\_dump\_task\_0x3971\_file\_idx\_0.bin (FSTEST~4.BIN) c=371499 s=10485760 (10M)

---

<div class="post-metadata">

**Author:** ![htibosch](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/htibosch/32/62_2.png) [@htibosch](https://forums.freertos.org/u/htibosch)\
**Post date:** [March 2, 2022, 8:34am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/2 "2022-03-02T08:34:08Z")

</div>

Interesting, and thanks for reporting this.

Did you also run fsck.vfat? And did it complain?

Would it be difficult for me to reproduce this? I guess that I need 4 tasks that run in parallel and created files with the same LFN?  
As you know, the SFN is “composed” by the driver, using certain standard rules to translate an LFN to a SFN.

The result it not what you want, but looking at the code, it is as expected:

Task 1 creates “fstest\_dump\_task\_0x3971\_file\_idx\_0.bin”, which results in a SFN “FSTEST~1.BIN”.  
Task 2 creates the same LFN, and the driver looks for the next available SFN, which is “FSTEST~2.BIN”.

But this is not what you want. Task 2 should not be able to succeed to create a file with mentioned LFN. It should get an error as long as task-1 has an open write handle to this file.

I will have a closer look.

I would be grateful if you can attach some testing code.

---

<div class="post-metadata">

**Author:** ![Austin](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/austin/32/242_2.png) [@Austin](https://forums.freertos.org/u/Austin)\
**Post date:** [March 2, 2022, 9:36am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/3 "2022-03-02T09:36:45Z")

</div>

This the test code, dump 10M memory content into file

FSTEST\_BUF\_ADDR is the memory address, can be changed in other environment

fopen/fwrite/fclose just a wrapper to ff\_open/etc

```auto
#define FSTEST_TASK_NUM 4
#define FSTEST_FILE_NUM 10
#define FSTEST_FILE_SIZE (10 * 1024 * 1024)
#define FSTEST_BUF_ADDR 0x1F700000U
static void fstest_write_file(void *p)
{
    int i=0;
    char fname[256];
    uint32_t *task_ptr = (uint32_t *)p;

    uint32_t task_id = 0x3971;

    for (uint32_t i = 0; i < FSTEST_FILE_NUM; i++) {
        sprintf(fname, "fstest_dump_task_0x%x_file_idx_%d.bin", task_id, i);
        FILE *fp = fopen(fname, "w");
        if (fp == NULL) {
            printf("Open file fail\n");
            break;
        }
        size_t size = fwrite((void *)FSTEST_BUF_ADDR, FSTEST_FILE_SIZE, 1, fp);
        if (size != 1U) {
            printf("Write file fail\n");
            fclose(fp);
            break;
        }
        fclose(fp);
        printf("task 0x%x file %d is written:%s\n", task_id, i, fname);
    }

    *task_ptr = *task_ptr + 1;
    printf("task 0x%x done: write %d files, join number=%d\n", task_id, param_num, *task_ptr);

    vTaskDelete(NULL);
}

static void test_filesystem()
{
    TaskHandle_t fstest_task[FSTEST_TASK_NUM];

    uint32_t join_num = 0U;
    /* Create Tasks */
    for (uint32_t i = 0; i < FSTEST_TASK_NUM; i++) {
        xTaskCreate(fstest_write_file, "fstest", 1024, (void *)(&join_num), 1, &fstest_task[i]);
    }

    while (join_num < FSTEST_TASK_NUM) {
        vTaskDelay(1000U);
    }

    printf("Test done, check filesystem on SDcard\n");
}

```

---

<div class="post-metadata">

**Author:** ![Austin](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/austin/32/242_2.png) [@Austin](https://forums.freertos.org/u/Austin)\
**Post date:** [March 2, 2022, 9:58am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/4 "2022-03-02T09:58:49Z")

</div>

> Task 1 creates “fstest\_dump\_task\_0x3971\_file\_idx\_0.bin”, which results in a SFN “FSTEST~1.BIN”.  
> Task 2 creates the same LFN, and the driver looks for the next available SFN, which is “FSTEST~2.BIN”.  
> But this is not what you want. Task 2 should not be able to succeed to create a file with mentioned LFN. It should get an error as long as task-1 has an open write handle to this file.  
> But this is not what you want. Task 2 should not be able to succeed to create a file with mentioned LFN. It should get an error as long as task-1 has an open write handle to this file.

For above test code, sometime there is “open fail” (see bellow log)  
The the first file (idx\_0) are all created for the four tasks  
And then the following files (idx\_1/2/…), the task may return “open fail”

FF\_Open may need to be protected by FF\_PendSemaphore( pxIOManager-\>pvSemaphore )

Test log (get “open fail” sometimes)

```auto
Conduct test for fs
task 0x3971 file 0 is written:fstest_dump_task_0x3971_file_idx_0.bin
task 0x3971 file 0 is written:fstest_dump_task_0x3971_file_idx_0.bin
task 0x3971 file 0 is written:fstest_dump_task_0x3971_file_idx_0.bin
task 0x3971 file 0 is written:fstest_dump_task_0x3971_file_idx_0.bin
Open file fail
task 0x3971 done: writtae sk1 0 f0xil39e7s1, jfoiline n1u imbse wrr=1it
 en:fstest_dump_task_0x3971_file_idx_1.bin
task 0x3971 file 1 is written:fstest_dump_task_0x3971_file_idx_1.bin
task 0x3971 file 1 is written:fstest_dump_task_0x3971_file_idx_1.bin
Open file fail
eask 0x3971 done: writtaes k 100x 3f9il7e1s f,i ljoe i2n insu mbwreir=t2t
 n:fstest_dump_task_0x3971_file_idx_2.bin
task 0x3971 file 2 is written:fstest_dump_task_0x3971_file_idx_2.bin
task 0x3971 file 3 is written:fstest_dump_task_0x3971_file_idx_3.bin
task 0x3971 file 3 is written:fstest_dump_task_0x3971_file_idx_3.bin
task 0x3971 file 4 is written:fstest_dump_task_0x3971_file_idx_4.bin
task 0x3971 file 4 is written:fstest_dump_task_0x3971_file_idx_4.bin
task 0x3971 file 5 is written:fstest_dump_task_0x3971_file_idx_5.bin
task 0x3971 file 5 is written:fstest_dump_task_0x3971_file_idx_5.bin

```

dir/ls in freertos

```auto
>ls
fstest_dump_task_0x3971_file_idx_0.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_0.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_0.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_0.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_1.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_1.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_1.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_2.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_2.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_3.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_3.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_4.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_4.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_5.bin [writable file] [size=4096]
fstest_dump_task_0x3971_file_idx_5.bin [writable file] [size=4096]

```

fsck result

```auto
$ sudo fsck.vfat /dev/sdd
fsck.fat 4.1 (2017-01-24)
0x41: Dirty bit is set. Fs was not properly unmounted and some data may be corrupt.
1) Remove dirty bit
2) No action
? 1
Perform changes ? (y/n) y
/dev/sdd: 23 files, 24/1893985 clusters

$ sudo mount /dev/sdd /mnt/tmp/
$ ls /mnt/tmp/
fstest_dump_task_0x3971_file_idx_0.bin fstest_dump_task_0x3971_file_idx_1.bin fstest_dump_task_0x3971_file_idx_3.bin fstest_dump_task_0x3971_file_idx_6.bin fstest_dump_task_0x3971_file_idx_8.bin
fstest_dump_task_0x3971_file_idx_0.bin fstest_dump_task_0x3971_file_idx_1.bin fstest_dump_task_0x3971_file_idx_4.bin fstest_dump_task_0x3971_file_idx_6.bin fstest_dump_task_0x3971_file_idx_9.bin
fstest_dump_task_0x3971_file_idx_0.bin fstest_dump_task_0x3971_file_idx_2.bin fstest_dump_task_0x3971_file_idx_4.bin fstest_dump_task_0x3971_file_idx_7.bin fstest_dump_task_0x3971_file_idx_9.bin
fstest_dump_task_0x3971_file_idx_0.bin fstest_dump_task_0x3971_file_idx_2.bin fstest_dump_task_0x3971_file_idx_5.bin fstest_dump_task_0x3971_file_idx_7.bin
fstest_dump_task_0x3971_file_idx_1.bin fstest_dump_task_0x3971_file_idx_3.bin fstest_dump_task_0x3971_file_idx_5.bin fstest_dump_task_0x3971_file_idx_8.bin

```

---

<div class="post-metadata">

**Author:** ![kanherea](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/kanherea/32/4106_2.png) [@kanherea](https://forums.freertos.org/u/kanherea)\
**Post date:** [March 3, 2022, 9:26pm UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/5 "2022-03-03T21:26:35Z")

</div>

Hello @Austin,

While I am unfamiliar with the FAT codebase, I see a potential race condition in your code: `*task_ptr = *task_ptr + 1;`. This line will be executed by all tasks in parallel and if they somehow coincide, it’ll lead to a different value.

I would suggest that you use task notifications in such scenarios. See this example: [FreeRTOS task notifications](https://www.freertos.org/RTOS_Task_Notification_As_Counting_Semaphore.html).

---

<div class="post-metadata">

**Author:** ![Austin](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/austin/32/242_2.png) [@Austin](https://forums.freertos.org/u/Austin)\
**Post date:** [March 4, 2022, 2:26am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/6 "2022-03-04T02:26:52Z")

</div>

Ok. Thanks for the comments

This is just make sure the parent task can wait till the four fork-ed tasks. It doesn’t impact the core issue we are discussing.

---

<div class="post-metadata">

**Author:** ![htibosch](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/htibosch/32/62_2.png) [@htibosch](https://forums.freertos.org/u/htibosch)\
**Post date:** [March 4, 2022, 4:54am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/7 "2022-03-04T04:54:35Z")

</div>

Thank you for this well documented report. It also works for me, I can reproduce the problem.

It looks indeed like a race between equal-priority tasks, which are trying to create the same object. When `ff_fopen()` returns a creation error, that is actually good.

The code would only close the file in case of an error. And also I would swap the COUNT and SIZE parameters of `fwrite()`, so you can see how many bytes (not blocks) have actually been written:

```diff
- size_t size = fwrite(pucBuffer, FSTEST_FILE_SIZE, 1, fp);
+ size_t size = fwrite(pucBuffer, 1, FSTEST_FILE_SIZE, fp);
+ fclose(fp);
- if (size != 1U) {
+ if (size != FSTEST_FILE_SIZE) {
            printf("Write '%s' failed\n", fname);
- fclose(fp);
            break;
        }

```

Now I will see if there is an easy solution.

---

<div class="post-metadata">

**Author:** ![htibosch](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/htibosch/32/62_2.png) [@htibosch](https://forums.freertos.org/u/htibosch)\
**Post date:** [March 5, 2022, 4:54am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/8 "2022-03-05T04:54:11Z")

</div>

@Austin wrote:

> FF\_Open may need to be protected by FF\_PendSemaphore( pxIOManager-\>pvSemaphore )

That will stop the race indeed!

The standard semaphore can not be used for this though: it would lead to a dead-lock.  
There is also a lock of “directory access”, and a lock on the FAT, but those are not-recursive.

What I did is add a new semaphore called `pvSemaphoreOpen`:

```c
pxIOManager->pvSemaphoreOpen = xSemaphoreCreateRecursiveMutex();

```

And protect the function `FF_Open()` with it, but only if a file is to be created.

I tested it and it works perfectly: only a single instance of each LFN (long file name) will be created on disk. Other tasks all receive an error because task-1 still has an open handle.

I would like to make it conditional on some macro.

You can find the new code [in this branch](https://github.com/htibosch/Lab-Project-FreeRTOS-FAT/tree/Protect_ff_open_with_semaphore).

I only changed 3 source files: [ff\_file.c](https://github.com/htibosch/Lab-Project-FreeRTOS-FAT/blob/Protect_ff_open_with_semaphore/ff_file.c), [ff\_ioman.c](https://github.com/htibosch/Lab-Project-FreeRTOS-FAT/blob/Protect_ff_open_with_semaphore/ff_ioman.c), and [ff\_ioman.h](https://github.com/htibosch/Lab-Project-FreeRTOS-FAT/blob/Protect_ff_open_with_semaphore/include/ff_ioman.h)

You you have a try with these changes? You will have to add define to your copy of FreeRTOSFATConfig.h:

```c
#define ffconfigPROTECT_FF_FOPEN_WITH_SEMAPHORE 1

```

You wrote:

> `#define FSTEST_FILE_SIZE (10 * 1024 * 1024)`

I only wrote 4 KB to each file to see the race.

Hein

---

<div class="post-metadata">

**Author:** ![htibosch](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/htibosch/32/62_2.png) [@htibosch](https://forums.freertos.org/u/htibosch)\
**Post date:** [March 5, 2022, 5:11am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/9 "2022-03-05T05:11:58Z")

</div>

I just presented my branch as a [pull request #26](https://github.com/FreeRTOS/Lab-Project-FreeRTOS-FAT/pull/26)

Could you give it a try?

---

<div class="post-metadata">

**Author:** ![Austin](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/austin/32/242_2.png) [@Austin](https://forums.freertos.org/u/Austin)\
**Post date:** [March 7, 2022, 7:22am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/10 "2022-03-07T07:22:11Z")

</div>

Thanks for the patch. Will verify and provide the feedback ASAP

---

<div class="post-metadata">

**Author:** ![Austin](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/austin/32/242_2.png) [@Austin](https://forums.freertos.org/u/Austin)\
**Post date:** [March 8, 2022, 1:28am UTC](https://forums.freertos.org/t/freertos-fat-creates-files-with-same-long-file-name-but-with-different-short-name/14585/11 "2022-03-08T01:28:52Z")

</div>

After test, there is only 1 file is created.  
Thank you for the quick fix.
