Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: disk: add loopback disk driver #69895

Merged
merged 2 commits into from Apr 15, 2024

Conversation

arbrauns
Copy link
Contributor

@arbrauns arbrauns commented Mar 7, 2024

This driver creates a disk_access that transparently reads from and writes to a file in a file system.

Copy link
Collaborator

@danieldegrasse danieldegrasse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting feature- thanks for the PR! I feel like this might make more sense as a subsystem extension to the filesystem API though, rather than a disk driver. @de-nordic, any thoughts here?

@de-nordic
Copy link
Collaborator

This is an interesting feature- thanks for the PR! I feel like this might make more sense as a subsystem extension to the filesystem API though, rather than a disk driver. @de-nordic, any thoughts here?

Hm. The example provided here, with FATFS, actually uses the Disk Driver as backend to storage access. So in this case it makes sense to provide the driver as disk access driver.
I do not find it useful too much, as it would probably will look like FAT FS->disk access to file ->FAT FS->disk access-> MMC device (or flash api->device).
I guess that there is probably usecase where user uploads disk images to FAT FS via FTP and then mounts them.
This does not seem to break anything and may be valuable to some users.
Worth noting that this may take a toll on device life time if such image is R/W mounted from internal flash with devices that have > 512B page sizes.

I think the feature is OK, and in the right place.

@danieldegrasse
Copy link
Collaborator

This does not seem to break anything and may be valuable to some users.
Worth noting that this may take a toll on device life time if such image is R/W mounted from internal flash with devices that have > 512B page sizes.

I think the feature is OK, and in the right place

This is fair- in many ways the disk drivers are different, since they all sit under the disk subsystem. That is a good point about internal flash devices. However, I think anyone using a flash device to emulate a disk already should be aware this will cause issues regarding wear leveling and such, since filesystems like FatFS aren't explicitly designed for that.

drivers/disk/Kconfig.loopback Show resolved Hide resolved
drivers/disk/loopback_disk.c Outdated Show resolved Hide resolved
*
* @param ctx Preallocated context structure
* @param file_path Path to backing file
* @param disk_access_name Name of the created disk access (for disk_access_*() functions)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the file_path and disk_access_name parameters, we should either:

  • document the requirement that these parameters should not be stack allocated (as they will be assigned to the ctx structure)
  • make the file_path and disk_access_name fields in ctx be char [] values, and use strncpy to copy the file_path and disk_access_name parameters provided by the user into those fields

As is stands right now, I worry a user might write code like the following:

struct loopback_disk_access global_ctx;
const char *name = "disk_name";

void my_init_func()
{
    const char *file_path = "my_path";

    loopback_disk_access_register(&global_ctx, file_path, name);
}


void write_func()
{
    ....
    /* Path temporary variable will have been deallocated here .. */
    disk_access_read(name,  data_buf, start_sector, num_sector);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would still be fine, since file_path is a string literal, but I get your point. I went with option 1, since I'm not a big fan of statically-sized string buffers.

I've also added an unregister function that will end the lifetime of these parameters.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would still be fine, since file_path is a string literal, but I get your point. I went with option 1, since I'm not a big fan of statically-sized string buffers.

This is true- perhaps not the best example. Glad it highlighted the point though

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that stack allocated things are ok as long as it is mentioned that they have to be valid through entire runtime.
This already happens when people create file in main of their code and pass it along (or use global to pass it).
And if you allow path to be passed, probably somebody would like to do the

snprintf(path, "/my_loopback/disks/%d.img", i);

at some point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that stack allocated things are ok as long as it is mentioned that they have to be valid through entire runtime.

I believe that's what the doc comment says, yes.

Comment on lines +35 to +41
#ifdef CONFIG_DISK_DRIVER_LOOPBACK
#define DISK_NAME "loopback0"
#else
#define DISK_NAME DISK_NAME_PHYS
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just add this to the above set of #if #else.
Does the FAT FS mounting work? The Fat FS has very limited number of mount points it can work with and these mountpoints are used also as disk names.

/* Zephyr uses FF_VOLUME_STRS */
#undef FF_STR_VOLUME_ID
#define FF_STR_VOLUME_ID 1
/* By default FF_STR_VOLUME_ID in ffconf.h is 0, which means that
* FF_VOLUME_STRS is not used. Zephyr uses FF_VOLUME_STRS, which
* by default holds 8 possible strings representing mount points,
* and FF_VOLUMES needs to reflect that, which means that dolt
* value of 1 is overridden here with 8.
*/
#undef FF_VOLUMES
#define FF_VOLUMES 8

https://github.com/zephyrproject-rtos/fatfs/blob/427159bf95ea49b7680facffaa29ad506b42709b/include/ffconf.h#L174C9-L174C23

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just add this to the above set of #if #else.

What exactly do you mean? In the loopback case, I need both DISK_NAME (for the actual disk access tests) and DISK_NAME_PHYS (for the setup of the loopback disk access).

Does the FAT FS mounting work?

The tests pass, so I presume it does? I believe it's using the RAM disk.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right. The FAT is not mounted on the loopback drive, the fat is the source of loopback image only

Comment on lines 22 to 34
drivers.disk.loopback:
extra_configs:
- CONFIG_DISK_DRIVER_LOOPBACK=y
- CONFIG_FILE_SYSTEM=y
- CONFIG_FILE_SYSTEM_MKFS=y
- CONFIG_FAT_FILESYSTEM_ELM=y
platform_allow: qemu_x86_64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to rather do native_sim target? (to be honest qemu is not my favourite debugging target...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I simply copied the existing test cases, should I change those too?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should I change those too?

I am asking about code in this PR not change in entire testcase.yaml; there is already native_sim target above your addition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed there is now, there wasn't before I rebased. native_sim however does not contain the ramdisk that qemu_x86_64 does; I have copy-pasted the ramdisk declaration from the qemu overlay, hope that's how it's supposed to be.

This driver creates a disk_access that transparently reads from and writes
to a file in a file system.

Signed-off-by: Armin Brauns <armin.brauns@embedded-solutions.at>
@arbrauns
Copy link
Contributor Author

Rebased to fix conflicts.

This sets up a backing device, creates a FAT file system, then opens a file
as a loopback device and runs the disk_access tests on that.

Signed-off-by: Armin Brauns <armin.brauns@embedded-solutions.at>
@@ -46,6 +58,43 @@ static uint32_t disk_sector_size;
/* + 4 to make sure the second buffer is dword-aligned for NVME */
static uint8_t scratch_buf[2][SECTOR_COUNT4 * SECTOR_SIZE + 4];

#ifdef CONFIG_DISK_DRIVER_LOOPBACK
#define BACKING_PATH "/"DISK_NAME_PHYS":"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably create this name from the DISK_NAME definition above with preprocessor concatenation, right? Might be worth looking at to avoid maintaining this name in two locations

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand, isn't that exactly what is happening? DISK_NAME_PHYS is a preprocessor macro.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is- sorry I missed this, was expecting to see # for concatenation, but this should work fine as is

Copy link
Collaborator

@de-nordic de-nordic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks OK.

@carlescufi carlescufi merged commit 2c8ea07 into zephyrproject-rtos:main Apr 15, 2024
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants