smartfs.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /****************************************************************************
  2. * fs/smartfs/smartfs.h
  3. *
  4. * Copyright (C) 2013-2014 Ken Pettit. All rights reserved.
  5. * Author: Ken Pettit <pettitkd@gmail.com>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. #ifndef __FS_SMARTFS_SMARTFS_H
  36. #define __FS_SMARTFS_SMARTFS_H
  37. /****************************************************************************
  38. * Included Files
  39. ****************************************************************************/
  40. #include <nuttx/config.h>
  41. #include <sys/types.h>
  42. #include <stdint.h>
  43. #include <stdbool.h>
  44. #include <semaphore.h>
  45. #include <nuttx/mtd/mtd.h>
  46. #include <nuttx/fs/smart.h>
  47. /****************************************************************************
  48. * Pre-processor Definitions
  49. ****************************************************************************/
  50. /* SMART Definitions ********************************************************/
  51. /* General SMART organization. The following example assumes 4 logical
  52. * sectors per FLASH erase block. The actual relationship is determined by
  53. * the FLASH geometry reported by the MTD driver.
  54. *
  55. * ERASE LOGICAL Sectors begin with a sector header. Sectors may
  56. * BLOCK SECTOR CONTENTS be marked as "released," pending garbage collection
  57. * n 4*n --+---------------+
  58. * Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
  59. * |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
  60. * |SSSSSSSSSSSSSSS| Status bits (1 byte)
  61. * +---------------+
  62. * |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
  63. * |NNNNNNNNNNNNNNN| Number of next logical sector in chain
  64. * |UUUUUUUUUUUUUUU| Number of bytes used in this sector
  65. * | |
  66. * | (Sector Data) |
  67. * | |
  68. * 4*n+1 --+---------------+
  69. * Sector Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
  70. * |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
  71. * |SSSSSSSSSSSSSSS| Status bits (1 byte)
  72. * +---------------+
  73. * FS Hdr |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
  74. * |NNNNNNNNNNNNNNN| Number of next logical sector in chain
  75. * |UUUUUUUUUUUUUUU| Number of bytes used in this sector
  76. * | |
  77. * | (Sector Data) |
  78. * | |
  79. * 4*n+2 --+---------------+
  80. * Sector Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
  81. * |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
  82. * |SSSSSSSSSSSSSSS| Status bits (1 byte)
  83. * +---------------+
  84. * FS Hdr |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
  85. * |NNNNNNNNNNNNNNN| Number of next logical sector in chain
  86. * |UUUUUUUUUUUUUUU| Number of bytes used in this sector
  87. * | |
  88. * | (Sector Data) |
  89. * | |
  90. * 4*n+3 --+---------------+
  91. * Sector Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
  92. * |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
  93. * |SSSSSSSSSSSSSSS| Status bits (1 byte)
  94. * +---------------+
  95. * FS Hdr |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
  96. * |NNNNNNNNNNNNNNN| Number of next logical sector in chain
  97. * |UUUUUUUUUUUUUUU| Number of bytes used in this sector
  98. * | |
  99. * | (Sector Data) |
  100. * | |
  101. * n+1 4*(n+1) --+---------------+
  102. * Sector Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
  103. * |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
  104. * |SSSSSSSSSSSSSSS| Status bits (1 byte)
  105. * +---------------+
  106. * FS Hdr |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
  107. * |NNNNNNNNNNNNNNN| Number of next logical sector in chain
  108. * |UUUUUUUUUUUUUUU| Number of bytes used in this sector
  109. * | |
  110. * | |
  111. * | |
  112. * --+---------------+
  113. *
  114. * General operation:
  115. * Physical sectors are allocated and assigned a logical sector number
  116. * and a starting sequence number of zero.
  117. *
  118. * SECTOR HEADER:
  119. * The sector header (first 5 bytes) tracks the state of each sector and
  120. * is used by the SMART MTD block driver. At the block level, there is
  121. * no notion of sector chaining, only allocated sectors within erase
  122. * blocks.
  123. *
  124. * FILE SYSTEM (FS) HEADER:
  125. * The file system header (next 5 bytes) tracks file and directory entries
  126. * and chains.
  127. *
  128. * SMART Limitations:
  129. * 1. SMART currently depends on the underlying MTD block driver supporting
  130. * single-byte programming operation. This is due to the method it
  131. * uses for marking a sector as "released", committed, etc.
  132. * 2. Garbage collection can occur when a new sector is allocated or when
  133. * existing sector data is overwritten with new data. Thus, occasionally,
  134. * file writing may take longer than other times.
  135. * 3. The implementation curently does not track bad blocks on the device.
  136. * 4. There is no true wear-leveling implemented yet, though provesion have
  137. * been made to reserve logical sectors to allow it to be added using
  138. * a "sector aging" tracking mechanism.
  139. */
  140. /* Values for SMART inode state.
  141. *
  142. * SMART_STATE_FILE - The inode is a valid usuable, file
  143. * INODE_STATE_DELETED - The inode has been deleted.
  144. * Other values - The inode is bad and has an invalid state.
  145. *
  146. * Care is taken so that the VALID to DELETED transition only involves burning
  147. * bits from the erased to non-erased state.
  148. */
  149. #define INODE_STATE_FILE (CONFIG_NXFFS_ERASEDSTATE ^ 0x22)
  150. #define INODE_STATE_DELETED (CONFIG_NXFFS_ERASEDSTATE ^ 0xaa)
  151. /* Directory entry flag definitions */
  152. #define SMARTFS_DIRENT_EMPTY 0x8000 /* Set to non-erase state when entry used */
  153. #define SMARTFS_DIRENT_ACTIVE 0x4000 /* Set to erase state when entry is active */
  154. #define SMARTFS_DIRENT_TYPE 0x2000 /* Indicates the type of entry (file/dir) */
  155. #define SMARTFS_DIRENT_DELETING 0x1000 /* Directory entry is being deleted */
  156. #define SMARTFS_DIRENT_RESERVED 0x0E00 /* Reserved bits */
  157. #define SMARTFS_DIRENT_MODE 0x01FF /* Mode the file was created with */
  158. #define SMARTFS_DIRENT_TYPE_DIR 0x2000
  159. #define SMARTFS_DIRENT_TYPE_FILE 0x0000
  160. /* Number of bytes in the SMART magic sequences */
  161. #define SMART_MAGICSIZE 4
  162. /* Quasi-standard definitions */
  163. #ifndef MIN
  164. # define MIN(a,b) (a < b ? a : b)
  165. #endif
  166. #ifndef MAX
  167. # define MAX(a,b) (a > b ? a : b)
  168. #endif
  169. /* Underlying MTD Block driver access functions */
  170. #define FS_BOPS(f) (f)->fs_blkdriver->u.i_bops
  171. #define FS_IOCTL(f,c,a) (FS_BOPS(f)->ioctl ? FS_BOPS(f)->ioctl((f)->fs_blkdriver,c,a) : (-ENOSYS))
  172. /* The logical sector number of the root directory. */
  173. #define SMARTFS_ROOT_DIR_SECTOR 3
  174. /* Defines the sector types */
  175. #define SMARTFS_SECTOR_TYPE_DIR 1
  176. #define SMARTFS_SECTOR_TYPE_FILE 2
  177. #ifndef CONFIG_SMARTFS_DIRDEPTH
  178. # define CONFIG_SMARTFS_DIRDEPTH 8
  179. #endif
  180. /* Buffer flags (when CRC enabled) */
  181. #define SMARTFS_BFLAG_DIRTY 0x01 /* Set if data changed in the sector */
  182. #define SMARTFS_BFLAG_NEWALLOC 0x02 /* Set if sector not written since alloc */
  183. #define SMARTFS_ERASEDSTATE_16BIT (uint16_t) ((CONFIG_SMARTFS_ERASEDSTATE << 8) | \
  184. CONFIG_SMARTFS_ERASEDSTATE)
  185. #ifndef offsetof
  186. #define offsetof(type, member) ( (size_t) &( ( (type *) 0)->member))
  187. #endif
  188. #define SMARTFS_NEXTSECTOR(h) ( *((uint16_t *) h->nextsector))
  189. #define SMARTFS_USED(h) ( *((uint16_t *) h->used))
  190. #ifdef CONFIG_MTD_SMART_ENABLE_CRC
  191. #define CONFIG_SMARTFS_USE_SECTOR_BUFFER
  192. #endif
  193. /****************************************************************************
  194. * Public Types
  195. ****************************************************************************/
  196. /* This structure defines each packed block on the FLASH media */
  197. /* This is an in-memory representation of the SMART inode as extracted from
  198. * FLASH and with additional state information.
  199. */
  200. struct smartfs_entry_s
  201. {
  202. uint16_t firstsector; /* Sector number of the name */
  203. uint16_t dsector; /* Sector number of the directory entry */
  204. uint16_t doffset; /* Offset of the directory entry */
  205. uint16_t dfirst; /* 1st sector number of the directory entry */
  206. uint16_t flags; /* Flags, including mode */
  207. FAR char *name; /* inode name */
  208. uint32_t utc; /* Time stamp */
  209. uint32_t datlen; /* Length of inode data */
  210. };
  211. /* This is an on-device representation of the SMART inode it esists on
  212. * the FLASH.
  213. */
  214. struct smartfs_entry_header_s
  215. {
  216. uint16_t flags; /* Flags, including permissions:
  217. 15: Empty entry
  218. 14: Active entry
  219. 12-0: Permissions bits */
  220. int16_t firstsector; /* Sector number of the name */
  221. uint32_t utc; /* Time stamp */
  222. char name[0]; /* inode name */
  223. };
  224. /* This structure describes the smartfs header at the start of each
  225. * sector. It manages the sector chain and used bytes in the sector.
  226. */
  227. #if defined(CONFIG_MTD_SMART_ENABLE_CRC) && defined(CONFIG_SMART_CRC_32)
  228. struct smartfs_chain_header_s
  229. {
  230. uint8_t nextsector[4];/* Next logical sector in the chain */
  231. uint8_t used[4]; /* Number of bytes used in this sector */
  232. uint8_t type; /* Type of sector entry (file or dir) */
  233. };
  234. #elif defined(CONFIG_MTD_SMART_ENABLE_CRC) && defined(CONFIG_SMART_CRC_16)
  235. struct smartfs_chain_header_s
  236. {
  237. uint8_t type; /* Type of sector entry (file or dir) */
  238. uint8_t nextsector[2];/* Next logical sector in the chain */
  239. uint8_t used[2]; /* Number of bytes used in this sector */
  240. };
  241. #else
  242. struct smartfs_chain_header_s
  243. {
  244. uint8_t type; /* Type of sector entry (file or dir) */
  245. uint8_t nextsector[2];/* Next logical sector in the chain */
  246. uint8_t used[2]; /* Number of bytes used in this sector */
  247. };
  248. #endif
  249. /* This structure describes the state of one open file. This structure
  250. * is protected by the volume semaphore.
  251. */
  252. struct smartfs_ofile_s
  253. {
  254. struct smartfs_ofile_s *fnext; /* Supports a singly linked list */
  255. #ifdef CONFIG_SMARTFS_USE_SECTOR_BUFFER
  256. uint8_t* buffer; /* Sector buffer to reduce writes */
  257. uint8_t bflags; /* Buffer flags */
  258. #endif
  259. int16_t crefs; /* Reference count */
  260. mode_t oflags; /* Open mode */
  261. struct smartfs_entry_s entry; /* Describes the SMARTFS inode entry */
  262. size_t filepos; /* Current file position */
  263. uint16_t currsector; /* Current sector of filepos */
  264. uint16_t curroffset; /* Current offset in sector */
  265. uint16_t byteswritten;/* Count of bytes written to currsector
  266. * that have not been recorded in the
  267. * sector yet. We delay updating the
  268. * used field until the file is closed,
  269. * a seek, or more data is written that
  270. * causes the sector to change. */
  271. };
  272. /* This structure represents the overall mountpoint state. An instance of this
  273. * structure is retained as inode private data on each mountpoint that is
  274. * mounted with a smartfs filesystem.
  275. */
  276. struct smartfs_mountpt_s
  277. {
  278. #if defined(CONFIG_SMARTFS_MULTI_ROOT_DIRS) || defined(CONFIG_FS_PROCFS)
  279. struct smartfs_mountpt_s *fs_next; /* Pointer to next SMART filesystem */
  280. #endif
  281. FAR struct inode *fs_blkdriver; /* Our underlying block device */
  282. sem_t *fs_sem; /* Used to assure thread-safe access */
  283. FAR struct smartfs_ofile_s *fs_head; /* A singly-linked list of open files */
  284. bool fs_mounted; /* true: The file system is ready */
  285. struct smart_format_s fs_llformat; /* Low level device format info */
  286. char *fs_rwbuffer; /* Read/Write working buffer */
  287. char *fs_workbuffer;/* Working buffer */
  288. uint8_t fs_rootsector;/* Root directory sector num */
  289. };
  290. /****************************************************************************
  291. * Public Data
  292. ****************************************************************************/
  293. /****************************************************************************
  294. * Internal function prototypes
  295. ****************************************************************************/
  296. /* Semaphore access for internal use */
  297. void smartfs_semtake(struct smartfs_mountpt_s *fs);
  298. void smartfs_semgive(struct smartfs_mountpt_s *fs);
  299. /* Forward references for utility functions */
  300. struct smartfs_mountpt_s;
  301. /* Utility functions */
  302. int smartfs_mount(struct smartfs_mountpt_s *fs, bool writeable);
  303. int smartfs_unmount(struct smartfs_mountpt_s *fs);
  304. int smartfs_finddirentry(struct smartfs_mountpt_s *fs,
  305. struct smartfs_entry_s *direntry, const char *relpath,
  306. uint16_t *parentdirsector, const char **filename);
  307. int smartfs_createentry(struct smartfs_mountpt_s *fs,
  308. uint16_t parentdirsector, const char* filename,
  309. uint16_t type,
  310. mode_t mode, struct smartfs_entry_s *direntry,
  311. uint16_t sectorno, FAR struct smartfs_ofile_s *sf);
  312. int smartfs_deleteentry(struct smartfs_mountpt_s *fs,
  313. struct smartfs_entry_s *entry);
  314. int smartfs_countdirentries(struct smartfs_mountpt_s *fs,
  315. struct smartfs_entry_s *entry);
  316. int smartfs_truncatefile(struct smartfs_mountpt_s *fs,
  317. struct smartfs_entry_s *entry, FAR struct smartfs_ofile_s *sf);
  318. uint16_t smartfs_rdle16(FAR const void *val);
  319. void smartfs_wrle16(void *dest, uint16_t val);
  320. uint32_t smartfs_rdle32(FAR const void *val);
  321. void smartfs_wrle32(uint8_t *dest, uint32_t val);
  322. #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS)
  323. struct smartfs_mountpt_s* smartfs_get_first_mount(void);
  324. #endif
  325. #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS)
  326. struct smartfs_mountpt_s* smartfs_get_first_mount(void);
  327. #endif
  328. struct file; /* Forward references */
  329. struct inode;
  330. struct fs_dirent_s;
  331. struct statfs;
  332. struct stat;
  333. #endif /* __FS_SMARTFS_SMARTFS_H */