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

subsys: fs: Implementation of ext2 file system #55152

Merged
merged 30 commits into from Aug 3, 2023

Conversation

fzdobylak
Copy link
Contributor

@fzdobylak fzdobylak commented Feb 24, 2023

This PR adds implementation of ext2 file system to Zephyr.

It allows mounting file systems from different disks (accessed by disk_access interface).

Features:

  • File system with different block sizes may be mounted (1k, 2k and 4k blocks)

Current limitations:

  • Only small file systems can be mounted (8MB for 1k blocks, 32MB for 2k blocks and 128MB for 4k blocks).
  • Only file systems with inode size equal to 128B can be mounted.
  • One can mount only one ext2 file system at a time.
  • File system may be used only by a single thread.
  • Only ext2 is supported, but it can be changed to a higher version of ext in the future by supporting more ext features.
  • GUID Partition Table is not supported. The starting sector of the file system must be specified by CONFIG_EXT2_DISK_STARTING_SECTOR. It also means that GPT won’t be updated if a new file system is created.

This supersedes #52895

Copy link
Collaborator

@nordicjm nordicjm left a comment

Choose a reason for hiding this comment

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

Gave the test a try with a microsd card on a bl5340_dvk_cpuapp and the results were interesting. Tests seemed to run OK until the test that writes an 8MB file and then truncates it - the 8MB write took minutes. Then when the test was finished I moved the card back to the PC to check it and it has used the whole card as the ext2 filesystem (8GB card) without setting up a partition map, so the card's old partition map of a single fat32 partition is still present.

Even more interesting is this:

df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/mmcblk0    7.8M  -20M   28M    - /tmp/tt

Something does not seem right here.

@nordicjm
Copy link
Collaborator

nordicjm commented Mar 6, 2023

I opened the test file in nano which said "this file should be read only", tried writing a new file and it caused a kernel panic on my system.

@fzdobylak
Copy link
Contributor Author

@nordicjm Thank you for your comments.

My implementation doesn't cover changing the GUID partition table. This is why we have to manually specify the sector where to start looking for the ext2 filesystem or where to create it. I think that implementation of maintaining GPT won’t be a part of this PR. I will update the description to include this information.

I will take a look at the problem that you have discovered. Although I know why you got kernel panic, and I will change it as soon as possible. This is due to the flag set by default in the superblock::s_errors field.

Copy link
Collaborator

@nordicjm nordicjm left a comment

Choose a reason for hiding this comment

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

Seems better but still not right. Modified fatfs sample to use ext2 instead, output (of 8GB card) whereby the zephyr app formats it, I've then created 2 files from a PC:

*** Booting Zephyr OS build zephyr-v3.3.0-1082-gd42db2a1d8c4 ***
[00:00:00.449,340] <inf> sd: Maximum SD clock is under 25MHz, using clock of 8000000Hz
[00:00:00.449,859] <inf> main: Block count 15126528
Sector size 512
Memory Size(MB) 7386
Disk mounted.

Listing dir /SD: ...
[DIR ] lost+found
[FILE] file1 (size = 10)
[FILE] file2 (size = 16736)

However, switch to a PC:

/dev/mmcblk0    7.8M   20K  7.8M   1% /tmp/qq

7.8MB?
Forgot that the limit is 8MB for 1k blocks from the original post

Also:

e2fsck -f /dev/mmcblk0 
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Free blocks count wrong for group #0 (7919, counted=7918).
Fix<y>? no
Padding at end of block bitmap is not set. Fix<y>? no

ext2: ********** WARNING: Filesystem still has errors **********

ext2: 13/1984 files (7.7% non-contiguous), 274/8192 blocks

This does not look good

@nordicjm
Copy link
Collaborator

Made a filesystem from the PC: mkfs.ext2 -b 4096 /dev/mmcblk0 32768 should be small enough to fit:

/dev/mmcblk0    120M   48K  114M   1% /tmp/qq

But does not:

*** Booting Zephyr OS build zephyr-v3.3.0-1082-gd42db2a1d8c4 ***
[00:00:00.369,873] <inf> sd: Maximum SD clock is under 25MHz, using clock of 8000000Hz
[00:00:00.370,391] <inf> main: Block count 15126528
Sector size 512
Memory Size(MB) 7386
[00:00:00.374,389] <wrn> ext2: File system can be mounted read only. RO features 3 detected.
Disk mounted.
[00:00:00.417,907] <err> fs: directory open error (-20)
Error opening dir /SD: [-20]

Tried again using: mkfs.ext2 -b 4096 -O filetype,-ext_attr,-resize_inode,-dir_index,-sparse_super,-large_file /dev/mmcblk0 32768, which gives me:

dumpe2fs /dev/mmcblk0 
dumpe2fs 1.47.0 (5-Feb-2023)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          d11a84c3-183a-4d0c-a499-91bd14931e14
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      filetype
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              32768
Block count:              32768
Reserved block count:     1638
Overhead clusters:        2052
Free blocks:              30711
Free inodes:              32757
First block:              0
Block size:               4096
Fragment size:            4096
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         32768
Inode blocks per group:   2048
Filesystem created:       Tue Mar 14 09:48:42 2023
Last mount time:          n/a
Last write time:          Tue Mar 14 09:48:43 2023
Mount count:              0
Maximum mount count:      -1
Last checked:             Tue Mar 14 09:48:42 2023
Check interval:           0 (<none>)
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               256
Required extra isize:     32
Desired extra isize:      32
Default directory hash:   half_md4
Directory Hash Seed:      b441ffbb-82b5-44f4-902b-0b7a6773a0ba


Group 0: (Blocks 0-32767)
  Primary superblock at 0, Group descriptors at 1-1
  Block bitmap at 2 (+2)
  Inode bitmap at 3 (+3)
  Inode table at 4-2051 (+4)
  30711 free blocks, 32757 free inodes, 2 directories
  Free blocks: 2057-32767
  Free inodes: 12-32768

But this just seems to give this:

[00:00:00.278,167] <inf> main: Block count 15126528
Sector size 512
Memory Size(MB) 7386
Disk mounted.
[00:00:00.325,744] <err> fs: directory open error (-20)
Error opening dir /SD: [-20]

So how can we actually use this?

@fzdobylak
Copy link
Contributor Author

@nordicjm Thank you.

The first problem that you have described I have discovered and I am working on it.

Actually I have used this implementation already to read some files stored on SD card in Zephyr. I will look at the second problem you have described.

@fzdobylak fzdobylak force-pushed the ext2-pr1 branch 5 times, most recently from 3336e94 to 32a57bd Compare March 20, 2023 09:01
@fzdobylak
Copy link
Contributor Author

fzdobylak commented Mar 20, 2023

@nordicjm Hi, I have created a sample to allow you to run my implementation as I was doing it. I hope it will work now.
I have also made a few changes to implementation to fix bugs that I have discovered so far (e.g. creating valid file system and counting free blocks properly).

Copy link
Collaborator

@nordicjm nordicjm left a comment

Choose a reason for hiding this comment

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

*** Booting Zephyr OS build zephyr-v3.3.0-1086-g32a57bd0efc0 ***rt                 
[00:00:00.288,757] <inf> sd: Maximum SD clock is under 25MHz, using clock of 8000000Hz
Mounted filesystem at '/ext'
total blocks: 32768
free blocks:  30711
block size:   4096
frag size:    4096
[00:00:00.390,594] <err> fs: directory open error (-20)
[00:00:00.396,423] <err> main: Error while listing directory: -20

Using the provided command for formatting and limiting partition size.

@fzdobylak
Copy link
Contributor Author

fzdobylak commented Mar 20, 2023

@nordicjm Could you give me some more information? Unfortunately I can't reproduce it in my setup (I have made all the steps once again and everything works fine for me).

I will add some more logging messages to see what happens. (You can turn it on by setting CONFIG_EXT2_LOG_LEVEL_DBG=1.) Could you send them too?

P.S. Huge thank you for your effort.

@fzdobylak
Copy link
Contributor Author

fzdobylak commented Mar 20, 2023

@nordicjm I can see what might cause the problem. You have the inode size set to 256. I haven't mentioned it, but implementation assumes that inodes has size 128.

@nordicjm
Copy link
Collaborator

I ran the command as your instructions say, can you update it with a fully working example?

@fzdobylak
Copy link
Contributor Author

Yes, I will do that and also add check into my implementation to show error when filesystem with wrong config is used. I have assumed the size of inode, because different inode sizes are supported only in ext4.

@fzdobylak fzdobylak force-pushed the ext2-pr1 branch 2 times, most recently from f5feb24 to 6344aee Compare March 20, 2023 12:56
Make test_fs_dirops test common.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Use test_fs_dirops in ext2 tests.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Introduce fs_sync function

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Make test_fs_basic test common.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Use test_fs_basic test in ext2 tests.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Changes:
  - Add fs::sync function
  - Make correct file system in mkfs
  - Add few assertions to ensure that all assumptions are correct

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Remove 'lost+found' dir in test that expects empty layout of directory.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Changes:
  - Added few assertions to check if some assumptions are correct
  - Fix removing blocks during trucate and inode removal
  - Clear entry in inode table after inode has been removed

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Create tests specific for ext2 implementation.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Added funtion that takes specified action when file system corruption is
detected. Possible actions are: do nothing, make mount point read-only,
panic.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Fix the behavior when data should be written to storage device. Now all
writes are done directly to disk_access layer (where it might possibly
be cached).

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Sample for FAT fs is reworked to run also with Ext2 file system

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
- `ext2_file` and `ext2_dir` merged into one struct and allocated from
  dedicated slab
- `ext2_inode` allocated from dedicated slab
- `ext2_disk_dentry` allocated from heap (because their size is not
  constant)
- `ext2_bgroup` and `ext2_disk_superblock` statically allocated

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
This commits changes how data on the disk is accessed. There are disk
structures which are packed and their fields are stored in little endian
byte order. To use data in the program structures it has to be translated
from little endian to cpu endianness.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
Add information about new support for ext2 and modified fs sample.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
@fzdobylak
Copy link
Contributor Author

@de-nordic @peter-mitsis Could you take a look and approve if you still agree with all the changes?

@fkokosinski
Copy link
Member

@peter-mitsis sorry for pinging again, but could you take a look? :) Thanks!

Copy link
Collaborator

@peter-mitsis peter-mitsis left a comment

Choose a reason for hiding this comment

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

Sorry for the lateness--I thought I had given it a +1, but apparently missed that crucial step.

@nashif nashif merged commit 62aa0fa into zephyrproject-rtos:main Aug 3, 2023
18 checks passed
@fzdobylak fzdobylak deleted the ext2-pr1 branch August 4, 2023 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: File System Release Notes To be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants