1 /*
2 * Copyright (c) 2023 Antmicro
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/fs/fs.h>
9 #include <zephyr/fs/ext2.h>
10 #include "utils.h"
11 #include "../../common/test_fs_util.h"
12
calculate_blocks(uint32_t freeb,uint32_t B)13 uint32_t calculate_blocks(uint32_t freeb, uint32_t B)
14 {
15 uint32_t blocks = 0;
16
17 if (freeb <= 12) {
18 return freeb;
19 }
20
21 blocks += 12;
22 freeb -= 12 + 1; /* direct blocks + top block of first level table */
23
24 if (freeb <= B) {
25 return blocks + freeb;
26 }
27
28 blocks += B;
29 freeb -= B + 1; /* 1st level blocks + top block of second level table */
30
31 if (freeb <= B * (B + 1)) {
32 uint32_t n = freeb / (B + 1);
33 uint32_t r = freeb % (B + 1);
34 uint32_t partial = r > 0 ? 1 : 0;
35
36 return blocks + n * B + r - partial;
37 }
38 return blocks;
39 /* TODO: revisit this and extend when 3rd level blocks will be possible */
40 }
41
writing_test(struct ext2_cfg * config)42 void writing_test(struct ext2_cfg *config)
43 {
44 int64_t ret = 0;
45 struct fs_file_t file;
46 struct fs_statvfs sbuf;
47 struct fs_dirent entry;
48 struct fs_mount_t *mp = &testfs_mnt;
49 static const char *file_path = "/sml/file";
50
51 ret = fs_mkfs(FS_EXT2, (uintptr_t)mp->storage_dev, config, 0);
52 zassert_equal(ret, 0, "Failed to mkfs with 2K blocks");
53
54 mp->flags = FS_MOUNT_FLAG_NO_FORMAT;
55 ret = fs_mount(mp);
56 zassert_equal(ret, 0, "Mount failed (ret=%d)", ret);
57
58 fs_file_t_init(&file);
59 ret = fs_open(&file, file_path, FS_O_RDWR | FS_O_CREATE);
60 zassert_equal(ret, 0, "File open failed (ret=%d)", ret);
61
62 ret = fs_statvfs(mp->mnt_point, &sbuf);
63 zassert_equal(ret, 0, "Expected success (ret=%d)", ret);
64
65
66 /* Calculate how many numbers will be written (use all available memory) */
67 uint32_t freeb = sbuf.f_bfree;
68 uint32_t bsize = sbuf.f_bsize;
69 uint32_t available_blocks = calculate_blocks(freeb, bsize / sizeof(uint32_t));
70
71 uint32_t bytes_to_write = bsize * available_blocks;
72
73 TC_PRINT("Available blocks: %d\nBlock size: %d\nBytes_to_write: %d\n",
74 available_blocks, bsize, bytes_to_write);
75
76 ret = testfs_write_incrementing(&file, 0, available_blocks * bsize);
77 zassert_equal(ret, bytes_to_write, "Different number of bytes written %ld (expected %ld)",
78 ret, bytes_to_write);
79
80 ret = fs_close(&file);
81 zassert_equal(ret, 0, "File close failed (ret=%d)", ret);
82
83
84 /* Check file size */
85 ret = fs_stat(file_path, &entry);
86 zassert_equal(ret, 0, "File stat failed (ret=%d)", ret);
87 zassert_equal(entry.size, bytes_to_write,
88 "Wrong file size %d (expected %d)", entry.size,
89 bytes_to_write);
90
91 fs_file_t_init(&file);
92 ret = fs_open(&file, file_path, FS_O_READ);
93 zassert_equal(ret, 0, "File open failed (ret=%d)", ret);
94
95
96 ret = testfs_verify_incrementing(&file, 0, available_blocks * bsize);
97 zassert_equal(ret, bytes_to_write, "Different number of bytes read %ld (expected %ld)",
98 ret, bytes_to_write);
99
100 ret = fs_close(&file);
101 zassert_equal(ret, 0, "File close failed (ret=%d)", ret);
102
103 uint32_t new_size = bytes_to_write;
104
105 while (new_size > 1) {
106 new_size = new_size / 8 * 3;
107
108 TC_PRINT("Truncating to %d\n", new_size);
109
110 ret = fs_open(&file, file_path, FS_O_RDWR);
111 zassert_equal(ret, 0, "File open failed (ret=%d)", ret);
112
113 ret = fs_truncate(&file, new_size);
114 zassert_equal(ret, 0, "File truncate failed (ret=%d)", ret);
115
116 ret = fs_stat(file_path, &entry);
117 zassert_equal(ret, 0, "File stat failed (ret=%d)", ret);
118 zassert_equal(entry.size, new_size,
119 "Wrong file size %d (expected %d)", entry.size, new_size);
120
121 ret = fs_seek(&file, 0, FS_SEEK_SET);
122 zassert_equal(ret, 0, "File seek failed (ret=%d)", ret);
123
124 ret = testfs_verify_incrementing(&file, 0, new_size);
125 zassert_equal(ret, new_size, "Different number of bytes read %ld (expected %ld)",
126 ret, new_size);
127
128 ret = fs_close(&file);
129 zassert_equal(ret, 0, "File close failed (ret=%d)", ret);
130 }
131
132 ret = fs_unmount(mp);
133 zassert_equal(ret, 0, "Unmount failed (ret=%d)", ret);
134 }
135
ZTEST(ext2tests,test_write_big_file)136 ZTEST(ext2tests, test_write_big_file)
137 {
138 writing_test(NULL);
139 }
140
141 #if defined(CONFIG_APP_TEST_BIG)
ZTEST(ext2tests,test_write_big_file_2K)142 ZTEST(ext2tests, test_write_big_file_2K)
143 {
144 struct ext2_cfg config = {
145 .block_size = 2048,
146 .fs_size = 0x2000000,
147 .bytes_per_inode = 0,
148 .volume_name[0] = 0,
149 .set_uuid = false,
150 };
151
152 writing_test(&config);
153 }
154
ZTEST(ext2tests,test_write_big_file_4K)155 ZTEST(ext2tests, test_write_big_file_4K)
156 {
157 struct ext2_cfg config = {
158 .block_size = 4096,
159 .fs_size = 0x8000000,
160 .bytes_per_inode = 0,
161 .volume_name[0] = 0,
162 .set_uuid = false,
163 };
164
165 writing_test(&config);
166 }
167 #endif
168