desertkun / littlefs-dokany

A https://github.com/dokan-dev/dokany implementation of littlefs
Do What The F*ck You Want To Public License
4 stars 1 forks source link

IO error with different parameters.... #1

Open keithdr00 opened 2 years ago

keithdr00 commented 2 years ago

Not sure if this project is still active, but curious if anyone is using this project with devices that have different parameters from the default? I am using LittleFS on an embedded project with parameters:

block_size = 4096 block_count = 32768 read_size = 16 prog_size = 16 cahce_size = 64 lookahead_size = 32

I have played around with modifying littlefs-dokany both via the existing command line parameters and directly in the code, but I have not been able to successfully mount this device.

I will be happy to provide additional details if anyone is still supporting this project.

Thanks!!!

desertkun commented 2 years ago

As per block_size, it is specified via command line --block-size 4096. This project, however, currently does not support specifying cache_size separately from read/prog size

        // read_size
        unit_size,
        // prog_size
        unit_size,
        // block_size
        block_size,
        // block_count
        block_count,
        // block_cycles
        1000,
        // cache_size
        unit_size,

but you can specify --unit-size 16. You can always open a pull request that would add a separate command line argument for cache size if needed.

Block count cannot be specified as it uses whole block device. Lookahead size is hardcoded to 128 currently.

have not been able to successfully mount this device.

Are you not able to mount it on an MC after being written out by windows, or you're not able to mount it on windows after it's been written by an MC? How do you mount it? Are you specifying correct block device?

Beware to distinguish mounting a partition (aka mounting E: into K:) from mounting a block device (PhysicalDrive2 into K:), the former uses MBR while the latter puts data right on the first bytes of the device.

keithdr00 commented 2 years ago

@desertkun thank you for the feedback. I attempted to push a new branch (eventually hoping to create a PR), but the request was denied. Is the product set up to take new branches from anyone, or do I need to be on a "contributors" list or something like that?

Regarding my specific use, I am actually connecting the MCU (specifically the LittleFS partition of the MCU) to a PC using USB MSC. This causes the device to be exposed as a Raw Device image. I'm trying to use littlefs-dokany to connect to/mount that Raw Device image as a drive for accessing in Windows. I have been able to do this on Linux using littlefs-fuse, so I believe it should be possible.

I will add command line arguments to make more parameters configurable so that I can be sure to align the parameters with my embedded configuration. I also appreciate your clarification on PHYSICALDRIVEx vs. drive letter access. I will definitely want/need to be using drive letter access since my partition does not have/use an MBR.

desertkun commented 2 years ago

To create a PR you have to fork first. You push to your copy and then open a pull request to merge from your copy to mine.

As per your issue, I see. It's not supposed to mount as there's garbage there. You need to FORMAT it (--format, missing in the doc). Beware as it's going to write to block device, destroying data that's there.

keithdr00 commented 2 years ago

Hmm, what do you mean by "there's garbage there"? The device that I'm connecting via USB MSC has a valid LFS image on it. I do not want to format that device as I would then not be able to read the content.

On Linux, I am able to use littlefs-fuse to mount the device and read data from the embedded LFS filesystem without formatting that embedded image.

Are there portions of the dokany internal state that need to be initialized/syncronized with the device state?

desertkun commented 2 years ago

I see. Maybe cache sizes and such are important. Do you care to share your LFS image so I'd try to mount it?

keithdr00 commented 2 years ago

Here is an image from my device. It only has one small file in a directory (settings/run). I am able to mount it in Linux using littlefs-fuse with the command line ./lfs --read_size=16 --prog_size=16 --block_size=4096 --block_count=32768 --cache_size=64 --lookahead_size=32 /dev/sda <mount point>.

I think you are correct that cache and lookahead sizes may matter. I also think there may be some overuse of the term "sector" where sometimes this means the read/prog size (i.e. unit_size) and other times it means the block size (i.e. block_size). I have been trying to follow parallel paths through littlefs-dokany and littlefs-fuse to look for differences, but have not made much progress yet.

lfs.zip unzip for the image file itself

keithdr00 commented 2 years ago

A little update here. After clearing up a few issues with my installation (I had the wrong version of Dokany installed), I am now able to mount the image file attached above using --block-size 4096 --unit-size 16 (and modifying the code to take/use the filename rather than a drive name/letter).

Unfortunately, if I dd that same image on to a USB drive I cannot mount it. The issue seems to come in lfs_bind_read() where the call to ReadFile() fails with error INVALID_PARAMETER (87). Searching around on that information leads me to this SO entry that seems to indicate there may be some alignment issues while reading the block device.

I am not familiar with the OVERLAPPED concept you're using when reading the file, is there some advantage to that method over a separate call to SetFilePointer() before calling ReadFile()?

keithdr00 commented 2 years ago

Great news! I believe I have things working (and by and large understand what is going on). Basically, as mentioned above, accesses to the volumes/raw devices must be aligned to the sector size of the device. As the code is written, it assumes (and enforces in main) that the media sector size is the same as the prog/read size of the LFS filesystem. So, any time I was trying to change the read/prog size to match my LFS instance, I was causing unaligned accesses to the raw device which causes errors during mounting.

Fortunately, the only parameter that must match the configuration of the filesystem being mounted is the block size. So, even though my LFS image was created using read/prog size of 16, it can be mounted with read/prog size of 512 (matching the sector size of the raw USB device) without corrupting the filesystem (it does affect the way the data is distributed across the device, but it does not affect the integrity of the filesystem). So, if I use only the --block-size 4096 option and leave the unit size at the default 512, things work as expected.

I have some ideas to allow separate read/prog size settings while still aligning the raw device accesses. I will submit those via PR in a week or two, but for now, I'm able to proceed with my development (I am going to submit a small PR with a couple of minor changes, but nothing significant yet).

Thank you for your responsiveness and for this nice tool for working with LFS devices.

desertkun commented 2 years ago

Thank you very much for your research. I will try to sneak some time on the weekends to see what can be done to fix this.