dfs_ext.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2017-11-11 parai@foxmail.com base porting
  9. * 2018-06-02 parai@foxmail.com fix mkfs issues
  10. * 2020-08-19 lizhirui porting to ls2k
  11. */
  12. #include <rtthread.h>
  13. #include <rtdef.h>
  14. #include <dfs.h>
  15. #include <dfs_fs.h>
  16. #include <dfs_file.h>
  17. #include <blk_device.h>
  18. #include "dfs_ext.h"
  19. #include "ext4.h"
  20. #include "ext4_mkfs.h"
  21. #include "ext4_config.h"
  22. #include "ext4_blockdev.h"
  23. #include "ext4_errno.h"
  24. #include "ext4_mbr.h"
  25. static int blockdev_open(struct ext4_blockdev *bdev);
  26. static int blockdev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
  27. uint32_t blk_cnt);
  28. static int blockdev_bwrite(struct ext4_blockdev *bdev, const void *buf,
  29. uint64_t blk_id, uint32_t blk_cnt);
  30. static int blockdev_close(struct ext4_blockdev *bdev);
  31. static int blockdev_lock(struct ext4_blockdev *bdev);
  32. static int blockdev_unlock(struct ext4_blockdev *bdev);
  33. EXT4_BLOCKDEV_STATIC_INSTANCE(ext4_blkdev, 4096, 0, blockdev_open,
  34. blockdev_bread, blockdev_bwrite, blockdev_close,
  35. blockdev_lock, blockdev_unlock);
  36. #if RT_DFS_EXT_DRIVES > 1
  37. EXT4_BLOCKDEV_STATIC_INSTANCE(ext4_blkdev1, 4096, 0, blockdev_open,
  38. blockdev_bread, blockdev_bwrite, blockdev_close,
  39. blockdev_lock, blockdev_unlock);
  40. #endif
  41. #if RT_DFS_EXT_DRIVES > 2
  42. EXT4_BLOCKDEV_STATIC_INSTANCE(ext4_blkdev2, 4096, 0, blockdev_open,
  43. blockdev_bread, blockdev_bwrite, blockdev_close,
  44. blockdev_lock, blockdev_unlock);
  45. #endif
  46. #if RT_DFS_EXT_DRIVES > 3
  47. EXT4_BLOCKDEV_STATIC_INSTANCE(ext4_blkdev3, 4096, 0, blockdev_open,
  48. blockdev_bread, blockdev_bwrite, blockdev_close,
  49. blockdev_lock, blockdev_unlock);
  50. #endif
  51. #if RT_DFS_EXT_DRIVES > 4
  52. #error dfs_ext by default support only 4 partitions!
  53. #endif
  54. static rt_device_t disk[RT_DFS_EXT_DRIVES] = {0};
  55. static rt_size_t disk_sector_size[RT_DFS_EXT_DRIVES] = {0};
  56. static struct ext4_blockdev * const ext4_blkdev_list[RT_DFS_EXT_DRIVES] =
  57. {
  58. &ext4_blkdev,
  59. #if RT_DFS_EXT_DRIVES > 1
  60. &ext4_blkdev1,
  61. #endif
  62. #if RT_DFS_EXT_DRIVES > 2
  63. &ext4_blkdev2,
  64. #endif
  65. #if RT_DFS_EXT_DRIVES > 3
  66. &ext4_blkdev3,
  67. #endif
  68. };
  69. static int get_disk(rt_device_t id)
  70. {
  71. int index;
  72. for (index = 0; index < RT_DFS_EXT_DRIVES; index ++)
  73. {
  74. if (disk[index] == id)
  75. return index;
  76. }
  77. return -1;
  78. }
  79. static int get_bdev(struct ext4_blockdev * bdev)
  80. {
  81. int index;
  82. for (index = 0; index < RT_DFS_EXT_DRIVES; index ++)
  83. {
  84. if (ext4_blkdev_list[index] == bdev)
  85. return index;
  86. }
  87. RT_ASSERT(0);
  88. return -1;
  89. }
  90. static int dfs_ext_mount(struct dfs_filesystem* fs, unsigned long rwflag, const void* data)
  91. {
  92. int rc;
  93. int index;
  94. long partid = (long)data;
  95. char* mp = fs->path; /*mount point */
  96. char* img = fs->dev_id->parent.name;
  97. /* get an empty position */
  98. index = get_disk(RT_NULL);
  99. if (index == -1)
  100. {
  101. rt_kprintf("dfs_ext_mount: get an empty position.\n");
  102. return -ENOENT;
  103. }
  104. if(partid >= 0 && partid <= 3)
  105. {
  106. ext4_blkdev_list[index]->part_offset = ((struct blk_device *)fs->dev_id)->ext4_partition.partitions[partid].part_offset;
  107. ext4_blkdev_list[index]->part_size = ((struct blk_device *)fs->dev_id)->ext4_partition.partitions[partid].part_size;
  108. }
  109. else
  110. {
  111. rt_kprintf("dfs_ext_mount: mount partid:%d ,the partid max is 3.\n", partid);
  112. ext4_blkdev_list[index]->part_offset = -1;
  113. }
  114. rc = ext4_device_register(ext4_blkdev_list[index], img);
  115. if(EOK == rc)
  116. {
  117. disk[index] = fs->dev_id;
  118. rc = ext4_mount(img, fs->path, false);
  119. if(EOK != rc)
  120. {
  121. disk[index] = NULL;
  122. rc = -rc;
  123. ext4_device_unregister(img);
  124. }
  125. }
  126. return rc;
  127. }
  128. static int dfs_ext_unmount(struct dfs_filesystem* fs)
  129. {
  130. int index;
  131. int rc;
  132. char* mp = fs->path; /*mount point */
  133. /* find the device index and then umount it */
  134. index = get_disk(fs->dev_id);
  135. if (index == -1) /* not found */
  136. return -ENOENT;
  137. rc = ext4_umount(mp);
  138. return rc;
  139. }
  140. static int dfs_ext_mkfs(rt_device_t devid)
  141. {
  142. int index;
  143. int rc;
  144. static struct ext4_fs fs;
  145. static struct ext4_mkfs_info info = {
  146. .block_size = 4096,
  147. .journal = true,
  148. };
  149. char* img = devid->parent.name;
  150. if (devid == RT_NULL)
  151. {
  152. return -EINVAL;
  153. }
  154. /* find the device index, already mount */
  155. index = get_disk(devid);
  156. if (index != -1)
  157. return -EBUSY;
  158. index = get_disk(RT_NULL);
  159. if (index == -1) /* not found */
  160. return -ENOSPC;
  161. rc = ext4_device_register(ext4_blkdev_list[index], img);
  162. if(EOK == rc)
  163. {
  164. disk[index] = devid;
  165. /* try to open device */
  166. rt_device_open(devid, RT_DEVICE_OFLAG_RDWR);
  167. rc = ext4_mkfs(&fs, ext4_blkdev_list[index], &info, F_SET_EXT4);
  168. /* no matter what, unregister */
  169. disk[index] = NULL;
  170. ext4_device_unregister(img);
  171. /* close device */
  172. rt_device_close(devid);
  173. }
  174. rc = -rc;
  175. return rc;
  176. }
  177. static int dfs_ext_ioctl(struct dfs_fd* file, int cmd, void* args)
  178. {
  179. return -RT_EIO;
  180. }
  181. static int dfs_ext_read(struct dfs_fd *fd, void *buf, size_t count)
  182. {
  183. size_t bytesread = 0;
  184. int r;
  185. r = ext4_fread(fd->data, buf, count, &bytesread);
  186. if (0 != r)
  187. {
  188. bytesread = 0;
  189. }
  190. return bytesread;
  191. }
  192. static int dfs_ext_write(struct dfs_fd *fd, const void *buf, size_t count)
  193. {
  194. size_t byteswritten = 0;
  195. int r;
  196. r = ext4_fwrite(fd->data, buf, count, &byteswritten);
  197. if (0 != r)
  198. {
  199. byteswritten = 0;
  200. }
  201. return byteswritten;
  202. }
  203. static int dfs_ext_flush(struct dfs_fd *fd)
  204. {
  205. (void)fd;
  206. return -ENOTSUP;
  207. }
  208. static int dfs_ext_lseek(struct dfs_fd* file, rt_off_t offset)
  209. {
  210. int r;
  211. r = ext4_fseek(file->data, offset, SEEK_SET);
  212. return -r;
  213. }
  214. static int dfs_ext_close(struct dfs_fd* file)
  215. {
  216. int r;
  217. if (file->type == FT_DIRECTORY)
  218. {
  219. r = ext4_fclose(file->data);
  220. rt_free(file->data);
  221. }
  222. else
  223. {
  224. r = ext4_fclose(file->data);
  225. if(EOK == r)
  226. {
  227. rt_free(file->data);
  228. }
  229. }
  230. return -r;
  231. }
  232. static int dfs_ext_open(struct dfs_fd* file)
  233. {
  234. int r = EOK;
  235. ext4_dir *dir;
  236. ext4_file *f;
  237. if (file->flags & O_DIRECTORY)
  238. {
  239. if (file->flags & O_CREAT)
  240. {
  241. r = ext4_dir_mk(file->path);
  242. }
  243. if(EOK == r)
  244. {
  245. dir = rt_malloc(sizeof(ext4_dir));
  246. r = ext4_dir_open(dir, file->path);
  247. if(EOK == r)
  248. {
  249. file->data = dir;
  250. }
  251. else
  252. {
  253. rt_free(dir);
  254. }
  255. }
  256. }
  257. else
  258. {
  259. f = rt_malloc(sizeof(ext4_file));
  260. r = ext4_fopen2(f, file->path, file->flags);
  261. if(EOK == r)
  262. {
  263. file->data = f;
  264. }
  265. else
  266. {
  267. rt_free(f);
  268. }
  269. }
  270. return -r;
  271. }
  272. static int dfs_ext_unlink (struct dfs_filesystem *fs, const char *pathname)
  273. {
  274. int r;
  275. r = ext4_fremove(pathname);
  276. return -r;
  277. }
  278. static int dfs_ext_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
  279. {
  280. int r;
  281. union {
  282. ext4_dir dir;
  283. ext4_file f;
  284. } var;
  285. r = ext4_dir_open(&(var.dir), path);
  286. if(0 == r)
  287. {
  288. (void) ext4_dir_close(&(var.dir));
  289. st->st_mode = S_IFDIR;
  290. st->st_size = 0;
  291. }
  292. else
  293. {
  294. r = ext4_fopen(&(var.f), path, "rb");
  295. if( 0 == r)
  296. {
  297. st->st_mode = S_IFREG;
  298. st->st_size = ext4_fsize(&(var.f));
  299. (void)ext4_fclose(&(var.f));
  300. }
  301. }
  302. return -r;
  303. }
  304. static int dfs_ext_getdents(struct dfs_fd* file, struct dirent* dirp, rt_uint32_t count)
  305. {
  306. int index;
  307. struct dirent *d;
  308. const ext4_direntry * rentry;
  309. /* make integer count */
  310. count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
  311. if (count == 0)
  312. return -EINVAL;
  313. index = 0;
  314. while (1)
  315. {
  316. d = dirp + index;
  317. rentry = ext4_dir_entry_next(file->data);
  318. if(NULL != rentry)
  319. {
  320. strncpy(d->d_name, rentry->name, DFS_PATH_MAX);
  321. if(EXT4_DE_DIR == rentry->inode_type)
  322. {
  323. d->d_type = DT_DIR;
  324. }
  325. else
  326. {
  327. d->d_type = DT_REG;
  328. }
  329. d->d_namlen = (rt_uint8_t)rentry->name_length;
  330. d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
  331. index ++;
  332. if (index * sizeof(struct dirent) >= count)
  333. break;
  334. }
  335. else
  336. {
  337. break;
  338. }
  339. }
  340. file->pos += index * sizeof(struct dirent);
  341. return index * sizeof(struct dirent);
  342. }
  343. static int dfs_ext_rename (struct dfs_filesystem *fs, const char *oldpath, const char *newpath)
  344. {
  345. int r;
  346. r = ext4_frename(oldpath, newpath);
  347. return -r;
  348. }
  349. static const struct dfs_file_ops _ext_fops =
  350. {
  351. dfs_ext_open,
  352. dfs_ext_close,
  353. dfs_ext_ioctl,
  354. dfs_ext_read,
  355. dfs_ext_write,
  356. dfs_ext_flush,
  357. dfs_ext_lseek,
  358. dfs_ext_getdents,
  359. };
  360. static const struct dfs_filesystem_ops _ext_fs =
  361. {
  362. "ext",
  363. DFS_FS_FLAG_DEFAULT,
  364. &_ext_fops,
  365. dfs_ext_mount,
  366. dfs_ext_unmount,
  367. dfs_ext_mkfs,
  368. NULL, /* statfs */
  369. dfs_ext_unlink,
  370. dfs_ext_stat,
  371. dfs_ext_rename
  372. };
  373. int dfs_ext_init(void)
  374. {
  375. /* register rom file system */
  376. dfs_register(&_ext_fs);
  377. return 0;
  378. }
  379. INIT_COMPONENT_EXPORT(dfs_ext_init);
  380. static int blockdev_open(struct ext4_blockdev *bdev)
  381. {
  382. int r;
  383. uint32_t size;
  384. int index = get_bdev(bdev);
  385. rt_device_t device = disk[index];
  386. struct rt_device_blk_geometry geometry;
  387. RT_ASSERT(index < RT_DFS_EXT_DRIVES);
  388. RT_ASSERT(device);
  389. r = rt_device_open(device,RT_DEVICE_OFLAG_RDWR);
  390. if(r != RT_EOK)
  391. {
  392. return r;
  393. }
  394. r = rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  395. if(RT_EOK == r)
  396. {
  397. if(bdev->part_offset == -1)
  398. {
  399. bdev->part_offset = 0;
  400. bdev->part_size = geometry.sector_count*geometry.bytes_per_sector;
  401. }
  402. disk_sector_size[index] = geometry.bytes_per_sector;
  403. bdev->bdif->ph_bcnt = bdev->part_size / bdev->bdif->ph_bsize;
  404. }
  405. return r;
  406. }
  407. static int blockdev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
  408. uint32_t blk_cnt)
  409. {
  410. int result;
  411. int index = get_bdev(bdev);
  412. rt_device_t device = disk[index];
  413. struct blk_device *blk = (struct blk_device *)device;
  414. RT_ASSERT(index < RT_DFS_EXT_DRIVES);
  415. RT_ASSERT(device);
  416. result = rt_device_read(device, blk_id*(bdev->bdif->ph_bsize/disk_sector_size[index]),
  417. buf, blk_cnt*(bdev->bdif->ph_bsize/disk_sector_size[index]));
  418. if((blk_cnt*(bdev->bdif->ph_bsize/disk_sector_size[index])) == result)
  419. {
  420. result = 0;
  421. }
  422. else
  423. {
  424. result = -EIO;
  425. }
  426. return result;
  427. }
  428. static int blockdev_bwrite(struct ext4_blockdev *bdev, const void *buf,
  429. uint64_t blk_id, uint32_t blk_cnt)
  430. {
  431. int result;
  432. int index = get_bdev(bdev);
  433. rt_device_t device = disk[index];
  434. RT_ASSERT(index < RT_DFS_EXT_DRIVES);
  435. RT_ASSERT(device);
  436. result = rt_device_write(device, blk_id*(bdev->bdif->ph_bsize/disk_sector_size[index]),
  437. buf, blk_cnt*(bdev->bdif->ph_bsize/disk_sector_size[index]));
  438. if((blk_cnt*(bdev->bdif->ph_bsize/disk_sector_size[index])) == result)
  439. {
  440. result = 0;
  441. }
  442. else
  443. {
  444. result = -EIO;
  445. }
  446. return result;
  447. }
  448. static int blockdev_close(struct ext4_blockdev *bdev)
  449. {
  450. int result;
  451. int index = get_bdev(bdev);
  452. rt_device_t device = disk[index];
  453. RT_ASSERT(index < RT_DFS_EXT_DRIVES);
  454. RT_ASSERT(device);
  455. result = rt_device_close(device);
  456. return result;
  457. }
  458. static int blockdev_lock(struct ext4_blockdev *bdev)
  459. {
  460. return 0;
  461. }
  462. static int blockdev_unlock(struct ext4_blockdev *bdev)
  463. {
  464. return 0;
  465. }