summaryrefslogtreecommitdiff
path: root/nuttx/fs/smartfs/smartfs.h
blob: 22b08501dd15bfcd53bbf4747487d8315b1a3d76 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/****************************************************************************
 * fs/smartfs/smartfs.h
 *
 *   Copyright (C) 2013 Ken Pettit. All rights reserved.
 *   Author: Ken Pettit <pettitkd@gmail.com>
 *
 * References: Linux/Documentation/filesystems/romfs.txt
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name NuttX nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

#ifndef __FS_SMARTFS_SMARTFS_H
#define __FS_SMARTFS_SMARTFS_H

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <nuttx/config.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <semaphore.h>

#include <nuttx/mtd/mtd.h>
#include <nuttx/fs/smart.h>

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/
/* SMART Definitions ********************************************************/
/* General SMART organization.  The following example assumes 4 logical
 * sectors per FLASH erase block.  The actual relationship is determined by
 * the FLASH geometry reported by the MTD driver.
 *
 * ERASE LOGICAL                   Sectors begin with a sector header.  Sectors may
 * BLOCK SECTOR      CONTENTS      be marked as "released," pending garbage collection
 *   n   4*n     --+---------------+
 *             Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
 *                 |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
 *                 |SSSSSSSSSSSSSSS| Status bits (1 byte)
 *                 +---------------+
 *                 |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
 *                 |NNNNNNNNNNNNNNN| Number of next logical sector in chain
 *                 |UUUUUUUUUUUUUUU| Number of bytes used in this sector
 *                 |               |
 *                 | (Sector Data) |
 *                 |               |
 *       4*n+1   --+---------------+
 *      Sector Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
 *                 |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
 *                 |SSSSSSSSSSSSSSS| Status bits (1 byte)
 *                 +---------------+
 *          FS Hdr |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
 *                 |NNNNNNNNNNNNNNN| Number of next logical sector in chain
 *                 |UUUUUUUUUUUUUUU| Number of bytes used in this sector
 *                 |               |
 *                 | (Sector Data) |
 *                 |               |
 *       4*n+2   --+---------------+
 *      Sector Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
 *                 |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
 *                 |SSSSSSSSSSSSSSS| Status bits (1 byte)
 *                 +---------------+
 *          FS Hdr |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
 *                 |NNNNNNNNNNNNNNN| Number of next logical sector in chain
 *                 |UUUUUUUUUUUUUUU| Number of bytes used in this sector
 *                 |               |
 *                 | (Sector Data) |
 *                 |               |
 *       4*n+3   --+---------------+
 *      Sector Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
 *                 |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
 *                 |SSSSSSSSSSSSSSS| Status bits (1 byte)
 *                 +---------------+
 *          FS Hdr |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
 *                 |NNNNNNNNNNNNNNN| Number of next logical sector in chain
 *                 |UUUUUUUUUUUUUUU| Number of bytes used in this sector
 *                 |               |
 *                 | (Sector Data) |
 *                 |               |
 *  n+1  4*(n+1) --+---------------+
 *      Sector Hdr |LLLLLLLLLLLLLLL| Logical sector number (2 bytes)
 *                 |QQQQQQQQQQQQQQQ| Sequence number (2 bytes)
 *                 |SSSSSSSSSSSSSSS| Status bits (1 byte)
 *                 +---------------+
 *          FS Hdr |TTTTTTTTTTTTTTT| Sector Type (dir or file) (1 byte)
 *                 |NNNNNNNNNNNNNNN| Number of next logical sector in chain
 *                 |UUUUUUUUUUUUUUU| Number of bytes used in this sector
 *                 |               |
 *                 |               |
 *                 |               |
 *               --+---------------+
 *
 * General operation:
 *   Physical sectors are allocated and assigned a logical sector number
 *   and a starting sequence number of zero.
 *
 * SECTOR HEADER:
 *   The sector header (first 5 bytes) tracks the state of each sector and
 *   is used by the SMART MTD block driver.  At the block level, there is
 *   no notion of sector chaining, only allocated sectors within erase
 *   blocks.
 *
 * FILE SYSTEM (FS) HEADER:
 *   The file system header (next 5 bytes) tracks file and directory entries
 *   and chains.
 *
 * SMART Limitations:
 * 1. SMART currently depends on the underlying MTD block driver supporting
 *    single-byte programming operation.  This is due to the method it
 *    uses for marking a sector as "released", committed, etc.
 * 2. Garbage collection can occur when a new sector is allocated or when
 *    existing sector data is overwritten with new data. Thus, occasionally,
 *    file writing may take longer than other times.
 * 3. The implementation curently does not track bad blocks on the device.
 * 4. There is no true wear-leveling implemented yet, though provesion have
 *    been made to reserve logical sectors to allow it to be added using
 *    a "sector aging" tracking mechanism.
 */

/* Values for SMART inode state.
 *
 * SMART_STATE_FILE    - The inode is a valid usuable, file
 * INODE_STATE_DELETED - The inode has been deleted.
 * Other values        - The inode is bad and has an invalid state.
 *
 * Care is taken so that the VALID to DELETED transition only involves burning
 * bits from the erased to non-erased state.
 */

#define INODE_STATE_FILE          (CONFIG_NXFFS_ERASEDSTATE ^ 0x22)
#define INODE_STATE_DELETED       (CONFIG_NXFFS_ERASEDSTATE ^ 0xaa)

/* Directory entry flag definitions */

#define SMARTFS_DIRENT_EMPTY      0x8000  /* Set to non-erase state when entry used */
#define SMARTFS_DIRENT_ACTIVE     0x4000  /* Set to erase state when entry is active */
#define SMARTFS_DIRENT_TYPE       0x2000  /* Indicates the type of entry (file/dir) */
#define SMARTFS_DIRENT_DELETING   0x1000  /* Directory entry is being deleted */
#define SMARTFS_DIRENT_RESERVED   0x0E00  /* Reserved bits */
#define SMARTFS_DIRENT_MODE       0x01FF  /* Mode the file was created with */

#define SMARTFS_DIRENT_TYPE_DIR   0x2000
#define SMARTFS_DIRENT_TYPE_FILE  0x0000

/* Number of bytes in the SMART magic sequences */

#define SMART_MAGICSIZE           4

/* Quasi-standard definitions */

#ifndef MIN
#  define MIN(a,b)                (a < b ? a : b)
#endif

#ifndef MAX
#  define MAX(a,b)                (a > b ? a : b)
#endif

/* Underlying MTD Block driver access functions */

#define FS_BOPS(f)        (f)->fs_blkdriver->u.i_bops
#define FS_IOCTL(f,c,a)   (FS_BOPS(f)->ioctl ? FS_BOPS(f)->ioctl((f)->fs_blkdriver,c,a) : (-ENOSYS))

/* The logical sector number of the root directory. */

#define SMARTFS_ROOT_DIR_SECTOR   3

/* Defines the sector types */

#define SMARTFS_SECTOR_TYPE_DIR   1
#define SMARTFS_SECTOR_TYPE_FILE  2

#ifndef CONFIG_SMARTFS_DIRDEPTH
#define   CONFIG_SMARTFS_DIRDEPTH 8
#endif

#define SMARTFS_ERASEDSTATE_16BIT (uint16_t) ((CONFIG_SMARTFS_ERASEDSTATE << 8) | \
                                    CONFIG_SMARTFS_ERASEDSTATE)

#ifndef offsetof
#define offsetof(type, member)   ( (size_t) &( ( (type *) 0)->member))
#endif

#define SMARTFS_NEXTSECTOR(h)    ( *((uint16_t *) h->nextsector))
#define SMARTFS_USED(h)          ( *((uint16_t *) h->used))

/****************************************************************************
 * Public Types
 ****************************************************************************/

/* This structure defines each packed block on the FLASH media */

/* This is an in-memory representation of the SMART inode as extracted from
 * FLASH and with additional state information.
 */

struct smartfs_entry_s
{
  uint16_t          firstsector;  /* Sector number of the name */
  uint16_t          dsector;      /* Sector number of the directory entry */
  uint16_t          doffset;      /* Offset of the directory entry */
  uint16_t          dfirst;       /* 1st sector number of the directory entry */
  uint16_t          flags;        /* Flags, including mode */
  FAR char          *name;        /* inode name */
  uint32_t          utc;          /* Time stamp */
  uint32_t          datlen;       /* Length of inode data */
};

/* This is an on-device representation of the SMART inode it esists on
 * the FLASH.
 */

struct smartfs_entry_header_s
{
  uint16_t          flags;        /* Flags, including permissions:
                                      15:   Empty entry
                                      14:   Active entry
                                      12-0: Permissions bits */
  int16_t           firstsector;  /* Sector number of the name */
  uint32_t          utc;          /* Time stamp */
  char              name[0];      /* inode name */
};

/* This structure describes the smartfs header at the start of each
 * sector.  It manages the sector chain and used bytes in the sector.
 */

struct smartfs_chain_header_s
{
  uint8_t           type;         /* Type of sector entry (file or dir) */
  uint8_t           nextsector[2];/* Next logical sector in the chain */
  uint8_t           used[2];      /* Number of bytes used in this sector */
};

/* This structure describes the state of one open file.  This structure
 * is protected by the volume semaphore.
 */

struct smartfs_ofile_s
{
  struct smartfs_ofile_s   *fnext;      /* Supports a singly linked list */
  int16_t                   crefs;      /* Reference count */
  mode_t                    oflags;     /* Open mode */
  struct smartfs_entry_s    entry;      /* Describes the SMARTFS inode entry */
  size_t                    filepos;    /* Current file position */
  uint16_t                  currsector; /* Current sector of filepos */
  uint16_t                  curroffset; /* Current offset in sector */
  uint16_t                  byteswritten;/* Count of bytes written to currsector
                                          * that have not been recorded in the
                                          * sector yet.  We delay updating the
                                          * used field until the file is closed,
                                          * a seek, or more data is written that
                                          * causes the sector to change. */
};

/* This structure represents the overall mountpoint state.  An instance of this
 * structure is retained as inode private data on each mountpoint that is
 * mounted with a smartfs filesystem.
 */

struct smartfs_mountpt_s
{
#ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
  struct smartfs_mountpt_s   *fs_next;      /* Pointer to next SMART filesystem */
#endif
  FAR struct inode           *fs_blkdriver; /* Our underlying block device */
  sem_t                      *fs_sem;       /* Used to assure thread-safe access */
  FAR struct smartfs_ofile_s *fs_head;      /* A singly-linked list of open files */
  bool                        fs_mounted;   /* true: The file system is ready */
  struct smart_format_s       fs_llformat;  /* Low level device format info */
  char                       *fs_rwbuffer;  /* Read/Write working buffer */
  char                       *fs_workbuffer;/* Working buffer */
  uint8_t                     fs_rootsector;/* Root directory sector num */
};

/****************************************************************************
 * Public Variables
 ****************************************************************************/

/****************************************************************************
 * Internal function prototypes
 ****************************************************************************/

/* Semaphore access for internal use */

void smartfs_semtake(struct smartfs_mountpt_s *fs);
void smartfs_semgive(struct smartfs_mountpt_s *fs);

/* Forward references for utility functions */

struct smartfs_mountpt_s;

/* Utility functions */

int smartfs_mount(struct smartfs_mountpt_s *fs, bool writeable);

int smartfs_unmount(struct smartfs_mountpt_s *fs);

int smartfs_finddirentry(struct smartfs_mountpt_s *fs,
        struct smartfs_entry_s *direntry, const char *relpath,
        uint16_t *parentdirsector, const char **filename);

int smartfs_createentry(struct smartfs_mountpt_s *fs,
        uint16_t parentdirsector, const char* filename,
        uint16_t type,
        mode_t mode, struct smartfs_entry_s *direntry,
        uint16_t sectorno);

int smartfs_deleteentry(struct smartfs_mountpt_s *fs,
        struct smartfs_entry_s *entry);

int smartfs_countdirentries(struct smartfs_mountpt_s *fs,
        struct smartfs_entry_s *entry);

int smartfs_truncatefile(struct smartfs_mountpt_s *fs,
        struct smartfs_entry_s *entry);

struct file;        /* Forward references */
struct inode;
struct fs_dirent_s;
struct statfs;
struct stat;

#endif /* __FS_SMARTFS_SMARTFS_H */