fs/littlefs: upgrade littlefs to v2.2.1
Since littlefs is in active development, it's not a good idea to use its source code files directly. So upgrade littlefs v2.2.1 by using the littlefs tar.gz release package instead. Change-Id: I16d9cf0b6bca700a54ca86ed11d7c8c7f27a898f Signed-off-by: liuhaitao <liuhaitao@xiaomi.com>
This commit is contained in:
parent
43ee4ae184
commit
fe0ba38580
@ -99,6 +99,8 @@ $(COBJS): %$(OBJEXT): %.c
|
||||
$(BIN): $(OBJS)
|
||||
$(call ARCHIVE, $@, $(OBJS))
|
||||
|
||||
context::
|
||||
|
||||
.depend: Makefile $(SRCS)
|
||||
$(Q) $(MKDEP) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
|
||||
$(Q) touch $@
|
||||
@ -109,7 +111,7 @@ clean:
|
||||
$(call DELFILE, $(BIN))
|
||||
$(call CLEAN)
|
||||
|
||||
distclean: clean
|
||||
distclean:: clean
|
||||
$(call DELFILE, Make.dep)
|
||||
$(call DELFILE, .depend)
|
||||
|
||||
|
4
fs/littlefs/.gitignore
vendored
Normal file
4
fs/littlefs/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/.littlefsunpack
|
||||
/littlefs
|
||||
/*tar.gz
|
||||
/*.zip
|
File diff suppressed because it is too large
Load Diff
@ -1,55 +1,52 @@
|
||||
#############################################################################
|
||||
############################################################################
|
||||
# fs/littlefs/Make.defs
|
||||
#
|
||||
# This file is a part of NuttX:
|
||||
# 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
|
||||
#
|
||||
# Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Ported by:
|
||||
# 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.
|
||||
#
|
||||
# Copyright (C) 2019 Pinecone Inc. All rights reserved.
|
||||
# Author: lihaichen <li8303@163.com>
|
||||
#
|
||||
# This port derives from ARM mbed logic which has a compatible 3-clause
|
||||
# BSD license:
|
||||
#
|
||||
# Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
#
|
||||
# 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 names ARM, 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.
|
||||
#
|
||||
#############################################################################
|
||||
############################################################################
|
||||
|
||||
ifeq ($(CONFIG_FS_LITTLEFS),y)
|
||||
# Files required for littlefs file system support
|
||||
|
||||
CSRCS += lfs.c lfs_util.c lfs_vfs.c
|
||||
CSRCS += lfs_vfs.c
|
||||
|
||||
DEPPATH += --dep-path littlefs
|
||||
VPATH += :littlefs
|
||||
|
||||
CSRCS += lfs.c lfs_util.c
|
||||
|
||||
DEPPATH += --dep-path littlefs/littlefs
|
||||
VPATH += :littlefs/littlefs
|
||||
|
||||
LITTLEFS_VERSION ?= 2.2.1
|
||||
LITTLEFS_TARBALL = v$(LITTLEFS_VERSION).tar.gz
|
||||
|
||||
$(LITTLEFS_TARBALL):
|
||||
$(Q) wget -P littlefs https://github.com/ARMmbed/littlefs/archive/$(LITTLEFS_TARBALL)
|
||||
|
||||
.littlefsunpack: $(LITTLEFS_TARBALL)
|
||||
$(Q) tar zxf littlefs/$(LITTLEFS_TARBALL) -C littlefs
|
||||
$(Q) mv littlefs/littlefs-$(LITTLEFS_VERSION) littlefs/littlefs
|
||||
$(Q) touch littlefs/.littlefsunpack
|
||||
|
||||
context:: .littlefsunpack
|
||||
|
||||
distclean::
|
||||
$(call DELFILE, littlefs/.littlefsunpack)
|
||||
$(call DELFILE, littlefs/$(LITTLEFS_TARBALL))
|
||||
$(call DELDIR, littlefs/littlefs)
|
||||
|
||||
endif
|
||||
|
@ -1,220 +0,0 @@
|
||||
## usage
|
||||
|
||||
depends on !DISABLE_MOUNTPOINT
|
||||
|
||||
1. register_mtddriver("/dev/w25", mtd, 0755, NULL);
|
||||
2. mount("/dev/w25", "/w25", "littlefs", 0, NULL);
|
||||
|
||||
## need to do
|
||||
|
||||
1. no format tool, mount auto format.
|
||||
|
||||
|
||||
## The little filesystem
|
||||
|
||||
A little fail-safe filesystem designed for embedded systems.
|
||||
|
||||
```
|
||||
| | | .---._____
|
||||
.-----. | |
|
||||
--|o |---| littlefs |
|
||||
--| |---| |
|
||||
'-----' '----------'
|
||||
| | |
|
||||
```
|
||||
|
||||
**Bounded RAM/ROM** - The littlefs is designed to work with a limited amount
|
||||
of memory. Recursion is avoided and dynamic memory is limited to configurable
|
||||
buffers that can be provided statically.
|
||||
|
||||
**Power-loss resilient** - The littlefs is designed for systems that may have
|
||||
random power failures. The littlefs has strong copy-on-write guarantees and
|
||||
storage on disk is always kept in a valid state.
|
||||
|
||||
**Wear leveling** - Since the most common form of embedded storage is erodible
|
||||
flash memories, littlefs provides a form of dynamic wear leveling for systems
|
||||
that can not fit a full flash translation layer.
|
||||
|
||||
## Example
|
||||
|
||||
Here's a simple example that updates a file named `boot_count` every time
|
||||
main runs. The program can be interrupted at any time without losing track
|
||||
of how many times it has been booted and without corrupting the filesystem:
|
||||
|
||||
``` c
|
||||
#include "lfs.h"
|
||||
|
||||
/* variables used by the filesystem */
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_file_t file;
|
||||
|
||||
/* configuration of the filesystem is provided by this struct */
|
||||
|
||||
const struct lfs_config cfg =
|
||||
{
|
||||
/* block device operations */
|
||||
|
||||
.read = user_provided_block_device_read,
|
||||
.prog = user_provided_block_device_prog,
|
||||
.erase = user_provided_block_device_erase,
|
||||
.sync = user_provided_block_device_sync,
|
||||
|
||||
/* block device configuration */
|
||||
|
||||
.read_size = 16,
|
||||
.prog_size = 16,
|
||||
.block_size = 4096,
|
||||
.block_count = 128,
|
||||
.lookahead = 128,
|
||||
};
|
||||
|
||||
/* entry point */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* mount the filesystem */
|
||||
|
||||
int err = lfs_mount(&lfs, &cfg);
|
||||
|
||||
/* reformat if we can't mount the filesystem
|
||||
* this should only happen on the first boot
|
||||
*/
|
||||
|
||||
if (err)
|
||||
{
|
||||
lfs_format(&lfs, &cfg);
|
||||
lfs_mount(&lfs, &cfg);
|
||||
}
|
||||
|
||||
/* read current count */
|
||||
|
||||
uint32_t boot_count = 0;
|
||||
lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
|
||||
lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));
|
||||
|
||||
/* update boot count */
|
||||
|
||||
boot_count += 1;
|
||||
lfs_file_rewind(&lfs, &file);
|
||||
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
|
||||
|
||||
/* remember the storage is not updated until the file is closed successfully */
|
||||
|
||||
lfs_file_close(&lfs, &file);
|
||||
|
||||
/* release any resources we were using */
|
||||
|
||||
lfs_unmount(&lfs);
|
||||
|
||||
/* print the boot count */
|
||||
|
||||
printf("boot_count: %d\n", boot_count);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Detailed documentation (or at least as much detail as is currently available)
|
||||
can be found in the comments in [lfs.h](lfs.h).
|
||||
|
||||
As you may have noticed, littlefs takes in a configuration structure that
|
||||
defines how the filesystem operates. The configuration struct provides the
|
||||
filesystem with the block device operations and dimensions, tweakable
|
||||
parameters that tradeoff memory usage for performance, and optional
|
||||
static buffers if the user wants to avoid dynamic memory.
|
||||
|
||||
The state of the littlefs is stored in the `lfs_t` type which is left up
|
||||
to the user to allocate, allowing multiple filesystems to be in use
|
||||
simultaneously. With the `lfs_t` and configuration struct, a user can
|
||||
format a block device or mount the filesystem.
|
||||
|
||||
Once mounted, the littlefs provides a full set of POSIX-like file and
|
||||
directory functions, with the deviation that the allocation of filesystem
|
||||
structures must be provided by the user.
|
||||
|
||||
All POSIX operations, such as remove and rename, are atomic, even in event
|
||||
of power-loss. Additionally, no file updates are actually committed to the
|
||||
filesystem until sync or close is called on the file.
|
||||
|
||||
## Other notes
|
||||
|
||||
All littlefs have the potential to return a negative error code. The errors
|
||||
can be either one of those found in the `enum lfs_error` in [lfs.h](lfs.h),
|
||||
or an error returned by the user's block device operations.
|
||||
|
||||
In the configuration struct, the `prog` and `erase` function provided by the
|
||||
user may return a `LFS_ERR_CORRUPT` error if the implementation already can
|
||||
detect corrupt blocks. However, the wear leveling does not depend on the return
|
||||
code of these functions, instead all data is read back and checked for
|
||||
integrity.
|
||||
|
||||
If your storage caches writes, make sure that the provided `sync` function
|
||||
flushes all the data to memory and ensures that the next read fetches the data
|
||||
from memory, otherwise data integrity can not be guaranteed. If the `write`
|
||||
function does not perform caching, and therefore each `read` or `write` call
|
||||
hits the memory, the `sync` function can simply return 0.
|
||||
|
||||
## Reference material
|
||||
|
||||
[DESIGN.md](DESIGN.md) - DESIGN.md contains a fully detailed dive into how
|
||||
littlefs actually works. I would encourage you to read it since the
|
||||
solutions and tradeoffs at work here are quite interesting.
|
||||
|
||||
[SPEC.md](SPEC.md) - SPEC.md contains the on-disk specification of littlefs
|
||||
with all the nitty-gritty details. Can be useful for developing tooling.
|
||||
|
||||
## Testing
|
||||
|
||||
The littlefs comes with a test suite designed to run on a PC using the
|
||||
[emulated block device](emubd/lfs_emubd.h) found in the emubd directory.
|
||||
The tests assume a Linux environment and can be started with make:
|
||||
|
||||
``` bash
|
||||
make test
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
The littlefs is provided under the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html)
|
||||
license. See [LICENSE.md](LICENSE.md) for more information. Contributions to
|
||||
this project are accepted under the same license.
|
||||
|
||||
Individual files contain the following tag instead of the full license text.
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
||||
|
||||
## Related projects
|
||||
|
||||
[Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) -
|
||||
The easiest way to get started with littlefs is to jump into [Mbed](https://os.mbed.com/),
|
||||
which already has block device drivers for most forms of embedded storage. The
|
||||
littlefs is available in Mbed OS as the [LittleFileSystem](https://os.mbed.com/docs/latest/reference/littlefilesystem.html)
|
||||
class.
|
||||
|
||||
[littlefs-fuse](https://github.com/geky/littlefs-fuse) - A [FUSE](https://github.com/libfuse/libfuse)
|
||||
wrapper for littlefs. The project allows you to mount littlefs directly on a
|
||||
Linux machine. Can be useful for debugging littlefs if you have an SD card
|
||||
handy.
|
||||
|
||||
[littlefs-js](https://github.com/geky/littlefs-js) - A javascript wrapper for
|
||||
littlefs. I'm not sure why you would want this, but it is handy for demos.
|
||||
You can see it in action [here](http://littlefs.geky.net/demo.html).
|
||||
|
||||
[mklfs](https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src) -
|
||||
A command line tool built by the [Lua RTOS](https://github.com/whitecatboard/Lua-RTOS-ESP32)
|
||||
guys for making littlefs images from a host PC. Supports Windows, Mac OS,
|
||||
and Linux.
|
||||
|
||||
[SPIFFS](https://github.com/pellepl/spiffs) - Another excellent embedded
|
||||
filesystem for NOR flash. As a more traditional logging filesystem with full
|
||||
static wear-leveling, SPIFFS will likely outperform littlefs on small
|
||||
memories such as the internal flash on microcontrollers.
|
||||
|
||||
[Dhara](https://github.com/dlbeer/dhara) - An interesting NAND flash
|
||||
translation layer designed for small MCUs. It offers static wear-leveling and
|
||||
power-resilience with only a fixed O(|address|) pointer structure stored on
|
||||
each block and in RAM.
|
@ -1,370 +0,0 @@
|
||||
## The little filesystem technical specification
|
||||
|
||||
This is the technical specification of the little filesystem. This document
|
||||
covers the technical details of how the littlefs is stored on disk for
|
||||
introspection and tooling development. This document assumes you are
|
||||
familiar with the design of the littlefs, for more info on how littlefs
|
||||
works check out [DESIGN.md](DESIGN.md).
|
||||
|
||||
```
|
||||
| | | .---._____
|
||||
.-----. | |
|
||||
--|o |---| littlefs |
|
||||
--| |---| |
|
||||
'-----' '----------'
|
||||
| | |
|
||||
```
|
||||
|
||||
## Some important details
|
||||
|
||||
- The littlefs is a block-based filesystem. This is, the disk is divided into
|
||||
an array of evenly sized blocks that are used as the logical unit of storage
|
||||
in littlefs. Block pointers are stored in 32 bits.
|
||||
|
||||
- There is no explicit free-list stored on disk, the littlefs only knows what
|
||||
is in use in the filesystem.
|
||||
|
||||
- The littlefs uses the value of 0xffffffff to represent a null block-pointer.
|
||||
|
||||
- All values in littlefs are stored in little-endian byte order.
|
||||
|
||||
## Directories / Metadata pairs
|
||||
|
||||
Metadata pairs form the backbone of the littlefs and provide a system for
|
||||
atomic updates. Even the superblock is stored in a metadata pair.
|
||||
|
||||
As their name suggests, a metadata pair is stored in two blocks, with one block
|
||||
acting as a redundant backup in case the other is corrupted. These two blocks
|
||||
could be anywhere in the disk and may not be next to each other, so any
|
||||
pointers to directory pairs need to be stored as two block pointers.
|
||||
|
||||
Here's the layout of metadata blocks on disk:
|
||||
|
||||
| offset | size | description |
|
||||
|--------|---------------|----------------|
|
||||
| 0x00 | 32 bits | revision count |
|
||||
| 0x04 | 32 bits | dir size |
|
||||
| 0x08 | 64 bits | tail pointer |
|
||||
| 0x10 | size-16 bytes | dir entries |
|
||||
| 0x00+s | 32 bits | CRC |
|
||||
|
||||
**Revision count** - Incremented every update, only the uncorrupted
|
||||
metadata-block with the most recent revision count contains the valid metadata.
|
||||
Comparison between revision counts must use sequence comparison since the
|
||||
revision counts may overflow.
|
||||
|
||||
**Dir size** - Size in bytes of the contents in the current metadata block,
|
||||
including the metadata-pair metadata. Additionally, the highest bit of the
|
||||
dir size may be set to indicate that the directory's contents continue on the
|
||||
next metadata-pair pointed to by the tail pointer.
|
||||
|
||||
**Tail pointer** - Pointer to the next metadata-pair in the filesystem.
|
||||
A null pair-pointer (0xffffffff, 0xffffffff) indicates the end of the list.
|
||||
If the highest bit in the dir size is set, this points to the next
|
||||
metadata-pair in the current directory, otherwise it points to an arbitrary
|
||||
metadata-pair. Starting with the superblock, the tail-pointers form a
|
||||
linked-list containing all metadata-pairs in the filesystem.
|
||||
|
||||
**CRC** - 32 bit CRC used to detect corruption from power-lost, from block
|
||||
end-of-life, or just from noise on the storage bus. The CRC is appended to
|
||||
the end of each metadata-block. The littlefs uses the standard CRC-32, which
|
||||
uses a polynomial of 0x04c11db7, initialized with 0xffffffff.
|
||||
|
||||
Here's an example of a simple directory stored on disk:
|
||||
```
|
||||
(32 bits) revision count = 10 (0x0000000a)
|
||||
(32 bits) dir size = 154 bytes, end of dir (0x0000009a)
|
||||
(64 bits) tail pointer = 37, 36 (0x00000025, 0x00000024)
|
||||
(32 bits) CRC = 0xc86e3106
|
||||
|
||||
00000000: 0a 00 00 00 9a 00 00 00 25 00 00 00 24 00 00 00 ........%...$...
|
||||
00000010: 22 08 00 03 05 00 00 00 04 00 00 00 74 65 61 22 "...........tea"
|
||||
00000020: 08 00 06 07 00 00 00 06 00 00 00 63 6f 66 66 65 ...........coffe
|
||||
00000030: 65 22 08 00 04 09 00 00 00 08 00 00 00 73 6f 64 e"...........sod
|
||||
00000040: 61 22 08 00 05 1d 00 00 00 1c 00 00 00 6d 69 6c a"...........mil
|
||||
00000050: 6b 31 22 08 00 05 1f 00 00 00 1e 00 00 00 6d 69 k1"...........mi
|
||||
00000060: 6c 6b 32 22 08 00 05 21 00 00 00 20 00 00 00 6d lk2"...!... ...m
|
||||
00000070: 69 6c 6b 33 22 08 00 05 23 00 00 00 22 00 00 00 ilk3"...#..."...
|
||||
00000080: 6d 69 6c 6b 34 22 08 00 05 25 00 00 00 24 00 00 milk4"...%...$..
|
||||
00000090: 00 6d 69 6c 6b 35 06 31 6e c8 .milk5.1n.
|
||||
```
|
||||
|
||||
A note about the tail pointer linked-list: Normally, this linked-list is
|
||||
threaded through the entire filesystem. However, after power-loss this
|
||||
linked-list may become out of sync with the rest of the filesystem.
|
||||
- The linked-list may contain a directory that has actually been removed
|
||||
- The linked-list may contain a metadata pair that has not been updated after
|
||||
a block in the pair has gone bad.
|
||||
|
||||
The threaded linked-list must be checked for these errors before it can be
|
||||
used reliably. Fortunately, the threaded linked-list can simply be ignored
|
||||
if littlefs is mounted read-only.
|
||||
|
||||
## Entries
|
||||
|
||||
Each metadata block contains a series of entries that follow a standard
|
||||
layout. An entry contains the type of the entry, along with a section for
|
||||
entry-specific data, attributes, and a name.
|
||||
|
||||
Here's the layout of entries on disk:
|
||||
|
||||
| offset | size | description |
|
||||
|---------|------------------------|----------------------------|
|
||||
| 0x0 | 8 bits | entry type |
|
||||
| 0x1 | 8 bits | entry length |
|
||||
| 0x2 | 8 bits | attribute length |
|
||||
| 0x3 | 8 bits | name length |
|
||||
| 0x4 | entry length bytes | entry-specific data |
|
||||
| 0x4+e | attribute length bytes | system-specific attributes |
|
||||
| 0x4+e+a | name length bytes | entry name |
|
||||
|
||||
**Entry type** - Type of the entry, currently this is limited to the following:
|
||||
- 0x11 - file entry
|
||||
- 0x22 - directory entry
|
||||
- 0x2e - superblock entry
|
||||
|
||||
Additionally, the type is broken into two 4 bit nibbles, with the upper nibble
|
||||
specifying the type's data structure used when scanning the filesystem. The
|
||||
lower nibble clarifies the type further when multiple entries share the same
|
||||
data structure.
|
||||
|
||||
The highest bit is reserved for marking the entry as "moved". If an entry
|
||||
is marked as "moved", the entry may also exist somewhere else in the
|
||||
filesystem. If the entry exists elsewhere, this entry must be treated as
|
||||
though it does not exist.
|
||||
|
||||
**Entry length** - Length in bytes of the entry-specific data. This does
|
||||
not include the entry type size, attributes, or name. The full size in bytes
|
||||
of the entry is 4 + entry length + attribute length + name length.
|
||||
|
||||
**Attribute length** - Length of system-specific attributes in bytes. Since
|
||||
attributes are system specific, there is not much guarantee on the values in
|
||||
this section, and systems are expected to work even when it is empty. See the
|
||||
[attributes](#entry-attributes) section for more details.
|
||||
|
||||
**Name length** - Length of the entry name. Entry names are stored as UTF8,
|
||||
although most systems will probably only support ASCII. Entry names can not
|
||||
contain '/' and can not be '.' or '..' as these are a part of the syntax of
|
||||
filesystem paths.
|
||||
|
||||
Here's an example of a simple entry stored on disk:
|
||||
```
|
||||
(8 bits) entry type = file (0x11)
|
||||
(8 bits) entry length = 8 bytes (0x08)
|
||||
(8 bits) attribute length = 0 bytes (0x00)
|
||||
(8 bits) name length = 12 bytes (0x0c)
|
||||
(8 bytes) entry data = 05 00 00 00 20 00 00 00
|
||||
(12 bytes) entry name = smallavacado
|
||||
|
||||
00000000: 11 08 00 0c 05 00 00 00 20 00 00 00 73 6d 61 6c ........ ...smal
|
||||
00000010: 6c 61 76 61 63 61 64 6f lavacado
|
||||
```
|
||||
|
||||
## Superblock
|
||||
|
||||
The superblock is the anchor for the littlefs. The superblock is stored as
|
||||
a metadata pair containing a single superblock entry. It is through the
|
||||
superblock that littlefs can access the rest of the filesystem.
|
||||
|
||||
The superblock can always be found in blocks 0 and 1, however fetching the
|
||||
superblock requires knowing the block size. The block size can be guessed by
|
||||
searching the beginning of disk for the string "littlefs", although currently
|
||||
the filesystems relies on the user providing the correct block size.
|
||||
|
||||
The superblock is the most valuable block in the filesystem. It is updated
|
||||
very rarely, only during format or when the root directory must be moved. It
|
||||
is encouraged to always write out both superblock pairs even though it is not
|
||||
required.
|
||||
|
||||
Here's the layout of the superblock entry:
|
||||
|
||||
| offset | size | description |
|
||||
|--------|------------------------|----------------------------------------|
|
||||
| 0x00 | 8 bits | entry type (0x2e for superblock entry) |
|
||||
| 0x01 | 8 bits | entry length (20 bytes) |
|
||||
| 0x02 | 8 bits | attribute length |
|
||||
| 0x03 | 8 bits | name length (8 bytes) |
|
||||
| 0x04 | 64 bits | root directory |
|
||||
| 0x0c | 32 bits | block size |
|
||||
| 0x10 | 32 bits | block count |
|
||||
| 0x14 | 32 bits | version |
|
||||
| 0x18 | attribute length bytes | system-specific attributes |
|
||||
| 0x18+a | 8 bytes | magic string ("littlefs") |
|
||||
|
||||
**Root directory** - Pointer to the root directory's metadata pair.
|
||||
|
||||
**Block size** - Size of the logical block size used by the filesystem.
|
||||
|
||||
**Block count** - Number of blocks in the filesystem.
|
||||
|
||||
**Version** - The littlefs version encoded as a 32 bit value. The upper 16 bits
|
||||
encodes the major version, which is incremented when a breaking-change is
|
||||
introduced in the filesystem specification. The lower 16 bits encodes the
|
||||
minor version, which is incremented when a backwards-compatible change is
|
||||
introduced. Non-standard Attribute changes do not change the version. This
|
||||
specification describes version 1.1 (0x00010001), which is the first version
|
||||
of littlefs.
|
||||
|
||||
**Magic string** - The magic string "littlefs" takes the place of an entry
|
||||
name.
|
||||
|
||||
Here's an example of a complete superblock:
|
||||
```
|
||||
(32 bits) revision count = 3 (0x00000003)
|
||||
(32 bits) dir size = 52 bytes, end of dir (0x00000034)
|
||||
(64 bits) tail pointer = 3, 2 (0x00000003, 0x00000002)
|
||||
(8 bits) entry type = superblock (0x2e)
|
||||
(8 bits) entry length = 20 bytes (0x14)
|
||||
(8 bits) attribute length = 0 bytes (0x00)
|
||||
(8 bits) name length = 8 bytes (0x08)
|
||||
(64 bits) root directory = 3, 2 (0x00000003, 0x00000002)
|
||||
(32 bits) block size = 512 bytes (0x00000200)
|
||||
(32 bits) block count = 1024 blocks (0x00000400)
|
||||
(32 bits) version = 1.1 (0x00010001)
|
||||
(8 bytes) magic string = littlefs
|
||||
(32 bits) CRC = 0xc50b74fa
|
||||
|
||||
00000000: 03 00 00 00 34 00 00 00 03 00 00 00 02 00 00 00 ....4...........
|
||||
00000010: 2e 14 00 08 03 00 00 00 02 00 00 00 00 02 00 00 ................
|
||||
00000020: 00 04 00 00 01 00 01 00 6c 69 74 74 6c 65 66 73 ........littlefs
|
||||
00000030: fa 74 0b c5 .t..
|
||||
```
|
||||
|
||||
## Directory entries
|
||||
|
||||
Directories are stored in entries with a pointer to the first metadata pair
|
||||
in the directory. Keep in mind that a directory may be composed of multiple
|
||||
metadata pairs connected by the tail pointer when the highest bit in the dir
|
||||
size is set.
|
||||
|
||||
Here's the layout of a directory entry:
|
||||
|
||||
| offset | size | description |
|
||||
|--------|------------------------|-----------------------------------------|
|
||||
| 0x0 | 8 bits | entry type (0x22 for directory entries) |
|
||||
| 0x1 | 8 bits | entry length (8 bytes) |
|
||||
| 0x2 | 8 bits | attribute length |
|
||||
| 0x3 | 8 bits | name length |
|
||||
| 0x4 | 64 bits | directory pointer |
|
||||
| 0xc | attribute length bytes | system-specific attributes |
|
||||
| 0xc+a | name length bytes | directory name |
|
||||
|
||||
**Directory pointer** - Pointer to the first metadata pair in the directory.
|
||||
|
||||
Here's an example of a directory entry:
|
||||
```
|
||||
(8 bits) entry type = directory (0x22)
|
||||
(8 bits) entry length = 8 bytes (0x08)
|
||||
(8 bits) attribute length = 0 bytes (0x00)
|
||||
(8 bits) name length = 3 bytes (0x03)
|
||||
(64 bits) directory pointer = 5, 4 (0x00000005, 0x00000004)
|
||||
(3 bytes) name = tea
|
||||
|
||||
00000000: 22 08 00 03 05 00 00 00 04 00 00 00 74 65 61 "...........tea
|
||||
```
|
||||
|
||||
## File entries
|
||||
|
||||
Files are stored in entries with a pointer to the head of the file and the
|
||||
size of the file. This is enough information to determine the state of the
|
||||
CTZ skip-list that is being referenced.
|
||||
|
||||
How files are actually stored on disk is a bit complicated. The full
|
||||
explanation of CTZ skip-lists can be found in [DESIGN.md](DESIGN.md#ctz-skip-lists).
|
||||
|
||||
A terribly quick summary: For every nth block where n is divisible by 2^x,
|
||||
the block contains a pointer to block n-2^x. These pointers are stored in
|
||||
increasing order of x in each block of the file preceding the data in the
|
||||
block.
|
||||
|
||||
The maximum number of pointers in a block is bounded by the maximum file size
|
||||
divided by the block size. With 32 bits for file size, this results in a
|
||||
minimum block size of 104 bytes.
|
||||
|
||||
Here's the layout of a file entry:
|
||||
|
||||
| offset | size | description |
|
||||
|--------|------------------------|------------------------------------|
|
||||
| 0x0 | 8 bits | entry type (0x11 for file entries) |
|
||||
| 0x1 | 8 bits | entry length (8 bytes) |
|
||||
| 0x2 | 8 bits | attribute length |
|
||||
| 0x3 | 8 bits | name length |
|
||||
| 0x4 | 32 bits | file head |
|
||||
| 0x8 | 32 bits | file size |
|
||||
| 0xc | attribute length bytes | system-specific attributes |
|
||||
| 0xc+a | name length bytes | directory name |
|
||||
|
||||
**File head** - Pointer to the block that is the head of the file's CTZ
|
||||
skip-list.
|
||||
|
||||
**File size** - Size of file in bytes.
|
||||
|
||||
Here's an example of a file entry:
|
||||
```
|
||||
(8 bits) entry type = file (0x11)
|
||||
(8 bits) entry length = 8 bytes (0x08)
|
||||
(8 bits) attribute length = 0 bytes (0x00)
|
||||
(8 bits) name length = 12 bytes (0x03)
|
||||
(32 bits) file head = 543 (0x0000021f)
|
||||
(32 bits) file size = 256 KB (0x00040000)
|
||||
(12 bytes) name = largeavacado
|
||||
|
||||
00000000: 11 08 00 0c 1f 02 00 00 00 00 04 00 6c 61 72 67 ............large
|
||||
00000010: 65 61 76 61 63 61 64 6f eavacado
|
||||
```
|
||||
|
||||
## Entry attributes
|
||||
|
||||
Each dir entry can have up to 256 bytes of system-specific attributes. Since
|
||||
these attributes are system-specific, they may not be portable between
|
||||
different systems. For this reason, all attributes must be optional. A minimal
|
||||
littlefs driver must be able to get away with supporting no attributes at all.
|
||||
|
||||
For some level of portability, littlefs has a simple scheme for attributes.
|
||||
Each attribute is prefixes with an 8-bit type that indicates what the attribute
|
||||
is. The length of attributes may also be determined from this type. Attributes
|
||||
in an entry should be sorted based on portability, since attribute parsing
|
||||
will end when it hits the first attribute it does not understand.
|
||||
|
||||
Each system should choose a 4-bit value to prefix all attribute types with to
|
||||
avoid conflicts with other systems. Additionally, littlefs drivers that support
|
||||
attributes should provide a "ignore attributes" flag to users in case attribute
|
||||
conflicts do occur.
|
||||
|
||||
Attribute types prefixes with 0x0 and 0xf are currently reserved for future
|
||||
standard attributes. Standard attributes will be added to this document in
|
||||
that case.
|
||||
|
||||
Here's an example of non-standard time attribute:
|
||||
```
|
||||
(8 bits) attribute type = time (0xc1)
|
||||
(72 bits) time in seconds = 1506286115 (0x0059c81a23)
|
||||
|
||||
00000000: c1 23 1a c8 59 00 .#..Y.
|
||||
```
|
||||
|
||||
Here's an example of non-standard permissions attribute:
|
||||
```
|
||||
(8 bits) attribute type = permissions (0xc2)
|
||||
(16 bits) permission bits = rw-rw-r-- (0x01b4)
|
||||
|
||||
00000000: c2 b4 01 ...
|
||||
```
|
||||
|
||||
Here's what a dir entry may look like with these attributes:
|
||||
```
|
||||
(8 bits) entry type = file (0x11)
|
||||
(8 bits) entry length = 8 bytes (0x08)
|
||||
(8 bits) attribute length = 9 bytes (0x09)
|
||||
(8 bits) name length = 12 bytes (0x0c)
|
||||
(8 bytes) entry data = 05 00 00 00 20 00 00 00
|
||||
(8 bits) attribute type = time (0xc1)
|
||||
(72 bits) time in seconds = 1506286115 (0x0059c81a23)
|
||||
(8 bits) attribute type = permissions (0xc2)
|
||||
(16 bits) permission bits = rw-rw-r-- (0x01b4)
|
||||
(12 bytes) entry name = smallavacado
|
||||
|
||||
00000000: 11 08 09 0c 05 00 00 00 20 00 00 00 c1 23 1a c8 ........ ....#..
|
||||
00000010: 59 00 c2 b4 01 73 6d 61 6c 6c 61 76 61 63 61 64 Y....smallavacad
|
||||
00000020: 6f o
|
||||
```
|
3464
fs/littlefs/lfs.c
3464
fs/littlefs/lfs.c
File diff suppressed because it is too large
Load Diff
@ -1,673 +0,0 @@
|
||||
/****************************************************************************
|
||||
* fs/littlefs/lfs.h
|
||||
*
|
||||
* This file is a part of NuttX:
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
*
|
||||
* Ported by:
|
||||
*
|
||||
* Copyright (C) 2019 Pinecone Inc. All rights reserved.
|
||||
* Author: lihaichen <li8303@163.com>
|
||||
*
|
||||
* This port derives from ARM mbed logic which has a compatible 3-clause
|
||||
* BSD license:
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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 names ARM, 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_LITTLEFS_LFS_H
|
||||
#define __FS_LITTLEFS_LFS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Version info */
|
||||
|
||||
/* Software library version
|
||||
* Major (top-nibble), incremented on backwards incompatible changes
|
||||
* Minor (bottom-nibble), incremented on feature additions
|
||||
*/
|
||||
|
||||
#define LFS_VERSION 0x00010007
|
||||
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
|
||||
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
|
||||
|
||||
/* Version of On-disk data structures
|
||||
* Major (top-nibble), incremented on backwards incompatible changes
|
||||
* Minor (bottom-nibble), incremented on feature additions
|
||||
*/
|
||||
|
||||
#define LFS_DISK_VERSION 0x00010001
|
||||
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
|
||||
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
|
||||
|
||||
/* Max name size in bytes */
|
||||
|
||||
#ifndef LFS_NAME_MAX
|
||||
# define LFS_NAME_MAX NAME_MAX
|
||||
#endif
|
||||
|
||||
/* Max file size in bytes */
|
||||
|
||||
#ifndef LFS_FILE_MAX
|
||||
# define LFS_FILE_MAX 2147483647
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef uint32_t lfs_size_t;
|
||||
typedef uint32_t lfs_off_t;
|
||||
|
||||
typedef int32_t lfs_ssize_t;
|
||||
typedef int32_t lfs_soff_t;
|
||||
|
||||
typedef uint32_t lfs_block_t;
|
||||
|
||||
/* Possible error codes, these are negative to allow
|
||||
* valid positive return values
|
||||
*/
|
||||
|
||||
enum lfs_error_e
|
||||
{
|
||||
LFS_ERR_OK = 0, /* No error */
|
||||
LFS_ERR_IO = -5, /* Error during device operation */
|
||||
LFS_ERR_CORRUPT = -52, /* Corrupted */
|
||||
LFS_ERR_NOENT = -2, /* No directory entry */
|
||||
LFS_ERR_EXIST = -17, /* Entry already exists */
|
||||
LFS_ERR_NOTDIR = -20, /* Entry is not a dir */
|
||||
LFS_ERR_ISDIR = -21, /* Entry is a dir */
|
||||
LFS_ERR_NOTEMPTY = -39, /* Dir is not empty */
|
||||
LFS_ERR_BADF = -9, /* Bad file number */
|
||||
LFS_ERR_FBIG = -27, /* File too large */
|
||||
LFS_ERR_INVAL = -22, /* Invalid parameter */
|
||||
LFS_ERR_NOSPC = -28, /* No space left on device */
|
||||
LFS_ERR_NOMEM = -12, /* No more memory available */
|
||||
};
|
||||
|
||||
/* File types */
|
||||
|
||||
enum lfs_type_e
|
||||
{
|
||||
LFS_TYPE_REG = 0x11,
|
||||
LFS_TYPE_DIR = 0x22,
|
||||
LFS_TYPE_SUPERBLOCK = 0x2e,
|
||||
};
|
||||
|
||||
/* File open flags */
|
||||
|
||||
enum lfs_open_flags_e
|
||||
{
|
||||
/* open flags */
|
||||
|
||||
LFS_O_RDONLY = 1, /* Open a file as read only */
|
||||
LFS_O_WRONLY = 2, /* Open a file as write only */
|
||||
LFS_O_RDWR = 3, /* Open a file as read and write */
|
||||
LFS_O_CREAT = 0x0100, /* Create a file if it does not exist */
|
||||
LFS_O_EXCL = 0x0200, /* Fail if a file already exists */
|
||||
LFS_O_TRUNC = 0x0400, /* Truncate the existing file to zero size */
|
||||
LFS_O_APPEND = 0x0800, /* Move to end of file on every write */
|
||||
|
||||
/* internally used flags */
|
||||
|
||||
LFS_F_DIRTY = 0x10000, /* File does not match storage */
|
||||
LFS_F_WRITING = 0x20000, /* File has been written since last flush */
|
||||
LFS_F_READING = 0x40000, /* File has been read since last flush */
|
||||
LFS_F_ERRED = 0x80000, /* An error occurred during write */
|
||||
};
|
||||
|
||||
/* File seek flags */
|
||||
|
||||
enum lfs_whence_flags_e
|
||||
{
|
||||
LFS_SEEK_SET = 0, /* Seek relative to an absolute position */
|
||||
LFS_SEEK_CUR = 1, /* Seek relative to the current file position */
|
||||
LFS_SEEK_END = 2, /* Seek relative to the end of the file */
|
||||
};
|
||||
|
||||
/* Configuration provided during initialization of the littlefs */
|
||||
|
||||
struct lfs_config_s
|
||||
{
|
||||
/* Opaque user provided context that can be used to pass
|
||||
* information to the block device operations
|
||||
*/
|
||||
|
||||
FAR void *context;
|
||||
|
||||
/* Read a region in a block. Negative error codes are propagated
|
||||
* to the user.
|
||||
*/
|
||||
|
||||
CODE int (*read)(FAR const struct lfs_config_s *c, lfs_block_t block,
|
||||
lfs_off_t off, FAR void *buffer, lfs_size_t size);
|
||||
|
||||
/* Program a region in a block. The block must have previously
|
||||
* been erased. Negative error codes are propagated to the user.
|
||||
* May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
*/
|
||||
|
||||
CODE int (*prog)(FAR const struct lfs_config_s *c, lfs_block_t block,
|
||||
lfs_off_t off, const void *buffer, lfs_size_t size);
|
||||
|
||||
/* Erase a block. A block must be erased before being programmed.
|
||||
* The state of an erased block is undefined. Negative error codes
|
||||
* are propagated to the user.
|
||||
* May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
*/
|
||||
|
||||
CODE int (*erase)(FAR const struct lfs_config_s *c, lfs_block_t block);
|
||||
|
||||
/* Sync the state of the underlying block device. Negative error codes
|
||||
* are propagated to the user.
|
||||
*/
|
||||
|
||||
CODE int (*sync)(FAR const struct lfs_config_s *c);
|
||||
|
||||
/* Minimum size of a block read. This determines the size of read buffers.
|
||||
* This may be larger than the physical read size to improve performance
|
||||
* by caching more of the block device.
|
||||
*/
|
||||
|
||||
lfs_size_t read_size;
|
||||
|
||||
/* Minimum size of a block program. This determines the size of program
|
||||
* buffers. This may be larger than the physical program size to improve
|
||||
* performance by caching more of the block device.
|
||||
* Must be a multiple of the read size.
|
||||
*/
|
||||
|
||||
lfs_size_t prog_size;
|
||||
|
||||
/* Size of an erasable block. This does not impact ram consumption and
|
||||
* may be larger than the physical erase size. However, this should be
|
||||
* kept small as each file currently takes up an entire block.
|
||||
* Must be a multiple of the program size.
|
||||
*/
|
||||
|
||||
lfs_size_t block_size;
|
||||
|
||||
/* Number of erasable blocks on the device. */
|
||||
|
||||
lfs_size_t block_count;
|
||||
|
||||
/* Number of blocks to lookahead during block allocation. A larger
|
||||
* lookahead reduces the number of passes required to allocate a block.
|
||||
* The lookahead buffer requires only 1 bit per block so it can be quite
|
||||
* large with little ram impact. Should be a multiple of 32.
|
||||
*/
|
||||
|
||||
lfs_size_t lookahead;
|
||||
|
||||
/* Optional, statically allocated read buffer. Must be read sized. */
|
||||
|
||||
FAR void *read_buffer;
|
||||
|
||||
/* Optional, statically allocated program buffer. Must be program sized. */
|
||||
|
||||
FAR void *prog_buffer;
|
||||
|
||||
/* Optional, statically allocated lookahead buffer. Must be 1 bit per
|
||||
* lookahead block.
|
||||
*/
|
||||
|
||||
FAR void *lookahead_buffer;
|
||||
|
||||
/* Optional, statically allocated buffer for files. Must be program sized.
|
||||
* If enabled, only one file may be opened at a time.
|
||||
*/
|
||||
|
||||
FAR void *file_buffer;
|
||||
};
|
||||
|
||||
/* Optional configuration provided during lfs_file_opencfg */
|
||||
|
||||
struct lfs_file_config_s
|
||||
{
|
||||
/* Optional, statically allocated buffer for files. Must be program sized.
|
||||
* If NULL, malloc will be used by default.
|
||||
*/
|
||||
|
||||
FAR void *buffer;
|
||||
};
|
||||
|
||||
/* File info structure */
|
||||
|
||||
struct lfs_info_s
|
||||
{
|
||||
/* Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR */
|
||||
|
||||
uint8_t type;
|
||||
|
||||
/* Size of the file, only valid for REG files */
|
||||
|
||||
lfs_size_t size;
|
||||
|
||||
/* Name of the file stored as a null-terminated string */
|
||||
|
||||
char name[LFS_NAME_MAX + 1];
|
||||
};
|
||||
|
||||
/* littlefs data structures */
|
||||
|
||||
typedef struct lfs_entry_s
|
||||
{
|
||||
lfs_off_t off;
|
||||
|
||||
struct lfs_disk_entry_s
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t elen;
|
||||
uint8_t alen;
|
||||
uint8_t nlen;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
lfs_block_t head;
|
||||
lfs_size_t size;
|
||||
} file;
|
||||
lfs_block_t dir[2];
|
||||
} u;
|
||||
} d;
|
||||
} lfs_entry_t;
|
||||
|
||||
typedef struct lfs_cache_s
|
||||
{
|
||||
lfs_block_t block;
|
||||
lfs_off_t off;
|
||||
FAR uint8_t *buffer;
|
||||
} lfs_cache_t;
|
||||
|
||||
typedef struct lfs_file_s
|
||||
{
|
||||
FAR struct lfs_file_s *next;
|
||||
lfs_block_t pair[2];
|
||||
lfs_off_t poff;
|
||||
|
||||
lfs_block_t head;
|
||||
lfs_size_t size;
|
||||
|
||||
FAR const struct lfs_file_config_s *cfg;
|
||||
uint32_t flags;
|
||||
lfs_off_t pos;
|
||||
lfs_block_t block;
|
||||
lfs_off_t off;
|
||||
lfs_cache_t cache;
|
||||
} lfs_file_t;
|
||||
|
||||
typedef struct lfs_dir_s
|
||||
{
|
||||
FAR struct lfs_dir_s *next;
|
||||
lfs_block_t pair[2];
|
||||
lfs_off_t off;
|
||||
|
||||
lfs_block_t head[2];
|
||||
lfs_off_t pos;
|
||||
|
||||
struct lfs_disk_dir_s
|
||||
{
|
||||
uint32_t rev;
|
||||
lfs_size_t size;
|
||||
lfs_block_t tail[2];
|
||||
} d;
|
||||
} lfs_dir_t;
|
||||
|
||||
typedef struct lfs_superblock_s
|
||||
{
|
||||
lfs_off_t off;
|
||||
|
||||
struct lfs_disk_superblock_s
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t elen;
|
||||
uint8_t alen;
|
||||
uint8_t nlen;
|
||||
lfs_block_t root[2];
|
||||
uint32_t block_size;
|
||||
uint32_t block_count;
|
||||
uint32_t version;
|
||||
char magic[8];
|
||||
} d;
|
||||
} lfs_superblock_t;
|
||||
|
||||
typedef struct lfs_free_s
|
||||
{
|
||||
lfs_block_t off;
|
||||
lfs_block_t size;
|
||||
lfs_block_t i;
|
||||
lfs_block_t ack;
|
||||
FAR uint32_t *buffer;
|
||||
} lfs_free_t;
|
||||
|
||||
/* The littlefs type */
|
||||
|
||||
typedef struct lfs_s
|
||||
{
|
||||
FAR const struct lfs_config_s *cfg;
|
||||
|
||||
lfs_block_t root[2];
|
||||
FAR lfs_file_t *files;
|
||||
lfs_dir_t *dirs;
|
||||
|
||||
lfs_cache_t rcache;
|
||||
lfs_cache_t pcache;
|
||||
|
||||
lfs_free_t free;
|
||||
bool deorphaned;
|
||||
bool moving;
|
||||
} lfs_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Filesystem functions */
|
||||
|
||||
/* Format a block device with the littlefs
|
||||
*
|
||||
* Requires a littlefs object and config struct. This clobbers the littlefs
|
||||
* object, and does not leave the filesystem mounted. The config struct must
|
||||
* be zeroed for defaults and backwards compatibility.
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_format(FAR lfs_t *lfs, FAR const struct lfs_config_s *config);
|
||||
|
||||
/* Mounts a littlefs
|
||||
*
|
||||
* Requires a littlefs object and config struct. Multiple filesystems
|
||||
* may be mounted simultaneously with multiple littlefs objects. Both
|
||||
* lfs and config must be allocated while mounted. The config struct must
|
||||
* be zeroed for defaults and backwards compatibility.
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_mount(FAR lfs_t *lfs, FAR const struct lfs_config_s *config);
|
||||
|
||||
/* Unmounts a littlefs
|
||||
*
|
||||
* Does nothing besides releasing any allocated resources.
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_unmount(FAR lfs_t *lfs);
|
||||
|
||||
/* General operations */
|
||||
|
||||
/* Removes a file or directory
|
||||
*
|
||||
* If removing a directory, the directory must be empty.
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_remove(FAR lfs_t *lfs, FAR const char *path);
|
||||
|
||||
/* Rename or move a file or directory
|
||||
*
|
||||
* If the destination exists, it must match the source in type.
|
||||
* If the destination is a directory, the directory must be empty.
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_rename(FAR lfs_t *lfs, FAR const char *oldpath, FAR
|
||||
const char *newpath);
|
||||
|
||||
/* Find info about a file or directory
|
||||
*
|
||||
* Fills out the info structure, based on the specified file or directory.
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_stat(FAR lfs_t *lfs, FAR const char *path,
|
||||
FAR struct lfs_info_s *info);
|
||||
|
||||
/* File operations */
|
||||
|
||||
/* Open a file
|
||||
*
|
||||
* The mode that the file is opened in is determined by the flags, which
|
||||
* are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_file_open(FAR lfs_t *lfs, FAR lfs_file_t *file,
|
||||
FAR const char *path, int flags);
|
||||
|
||||
/* Open a file with extra configuration
|
||||
*
|
||||
* The mode that the file is opened in is determined by the flags, which
|
||||
* are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||
*
|
||||
* The config struct provides additional config options per file as described
|
||||
* above. The config struct must be allocated while the file is open, and the
|
||||
* config struct must be zeroed for defaults and backwards compatibility.
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_file_opencfg(FAR lfs_t *lfs, FAR lfs_file_t *file,
|
||||
FAR const char *path, int flags,
|
||||
FAR const struct lfs_file_config_s *config);
|
||||
|
||||
/* Close a file
|
||||
*
|
||||
* Any pending writes are written out to storage as though
|
||||
* sync had been called and releases any allocated resources.
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_file_close(FAR lfs_t *lfs, FAR lfs_file_t *file);
|
||||
|
||||
/* Synchronize a file on storage
|
||||
*
|
||||
* Any pending writes are written out to storage.
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_file_sync(FAR lfs_t *lfs, FAR lfs_file_t *file);
|
||||
|
||||
/* Read data from file
|
||||
*
|
||||
* Takes a buffer and size indicating where to store the read data.
|
||||
* Returns the number of bytes read, or a negative error code on failure.
|
||||
*/
|
||||
|
||||
lfs_ssize_t lfs_file_read(FAR lfs_t *lfs, FAR lfs_file_t *file,
|
||||
FAR void *buffer, lfs_size_t size);
|
||||
|
||||
/* Write data to file
|
||||
*
|
||||
* Takes a buffer and size indicating the data to write. The file will not
|
||||
* actually be updated on the storage until either sync or close is called.
|
||||
*
|
||||
* Returns the number of bytes written, or a negative error code on failure.
|
||||
*/
|
||||
|
||||
lfs_ssize_t lfs_file_write(FAR lfs_t *lfs, FAR lfs_file_t *file,
|
||||
FAR const void *buffer, lfs_size_t size);
|
||||
|
||||
/* Change the position of the file
|
||||
*
|
||||
* The change in position is determined by the offset and whence flag.
|
||||
* Returns the old position of the file, or a negative error code on failure.
|
||||
*/
|
||||
|
||||
lfs_soff_t lfs_file_seek(FAR lfs_t *lfs, FAR lfs_file_t *file,
|
||||
lfs_soff_t off, int whence);
|
||||
|
||||
/* Truncates the size of the file to the specified size
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_file_truncate(FAR lfs_t *lfs, FAR lfs_file_t *file,
|
||||
lfs_off_t size);
|
||||
|
||||
/* Return the position of the file
|
||||
*
|
||||
* Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
|
||||
* Returns the position of the file, or a negative error code on failure.
|
||||
*/
|
||||
|
||||
lfs_soff_t lfs_file_tell(FAR lfs_t *lfs, FAR lfs_file_t *file);
|
||||
|
||||
/* Change the position of the file to the beginning of the file
|
||||
*
|
||||
* Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_file_rewind(FAR lfs_t *lfs, FAR lfs_file_t *file);
|
||||
|
||||
/* Return the size of the file
|
||||
*
|
||||
* Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
|
||||
* Returns the size of the file, or a negative error code on failure.
|
||||
*/
|
||||
|
||||
lfs_soff_t lfs_file_size(FAR lfs_t *lfs, FAR lfs_file_t *file);
|
||||
|
||||
/* Directory operations */
|
||||
|
||||
/* Create a directory
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_mkdir(FAR lfs_t *lfs, FAR const char *path);
|
||||
|
||||
/* Open a directory
|
||||
*
|
||||
* Once open a directory can be used with read to iterate over files.
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_dir_open(FAR lfs_t *lfs, FAR lfs_dir_t *dir, FAR const char *path);
|
||||
|
||||
/* Close a directory
|
||||
*
|
||||
* Releases any allocated resources.
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_dir_close(FAR lfs_t *lfs, FAR lfs_dir_t *dir);
|
||||
|
||||
/* Read an entry in the directory
|
||||
*
|
||||
* Fills out the info structure, based on the specified file or directory.
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_dir_read(FAR lfs_t *lfs, FAR lfs_dir_t *dir,
|
||||
FAR struct lfs_info_s *info);
|
||||
|
||||
/* Change the position of the directory
|
||||
*
|
||||
* The new off must be a value previous returned from tell and specifies
|
||||
* an absolute offset in the directory seek.
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_dir_seek(FAR lfs_t *lfs, FAR lfs_dir_t *dir, lfs_off_t off);
|
||||
|
||||
/* Return the position of the directory
|
||||
*
|
||||
* The returned offset is only meant to be consumed by seek and may not make
|
||||
* sense, but does indicate the current position in the directory iteration.
|
||||
*
|
||||
* Returns the position of the directory, or a negative error code on failure
|
||||
*/
|
||||
|
||||
lfs_soff_t lfs_dir_tell(FAR lfs_t *lfs, FAR lfs_dir_t *dir);
|
||||
|
||||
/* Change the position of the directory to the beginning of the directory
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_dir_rewind(FAR lfs_t *lfs, FAR lfs_dir_t *dir);
|
||||
|
||||
/* Miscellaneous littlefs specific operations */
|
||||
|
||||
/* Traverse through all blocks in use by the filesystem
|
||||
*
|
||||
* The provided callback will be called with each block address that is
|
||||
* currently in use by the filesystem. This can be used to determine which
|
||||
* blocks are in use or how much of the storage is available.
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_traverse(FAR lfs_t *lfs, CODE int (*cb)(FAR void *, lfs_block_t),
|
||||
FAR void *data);
|
||||
|
||||
/* Prunes any recoverable errors that may have occurred in the filesystem
|
||||
*
|
||||
* Not needed to be called by user unless an operation is interrupted
|
||||
* but the filesystem is still mounted. This is already called on first
|
||||
* allocation.
|
||||
*
|
||||
* Returns a negative error code on failure.
|
||||
*/
|
||||
|
||||
int lfs_deorphan(FAR lfs_t *lfs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FS_LITTLEFS_LFS_H */
|
@ -1,83 +0,0 @@
|
||||
/****************************************************************************
|
||||
* fs/littlefs/lfs_util.c
|
||||
*
|
||||
* This file is a part of NuttX:
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
*
|
||||
* Ported by:
|
||||
*
|
||||
* Copyright (C) 2019 Pinecone Inc. All rights reserved.
|
||||
* Author: lihaichen <li8303@163.com>
|
||||
*
|
||||
* This port derives from ARM mbed logic which has a compatible 3-clause
|
||||
* BSD license:
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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 names ARM, 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "lfs.h"
|
||||
#include "lfs_util.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Only compile if user does not provide custom config */
|
||||
|
||||
#ifndef LFS_CONFIG
|
||||
|
||||
/* Software CRC implementation with small lookup table */
|
||||
|
||||
void lfs_crc(FAR uint32_t *crc, FAR const void *buffer, size_t size)
|
||||
{
|
||||
static const uint32_t rtable[16] =
|
||||
{
|
||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4,
|
||||
0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
||||
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
|
||||
};
|
||||
|
||||
FAR const uint8_t *data = buffer;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf];
|
||||
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,275 +0,0 @@
|
||||
/****************************************************************************
|
||||
* fs/littlefs/lfs_util.h
|
||||
*
|
||||
* This file is a part of NuttX:
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
*
|
||||
* Ported by:
|
||||
*
|
||||
* Copyright (C) 2019 Pinecone Inc. All rights reserved.
|
||||
* Author: lihaichen <li8303@163.com>
|
||||
*
|
||||
* This port derives from ARM mbed logic which has a compatible 3-clause
|
||||
* BSD license:
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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 names ARM, 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_LITTLEFS_LFS_UTIL_H
|
||||
#define __FS_LITTLEFS_LFS_UTIL_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
/* Users can override lfs_util.h with their own configuration by defining
|
||||
* LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
|
||||
*
|
||||
* If LFS_CONFIG is used, none of the default utils will be emitted and must be
|
||||
* provided by the config file. To start I would suggest copying lfs_util.h and
|
||||
* modifying as needed.
|
||||
*/
|
||||
|
||||
#ifdef LFS_CONFIG
|
||||
# define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
|
||||
# define LFS_STRINGIZE2(x) #x
|
||||
# include LFS_STRINGIZE(LFS_CONFIG)
|
||||
#else
|
||||
|
||||
/* System includes */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef LFS_NO_MALLOC
|
||||
# include <nuttx/kmalloc.h>
|
||||
#endif
|
||||
#ifndef LFS_NO_ASSERT
|
||||
# include <assert.h>
|
||||
#endif
|
||||
#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR)
|
||||
# include <debug.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Macros, may be replaced by system specific wrappers. Arguments to these
|
||||
* macros must not have side-effects as the macros can be removed for a smaller
|
||||
* code footprint
|
||||
*/
|
||||
|
||||
/* Logging functions */
|
||||
|
||||
#ifndef LFS_NO_DEBUG
|
||||
# define LFS_DEBUG(fmt, ...) \
|
||||
finfo("lfs debug:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
# define LFS_DEBUG(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifndef LFS_NO_WARN
|
||||
# define LFS_WARN(fmt, ...) \
|
||||
fwarn("lfs warn:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
# define LFS_WARN(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifndef LFS_NO_ERROR
|
||||
# define LFS_ERROR(fmt, ...) \
|
||||
ferr("lfs error:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
# define LFS_ERROR(fmt, ...)
|
||||
#endif
|
||||
|
||||
/* Runtime assertions */
|
||||
|
||||
#ifndef LFS_NO_ASSERT
|
||||
# define LFS_ASSERT(test) DEBUGASSERT(test)
|
||||
#else
|
||||
# define LFS_ASSERT(test)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Builtin functions, these may be replaced by more efficient
|
||||
* toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
|
||||
* expensive basic C implementation for debugging purposes
|
||||
*/
|
||||
|
||||
/* Min/max functions for unsigned 32-bit numbers */
|
||||
|
||||
static inline uint32_t lfs_max(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_min(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
/* Find the next smallest power of 2 less than or equal to a */
|
||||
|
||||
static inline uint32_t lfs_npw2(uint32_t a)
|
||||
{
|
||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||
return 32 - __builtin_clz(a - 1);
|
||||
#else
|
||||
uint32_t r = 0;
|
||||
uint32_t s;
|
||||
a -= 1;
|
||||
s = (a > 0xffff) << 4;
|
||||
a >>= s;
|
||||
r |= s;
|
||||
s = (a > 0xff) << 3;
|
||||
a >>= s;
|
||||
r |= s;
|
||||
s = (a > 0xf) << 2;
|
||||
a >>= s;
|
||||
r |= s;
|
||||
s = (a > 0x3) << 1;
|
||||
a >>= s;
|
||||
r |= s;
|
||||
return (r | (a >> 1)) + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Count the number of trailing binary zeros in a
|
||||
* lfs_ctz(0) may be undefined
|
||||
*/
|
||||
|
||||
static inline uint32_t lfs_ctz(uint32_t a)
|
||||
{
|
||||
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
|
||||
return __builtin_ctz(a);
|
||||
#else
|
||||
return lfs_npw2((a & -a) + 1) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Count the number of binary ones in a */
|
||||
|
||||
static inline uint32_t lfs_popc(uint32_t a)
|
||||
{
|
||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||
return __builtin_popcount(a);
|
||||
#else
|
||||
a = a - ((a >> 1) & 0x55555555);
|
||||
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
|
||||
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Find the sequence comparison of a and b, this is the distance
|
||||
* between a and b ignoring overflow
|
||||
*/
|
||||
|
||||
static inline int lfs_scmp(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (int)(unsigned)(a - b);
|
||||
}
|
||||
|
||||
/* Convert from 32-bit little-endian to native order */
|
||||
|
||||
static inline uint32_t lfs_fromle32(uint32_t a)
|
||||
{
|
||||
#if !defined(CONFIG_ENDIAN_BIG)
|
||||
return a;
|
||||
#elif !defined(LFS_NO_INTRINSICS)
|
||||
return __builtin_bswap32(a);
|
||||
#else
|
||||
return (((uint8_t *)&a)[0] << 0) | (((uint8_t *)&a)[1] << 8) |
|
||||
(((uint8_t *)&a)[2] << 16) | (((uint8_t *)&a)[3] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert to 32-bit little-endian from native order */
|
||||
|
||||
static inline uint32_t lfs_tole32(uint32_t a)
|
||||
{
|
||||
return lfs_fromle32(a);
|
||||
}
|
||||
|
||||
/* Allocate memory, only used if buffers are not provided to littlefs */
|
||||
|
||||
static inline void *lfs_malloc(size_t size)
|
||||
{
|
||||
#ifndef LFS_NO_MALLOC
|
||||
return kmm_malloc(size);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Deallocate memory, only used if buffers are not provided to littlefs */
|
||||
|
||||
static inline void lfs_free(FAR void *p)
|
||||
{
|
||||
#ifndef LFS_NO_MALLOC
|
||||
kmm_free(p);
|
||||
#else
|
||||
(void)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Calculate CRC-32 with polynomial = 0x04c11db7 */
|
||||
|
||||
void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* __FS_LITTLEFS_LFS_UTIL_H */
|
@ -1,46 +1,20 @@
|
||||
/****************************************************************************
|
||||
* fs/littlefs/lfs_vfs.c
|
||||
*
|
||||
* This file is a part of NuttX:
|
||||
* 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
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Ported by:
|
||||
*
|
||||
* Copyright (C) 2019 Pinecone Inc. All rights reserved.
|
||||
* Author: lihaichen <li8303@163.com>
|
||||
*
|
||||
* This port derives from ARM mbed logic which has a compatible 3-clause
|
||||
* BSD license:
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
*
|
||||
* 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 names ARM, 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.
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -56,14 +30,15 @@
|
||||
|
||||
#include <nuttx/fs/dirent.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#include "lfs.h"
|
||||
#include "lfs_util.h"
|
||||
#include "littlefs/lfs.h"
|
||||
#include "littlefs/lfs_util.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
@ -79,7 +54,7 @@ struct littlefs_mountpt_s
|
||||
sem_t sem;
|
||||
FAR struct inode *drv;
|
||||
struct mtd_geometry_s geo;
|
||||
struct lfs_config_s cfg;
|
||||
struct lfs_config cfg;
|
||||
lfs_t lfs;
|
||||
};
|
||||
|
||||
@ -249,7 +224,7 @@ static int littlefs_open(FAR struct file *filep, FAR const char *relpath,
|
||||
int oflags, mode_t mode)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_file_s *priv;
|
||||
FAR struct lfs_file *priv;
|
||||
FAR struct inode *inode;
|
||||
int ret;
|
||||
|
||||
@ -327,7 +302,7 @@ errsem:
|
||||
static int littlefs_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_file_s *priv;
|
||||
FAR struct lfs_file *priv;
|
||||
FAR struct inode *inode;
|
||||
int ret;
|
||||
|
||||
@ -363,7 +338,7 @@ static ssize_t littlefs_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_file_s *priv;
|
||||
FAR struct lfs_file *priv;
|
||||
FAR struct inode *inode;
|
||||
ssize_t ret;
|
||||
int semret;
|
||||
@ -401,7 +376,7 @@ static ssize_t littlefs_write(FAR struct file *filep, const char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_file_s *priv;
|
||||
FAR struct lfs_file *priv;
|
||||
FAR struct inode *inode;
|
||||
ssize_t ret;
|
||||
int semret;
|
||||
@ -438,7 +413,7 @@ static ssize_t littlefs_write(FAR struct file *filep, const char *buffer,
|
||||
static off_t littlefs_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_file_s *priv;
|
||||
FAR struct lfs_file *priv;
|
||||
FAR struct inode *inode;
|
||||
off_t ret;
|
||||
int semret;
|
||||
@ -505,7 +480,7 @@ static int littlefs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
static int littlefs_sync(FAR struct file *filep)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_file_s *priv;
|
||||
FAR struct lfs_file *priv;
|
||||
FAR struct inode *inode;
|
||||
int ret;
|
||||
|
||||
@ -551,7 +526,7 @@ static int littlefs_dup(FAR const struct file *oldp, FAR struct file *newp)
|
||||
static int littlefs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_file_s *priv;
|
||||
FAR struct lfs_file *priv;
|
||||
FAR struct inode *inode;
|
||||
int ret;
|
||||
|
||||
@ -598,7 +573,7 @@ static int littlefs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
||||
static int littlefs_truncate(FAR struct file *filep, off_t length)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_file_s *priv;
|
||||
FAR struct lfs_file *priv;
|
||||
FAR struct inode *inode;
|
||||
int ret;
|
||||
|
||||
@ -634,7 +609,7 @@ static int littlefs_opendir(FAR struct inode *mountpt,
|
||||
FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_dir_s *priv;
|
||||
FAR struct lfs_dir *priv;
|
||||
int ret;
|
||||
|
||||
/* Recover our private data from the inode instance */
|
||||
@ -689,7 +664,7 @@ static int littlefs_closedir(FAR struct inode *mountpt,
|
||||
FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_dir_s *priv;
|
||||
FAR struct lfs_dir *priv;
|
||||
int ret;
|
||||
|
||||
/* Recover our private data from the inode instance */
|
||||
@ -724,8 +699,8 @@ static int littlefs_readdir(FAR struct inode *mountpt,
|
||||
FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_dir_s *priv;
|
||||
struct lfs_info_s info;
|
||||
FAR struct lfs_dir *priv;
|
||||
struct lfs_info info;
|
||||
int ret;
|
||||
|
||||
/* Recover our private data from the inode instance */
|
||||
@ -777,7 +752,7 @@ static int littlefs_rewinddir(FAR struct inode *mountpt,
|
||||
FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
struct littlefs_mountpt_s *fs;
|
||||
FAR struct lfs_dir_s *priv;
|
||||
FAR struct lfs_dir *priv;
|
||||
int ret;
|
||||
|
||||
/* Recover our private data from the inode instance */
|
||||
@ -815,7 +790,7 @@ static int littlefs_rewinddir(FAR struct inode *mountpt,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int littlefs_read_block(FAR const struct lfs_config_s *c,
|
||||
static int littlefs_read_block(FAR const struct lfs_config *c,
|
||||
lfs_block_t block, lfs_off_t off,
|
||||
FAR void *buffer, lfs_size_t size)
|
||||
{
|
||||
@ -843,7 +818,7 @@ static int littlefs_read_block(FAR const struct lfs_config_s *c,
|
||||
* Name: littlefs_write_block
|
||||
****************************************************************************/
|
||||
|
||||
static int littlefs_write_block(FAR const struct lfs_config_s *c,
|
||||
static int littlefs_write_block(FAR const struct lfs_config *c,
|
||||
lfs_block_t block, lfs_off_t off,
|
||||
FAR const void *buffer, lfs_size_t size)
|
||||
{
|
||||
@ -871,7 +846,7 @@ static int littlefs_write_block(FAR const struct lfs_config_s *c,
|
||||
* Name: littlefs_erase_block
|
||||
****************************************************************************/
|
||||
|
||||
static int littlefs_erase_block(FAR const struct lfs_config_s *c,
|
||||
static int littlefs_erase_block(FAR const struct lfs_config *c,
|
||||
lfs_block_t block)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs = c->context;
|
||||
@ -894,7 +869,7 @@ static int littlefs_erase_block(FAR const struct lfs_config_s *c,
|
||||
* Name: littlefs_sync_block
|
||||
****************************************************************************/
|
||||
|
||||
static int littlefs_sync_block(FAR const struct lfs_config_s *c)
|
||||
static int littlefs_sync_block(FAR const struct lfs_config *c)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs = c->context;
|
||||
FAR struct inode *drv = fs->drv;
|
||||
@ -988,21 +963,19 @@ static int littlefs_bind(FAR struct inode *driver, FAR const void *data,
|
||||
|
||||
/* Initialize lfs_config structure */
|
||||
|
||||
fs->cfg.context = fs;
|
||||
fs->cfg.read = littlefs_read_block;
|
||||
fs->cfg.prog = littlefs_write_block;
|
||||
fs->cfg.erase = littlefs_erase_block;
|
||||
fs->cfg.sync = littlefs_sync_block;
|
||||
fs->cfg.read_size = fs->geo.blocksize;
|
||||
fs->cfg.prog_size = fs->geo.blocksize;
|
||||
fs->cfg.block_size = fs->geo.erasesize;
|
||||
fs->cfg.block_count = fs->geo.neraseblocks;
|
||||
fs->cfg.lookahead = 32 * ((fs->cfg.block_count + 31) / 32);
|
||||
|
||||
if (fs->cfg.lookahead > 32 * fs->cfg.read_size)
|
||||
{
|
||||
fs->cfg.lookahead = 32 * fs->cfg.read_size;
|
||||
}
|
||||
fs->cfg.context = fs;
|
||||
fs->cfg.read = littlefs_read_block;
|
||||
fs->cfg.prog = littlefs_write_block;
|
||||
fs->cfg.erase = littlefs_erase_block;
|
||||
fs->cfg.sync = littlefs_sync_block;
|
||||
fs->cfg.read_size = fs->geo.blocksize;
|
||||
fs->cfg.prog_size = fs->geo.blocksize;
|
||||
fs->cfg.block_size = fs->geo.erasesize;
|
||||
fs->cfg.block_count = fs->geo.neraseblocks;
|
||||
fs->cfg.block_cycles = 500;
|
||||
fs->cfg.cache_size = fs->geo.blocksize;
|
||||
fs->cfg.lookahead_size = lfs_min(lfs_alignup(fs->cfg.block_count / 8, 8),
|
||||
fs->cfg.read_size);
|
||||
|
||||
/* Then get information about the littlefs filesystem on the devices
|
||||
* managed by this driver.
|
||||
@ -1116,20 +1089,6 @@ static int littlefs_unbind(FAR void *handle, FAR struct inode **driver,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: littlefs_used_block
|
||||
****************************************************************************/
|
||||
|
||||
static int littlefs_used_block(void *arg, lfs_block_t block)
|
||||
{
|
||||
FAR struct statfs *buf = arg;
|
||||
|
||||
buf->f_bfree--;
|
||||
buf->f_bavail--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: littlefs_statfs
|
||||
*
|
||||
@ -1162,7 +1121,15 @@ static int littlefs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = lfs_traverse(&fs->lfs, littlefs_used_block, buf);
|
||||
ret = lfs_fs_size(&fs->lfs);
|
||||
if (ret > 0)
|
||||
{
|
||||
buf->f_bfree -= ret;
|
||||
buf->f_bavail -= ret;
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
littlefs_semgive(fs);
|
||||
|
||||
return ret;
|
||||
@ -1285,7 +1252,7 @@ static int littlefs_stat(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR struct stat *buf)
|
||||
{
|
||||
FAR struct littlefs_mountpt_s *fs;
|
||||
struct lfs_info_s info;
|
||||
struct lfs_info info;
|
||||
int ret;
|
||||
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
|
@ -74,7 +74,7 @@ endif
|
||||
|
||||
KERNDEPDIRS += sched drivers boards $(ARCH_SRC)
|
||||
KERNDEPDIRS += fs binfmt
|
||||
CONTEXTDIRS = boards $(APPDIR)
|
||||
CONTEXTDIRS = boards fs $(APPDIR)
|
||||
CLEANDIRS += pass1
|
||||
|
||||
ifeq ($(CONFIG_BUILD_FLAT),y)
|
||||
|
Loading…
Reference in New Issue
Block a user