dfs_ext.c 10 KB

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