nuttx/fs/smartfs/smartfs.h
Michal Lenc 01bed328ef smartfs: add support for FIOC_FILEPATH ioctl
The FIOC_FILEPATH ioctl call is required if smartfs is to be used
together with inotify monitoring system. This implements the
call support to smartfs file system. The path to the file has to
be stored in smartfs_ofile_s structure during file open (and is freed
during close) as smartfs currently is not able to obtain the path
knowing only the file node. The full path is concatenated with the file
name and creates the full path needed for inotify to detect whether
the file is on the watchlist.

Signed-off-by: Michal Lenc <michallenc@seznam.cz>
2024-10-10 15:30:41 +02:00

401 lines
16 KiB
C

/****************************************************************************
* fs/smartfs/smartfs.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#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 <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 be marked as "released,"
* BLOCK SECTOR CONTENTS 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 currently 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 usable, 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
/* 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
/* Buffer flags (when CRC enabled) */
#define SMARTFS_BFLAG_DIRTY 0x01 /* Set if data changed in the sector */
#define SMARTFS_BFLAG_NEWALLOC 0x02 /* Set if sector not written since alloc */
#define SMARTFS_ERASEDSTATE_16BIT (uint16_t) ((CONFIG_SMARTFS_ERASEDSTATE << 8) | \
CONFIG_SMARTFS_ERASEDSTATE)
/* Size of temporary buffer used when a file is zero extended by ftruncate()
* logic.
*/
#define SMARTFS_TRUNCBUFFER_SIZE 512
#ifndef offsetof
# define offsetof(type, member) ((size_t)&(((FAR type *)0)->member))
#endif
#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
# define SMARTFS_NEXTSECTOR(h) (smartfs_rdle16(h->nextsector))
# define SMARTFS_SET_NEXTSECTOR(h, v) smartfs_wrle16(h->nextsector, \
(uint16_t)(v))
# define SMARTFS_USED(h) (smartfs_rdle16(h->used))
# define SMARTFS_SET_USED(h, v) smartfs_wrle16(h->used, \
(uint16_t)(v))
#else
# define SMARTFS_NEXTSECTOR(h) (*((FAR uint16_t *)h->nextsector))
# define SMARTFS_SET_NEXTSECTOR(h, v) ((*((FAR uint16_t *)h->nextsector)) = \
(uint16_t)(v))
# define SMARTFS_USED(h) (*((FAR uint16_t *)h->used))
# define SMARTFS_SET_USED(h, v) ((*((FAR uint16_t *)h->used)) = \
(uint16_t)(v))
#endif
#ifdef CONFIG_MTD_SMART_ENABLE_CRC
#define CONFIG_SMARTFS_USE_SECTOR_BUFFER
#endif
/****************************************************************************
* 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 as it exists 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.
*/
#if defined(CONFIG_MTD_SMART_ENABLE_CRC) && defined(CONFIG_SMART_CRC_32)
struct smartfs_chain_header_s
{
uint8_t nextsector[4]; /* Next logical sector in the chain */
uint8_t used[4]; /* Number of bytes used in this sector */
uint8_t type; /* Type of sector entry (file or dir) */
};
#elif defined(CONFIG_MTD_SMART_ENABLE_CRC) && defined(CONFIG_SMART_CRC_16)
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 */
};
#else
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 */
};
#endif
/* This structure describes the state of one open file. This structure
* is protected by the volume semaphore.
*/
struct smartfs_ofile_s
{
FAR struct smartfs_ofile_s *fnext; /* Supports a singly linked list */
#ifdef CONFIG_SMARTFS_USE_SECTOR_BUFFER
FAR uint8_t *buffer; /* Sector buffer to reduce writes */
uint8_t bflags; /* Buffer flags */
#endif
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.
*/
char path[1]; /* The full path to the file */
};
/* 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
{
#if defined(CONFIG_SMARTFS_MULTI_ROOT_DIRS) || defined(CONFIG_FS_PROCFS)
FAR struct smartfs_mountpt_s *fs_next; /* Pointer to next SMART filesystem */
#endif
FAR struct inode *fs_blkdriver; /* Our underlying block device */
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 */
FAR char *fs_rwbuffer; /* Read/Write working buffer */
FAR char *fs_workbuffer; /* Working buffer */
uint8_t fs_rootsector; /* Root directory sector num */
};
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Public Functions Prototypes
****************************************************************************/
/* Forward references for utility functions */
struct smartfs_mountpt_s;
/* Utility functions */
int smartfs_mount(FAR struct smartfs_mountpt_s *fs, bool writeable);
int smartfs_unmount(FAR struct smartfs_mountpt_s *fs);
int smartfs_finddirentry(FAR struct smartfs_mountpt_s *fs,
FAR struct smartfs_entry_s *direntry, FAR const char *relpath,
FAR uint16_t *parentdirsector, FAR const char **filename);
int smartfs_createentry(FAR struct smartfs_mountpt_s *fs,
uint16_t parentdirsector, FAR const char *filename,
uint16_t type,
mode_t mode, FAR struct smartfs_entry_s *direntry,
uint16_t sectorno, FAR struct smartfs_ofile_s *sf);
int smartfs_deleteentry(FAR struct smartfs_mountpt_s *fs,
FAR struct smartfs_entry_s *entry);
int smartfs_countdirentries(FAR struct smartfs_mountpt_s *fs,
FAR struct smartfs_entry_s *entry);
int smartfs_sync_internal(FAR struct smartfs_mountpt_s *fs,
FAR struct smartfs_ofile_s *sf);
off_t smartfs_seek_internal(FAR struct smartfs_mountpt_s *fs,
FAR struct smartfs_ofile_s *sf, off_t offset, int whence);
int smartfs_shrinkfile(FAR struct smartfs_mountpt_s *fs,
FAR struct smartfs_ofile_s *sf, off_t length);
int smartfs_extendfile(FAR struct smartfs_mountpt_s *fs,
FAR struct smartfs_ofile_s *sf, off_t length);
uint16_t smartfs_rdle16(FAR const void *val);
void smartfs_wrle16(FAR void *dest, uint16_t val);
uint32_t smartfs_rdle32(FAR const void *val);
void smartfs_wrle32(FAR uint8_t *dest, uint32_t val);
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS)
FAR struct smartfs_mountpt_s *smartfs_get_first_mount(void);
#endif
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS)
FAR struct smartfs_mountpt_s *smartfs_get_first_mount(void);
#endif
struct file; /* Forward references */
struct inode;
struct fs_dirent_s;
struct statfs;
struct stat;
#endif /* __FS_SMARTFS_SMARTFS_H */