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
drivers: disk: add loopback disk driver #69895
Conversation
4e08052
to
91be850
Compare
There was a problem hiding this 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?
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 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. |
* | ||
* @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) |
There was a problem hiding this comment.
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
anddisk_access_name
fields inctx
bechar []
values, and usestrncpy
to copy thefile_path
anddisk_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);
}
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
91be850
to
051ae9d
Compare
#ifdef CONFIG_DISK_DRIVER_LOOPBACK | ||
#define DISK_NAME "loopback0" | ||
#else | ||
#define DISK_NAME DISK_NAME_PHYS | ||
#endif |
There was a problem hiding this comment.
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/modules/fatfs/zephyr_fatfs_config.h
Lines 84 to 95 in 51d80a9
/* 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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
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 |
There was a problem hiding this comment.
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...)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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>
051ae9d
to
64580ea
Compare
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>
64580ea
to
3dbeba6
Compare
@@ -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":" |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks OK.
This driver creates a disk_access that transparently reads from and writes to a file in a file system.