mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
Fix for RUTX platform
This commit is contained in:
parent
ccdb64ad45
commit
59bc57d5d5
7254 changed files with 1810270 additions and 7 deletions
201
root/package/utils/sysupgrade-helper/src/fs/yaffs2/README-linux
Normal file
201
root/package/utils/sysupgrade-helper/src/fs/yaffs2/README-linux
Normal file
|
@ -0,0 +1,201 @@
|
|||
Welcome to YAFFS, the first file system developed specifically for NAND flash.
|
||||
|
||||
It is now YAFFS2 - original YAFFS (AYFFS1) only supports 512-byte page
|
||||
NAND and is now deprectated. YAFFS2 supports 512b page in 'YAFFS1
|
||||
compatibility' mode (CONFIG_YAFFS_YAFFS1) and 2K or larger page NAND
|
||||
in YAFFS2 mode (CONFIG_YAFFS_YAFFS2).
|
||||
|
||||
|
||||
A note on licencing
|
||||
-------------------
|
||||
YAFFS is available under the GPL and via alternative licensing
|
||||
arrangements with Aleph One. If you're using YAFFS as a Linux kernel
|
||||
file system then it will be under the GPL. For use in other situations
|
||||
you should discuss licensing issues with Aleph One.
|
||||
|
||||
|
||||
Terminology
|
||||
-----------
|
||||
Page - NAND addressable unit (normally 512b or 2Kbyte size) - can
|
||||
be read, written, marked bad. Has associated OOB.
|
||||
Block - Eraseable unit. 64 Pages. (128K on 2K NAND, 32K on 512b NAND)
|
||||
OOB - 'spare area' of each page for ECC, bad block marked and YAFFS
|
||||
tags. 16 bytes per 512b - 64 bytes for 2K page size.
|
||||
Chunk - Basic YAFFS addressable unit. Same size as Page.
|
||||
Object - YAFFS Object: File, Directory, Link, Device etc.
|
||||
|
||||
YAFFS design
|
||||
------------
|
||||
|
||||
YAFFS is a log-structured filesystem. It is designed particularly for
|
||||
NAND (as opposed to NOR) flash, to be flash-friendly, robust due to
|
||||
journalling, and to have low RAM and boot time overheads. File data is
|
||||
stored in 'chunks'. Chunks are the same size as NAND pages. Each page
|
||||
is marked with file id and chunk number. These marking 'tags' are
|
||||
stored in the OOB (or 'spare') region of the flash. The chunk number
|
||||
is determined by dividing the file position by the chunk size. Each
|
||||
chunk has a number of valid bytes, which equals the page size for all
|
||||
except the last chunk in a file.
|
||||
|
||||
File 'headers' are stored as the first page in a file, marked as a
|
||||
different type to data pages. The same mechanism is used to store
|
||||
directories, device files, links etc. The first page describes which
|
||||
type of object it is.
|
||||
|
||||
YAFFS2 never re-writes a page, because the spec of NAND chips does not
|
||||
allow it. (YAFFS1 used to mark a block 'deleted' in the OOB). Deletion
|
||||
is managed by moving deleted objects to the special, hidden 'unlinked'
|
||||
directory. These records are preserved until all the pages containing
|
||||
the object have been erased (We know when this happen by keeping a
|
||||
count of chunks remaining on the system for each object - when it
|
||||
reaches zero the object really is gone).
|
||||
|
||||
When data in a file is overwritten, the relevant chunks are replaced
|
||||
by writing new pages to flash containing the new data but the same
|
||||
tags.
|
||||
|
||||
Pages are also marked with a short (2 bit) serial number that
|
||||
increments each time the page at this position is incremented. The
|
||||
reason for this is that if power loss/crash/other act of demonic
|
||||
forces happens before the replaced page is marked as discarded, it is
|
||||
possible to have two pages with the same tags. The serial number is
|
||||
used to arbitrate.
|
||||
|
||||
A block containing only discarded pages (termed a dirty block) is an
|
||||
obvious candidate for garbage collection. Otherwise valid pages can be
|
||||
copied off a block thus rendering the whole block discarded and ready
|
||||
for garbage collection.
|
||||
|
||||
In theory you don't need to hold the file structure in RAM... you
|
||||
could just scan the whole flash looking for pages when you need them.
|
||||
In practice though you'd want better file access times than that! The
|
||||
mechanism proposed here is to have a list of __u16 page addresses
|
||||
associated with each file. Since there are 2^18 pages in a 128MB NAND,
|
||||
a __u16 is insufficient to uniquely identify a page but is does
|
||||
identify a group of 4 pages - a small enough region to search
|
||||
exhaustively. This mechanism is clearly expandable to larger NAND
|
||||
devices - within reason. The RAM overhead with this approach is approx
|
||||
2 bytes per page - 512kB of RAM for a whole 128MB NAND.
|
||||
|
||||
Boot-time scanning to build the file structure lists only requires
|
||||
one pass reading NAND. If proper shutdowns happen the current RAM
|
||||
summary of the filesystem status is saved to flash, called
|
||||
'checkpointing'. This saves re-scanning the flash on startup, and gives
|
||||
huge boot/mount time savings.
|
||||
|
||||
YAFFS regenerates its state by 'replaying the tape' - i.e. by
|
||||
scanning the chunks in their allocation order (i.e. block sequence ID
|
||||
order), which is usually different form the media block order. Each
|
||||
block is still only read once - starting from the end of the media and
|
||||
working back.
|
||||
|
||||
YAFFS tags in YAFFS1 mode:
|
||||
|
||||
18-bit Object ID (2^18 files, i.e. > 260,000 files). File id 0- is not
|
||||
valid and indicates a deleted page. File od 0x3ffff is also not valid.
|
||||
Synonymous with inode.
|
||||
2-bit serial number
|
||||
20-bit Chunk ID within file. Limit of 2^20 chunks/pages per file (i.e.
|
||||
> 500MB max file size). Chunk ID 0 is the file header for the file.
|
||||
10-bit counter of the number of bytes used in the page.
|
||||
12 bit ECC on tags
|
||||
|
||||
YAFFS tags in YAFFS2 mode:
|
||||
4 bytes 32-bit chunk ID
|
||||
4 bytes 32-bit object ID
|
||||
2 bytes Number of data bytes in this chunk
|
||||
4 bytes Sequence number for this block
|
||||
3 bytes ECC on tags
|
||||
12 bytes ECC on data (3 bytes per 256 bytes of data)
|
||||
|
||||
|
||||
Page allocation and garbage collection
|
||||
|
||||
Pages are allocated sequentially from the currently selected block.
|
||||
When all the pages in the block are filled, another clean block is
|
||||
selected for allocation. At least two or three clean blocks are
|
||||
reserved for garbage collection purposes. If there are insufficient
|
||||
clean blocks available, then a dirty block ( ie one containing only
|
||||
discarded pages) is erased to free it up as a clean block. If no dirty
|
||||
blocks are available, then the dirtiest block is selected for garbage
|
||||
collection.
|
||||
|
||||
Garbage collection is performed by copying the valid data pages into
|
||||
new data pages thus rendering all the pages in this block dirty and
|
||||
freeing it up for erasure. I also like the idea of selecting a block
|
||||
at random some small percentage of the time - thus reducing the chance
|
||||
of wear differences.
|
||||
|
||||
YAFFS is single-threaded. Garbage-collection is done as a parasitic
|
||||
task of writing data. So each time some data is written, a bit of
|
||||
pending garbage collection is done. More pages are garbage-collected
|
||||
when free space is tight.
|
||||
|
||||
|
||||
Flash writing
|
||||
|
||||
YAFFS only ever writes each page once, complying with the requirements
|
||||
of the most restricitve NAND devices.
|
||||
|
||||
Wear levelling
|
||||
|
||||
This comes as a side-effect of the block-allocation strategy. Data is
|
||||
always written on the next free block, so they are all used equally.
|
||||
Blocks containing data that is written but never erased will not get
|
||||
back into the free list, so wear is levelled over only blocks which
|
||||
are free or become free, not blocks which never change.
|
||||
|
||||
|
||||
|
||||
Some helpful info
|
||||
-----------------
|
||||
|
||||
Formatting a YAFFS device is simply done by erasing it.
|
||||
|
||||
Making an initial filesystem can be tricky because YAFFS uses the OOB
|
||||
and thus the bytes that get written depend on the YAFFS data (tags),
|
||||
and the ECC bytes and bad block markers which are dictated by the
|
||||
hardware and/or the MTD subsystem. The data layout also depends on the
|
||||
device page size (512b or 2K). Because YAFFS is only responsible for
|
||||
some of the OOB data, generating a filesystem offline requires
|
||||
detailed knowledge of what the other parts (MTD and NAND
|
||||
driver/hardware) are going to do.
|
||||
|
||||
To make a YAFFS filesystem you have 3 options:
|
||||
|
||||
1) Boot the system with an empty NAND device mounted as YAFFS and copy
|
||||
stuff on.
|
||||
|
||||
2) Make a filesystem image offline, then boot the system and use
|
||||
MTDutils to write an image to flash.
|
||||
|
||||
3) Make a filesystem image offline and use some tool like a bootloader to
|
||||
write it to flash.
|
||||
|
||||
Option 1 avoids a lot of issues because all the parts
|
||||
(YAFFS/MTD/hardware) all take care of their own bits and (if you have
|
||||
put things together properly) it will 'just work'. YAFFS just needs to
|
||||
know how many bytes of the OOB it can use. However sometimes it is not
|
||||
practical.
|
||||
|
||||
Option 2 lets MTD/hardware take care of the ECC so the filesystem
|
||||
image just had to know which bytes to use for YAFFS Tags.
|
||||
|
||||
Option 3 is hardest as the image creator needs to know exactly what
|
||||
ECC bytes, endianness and algorithm to use as well as which bytes are
|
||||
available to YAFFS.
|
||||
|
||||
mkyaffs2image creates an image suitable for option 3 for the
|
||||
particular case of yaffs2 on 2K page NAND with default MTD layout.
|
||||
|
||||
mkyaffsimage creates an equivalent image for 512b page NAND (i.e.
|
||||
yaffs1 format).
|
||||
|
||||
Bootloaders
|
||||
-----------
|
||||
|
||||
A bootloader using YAFFS needs to know how MTD is laying out the OOB
|
||||
so that it can skip bad blocks.
|
||||
|
||||
YAFFS Tracing
|
||||
-------------
|
Loading…
Add table
Add a link
Reference in a new issue