FEATURES:
[lwext4.git] / demos / generic / main.c
1 /*\r
2  * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * - Redistributions of source code must retain the above copyright\r
10  *   notice, this list of conditions and the following disclaimer.\r
11  * - Redistributions in binary form must reproduce the above copyright\r
12  *   notice, this list of conditions and the following disclaimer in the\r
13  *   documentation and/or other materials provided with the distribution.\r
14  * - The name of the author may not be used to endorse or promote products\r
15  *   derived from this software without specific prior written permission.\r
16  *\r
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  */\r
28 \r
29 #include <stdio.h>\r
30 #include <stdlib.h>\r
31 #include <string.h>\r
32 #include <unistd.h>\r
33 #include <getopt.h>\r
34 #include <stdbool.h>\r
35 \r
36 #include <ext4_filedev.h>\r
37 #include <ext4.h>\r
38 \r
39 char input_name[128] = "ext2";\r
40 \r
41 /**@brief       Read-write size*/\r
42 static int rw_szie  = 1024;\r
43 \r
44 /**@brief       Read-write size*/\r
45 static int rw_count = 10000;\r
46 \r
47 /**@brief   Directory test count*/\r
48 static int dir_cnt  = 10;\r
49 \r
50 /**@brief   Static or dynamic cache mode*/\r
51 static bool cache_mode = false;\r
52 \r
53 /**@brief   Cleanup after test.*/\r
54 static bool cleanup_flag = false;\r
55 \r
56 /**@brief   Block device stats.*/\r
57 static bool bstat = false;\r
58 \r
59 /**@brief   Superblock stats.*/\r
60 static bool sbstat = false;\r
61 \r
62 /**@brief       File write buffer*/\r
63 static uint8_t  *wr_buff;\r
64 \r
65 /**@brief       File read buffer.*/\r
66 static uint8_t  *rd_buff;\r
67 \r
68 /**@brief       Block device handle.*/\r
69 static struct ext4_blockdev *bd;\r
70 \r
71 /**@brief       Block cache handle.*/\r
72 static struct ext4_bcache   *bc;\r
73 \r
74 static const char *usage = "                                                                    \n\\r
75 Welcome in ext4 generic demo.                                                                   \n\\r
76 Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)  \n\\r
77 Usage:                                                                                                                  \n\\r
78         -i   - input file             (default = ext2)                          \n\\r
79         -rws - single R/W size        (default = 1024)                          \n\\r
80         -rwc - R/W count              (default = 10000)                         \n\\r
81         -cache  - 0 static, 1 dynamic  (default = 0)                \n\\r
82     -dirs   - directory test count (default = 10)               \n\\r
83     -clean  - clean up after test                               \n\\r
84     -bstat  - block device stats                                \n\\r
85     -sbstat - superblock stats                                  \n\\r
86 \n";\r
87 \r
88 static char* entry_to_str(uint8_t type)\r
89 {\r
90         switch(type){\r
91         case EXT4_DIRENTRY_UNKNOWN:\r
92                 return "[UNK] ";\r
93         case EXT4_DIRENTRY_REG_FILE:\r
94                 return "[FIL] ";\r
95         case EXT4_DIRENTRY_DIR:\r
96                 return "[DIR] ";\r
97         case EXT4_DIRENTRY_CHRDEV:\r
98                 return "[CHA] ";\r
99         case EXT4_DIRENTRY_BLKDEV:\r
100                 return "[BLK] ";\r
101         case EXT4_DIRENTRY_FIFO:\r
102                 return "[FIF] ";\r
103         case EXT4_DIRENTRY_SOCK:\r
104                 return "[SOC] ";\r
105         case EXT4_DIRENTRY_SYMLINK:\r
106                 return "[SYM] ";\r
107         default:\r
108                 break;\r
109         }\r
110         return "[???]";\r
111 }\r
112 \r
113 static void dir_ls(const char *path)\r
114 {\r
115         int j = 0;\r
116         char sss[255];\r
117         ext4_dir d;\r
118         ext4_direntry *de;\r
119 \r
120         printf("**********************************************\n");\r
121 \r
122         ext4_dir_open(&d, path);\r
123         de = ext4_dir_entry_get(&d, j++);\r
124         printf("ls %s\n", path);\r
125 \r
126         while(de){\r
127                 memcpy(sss, de->name, de->name_length);\r
128                 sss[de->name_length] = 0;\r
129                 printf(entry_to_str(de->inode_type));\r
130                 printf(sss);\r
131                 printf("\n");\r
132                 de = ext4_dir_entry_get(&d, j++);\r
133         }\r
134         printf("**********************************************\n");\r
135         ext4_dir_close(&d);\r
136 }\r
137 \r
138 static void mp_stats(void)\r
139 {\r
140     struct ext4_mount_stats stats;\r
141     ext4_mount_point_stats("/mp/", &stats);\r
142 \r
143     printf("**********************************************\n");\r
144     printf("ext4_mount_point_stats\n");\r
145     printf("inodes_count        = %u\n", stats.inodes_count);\r
146     printf("free_inodes_count   = %u\n", stats.free_inodes_count);\r
147     printf("blocks_count        = %u\n", (uint32_t)stats.blocks_count);\r
148     printf("free_blocks_count   = %u\n", (uint32_t)stats.free_blocks_count);\r
149     printf("block_size          = %u\n", stats.block_size);\r
150     printf("block_group_count   = %u\n", stats.block_group_count);\r
151     printf("blocks_per_group    = %u\n", stats.blocks_per_group);\r
152     printf("inodes_per_group    = %u\n", stats.inodes_per_group);\r
153     printf("volume_name         = %s\n", stats.volume_name);\r
154 \r
155     printf("**********************************************\n");\r
156 \r
157 }\r
158 \r
159 static void block_stats(void)\r
160 {\r
161     uint32_t i;\r
162 \r
163     printf("**********************************************\n");\r
164     printf("ext4 blockdev stats\n");\r
165     printf("bdev->bread_ctr          = %u\n", bd->bread_ctr);\r
166     printf("bdev->bwrite_ctr         = %u\n", bd->bwrite_ctr);\r
167 \r
168 \r
169     printf("bcache->ref_blocks       = %u\n", bc->ref_blocks);\r
170     printf("bcache->max_ref_blocks   = %u\n", bc->max_ref_blocks);\r
171     printf("bcache->lru_ctr          = %u\n", bc->lru_ctr);\r
172 \r
173     printf("\n");\r
174     for (i = 0; i < bc->cnt; ++i) {\r
175         printf("bcache->refctr[%d]     = %u\n", i, bc->refctr[i]);\r
176     }\r
177 \r
178     printf("\n");\r
179     for (i = 0; i < bc->cnt; ++i) {\r
180         printf("bcache->lru_id[%d]     = %u\n", i, bc->lru_id[i]);\r
181     }\r
182 \r
183     printf("\n");\r
184     for (i = 0; i < bc->cnt; ++i) {\r
185         printf("bcache->free_delay[%d] = %d\n", i, bc->free_delay[i]);\r
186     }\r
187 \r
188     printf("\n");\r
189     for (i = 0; i < bc->cnt; ++i) {\r
190         printf("bcache->lba[%d]        = %u\n", i, (uint32_t)bc->lba[i]);\r
191     }\r
192 \r
193 \r
194 \r
195     printf("**********************************************\n");\r
196 }\r
197 \r
198 static bool dir_test(int len)\r
199 {\r
200     ext4_file f;\r
201     int       r;\r
202     int       i;\r
203     char path[64];\r
204 \r
205     printf("Directory create: /mp/dir1\n");\r
206     r = ext4_dir_mk("/mp/dir1");\r
207     if(r != EOK){\r
208         printf("Unable to create directory: /mp/dir1\n");\r
209         return false;\r
210     }\r
211 \r
212 \r
213     printf("Add files to: /mp/dir1\n");\r
214     for (i = 0; i < len; ++i) {\r
215         sprintf(path, "/mp/dir1/f%d", i);\r
216         r = ext4_fopen(&f, path, "wb");\r
217         if(r != EOK){\r
218             printf("Unable to create file in directory: /mp/dir1\n");\r
219             return false;\r
220         }\r
221     }\r
222 \r
223     dir_ls("/mp/dir1");\r
224     return true;\r
225 }\r
226 \r
227 static void cleanup(void)\r
228 {\r
229     ext4_fremove("/mp/hello.txt");\r
230     ext4_fremove("/mp/test1");\r
231     ext4_dir_rm("/mp/dir1");\r
232 }\r
233 \r
234 int main(int argc, char **argv)\r
235 {\r
236         int option_index = 0;\r
237         int     c;\r
238         int     r;\r
239         int     i;\r
240         uint32_t  size;\r
241         ext4_file f;\r
242 \r
243     static struct option long_options[] =\r
244       {\r
245         {"in",          required_argument, 0, 'a'},\r
246         {"rws",     required_argument, 0, 'b'},\r
247         {"rwc",         required_argument, 0, 'c'},\r
248         {"cache",   required_argument, 0, 'd'},\r
249         {"dirs",    required_argument, 0, 'e'},\r
250         {"clean",   no_argument,       0, 'f'},\r
251         {"bstat",   no_argument,       0, 'g'},\r
252         {"sbstat",  no_argument,       0, 'h'},\r
253         {0, 0, 0, 0}\r
254       };\r
255 \r
256     while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:e:fgh", long_options, &option_index))) {\r
257 \r
258         switch(c){\r
259                 case 'a':\r
260                         strcpy(input_name, optarg);\r
261                         break;\r
262                 case 'b':\r
263                         rw_szie = atoi(optarg);\r
264                         break;\r
265                 case 'c':\r
266                         rw_count = atoi(optarg);\r
267                         break;\r
268                 case 'd':\r
269                         cache_mode = atoi(optarg);\r
270                         break;\r
271             case 'e':\r
272                 dir_cnt = atoi(optarg);\r
273                 break;\r
274             case 'f':\r
275                 cleanup_flag = true;\r
276                 break;\r
277             case 'g':\r
278                 bstat = true;\r
279                 break;\r
280             case 'h':\r
281                 sbstat = true;\r
282                 break;\r
283                 default:\r
284                         printf(usage);\r
285                         return EXIT_FAILURE;\r
286 \r
287         }\r
288     }\r
289 \r
290     printf("Test conditions:\n");\r
291     printf("Imput name: %s\n", input_name);\r
292     printf("RW size: %d\n",  rw_szie);\r
293     printf("RW count: %d\n", rw_count);\r
294     printf("Cache mode: %s\n", cache_mode ? "dynamic" : "static");\r
295 \r
296 \r
297 \r
298     ext4_filedev_filename(input_name);\r
299 \r
300     wr_buff = malloc(rw_szie);\r
301     rd_buff = malloc(rw_szie);\r
302 \r
303     if(!wr_buff || !rd_buff){\r
304         printf("Read-Write allocation ERROR\n");\r
305         return EXIT_FAILURE;\r
306     }\r
307 \r
308         bd = ext4_filedev_get();\r
309         bc = ext4_filecache_get();\r
310 \r
311     if(!bd || !bc){\r
312         printf("Block device ERROR\n");\r
313         return EXIT_FAILURE;\r
314     }\r
315 \r
316         ext4_dmask_set(EXT4_DEBUG_ALL);\r
317 \r
318         r = ext4_device_register(bd, cache_mode ? 0 : bc, "ext4_filesim");\r
319         if(r != EOK){\r
320                 printf("ext4_device_register ERROR = %d\n", r);\r
321                 return EXIT_FAILURE;\r
322         }\r
323 \r
324         r = ext4_mount("ext4_filesim", "/mp/");\r
325         if(r != EOK){\r
326                 printf("ext4_mount ERROR = %d\n", r);\r
327                 return EXIT_FAILURE;\r
328         }\r
329 \r
330         cleanup();\r
331 \r
332     if(sbstat)\r
333         mp_stats();\r
334 \r
335 \r
336     dir_ls("/mp/");\r
337         dir_test(dir_cnt);\r
338 \r
339     /*Add hello world file.*/\r
340     r = ext4_fopen(&f, "/mp/hello.txt", "wb");\r
341     r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);\r
342     r = ext4_fclose(&f);\r
343 \r
344 \r
345         printf("ext4_fopen: test1\n");\r
346 \r
347         r = ext4_fopen(&f, "/mp/test1", "wb");\r
348         if(r != EOK){\r
349                 printf("ext4_fopen ERROR = %d\n", r);\r
350                 return EXIT_FAILURE;\r
351         }\r
352 \r
353         printf("ext4_write: %d * %d ..." , rw_count, rw_szie);\r
354 \r
355         for (i = 0; i < rw_count; ++i) {\r
356 \r
357                 memset(wr_buff, i & 0xFF, rw_szie);\r
358 \r
359                 r = ext4_fwrite(&f, wr_buff, rw_szie, &size);\r
360 \r
361                 if((r != EOK) || (size != rw_szie))\r
362                         break;\r
363         }\r
364 \r
365         if(i != rw_count){\r
366                 printf("ERROR: rw_count = %d\n", i);\r
367                 return EXIT_FAILURE;\r
368         }\r
369 \r
370         printf("OK\n");\r
371         r = ext4_fclose(&f);\r
372         printf("ext4_fopen: test1\n");\r
373 \r
374         r = ext4_fopen(&f, "/mp/test1", "r+");\r
375         if(r != EOK){\r
376                 printf("ext4_fopen ERROR = %d\n", r);\r
377                 return EXIT_FAILURE;\r
378         }\r
379 \r
380         printf("ext4_read: %d * %d ..." , rw_count, rw_szie);\r
381 \r
382         for (i = 0; i < rw_count; ++i) {\r
383                 memset(wr_buff, i & 0xFF, rw_szie);\r
384                 r = ext4_fread(&f, rd_buff, rw_szie, &size);\r
385 \r
386                 if((r != EOK) || (size != rw_szie))\r
387                         break;\r
388 \r
389                 if(memcmp(rd_buff, wr_buff, rw_szie)){\r
390                         break;\r
391                 }\r
392         }\r
393         if(i != rw_count){\r
394                 printf("ERROR: rw_count = %d\n", i);\r
395                 return EXIT_FAILURE;\r
396         }\r
397 \r
398         printf("OK\n");\r
399         r = ext4_fclose(&f);\r
400 \r
401         dir_ls("/mp/");\r
402 \r
403         if(sbstat)\r
404             mp_stats();\r
405 \r
406         if(bstat)\r
407             block_stats();\r
408 \r
409         if(cleanup_flag)\r
410             cleanup();\r
411 \r
412         r = ext4_umount("/mp/");\r
413         printf("Test finish: OK\n");\r
414     return EXIT_SUCCESS;\r
415 \r
416 }\r