('values:node:37','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"570\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1496361508\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:2:\"37\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:4:\"page\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"5395b75f-7832-44a7-9a49-e57b466031b7\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:28:\"Yaffs Original Specification\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1116847901\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496361508\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:34409:\"<p>YAFFS (Yet Another Flash File System)</p>\r\n\r\n<h4>Version 0.3</h4>\r\n\r\n<h4>Charles Manning (and Wookey), December 2001</h4>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h2>Revision History</h2>\r\n\r\n<p>V0.0 20/12/01 First Draft</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n			<td>\r\n			<p>V0.1</p>\r\n			</td>\r\n			<td>\r\n			<p>11/01/02</p>\r\n			</td>\r\n			<td>\r\n			<p>Minor corrections &amp; cosmetics.<br />\r\n			Change use of data status byte.</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>V0.2</p>\r\n			</td>\r\n			<td>\r\n			<p>28/01/02</p>\r\n			</td>\r\n			<td>\r\n			<p>Added observations about inodes, file headers and hard links.</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>V0.3</p>\r\n			</td>\r\n			<td>\r\n			<p>26/02/02</p>\r\n			</td>\r\n			<td>\r\n			<p>W:Added some general observations on compatibility, partitions and bootloading.</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h2>Scope</h2>\r\n\r\n<p>The purpose of this document is to outline a potential NAND-friendly file system for Linux.</p>\r\n\r\n<h2>Background</h2>\r\n\r\n<p>There are already various flash-file systems (FFSs) or block drivers for flash (on top of which a regular FS runs). There are pros and cons with all of these.</p>\r\n\r\n<p>Flash memory has quite a few constraints which will not be addressed here. Various approaches are available to work around these constraints to provide a file system. It is important to recognise that \"flash\" includes both NOR and NAND flash which have different sets of constraints. It is easy to be mislead by the generic term \"flash\" into thinking that approaches appropriate for NOR flash are immediately suitable for NAND flash.</p>\r\n\r\n<p>The NAND block drivers (eg. SmartMedia [currently not available for Linux] and DiskOnChip NFTL) typically use FAT16 as the file system. This isn\'t too robust and nor is it that flash-friendly. These block drivers provide a logical to physical mapping layer to emulate rewritable blocks that look like disk sectors. When used with FAT16, these file systems work reasonably well. They have a low memory footprint and scale well. Like all FAT based systems they are prone to corruption (\"lost clusters etc\").</p>\r\n\r\n<p>The other approach is to design an entire file system which does not work through a block driver layer and is flash-friendly. This allows more scope to work around issues.</p>\r\n\r\n<p>Currently, two Linux file systems that support NOR flash very well are JFFS and its derivative JFFS2. Both of these are based on the principles of journaling (hence the leading J) which significantly increases robustness - a particularly important feature in embedded systems. Unfortunately neither of these file systems scale particularly well in both boot time and RAM usage. Scaling is particularly relevant when one considers that a 16MB NOR array would be considered large while a 128MB NAND is available as a single chip.</p>\r\n\r\n<p>JFFS requires a RAM-based jffs_node structure for each journalling node in the flash. Each of these nodes is 48 bytes. JFFS2 makes a significant improvement here by reducing the equivalent structure (jffs2_raw_node_ref) to 16 bytes. Still, at say an average node-size of 512 bytes, a 128MB NAND might need 250000 of these ... 4MB!</p>\r\n\r\n<p>Both JFFS and JFFS2 require scanning the flash array at boot time to find the journaling nodes and determine the file structures. Since NAND is large, slow, serially accessed and needs ECC this does not scale well and will take an unacceptably long boot time for the target systems. As a thumb-suck, the scanning of a 128MB NAND array might take approx 25 seconds.</p>\r\n\r\n<p>The intentions of the design sketched here are:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Be NAND-flash friendly.</p>\r\n	</li>\r\n	<li>\r\n	<p>Robustness through journaling strategies.</p>\r\n	</li>\r\n	<li>\r\n	<p>Significantly reduce the RAM overheads and boot times associated with JFFSx.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>This FS is intended primarily for internal NAND rather than removable NAND (SM cards). On removable SM cards Smartmedia compatibility is likely to be important so SM/FAT will normally be used, although of course YAFFS makes a lot of sense if reliability is more important than compatibility.</p>\r\n\r\n<h2>Overview</h2>\r\n\r\n<p>Here follows a simplified overview of YAFFS.</p>\r\n\r\n<p>YAFFS uses a physical flash format similar to SmartMedia. This is done for various reasons:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Some of the formatting, eg placement of bad block markers is determined by the NAND manufacturers and can\'t be changed.</p>\r\n	</li>\r\n	<li>\r\n	<p>Potential to reuse code.</p>\r\n	</li>\r\n	<li>\r\n	<p>If it ain\'t broke don\'t fix.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>Some of the fields are obviously different to reflect the different usage. Despite the similarities YAFFS is not actually compatible with SM/FAT. SM cards need to be reformatted to switch from using SM/FAT to YAFFS or vice versa.</p>\r\n\r\n<p>File data is stored in fixed size \"chunks\" consistent with the size of a page (ie. 512 bytes). Each page is marked with a file id and chunk number. These tags are stored in the \"spare data\" region of the flash. The chunk number is determined by dividing the file position by the chunk size.</p>\r\n\r\n<p>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. The overwritten data is marked as \"discarded\".</p>\r\n\r\n<p>File \"headers\" are stored as a single page, marked so as to be differentiated from data pages.</p>\r\n\r\n<p>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.</p>\r\n\r\n<p>A block containing only discarded pages (termed a <em>dirty block</em>) 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.</p>\r\n\r\n<p>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 218 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.</p>\r\n\r\n<p>Boot-time scanning to build the file structure lists should require just one pass reading NAND. Since only the the spare data needs to be read, this should be relatively fast ( approx 3 seconds for 128MB). Improvements can be achieved by partitioning the NAND. ie. mount the critical partition first then mount the data partition afterwards.</p>\r\n\r\n<p>Various runtime improvements can be achieved by changing the \"chunk size\" to 1024 bytes or more. However this would likely reduce flash efficiency. As always, life is a compromise....</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h3>Spare area details</h3>\r\n\r\n<p>The following table summarizes the layout of the spare area of each page.</p>\r\n\r\n<p>Byte #SmartMedia usageYAFFS usage</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n			<td>\r\n			<p>0..511</p>\r\n			</td>\r\n			<td>\r\n			<p>Data</p>\r\n			</td>\r\n			<td>\r\n			<p>Data. either file data or file header depending on tags</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>512..515</p>\r\n			</td>\r\n			<td>\r\n			<p>Reserved</p>\r\n			</td>\r\n			<td>\r\n			<p>Tags</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>516</p>\r\n			</td>\r\n			<td>\r\n			<p>Data status byte. Not used in SM code from Samsung</p>\r\n			</td>\r\n			<td>\r\n			<p>Data status byte. If more than 4 bits are zero, then this page is discarded.</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>517</p>\r\n			</td>\r\n			<td>\r\n			<p>Block status byte</p>\r\n			</td>\r\n			<td>\r\n			<p>Block status byte</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>518..519</p>\r\n			</td>\r\n			<td>\r\n			<p>Block address</p>\r\n			</td>\r\n			<td>\r\n			<p>Tags</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>520..522</p>\r\n			</td>\r\n			<td>\r\n			<p>ECC on second 256 bytes part of data</p>\r\n			</td>\r\n			<td>\r\n			<p>ECC on second 256 bytes of data</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>523..524</p>\r\n			</td>\r\n			<td>\r\n			<p>Block address</p>\r\n			</td>\r\n			<td>\r\n			<p>Tags</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>525..527</p>\r\n			</td>\r\n			<td>\r\n			<p>ECC on first 256 bytes part of data</p>\r\n			</td>\r\n			<td>\r\n			<p>ECC on first 256 bytes part of data</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>The block status is a reserved value that shows whether the block is damaged.</p>\r\n\r\n<p>The data status tracks whether the page is valid. If less than 4 bits are zero, then the page is valid otherwise it is discarded.</p>\r\n\r\n<p>There are 8 bytes (64 bits) for use by YAFFS tags. This is partitioned as follows:</p>\r\n\r\n<p>Number of bitsUsage</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n			<td>\r\n			<p>18</p>\r\n			</td>\r\n			<td>\r\n			<p>18-bit file id. ie. Limit of 218 (over 260000) files. File id 0 is not valid and indicates a deleted page. File Id 0x3FFFF i is also not valid.</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>2</p>\r\n			</td>\r\n			<td>\r\n			<p>2-bit serial number.</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>20</p>\r\n			</td>\r\n			<td>\r\n			<p>20-bit page id within file. Limit of 220 pages per file. ie. over 500MB file max size. Page id 0 means the file header for this file.</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>10</p>\r\n			</td>\r\n			<td>\r\n			<p>10-bit counter of the number of bytes used in the page.</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>12</p>\r\n			</td>\r\n			<td>\r\n			<p>12-bit ECC on tags.</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>2</p>\r\n			</td>\r\n			<td>\r\n			<p>Unused. Keep as 1.</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p><strong>64</strong></p>\r\n			</td>\r\n			<td>\r\n			<p><strong>Total</strong></p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>A bit of explanation on the usage of some of these fields:</p>\r\n\r\n<p>file Id is synonymous with inode.</p>\r\n\r\n<p>The serial number is incremented each time a page with the same file_id:page_id is rewritten (because of data changes or copy during garbage collection). When a page is replaced, there is a brief period during which there are two pages with the same id. The serial number resolves this. Since there should never be a difference of less than more than one, a two-bit counter is sufficient to determine which is the current page.</p>\r\n\r\n<p>When the page is rewritten, the file id, these data status byte and the 12-bit ECC are all written to zero.</p>\r\n\r\n<p>The byte counter indicates how many bytes are valid in this page. Since the page would not exist if it contains zero bytes, this field should thus hold 512 for all pages except the last page in the file. The use of counters means that the file length integrity is preserved while the file is open without having to constantly update the file length in the file header. The file header only needs to be refreshed when the file is closed (rather than whenever it is appended to). This field is wide enough to allow expansion to 1024-byte \"chunks\".</p>\r\n\r\n<p>File \"headers\" come in two flavours:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>file info ( the mode, ower id, group id, length,...)</p>\r\n	</li>\r\n	<li>\r\n	<p>the hard link(s) that refers to the file.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>A directory also appears as a file (ie. has an inode and hard link(s)) but has no data.</p>\r\n\r\n<p>The 12-bit ECC applies to only the tag data uses a similar algorithm to the 22-bit ECCs used for file system data. They are kept independent.</p>\r\n\r\n<h3>RAM data details</h3>\r\n\r\n<p>Block management details are reasonably obvious and, I feel, don\'t need to be addressed here apart from stating that there will be a structure to track block status (eg. number of pages in use, failed blocks, and which are candidates for garbage collection etc).</p>\r\n\r\n<p>The files need an indexing structure of sorts to locate and track the pages in the file. Some sort of tree structure should work rather well. The look-up needs to be quite efficient in both CPU time and space.</p>\r\n\r\n<h3>Page allocation and garbage collection</h3>\r\n\r\n<p>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.</p>\r\n\r\n<p>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.</p>\r\n\r\n<p>Relative to NOR, NAND writes and erases very fast. Therefore garbage collection might be performed on-demand (eg. during a write) without significant degradation in performance. Alternatively garbage collection might be delegated to a kernel tasklet.</p>\r\n\r\n<p>Relative to JFFSx, the garbage collection presented here is incredibly simple - thanks mainly to the use of fixed-size pages instead of journaling nodes.</p>\r\n\r\n<h3>Flash writing</h3>\r\n\r\n<p>As presented here, YAFFS only writes to the page\'s data area once and to the spare area twice (once when new page is written and once when it gets stomped on) before an erasure. This is within the limits of the most restrictive NAND flashes.</p>\r\n\r\n<h3>Wear levelling</h3>\r\n\r\n<p>No wear levelling is explicitly used here. Instead we rely on two \"strategies\":</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Reserving some blocks to cater for failure. You need to do this anyway with NAND. The main purpose behind wear levelling is to prevent some blocks getting more wear and failing. Since we expect, and handle, failure this is no longer as important.</p>\r\n	</li>\r\n	<li>\r\n	<p>The infrequent random block selection should prevent low-wear blocks getting \"stuck\".</p>\r\n	</li>\r\n</ul>\r\n\r\n<h3>Partitioning</h3>\r\n\r\n<p>Partitioning is not included in this spec, but could be added if required.</p>\r\n\r\n<h3>Bootloading</h3>\r\n\r\n<p>Bootloaders cannot just read files direct from NAND due to the high probability of bad blocks. Because YAFFS is quite simple it will be relatively straightforward for bootloaders to read from it (eg reading a kernel).</p>\r\n\r\n<h3>Conclusion</h3>\r\n\r\n<p>YAFFS is very simple. It is also NAND-friendly, is relatively frugal with resources (especially RAM) and boots quickly. Like JFFSx it has journaling which makes it far more robust than FAT.</p>\r\n\r\n<p>While it might seem high-risk to develop YAFFS, it is probably about the same amount of effort as implementing changes to JFFS to get it to work effectively within the constraints of NAND. A resulting JFFSx system would still require significant amounts of RAM and have long boot times.</p>\r\n\r\n<p>While YAFFS is indeed a new file system internally, much of the file system glue code (including inode management, link management etc) can likely be stolen from JFFSx.</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>YAFFS Development Notes</p>\r\n\r\n<h3>Build options</h3>\r\n\r\n<p>Yaffs can be built as either a kernel module (ie. a Linux file system) or as an application.</p>\r\n\r\n<p>Of course the goal is to build yaffs as a file system running on top of real NAND flash, but yaffs can be built to run on a RAM emulation layer for in-kernel testing without NAND flash in the system.</p>\r\n\r\n<p>Building as an application allows the yaffs_guts algorithms to be tested/debugged in a more friendly debugging environment. The test harness is in yaffsdev.c</p>\r\n\r\n<h3>Trying it out</h3>\r\n\r\n<p>YAFFS can be built to run with either mtd or RAM emulation, or both. The file system that interfaces to mtd is called <strong>yaffs</strong>, the file system that uses internal ram is called <strong>yaffsram</strong>. YAFFS simultaneously supports both if they are enabled.</p>\r\n\r\n<ol>\r\n	<li>\r\n	<p>Hack the Makefile and change the KERNELDIR define to your kernel directory.</p>\r\n	</li>\r\n	<li>\r\n	<p>If you don\'t have mtd support in your kernel, then you might need to turn off USE_MTD otherwise the yaffs module might not load.</p>\r\n	</li>\r\n	<li>\r\n	<p>Type <strong>make clean; make</strong> to build yaffs</p>\r\n	</li>\r\n	<li>\r\n	<p>Load yaffs as a module by typing <strong>/sbin/insmod yaffs.o</strong> (ya gotta be root!).</p>\r\n	</li>\r\n	<li>\r\n	<p>Create a mount point eg. <strong>mkdir /mnt/y</strong></p>\r\n	</li>\r\n	<li>\r\n	<p>To mount the RAM emulation version of yaffs, <strong>mount -t yaffsram none /mnt/y</strong></p>\r\n	</li>\r\n	<li>\r\n	<p>Alternatively, to mount the mtd version of yaffs,<strong> mount -t yaffs /dev/mtd0 /mnt/y</strong></p>\r\n	</li>\r\n</ol>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h3>YAFFS Data structures</h3>\r\n\r\n<p>All data types are defined in yaffs_guts.h</p>\r\n\r\n<p>Yaffs uses the following major objects:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>yaffs_Object: A yaffs_Object can be a file, directory, symlink or hardlink. The yaffs_Objects \"know\" about their corresponding yaffs_ObjectHeader in NAND and the data for that object. yaffs_Objects also bind together the directory structure as follows:</p>\r\n	</li>\r\n	<li>\r\n	<p>parent: pointer to the yaffs_Object that is a parent of this yaffs_Object in the directory structure.</p>\r\n	</li>\r\n	<li>\r\n	<p>siblings: this field is used to link together a list of all the yaffs_Objects in the same directory.</p>\r\n	</li>\r\n	<li>\r\n	<p>children: if the object is a directory, then children holds the head of the list of objects in the directory.</p>\r\n	</li>\r\n	<li>\r\n	<p>yaffs_Tnode: yaffs_Tnodes form a tree structure that speeds up the search for data chunks in a file. As the file grows in size, the levels increase. The Tnodes are a constant size (32 bytes). Level 0 (ie the lowest level) comprise 16 2-byte entries giving an index used to search for the chunkId. Tnodes at other levels comprise 8 4-byte pointer entries to other tnodes lower in the tree.</p>\r\n	</li>\r\n	<li>\r\n	<p>yaffs_Device: this holds the device context and is in some ways analogous to the VFS superblock. It stores the data used to access the mtd as well as function pointers to access the NAND data.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>The Tnodes and Objects are allocated in groups to reduce memory allocation/freeing overheads. Freed up tnodes and objects are kept in a free list and re-used.</p>\r\n\r\n<h3>yaffs_Object</h3>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>struct yaffs_ObjectStruct</p>\r\n\r\n<p>{</p>\r\n\r\n<p>__u8 fake:1; // A fake object has no presence on NAND.</p>\r\n\r\n<p>__u8 renameAllowed:1; // Are we allowed to rename it?</p>\r\n\r\n<p>__u8 unlinkAllowed:1; // Are we allowed to unlink it?</p>\r\n\r\n<p>__u8 dirty:1; // the object needs to be written to flash</p>\r\n\r\n<p>__u8 valid:1; // When the file system is being loaded up, this</p>\r\n\r\n<p>// object might be created before the data</p>\r\n\r\n<p>// is available (ie. file data records appear before the header).</p>\r\n\r\n<p>__u8 serial; // serial number of chunk in NAND. Store here so we don\'t have to</p>\r\n\r\n<p>// read back the old one to update.</p>\r\n\r\n<p>__u16 sum; // sum of the name to speed searching</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>struct yaffs_DeviceStruct *myDev; // The device I\'m on</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>struct list_head hashLink; // list of objects in this hash bucket</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>struct list_head hardLinks; // all the equivalent hard linked objects</p>\r\n\r\n<p>// live on this list</p>\r\n\r\n<p>// directory structure stuff</p>\r\n\r\n<p>struct yaffs_ObjectStruct *parent; //my parent directory</p>\r\n\r\n<p>struct list_head siblings; // siblings in a directory</p>\r\n\r\n<p>// also used for linking up the free list</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>// Where\'s my data in NAND?</p>\r\n\r\n<p>int chunkId; // where it lives</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>__u32 objectId; // the object id value</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>__u32 st_mode; // protection</p>\r\n\r\n<p>__u32 st_uid; // user ID of owner</p>\r\n\r\n<p>__u32 st_gid; // group ID of owner</p>\r\n\r\n<p>__u32 st_atime; // time of last access</p>\r\n\r\n<p>__u32 st_mtime; // time of last modification</p>\r\n\r\n<p>__u32 st_ctime; // time of last change</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>yaffs_ObjectType variantType;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>yaffs_ObjectVariant variant;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>};</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>Obvious stuff skipped....</p>\r\n\r\n<p>fake, renameAllowed, unlinkAllowed are special flags for handling \"fake\" objects which live in the file system but do not live on NAND. Currently there are only two such objects: the root object and the lost+found directory. None of these may be renamed or unlinked.</p>\r\n\r\n<p>serial, sum: see yaffs_ObjectHeader.</p>\r\n\r\n<p>dirty indicates that the object\'s contents has changed and a new yaffs_ObjectHeader must be written to flash.</p>\r\n\r\n<p>valid indicates that the object has been loaded up. This is only used during scanning (yaffs_Scan()) since we can know of an object\'s existance - and thus need to create the object header - before we encounter the associated yaffs_ObjectHeader.</p>\r\n\r\n<p>hashlink is a list of Objects in the same hash bucket.</p>\r\n\r\n<p>The four variants hold extra info:</p>\r\n\r\n<p>Files hold the file size and the top level and pointer to the tnode tree for the file.</p>\r\n\r\n<p>Directories hold a list of children objects.</p>\r\n\r\n<p>Symlinks hold a pointer to the alias string. This is probably inefficient, but that probably does not matter since we don\'t expect to see many of these.</p>\r\n\r\n<p>Hardlinks hold information to identify the equivalent object.</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h3>File structure (tnodes)</h3>\r\n\r\n<p>File structures are done with a tiered indexing structure</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p><img alt=\"\" height=\"294\" src=\"yaffs/sv9349341.gif\" width=\"491\" /><br />\r\n<br />\r\n&nbsp;</p>\r\n\r\n<p>The file structure is maintained by a tree structure. Depending where it is in the tree, each tree node (<strong><em>tnode</em></strong>) (the blue/things) holds either:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>.... if it is at the lowest level, then 16 __u16s which identify the page.</p>\r\n	</li>\r\n	<li>\r\n	<p>.... if it is at a higher level (ie an internal tnode), then 8 pointers to lowest-level tnodes.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>When the file starts out, it is assigned only one low-level tnode. When the file expands past what a single tnode can hold, then it is assigned a second tnode and an internal node is added to point to the two tnodes. As the file grows, more low-level tnodes and high level tnodes are added.</p>\r\n\r\n<p>Traversing the tnode tree to find a particular page in a file is quite simple: each internal tnode is selected from by using 3 bits of the page offset in the file. The level 0 page resolves 4 bits.</p>\r\n\r\n<p>For example, finding page 0x235 (ie. the one starting at file position 0x46800 would proceed as follows:</p>\r\n\r\n<p>0x235 is 0000001000110101, partitioned as follows. 000.000.100.011.0101</p>\r\n\r\n<p>LevelBitsSelected value</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n			<td>\r\n			<p>3 or more if they exist</p>\r\n			</td>\r\n			<td>\r\n			<p>&gt;= 10</p>\r\n			</td>\r\n			<td>\r\n			<p>Zero</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>2</p>\r\n			</td>\r\n			<td>\r\n			<p>9 to 7</p>\r\n			</td>\r\n			<td>\r\n			<p>100 binary = 4</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>1</p>\r\n			</td>\r\n			<td>\r\n			<p>6 to 4</p>\r\n			</td>\r\n			<td>\r\n			<p>011 binary = 3</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>0</p>\r\n			</td>\r\n			<td>\r\n			<p>3 to 0</p>\r\n			</td>\r\n			<td>\r\n			<p>0101 binary = 5</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>Free tnodes are stored in a list. When the list is exhausted, more are allocated.</p>\r\n\r\n<p>Each tnode takes 32 bytes. Each file needs at least one level 0 tnode. How many do we need? A full 16MB file system needs at least 16MB/512/16 = 2000 level zero tnodes. More for internal tnodes. More for files smaller than optimal.</p>\r\n\r\n<p>The tree grows as required. When the file is resized to a smaller size then it is pruned.</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h3>NAND data</h3>\r\n\r\n<p>Data is stored on NAND in \"chunks\". Currently each chunk is the same size as a NAND flash page (ie. 512 bytes + 16 byte spare). In the future we might decide to allow for different chunk sizes. Chunks can hold either:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>A yaffs_ObjectHeader. This is the way a yaffs_Object gets stored on NAND.</p>\r\n	</li>\r\n	<li>\r\n	<p>A chunk of file data.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>The 16 byte spare area contains:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>8 bytes of tags,</p>\r\n	</li>\r\n	<li>\r\n	<p>6 bytes of ECC data</p>\r\n	</li>\r\n	<li>\r\n	<p>1 byte block status (used to identify damaged blocks)</p>\r\n	</li>\r\n	<li>\r\n	<p>1 byte data status (currently unused).</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>The tags are made up as follows:</p>\r\n\r\n<p>typedef struct</p>\r\n\r\n<p>{</p>\r\n\r\n<p>unsigned chunkId:20; //chunk number in file</p>\r\n\r\n<p>unsigned serialNumber:2; //serial number for chunk</p>\r\n\r\n<p>unsigned byteCount:10; //number of bytes of data used in this chunk</p>\r\n\r\n<p>unsigned objectId:18; //the object id that this chunk belongs to.</p>\r\n\r\n<p>unsigned ecc:12; //ECC on tags</p>\r\n\r\n<p>unsigned unusedStuff:2; //unused</p>\r\n\r\n<p>} yaffs_Tags;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>A chunkId of zero indicates that this chunk holds a yaffs_ObjectHeader. A non zero value indicates that this is a data chunk and the position of the chunk in the file (ie. the first chunk - at offset 0 - has chunkId 1). See yaffs_guts.c:yaffs_Scan () to see how this is done.</p>\r\n\r\n<p>When a chunk is replaced (eg. file details changed or a part of a file was overwritten), the new chunk is written before the old chunk is deleted. This means that we don\'t lose data if there is a power loss after the new chunk is created but before the old one is discarded, but it does mean that we can encounter the situation where we find both the old and the new chunks in flash. The serialNumber is incremented each time the chunk is written. 2 bits is sufficient to resolve any ambiguity.</p>\r\n\r\n<p>bytecount applies only to data chunks and tells how many of the data bytes are valid.</p>\r\n\r\n<p>objectId says which object this chunk belongs to.</p>\r\n\r\n<p>ecc is used to perform error correction on the tags. Another ecc field is used to error correct the data.</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h3>yaffs_ObjectHeader</h3>\r\n\r\n<p>typedef struct</p>\r\n\r\n<p>{</p>\r\n\r\n<p>yaffs_ObjectType type;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>// Apply to everything</p>\r\n\r\n<p>int parentObjectId;</p>\r\n\r\n<p>__u16 sum; // checksum of name</p>\r\n\r\n<p>char name[YAFFS_MAX_NAME_LENGTH + 1];</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>// Thes following apply to directories, files, symlinks - not hard links</p>\r\n\r\n<p>__u32 st_mode; // protection</p>\r\n\r\n<p>__u32 st_uid; // user ID of owner</p>\r\n\r\n<p>__u32 st_gid; // group ID of owner</p>\r\n\r\n<p>__u32 st_atime; // time of last access</p>\r\n\r\n<p>__u32 st_mtime; // time of last modification</p>\r\n\r\n<p>__u32 st_ctime; // time of last change</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>// File size applies to files only</p>\r\n\r\n<p>int fileSize;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>// Equivalent object id applies to hard links only.</p>\r\n\r\n<p>int equivalentObjectId;</p>\r\n\r\n<p>// alias only applies to symlinks</p>\r\n\r\n<p>char alias[YAFFS_MAX_ALIAS_LENGTH + 1];</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>} yaffs_ObjectHeader;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>A yaffs_ObjectHeader is stored in NAND for every yaffs_Object.</p>\r\n\r\n<p>type holds the type of yaffs_Object (file,directory,hardlink or symlink).</p>\r\n\r\n<p>parentObject is the objectId of this object\'s parent. name holds the object\'s name. Together these form the directory structure of the file system. Also worth mention is sum. This is a \"checksum\" on the name which speeds directory searching (ie. when searching the directory we only compare the name for those entries where sum matches).</p>\r\n\r\n<p>Obvious stuff skipped....</p>\r\n\r\n<p>equivalentObjectId is used by hardlinks. A hardlink to an object uses this field to specify the object that this links to. This way of doing things is a bit different than the normal Linux way of doing things (ie. keeping the links distinct from the inode) but is simpler and uses less space except for a few corner cases with hardlinks.</p>\r\n\r\n<p>alias is used by symlinks to hold the symlink alias string. This limits the size of the symlink alias. In future we should expand YAFFS to use data chunks to store aliases too long to fit into the yaffs_ObjectHeader.</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h3>NAND Interface</h3>\r\n\r\n<p>All NAND access is performed via four functions pointed to by yaffs_Device. At the moment a chunk is a page.</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>int WriteChunkToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare)</p>\r\n	</li>\r\n	<li>\r\n	<p>int ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);</p>\r\n	</li>\r\n	<li>\r\n	<p>int EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND);</p>\r\n	</li>\r\n	<li>\r\n	<p>int InitialiseNAND(struct yaffs_DeviceStruct *dev);</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>In the Readxxx and Writexxx functions, the data and/or spare pointers may be NULL in which case these data transfers are ignored.</p>\r\n\r\n<p>A quick note about NAND:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>NAND is not random access, but page oriented. Thus, we do all reads &amp; writes in pages.</p>\r\n	</li>\r\n	<li>\r\n	<p>Each NAND page holds 512 bytes of data and 16 \"spare\" bytes. Yaffs structures the spare area with tags used to identify what is stored in the data area. There are 32 such pages to a block.</p>\r\n	</li>\r\n	<li>\r\n	<p>NAND writes will only change 1 bits to 0. eg. if a byte holds 10110011 and you write 11011010 to it you will get the logical and of the two values: 10010010. The only way to get 1s again is to erase the entire block.</p>\r\n	</li>\r\n	<li>\r\n	<p>You may only write to a page a few times before erasing the entire block. Yaffs lives within these limitations. Each page only gets written to twice (once when written and once when discarded).</p>\r\n	</li>\r\n	<li>\r\n	<p>ECC is normally used with NAND to correct for single bit errors. YAFFS applies the ECC itself, so the MTD should not do this.</p>\r\n	</li>\r\n	<li>\r\n	<p>The current mtd interfaces are not particularly well suited to YAFFS and we will address the issue with the mtd group. (The mtd interface does not support page-oriented read/write which YAFFS would prefer).</p>\r\n	</li>\r\n</ul>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h3>mkyaffs</h3>\r\n\r\n<p>mkyaffs is the tool to format a NAND mtd to be used for YAFFS. This is quite simple, just erase all the undamaged blocks. YAFFS treats erased blocks as free (empty) space.</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h2>Expected performance</h2>\r\n\r\n<p>The following numbers should give an indication of the performance we should expect from YAFFS.</p>\r\n\r\n<p>As an example, I\'ll use the following numbers. Since the hardware is capable of 50ns read/write, these numbers allow for some other ovberheads. Clearly though, the performance can be degraded in various ways.</p>\r\n\r\n<p>Seek10uS/page</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n			<td>\r\n			<p>Read</p>\r\n			</td>\r\n			<td>\r\n			<p>100nS/byte</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Write</p>\r\n			</td>\r\n			<td>\r\n			<p>100nS/byte</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Program</p>\r\n			</td>\r\n			<td>\r\n			<p>200uS/page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Erase</p>\r\n			</td>\r\n			<td>\r\n			<p>2mS/block</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>From this we can derive some higher-level numbers:</p>\r\n\r\n<p>OperationTimeCalculation</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n			<td>\r\n			<p>Read spare</p>\r\n			</td>\r\n			<td>\r\n			<p>12uS</p>\r\n			</td>\r\n			<td>\r\n			<p>seek + 16 * read</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Read page</p>\r\n			</td>\r\n			<td>\r\n			<p>63 uS</p>\r\n			</td>\r\n			<td>\r\n			<p>seek + 528 * read</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Write page</p>\r\n			</td>\r\n			<td>\r\n			<p>326 uS</p>\r\n			</td>\r\n			<td>\r\n			<p>seek + 528 * write + program + read page (for verification)</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Discard page</p>\r\n			</td>\r\n			<td>\r\n			<p>212 uS</p>\r\n			</td>\r\n			<td>\r\n			<p>seek + 16 * write + program</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Overwrite page</p>\r\n			</td>\r\n			<td>\r\n			<p>538 uS</p>\r\n			</td>\r\n			<td>\r\n			<p>write page + discard page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Erase overhead per page</p>\r\n			</td>\r\n			<td>\r\n			<p>63uS</p>\r\n			</td>\r\n			<td>\r\n			<p>erase/32</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>From this we can infer the following flash access times:</p>\r\n\r\n<p>OperationTimeCalculation</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n			<td>\r\n			<p>Read 1MB file</p>\r\n			</td>\r\n			<td>\r\n			<p>0.13s (about 7.5 MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * read page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Write 1MB (clean system)</p>\r\n			</td>\r\n			<td>\r\n			<p>0.53s (about 1.8 MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * write page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Overwrite 1MB file (no gc)</p>\r\n			</td>\r\n			<td>\r\n			<p>1.08s (about 0.9MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * overwrite page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Overwrite 1MB with 50% gc</p>\r\n			</td>\r\n			<td>\r\n			<p>2.4s (about 0.4 MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * overwrite page + 2000 * page copy (== overwrite page) + 4000 * erase overhead</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Delete 1MB file</p>\r\n			</td>\r\n			<td>\r\n			<p>0.43s (about 2.2 MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * discard page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Delete 1MB file with 50% gc</p>\r\n			</td>\r\n			<td>\r\n			<p>0.49s (about 2.0MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * discard page + 1000 * erase overhead</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p>&nbsp;</p>\r\n\";s:7:\"summary\";s:223:\"The initial specification for Yaffs. Circa 2002. Details of the filing system, including short backgrounder. Read this if you want to know what it is, what it does and how it works. This specification does not cover Yaffs2.\";s:6:\"format\";s:10:\"basic_html\";}}}s:19:\"field_document_type\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:9:\"target_id\";s:3:\"346\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:4:\"page\";s:2:\"id\";s:2:\"37\";s:8:\"revision\";s:3:\"570\";s:4:\"uuid\";s:36:\"5395b75f-7832-44a7-9a49-e57b466031b7\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:28:\"Yaffs Original Specification\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"570\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655169.097,1,'entity_field_info node_values','866'),('values:node:370','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:18:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"371\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1244212473\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";s:102:\"Not sure where images from porting page have gone so seeing if I need to add them separately like this\";}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"370\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"image\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"4ddba847-c91b-4a04-95d9-80ed994cae87\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:37:\"yaffs_porting_guide_html_2de490f8.png\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1244212305\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1244212473\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"image\";s:2:\"id\";s:3:\"370\";s:8:\"revision\";s:3:\"371\";s:4:\"uuid\";s:36:\"4ddba847-c91b-4a04-95d9-80ed994cae87\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:37:\"yaffs_porting_guide_html_2de490f8.png\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"371\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674351.010,1,'entity_field_info node_values','866'),('values:node:371','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:18:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"372\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1244214689\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";s:102:\"Not sure where images from porting page have gone so seeing if I need to add them separately like this\";}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"371\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"image\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"5accfa24-1487-463a-839b-ef98a18344fe\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:38:\"yaffs_porting_guide_html_m11b1f893.png\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1244212305\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1244214689\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"image\";s:2:\"id\";s:3:\"371\";s:8:\"revision\";s:3:\"372\";s:4:\"uuid\";s:36:\"5accfa24-1487-463a-839b-ef98a18344fe\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:38:\"yaffs_porting_guide_html_m11b1f893.png\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"372\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674351.050,1,'entity_field_info node_values','866'),('values:node:372','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:18:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"373\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1244214744\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";s:102:\"Not sure where images from porting page have gone so seeing if I need to add them separately like this\";}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"372\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"image\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"eecbcfd1-c44e-4d8c-8117-7d0f65b5ddcd\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:38:\"yaffs_porting_guide_html_m4650262f.png\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1244212305\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1244214744\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"image\";s:2:\"id\";s:3:\"372\";s:8:\"revision\";s:3:\"373\";s:4:\"uuid\";s:36:\"eecbcfd1-c44e-4d8c-8117-7d0f65b5ddcd\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:38:\"yaffs_porting_guide_html_m4650262f.png\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"373\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674351.074,1,'entity_field_info node_values','866'),('values:node:374','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:18:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"375\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1263783268\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"374\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"image\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"0adf7c47-37bc-424d-b254-3fd339c29144\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:16:\"YAFFS Tnode tree\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1263783089\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1263783268\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"image\";s:2:\"id\";s:3:\"374\";s:8:\"revision\";s:3:\"375\";s:4:\"uuid\";s:36:\"0adf7c47-37bc-424d-b254-3fd339c29144\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:16:\"YAFFS Tnode tree\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"375\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674351.090,1,'entity_field_info node_values','866'),('values:node:376','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:18:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"377\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1263783445\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"376\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"image\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"9b2e6c56-fa1d-477c-814e-83c717c23aad\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:35:\"YAFFS - directory structure example\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1263783335\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1263783445\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"image\";s:2:\"id\";s:3:\"376\";s:8:\"revision\";s:3:\"377\";s:4:\"uuid\";s:36:\"9b2e6c56-fa1d-477c-814e-83c717c23aad\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:35:\"YAFFS - directory structure example\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"377\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674351.106,1,'entity_field_info node_values','866'),('values:node:377','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:18:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"378\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1263783571\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"377\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"image\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"d66a89b6-b62f-4794-9eef-bd8b09201ead\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:20:\"YAFFS - Block states\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1263783506\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1263783571\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"image\";s:2:\"id\";s:3:\"377\";s:8:\"revision\";s:3:\"378\";s:4:\"uuid\";s:36:\"d66a89b6-b62f-4794-9eef-bd8b09201ead\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:20:\"YAFFS - Block states\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"378\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674351.129,1,'entity_field_info node_values','866'),('values:node:38','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"571\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1496365861\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:2:\"38\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:4:\"page\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"10044baf-840c-421b-9888-e789cd7d53e3\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:21:\"Yaffs 2 Specification\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"3\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1116848038\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496365861\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:10894:\"<h2>Summary</h2>\r\n\r\n<p>The original motivation for Yaffs 2 was to add support for the new NAND with 2kB pages instead of 512-byte pages and strictly sequential page writing order.</p>\r\n\r\n<p>To achieve this, a new design is used which also realises the following benefits:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Zero page rewrites means faster operation. (Yaffs1 uses a single rewrite in the spare area to delete a page).</p>\r\n	</li>\r\n	<li>\r\n	<p>Ability to exploit simultaneous page programming on some chips.</p>\r\n	</li>\r\n	<li>\r\n	<p>Improves performance relative to Yaffs1 speed(write:1.5x to 5x, delete: 4x, garbage collection: 2x)</p>\r\n	</li>\r\n	<li>\r\n	<p>Lower RAM footprint (approx. 25% to 50% of Yaffs1).</p>\r\n	</li>\r\n	<li>\r\n	<p>Can support Toshiba/Sandisk MLC parts.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>Most of Yaffs1 and Yaffs2 code is common, therefore the code will likely be kept common with Yaffs1 vs Yaffs2 being run-time selected.</p>\r\n\r\n<h4>Method</h4>\r\n\r\n<p>The main philosophical difference between Yaffs&nbsp;and Yaffs2 is how discarded status is tracked. Since we can\'t do any re-writing, we can\'t use the \"discarded\" flags in Yaffs2.</p>\r\n\r\n<p>Instead Yaffs2 uses two mechanisms to resolve data state.</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Yaffs2 chunks have more tag information, including a block sequence Id. From that we can determine the chunk sequence Id since the chunks are allocated sequentially in a block. Thus we always know the patch order for all chunks in the system.</p>\r\n	</li>\r\n	<li>\r\n	<p>The above helps us track stale -vs- fresh data, but does not help determine when a file/object is deleted. Deletion is achieved by moving the object to the \"unlinked\" directory. We also keep track of the number of chunks (both stale and current) in the system for each object. While this number indicates that there are still chunks associated with this object we keep the deletion record. When the last trace of the object has been really erased from NAND, we can forget about the deletion record too.</p>\r\n	</li>\r\n	<li>\r\n	<p>Since there is no deletion, a resize (shrinking) of a file will still have valid data chunks past the end of file on the NAND. However, we write a new ObjectHeader at the time of the resize, therefore this shows the shrunken file size.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>This changes erasure slightly:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>During garbage collection we can\'t just look at chunk state flags, instead we must read the tags of each chunk to determine which object\'s chunk count we must decrement. This step must also be performed when a block is erased (as part of deletion).</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>This makes erasure &amp; garbage collection more expensive (by adding reads), but remember that ion Yaffs2 we don\'t need to do page deletions which are much more expensive operations. Thus, all-up Yaffs2 wins.</p>\r\n\r\n<h4>Tag structure</h4>\r\n\r\n<p>Each chunk in Yaffs2 has the following information:</p>\r\n\r\n<p>Field</p>\r\n\r\n<p>Comment</p>\r\n\r\n<p>Size for 1kb chunks</p>\r\n\r\n<p>Size for 2kB chunks</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>blockState</p>\r\n			</td>\r\n			<td>\r\n			<p>Block state. non-0xFF for bad block</p>\r\n			</td>\r\n			<td>\r\n			<p>1 byte</p>\r\n			</td>\r\n			<td>\r\n			<p>1 byte</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>chunkId</p>\r\n			</td>\r\n			<td>\r\n			<p>32-bit chunk Id</p>\r\n			</td>\r\n			<td>\r\n			<p>4 bytes</p>\r\n			</td>\r\n			<td>\r\n			<p>4 bytes</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>objectId</p>\r\n			</td>\r\n			<td>\r\n			<p>32-bit object Id</p>\r\n			</td>\r\n			<td>\r\n			<p>4 bytes</p>\r\n			</td>\r\n			<td>\r\n			<p>4 bytes</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>nBytes</p>\r\n			</td>\r\n			<td>\r\n			<p>Number of data bytes in this chunk</p>\r\n			</td>\r\n			<td>\r\n			<p>2 bytes</p>\r\n			</td>\r\n			<td>\r\n			<p>2 bytes</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>blockSequence</p>\r\n			</td>\r\n			<td>\r\n			<p>sequence number for this block</p>\r\n			</td>\r\n			<td>\r\n			<p>4 bytes</p>\r\n			</td>\r\n			<td>\r\n			<p>4 bytes</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>tagsEcc</p>\r\n			</td>\r\n			<td>\r\n			<p>ECC on tags area</p>\r\n			</td>\r\n			<td>\r\n			<p>3 bytes</p>\r\n			</td>\r\n			<td>\r\n			<p>3 bytes</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>ecc</p>\r\n			</td>\r\n			<td>\r\n			<p>ECC, 3 bytes/256 bytes of data</p>\r\n			</td>\r\n			<td>\r\n			<p>12 bytes</p>\r\n			</td>\r\n			<td>\r\n			<p>24 bytes</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p><strong>Total</strong></p>\r\n			</td>\r\n			<td>\r\n			<p>&nbsp;</p>\r\n			</td>\r\n			<td>\r\n			<p><strong>30 bytes</strong></p>\r\n			</td>\r\n			<td>\r\n			<p><strong>42 bytes</strong></p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>To get enough spare bytes for this tagging structure requires a chunk-size of at least 1kB.</p>\r\n\r\n<p>The blockSequence increments each time a block is allocated. (ie. the first block allocated is block 1, and so on).</p>\r\n\r\n<h4>Scanning</h4>\r\n\r\n<p>The only reason we need to keep track of data status on NAND is to be able to recreate the file system state during scanning. Since we no longer have chunk deletion status flags we use a slightly different process for scanning a Yaffs2 system.</p>\r\n\r\n<p>In effect, Yaffs2 recreates its state by \"replaying the tape\". ie. it scans the chunks in their allocation order (block sequence Id order) rather than in their order on the media. This implies that at start up, the blocks must be read and their block sequence determined.</p>\r\n\r\n<h4>Performance</h4>\r\n\r\n<p>Times for 2kB read(units of 1uS).</p>\r\n\r\n<p>Operation</p>\r\n\r\n<p>Yaffs1</p>\r\n\r\n<p>Yaffs2 (512b pages)</p>\r\n\r\n<p>Yaffs2 (2kB pages)</p>\r\n\r\n<p>Yaffs2(2kB pages, x16)</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Seek</p>\r\n			</td>\r\n			<td>\r\n			<p>40</p>\r\n			</td>\r\n			<td>\r\n			<p>40</p>\r\n			</td>\r\n			<td>\r\n			<p>10</p>\r\n			</td>\r\n			<td>\r\n			<p>10</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Read</p>\r\n			</td>\r\n			<td>\r\n			<p>220</p>\r\n			</td>\r\n			<td>\r\n			<p>220</p>\r\n			</td>\r\n			<td>\r\n			<p>220</p>\r\n			</td>\r\n			<td>\r\n			<p>110</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Total</p>\r\n			</td>\r\n			<td>\r\n			<p>260</p>\r\n			</td>\r\n			<td>\r\n			<p>260</p>\r\n			</td>\r\n			<td>\r\n			<p>230</p>\r\n			</td>\r\n			<td>\r\n			<p>120</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>MB/s</p>\r\n			</td>\r\n			<td>\r\n			<p>7.6</p>\r\n			</td>\r\n			<td>\r\n			<p>7.6</p>\r\n			</td>\r\n			<td>\r\n			<p>8.7</p>\r\n			</td>\r\n			<td>\r\n			<p>16.7</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Relative speed</p>\r\n			</td>\r\n			<td>\r\n			<p>1</p>\r\n			</td>\r\n			<td>\r\n			<p>1</p>\r\n			</td>\r\n			<td>\r\n			<p>1.1</p>\r\n			</td>\r\n			<td>\r\n			<p>2.2</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>Times for 2kB writes(units of 1uS).</p>\r\n\r\n<p>Operation</p>\r\n\r\n<p>Yaffs1</p>\r\n\r\n<p>Yaffs2 (512b pages)</p>\r\n\r\n<p>Yaffs2 (2kB pages)</p>\r\n\r\n<p>Yaffs2(2kB pages, x16)</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Seek</p>\r\n			</td>\r\n			<td>\r\n			<p>40</p>\r\n			</td>\r\n			<td>\r\n			<p>40</p>\r\n			</td>\r\n			<td>\r\n			<p>10</p>\r\n			</td>\r\n			<td>\r\n			<p>10</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Program</p>\r\n			</td>\r\n			<td>\r\n			<p>800</p>\r\n			</td>\r\n			<td>\r\n			<p>800</p>\r\n			</td>\r\n			<td>\r\n			<p>200</p>\r\n			</td>\r\n			<td>\r\n			<p>200</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Seek</p>\r\n			</td>\r\n			<td>\r\n			<p>40</p>\r\n			</td>\r\n			<td>\r\n			<p>40</p>\r\n			</td>\r\n			<td>\r\n			<p>10</p>\r\n			</td>\r\n			<td>\r\n			<p>10</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Read</p>\r\n			</td>\r\n			<td>\r\n			<p>220</p>\r\n			</td>\r\n			<td>\r\n			<p>220</p>\r\n			</td>\r\n			<td>\r\n			<p>220</p>\r\n			</td>\r\n			<td>\r\n			<p>110</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Total</p>\r\n			</td>\r\n			<td>\r\n			<p>1320</p>\r\n			</td>\r\n			<td>\r\n			<p>1320</p>\r\n			</td>\r\n			<td>\r\n			<p>660</p>\r\n			</td>\r\n			<td>\r\n			<p>440</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>MB/s</p>\r\n			</td>\r\n			<td>\r\n			<p>1.5</p>\r\n			</td>\r\n			<td>\r\n			<p>1.5</p>\r\n			</td>\r\n			<td>\r\n			<p>3</p>\r\n			</td>\r\n			<td>\r\n			<p>4.5</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Relative speed</p>\r\n			</td>\r\n			<td>\r\n			<p>1</p>\r\n			</td>\r\n			<td>\r\n			<p>1</p>\r\n			</td>\r\n			<td>\r\n			<p>2</p>\r\n			</td>\r\n			<td>\r\n			<p>3</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>Times for 1MB delete (units of 1uS).</p>\r\n\r\n<p>Operation</p>\r\n\r\n<p>Yaffs1</p>\r\n\r\n<p>Yaffs2 (512b pages)</p>\r\n\r\n<p>Yaffs2 (2kB pages)</p>\r\n\r\n<p>Yaffs2(2kB pages, x16)</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Seek</p>\r\n			</td>\r\n			<td>\r\n			<p>20480</p>\r\n			</td>\r\n			<td>\r\n			<p>0</p>\r\n			</td>\r\n			<td>\r\n			<p>0</p>\r\n			</td>\r\n			<td>\r\n			<p>0</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Program</p>\r\n			</td>\r\n			<td>\r\n			<p>409600</p>\r\n			</td>\r\n			<td>\r\n			<p>0</p>\r\n			</td>\r\n			<td>\r\n			<p>0</p>\r\n			</td>\r\n			<td>\r\n			<p>0</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Erase</p>\r\n			</td>\r\n			<td>\r\n			<p>128000</p>\r\n			</td>\r\n			<td>\r\n			<p>128000</p>\r\n			</td>\r\n			<td>\r\n			<p>16000</p>\r\n			</td>\r\n			<td>\r\n			<p>16000</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Total</p>\r\n			</td>\r\n			<td>\r\n			<p>558080</p>\r\n			</td>\r\n			<td>\r\n			<p>128000</p>\r\n			</td>\r\n			<td>\r\n			<p>16000</p>\r\n			</td>\r\n			<td>\r\n			<p>16000</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>MB/s</p>\r\n			</td>\r\n			<td>\r\n			<p>1.8</p>\r\n			</td>\r\n			<td>\r\n			<p>7.8</p>\r\n			</td>\r\n			<td>\r\n			<p>62.5</p>\r\n			</td>\r\n			<td>\r\n			<p>62.5</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Relative speed</p>\r\n			</td>\r\n			<td>\r\n			<p>1</p>\r\n			</td>\r\n			<td>\r\n			<p>4</p>\r\n			</td>\r\n			<td>\r\n			<p>34</p>\r\n			</td>\r\n			<td>\r\n			<p>34</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>Times for 1MB of garbage collection at 50% dirty (units of 1uS).</p>\r\n\r\n<p>Operation</p>\r\n\r\n<p>Yaffs1</p>\r\n\r\n<p>Yaffs2 (512b pages)</p>\r\n\r\n<p>Yaffs2 (2kB pages)</p>\r\n\r\n<p>Yaffs2(2kB pages, x16)</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Delete 1MB</p>\r\n			</td>\r\n			<td>\r\n			<p>558080</p>\r\n			</td>\r\n			<td>\r\n			<p>128000</p>\r\n			</td>\r\n			<td>\r\n			<p>16000</p>\r\n			</td>\r\n			<td>\r\n			<p>16000</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Write 0.5MB</p>\r\n			</td>\r\n			<td>\r\n			<p>337920</p>\r\n			</td>\r\n			<td>\r\n			<p>337920</p>\r\n			</td>\r\n			<td>\r\n			<p>168960</p>\r\n			</td>\r\n			<td>\r\n			<p>112640</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Total</p>\r\n			</td>\r\n			<td>\r\n			<p>896000</p>\r\n			</td>\r\n			<td>\r\n			<p>465920</p>\r\n			</td>\r\n			<td>\r\n			<p>184960</p>\r\n			</td>\r\n			<td>\r\n			<p>128640</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>MB/s</p>\r\n			</td>\r\n			<td>\r\n			<p>1.1</p>\r\n			</td>\r\n			<td>\r\n			<p>2.1</p>\r\n			</td>\r\n			<td>\r\n			<p>5.4</p>\r\n			</td>\r\n			<td>\r\n			<p>7.7</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Relative speed</p>\r\n			</td>\r\n			<td>\r\n			<p>1</p>\r\n			</td>\r\n			<td>\r\n			<p>1.9</p>\r\n			</td>\r\n			<td>\r\n			<p>4.9</p>\r\n			</td>\r\n			<td>\r\n			<p>7</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\";s:7:\"summary\";s:323:\"<p>The initial specification for Yaffs version 2. Describes the development of Yaffs to deal with next-generation NAND chips which have larger (2Kb) pages and don\'t allow page rewrites. This newer design is be significantly faster (write: 1.5x-5x, delete: 4x, garbage collection: 2x) and has 25-50% lower RAM footfrint.</p>\";s:6:\"format\";s:9:\"full_html\";}}}s:19:\"field_document_type\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:9:\"target_id\";s:3:\"345\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:4:\"page\";s:2:\"id\";s:2:\"38\";s:8:\"revision\";s:3:\"571\";s:4:\"uuid\";s:36:\"10044baf-840c-421b-9888-e789cd7d53e3\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:21:\"Yaffs 2 Specification\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"3\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"571\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510657411.357,1,'entity_field_info node_values','866'),('values:node:380','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:19:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"381\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1441709157\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"5\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"380\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:4:\"page\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"8ac866f7-55a9-4957-9251-b56a24da9079\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:7:\"Support\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1330383366\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1441709157\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:806:\"<p>We offer support for Yaffs through the <a href=\"http://stoneboat.aleph1.co.uk/mailman/listinfo/yaffs\">Yaffs mailing list</a>. It\'s best to start by searching the <a href=\"http://www.aleph1.co.uk/lurker/list/yaffs.html\">list archive</a> to see if someone has already asked the same question.</p><p>If you feel uncomfortable asking your question on an open mailing list you can try mailing us, but we (or you) may say \'You should be paying for this\', and if that is agreed, then we can accept payments via PayPal or other means.</p><p>Serious long-term work is best done as a negotiated contract; for instance we have built special features for clients with very particular needs. If you think you may want this sort of help then <a href=\"/contact\">contact us</a>, telling us a bit about your problem.</p>\";s:7:\"summary\";s:189:\"<p>We offer support for Yaffs through the&nbsp;<a href=\"http://stoneboat.aleph1.co.uk/mailman/listinfo/yaffs\">Yaffs mailing list</a>. We also offer paid contracts for longer term needs.</p>\";s:6:\"format\";s:9:\"full_html\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:4:\"page\";s:2:\"id\";s:3:\"380\";s:8:\"revision\";s:3:\"381\";s:4:\"uuid\";s:36:\"8ac866f7-55a9-4957-9251-b56a24da9079\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:7:\"Support\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"381\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655093.546,1,'entity_field_info node_values','866'),('values:node:382','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:19:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"639\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1502716247\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"382\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:4:\"page\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"19de3020-5652-413a-b53d-9a026f380ae3\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:9:\"Get Yaffs\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1330444044\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1502716247\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:2270:\"<h2>Licences</h2>\r\n\r\n<p>Yaffs belongs to Aleph One Limited. It&nbsp;is available under two licences:</p>\r\n\r\n<ul>\r\n	<li>The <a href=\"https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html\">GPL Version 2</a> (GNU Public Licence, Version 2). You can try it for free under this licence, and you can use Yaffs&nbsp;in GPL licensed software.&nbsp;</li>\r\n	<li>A proprietary, <a href=\"commercial-licences\">commercial licence</a> from Aleph One Limited, for use with proprietary, or closed-source software.&nbsp;These licences are non-exclusive, perpetual, world-wide, royalty-free and paid for with a single fee for one product.</li>\r\n</ul>\r\n\r\n<p>Yaffs functionality is the same under both licences, and both licences are royalty-free, but the terms of the GPL place significant obligations on<strong>&nbsp;all who&nbsp;use Yaffs under GPL</strong>. Please be certain to <a href=\"/yaffs-gpl\">understand these legal obligations</a> before distributing any software together with Yaffs.</p>\r\n\r\n<h2>Download options</h2>\r\n\r\n<p>We use <a href=\"https://git-scm.com/\">Git</a> to manage our software development.</p>\r\n\r\n<ul>\r\n	<li>To browse or download code,&nbsp;<strong><a href=\"http://www.aleph1.co.uk/gitweb?p=yaffs2.git;a=summary\" target=\"_self\">access our Git repository over the web</a></strong>. This is also the best option if you are behind a firewall that does not allow direct Git&nbsp;access.</li>\r\n	<li>To get a tarball of the top of the tree, just click \'snapshot\' for the release that you want, or to quickly obtain a snapshot of the top of the tree you can <a href=\"http://aleph1.co.uk/gitweb?p=yaffs2.git;a=snapshot;h=HEAD;\" target=\"_self\">use this URL</a>.</li>\r\n	<li>Clone Yaffs using:</li>\r\n</ul>\r\n\r\n<pre>\r\ngit clone git://www.aleph1.co.uk/yaffs2\r\n</pre>\r\n\r\n<ul>\r\n	<li>If you are a registered developer with a server account you can get read/write access using:</li>\r\n</ul>\r\n\r\n<pre>\r\ngit clone ssh://www.aleph1.co.uk/home/aleph1/git/yaffs2</pre>\r\n\r\n<p>&nbsp;&nbsp;</p>\r\n\r\n<p wrap=\"\">If you have any questions, or would like to buy a commercial licence, please contact us either at&nbsp;+44 (0)1223 811679 or email&nbsp; sales@aleph1.co.uk&nbsp; or see our Contacts page:-&nbsp; <a href=\"http://www.aleph1.co.uk/contact\">http://www.aleph1.co.uk/contact</a></p>\r\n\";s:7:\"summary\";s:441:\"<p>For experimental purposes you can grab Yaffs free of charge right now&nbsp;<a href=\"/download-yaffs-using-git\">from our GIT repository</a>.</p><p>If you distribute a product using Yaffs you must release all your linked source code in accordance with the <a href=\"http://www.gnu.org/licenses/gpl-2.0.html\">GNU General Public Licence</a>. Alternatively if you do not wish to disclose your Source Code, commercial licences are available.</p>\";s:6:\"format\";s:9:\"full_html\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:4:\"page\";s:2:\"id\";s:3:\"382\";s:8:\"revision\";s:3:\"639\";s:4:\"uuid\";s:36:\"19de3020-5652-413a-b53d-9a026f380ae3\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:9:\"Get Yaffs\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"639\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510654669.698,1,'entity_field_info node_values','866'),('values:node:384','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"385\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1430391793\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"384\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"664b09ab-a5dc-4e2f-9889-9a8f61b0017c\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:16:\"Royalty Free... \";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1330455802\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1498518115\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:342:\"<p><strong>100% ROYALTY FREE</strong></p>\r\n\r\n<p>Of course there\'s no royalty when you use Yaffs under the GPL; it\'s the GPL!</p>\r\n\r\n<p>Our commercial licences are paid for once at the time of buying the Licence, and so they are also royalty free. No accounting and no need to worry about increasing costs as you make or sell more units.</p>\r\n\";s:7:\"summary\";s:177:\"Whether you use Yaffs under the GNU General Public Licence or under a commercial licence, Yaffs is free of any royalty. No need to worry about rising costs for your hit product!\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:12:\"fa-thumbs-up\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"384\";s:8:\"revision\";s:3:\"385\";s:4:\"uuid\";s:36:\"664b09ab-a5dc-4e2f-9889-9a8f61b0017c\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:16:\"Royalty Free... \";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"385\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.803,1,'entity_field_info node_values','866'),('values:node:385','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"386\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1354548038\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"385\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"dc36c8cd-8e9f-468a-91dd-af26f383fa03\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:29:\"A robust flash file system...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1330456244\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496412025\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:400:\"<p>As part of our regular testing, we run power-fail tests. Whether it\'s during a read or a write, Yaffs is designed to preserve your existing data during a device power failure. And because Yaffs is open source, you can download the tests and run them yourself in the most severe conditions you expect the product to encounter. See:- http://www.yaffs.net/documents/yaffs-robustness-and-testing</p>\r\n\";s:7:\"summary\";s:135:\"After more than 100,000 <strong>random</strong> power-failures during reading or writing, a test file showed NO data corruption at all!\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:9:\"fa-shield\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"385\";s:8:\"revision\";s:3:\"386\";s:4:\"uuid\";s:36:\"dc36c8cd-8e9f-468a-91dd-af26f383fa03\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:29:\"A robust flash file system...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"386\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.817,1,'entity_field_info node_values','866'),('values:node:388','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"389\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1430391671\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"388\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"44690426-a9a6-466e-adb5-e4e58521c2be\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:23:\"Yaffs is Open Source...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1330467790\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496401931\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:590:\"<p>Yaffs is downloadable with a GNU General Public Licence v.2, as at&nbsp; http://www.gnu.org/licenses/gpl-2.0.html&nbsp;&nbsp; You get the source code, with all the benefits that brings. And of course, if you buy a commercial licence, you get the source code too, but without the encumberance of your responsibilities under the GNU GPL</p>\r\n\r\n<p>Because it\'s Open Source, you can always see what the code is doing and trace through; and having the code means you\'ll never be in a situation where you are critically dependent on us, either from a technical or a business perspective.</p>\r\n\";s:7:\"summary\";s:168:\"You can have a look at the code at any time. <a title=\"Get it now!\" href=\"/downloads\">Download it now</a>! And it\'s suitable for GPL and commercially licensed projects.\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:8:\"fa-heart\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"388\";s:8:\"revision\";s:3:\"389\";s:4:\"uuid\";s:36:\"44690426-a9a6-466e-adb5-e4e58521c2be\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:23:\"Yaffs is Open Source...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"389\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.820,1,'entity_field_info node_values','866'),('values:node:389','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"390\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1378306103\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"389\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"d884956b-47ae-45e1-bb19-25349e1f14db\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:42:\"Tried and tested in millions of devices...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1330468194\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496407203\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:368:\"<p>Yaffs is the leading Flash file system, running in millions of devices. It\'s been used on Linux computers, in cameras, mobile phones, hard drives, and on many custom boards. People and companies trust it to keep their data safe. Read more about <a href=\"/documents/yaffs-robustness-and-testing\">how we test Yaffs in our Robustness and Testing white paper</a>.</p>\r\n\";s:7:\"summary\";s:177:\"Yaffs is widely used in Linux and proprietary commercial RTOSs. It\'s been included in hundreds of devices, and shipped as part of Google\'s Android, with millions of units sold. \";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:15:\"fa-mobile-phone\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"389\";s:8:\"revision\";s:3:\"390\";s:4:\"uuid\";s:36:\"d884956b-47ae-45e1-bb19-25349e1f14db\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:42:\"Tried and tested in millions of devices...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"390\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.823,1,'entity_field_info node_values','866'),('values:node:39','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"572\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1496365925\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:2:\"39\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:4:\"page\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"a403e5ec-a8d5-45be-aa0c-7201aabd03f2\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:32:\"Yaffs (Yaffs1) Development Notes\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1116848206\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496365925\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:18795:\"<p><em>These notes relate to Yaffs1. Yaffs version 2, or Yaffs2, is the current version of Yaffs. While many of the details below remain the same, you can find up to date information split between the How Yaffs Works, Yaffs Tuning and Yaffs Direct documents.</em></p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<h2>Build options</h2>\r\n\r\n<p>Yaffs1 can be built as either a kernel module (ie. a Linux file system) or as an application.</p>\r\n\r\n<p>Of course the goal is to build Yaffs as a file system running on top of real NAND flash, but yaffs can be built to run on a RAM emulation layer for in-kernel testing without NAND flash in the system.</p>\r\n\r\n<p>Building as an application allows the yaffs_guts algorithms to be tested/debugged in a more friendly debugging environment. The test harness is in yaffsdev.c</p>\r\n\r\n<h3>Trying it out</h3>\r\n\r\n<p>Yaffs1 can be built to run with either mtd or RAM emulation, or both. The file system that interfaces to mtd is called <strong>yaffs</strong>, the file system that uses internal ram is called <strong>yaffsram</strong>. Yaffs1 simultaneously supports both if they are enabled.</p>\r\n\r\n<ol>\r\n	<li>\r\n	<p>Hack the Makefile and change the KERNELDIR define to your kernel directory.</p>\r\n	</li>\r\n	<li>\r\n	<p>If you don\'t have mtd support in your kernel, then you might need to turn off USE_MTD otherwise the Yaffs module might not load.</p>\r\n	</li>\r\n	<li>\r\n	<p>Type <strong>make clean; make</strong> to build yaffs</p>\r\n	</li>\r\n	<li>\r\n	<p>Load Yaffs as a module by typing <strong>/sbin/insmod yaffs.o</strong> (ya gotta be root!).</p>\r\n	</li>\r\n	<li>\r\n	<p>Create a mount point eg. <strong>mkdir /mnt/y</strong></p>\r\n	</li>\r\n	<li>\r\n	<p>To mount the RAM emulation version of yaffs, <strong>mount -t yaffsram none /mnt/y</strong></p>\r\n	</li>\r\n	<li>\r\n	<p>Alternatively, to mount the mtd version of yaffs,<strong> mount -t yaffs /dev/mtd0 /mnt/y</strong></p>\r\n	</li>\r\n</ol>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h3>Yaffs1 Data structures</h3>\r\n\r\n<p>All data types are defined in yaffs_guts.h</p>\r\n\r\n<p>Yaffs1 uses the following major objects:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>yaffs_Object: A yaffs_Object can be a file, directory, symlink or hardlink. The yaffs_Objects \"know\" about their corresponding yaffs_ObjectHeader in NAND and the data for that object. yaffs_Objects also bind together the directory structure as follows:</p>\r\n	</li>\r\n	<li>\r\n	<p>parent: pointer to the yaffs_Object that is a parent of this yaffs_Object in the directory structure.</p>\r\n	</li>\r\n	<li>\r\n	<p>siblings: this field is used to link together a list of all the yaffs_Objects in the same directory.</p>\r\n	</li>\r\n	<li>\r\n	<p>children: if the object is a directory, then children holds the head of the list of objects in the directory.</p>\r\n	</li>\r\n	<li>\r\n	<p>yaffs_Tnode: yaffs_Tnodes form a tree structure that speeds up the search for data chunks in a file. As the file grows in size, the levels increase. The Tnodes are a constant size (32 bytes). Level 0 (ie the lowest level) comprise 16 2-byte entries giving an index used to search for the chunkId. Tnodes at other levels comprise 8 4-byte pointer entries to other tnodes lower in the tree.</p>\r\n	</li>\r\n	<li>\r\n	<p>yaffs_Device: this holds the device context and is in some ways analogous to the VFS superblock. It stores the data used to access the mtd as well as function pointers to access the NAND data.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>The Tnodes and Objects are allocated in groups to reduce memory allocation/freeing overheads. Freed up tnodes and objects are kept in a free list and re-used.</p>\r\n\r\n<h3>yaffs_Object</h3>\r\n\r\n<p>struct yaffs_ObjectStruct</p>\r\n\r\n<p>{</p>\r\n\r\n<p>__u8 fake:1; // A fake object has no presence on NAND.</p>\r\n\r\n<p>__u8 renameAllowed:1; // Are we allowed to rename it?</p>\r\n\r\n<p>__u8 unlinkAllowed:1; // Are we allowed to unlink it?</p>\r\n\r\n<p>__u8 dirty:1; // the object needs to be written to flash</p>\r\n\r\n<p>__u8 valid:1; // When the file system is being loaded up, this</p>\r\n\r\n<p>// object might be created before the data</p>\r\n\r\n<p>// is available (ie. file data records appear before the header).</p>\r\n\r\n<p>__u8 serial; // serial number of chunk in NAND. Store here so we don\'t have to</p>\r\n\r\n<p>// read back the old one to update.</p>\r\n\r\n<p>__u16 sum; // sum of the name to speed searching</p>\r\n\r\n<p>struct yaffs_DeviceStruct *myDev; // The device I\'m on</p>\r\n\r\n<p>struct list_head hashLink; // list of objects in this hash bucket</p>\r\n\r\n<p>struct list_head hardLinks; // all the equivalent hard linked objects</p>\r\n\r\n<p>// live on this list</p>\r\n\r\n<p>// directory structure stuff</p>\r\n\r\n<p>struct yaffs_ObjectStruct *parent; //my parent directory</p>\r\n\r\n<p>struct list_head siblings; // siblings in a directory</p>\r\n\r\n<p>// also used for linking up the free list</p>\r\n\r\n<p>// Where\'s my data in NAND?</p>\r\n\r\n<p>int chunkId; // where it lives</p>\r\n\r\n<p>__u32 objectId; // the object id value</p>\r\n\r\n<p>__u32 st_mode; // protection</p>\r\n\r\n<p>__u32 st_uid; // user ID of owner</p>\r\n\r\n<p>__u32 st_gid; // group ID of owner</p>\r\n\r\n<p>__u32 st_atime; // time of last access</p>\r\n\r\n<p>__u32 st_mtime; // time of last modification</p>\r\n\r\n<p>__u32 st_ctime; // time of last change</p>\r\n\r\n<p>yaffs_ObjectType variantType;</p>\r\n\r\n<p>yaffs_ObjectVariant variant;</p>\r\n\r\n<p>};</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>Obvious stuff skipped....</p>\r\n\r\n<p>fake, renameAllowed, unlinkAllowed are special flags for handling \"fake\" objects which live in the file system but do not live on NAND. Currently there are only two such objects: the root object and the lost+found directory. None of these may be renamed or unlinked.</p>\r\n\r\n<p>serial, sum: see yaffs_ObjectHeader.</p>\r\n\r\n<p>dirty indicates that the object\'s contents has changed and a new yaffs_ObjectHeader must be written to flash.</p>\r\n\r\n<p>valid indicates that the object has been loaded up. This is only used during scanning (yaffs_Scan()) since we can know of an object\'s existance - and thus need to create the object header - before we encounter the associated yaffs_ObjectHeader.</p>\r\n\r\n<p>hashlink is a list of Objects in the same hash bucket.</p>\r\n\r\n<p>The four variants hold extra info:</p>\r\n\r\n<p>Files hold the file size and the top level and pointer to the tnode tree for the file.</p>\r\n\r\n<p>Directories hold a list of children objects.</p>\r\n\r\n<p>Symlinks hold a pointer to the alias string. This is probably inefficient, but that probably does not matter since we don\'t expect to see many of these.</p>\r\n\r\n<p>Hardlinks hold information to identify the equivalent object.</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<h3>File structure (tnodes)</h3>\r\n\r\n<p>File structures are done with a tiered indexing structure</p>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p><img alt=\"\" height=\"294\" src=\"http://www.aleph1.co.uk/yaffs/sv9349341.gif\" width=\"491\" /><br />\r\n<br />\r\n&nbsp;</p>\r\n\r\n<p>The file structure is maintained by a tree structure. Depending where it is in the tree, each tree node (<strong><em>tnode</em></strong>) (the blue/things) holds either:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>.... if it is at the lowest level, then 16 __u16s which identify the page.</p>\r\n	</li>\r\n	<li>\r\n	<p>.... if it is at a higher level (ie an internal tnode), then 8 pointers to lowest-level tnodes.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>When the file starts out, it is assigned only one low-level tnode. When the file expands past what a single tnode can hold, then it is assigned a second tnode and an internal node is added to point to the two tnodes. As the file grows, more low-level tnodes and high level tnodes are added.</p>\r\n\r\n<p>Traversing the tnode tree to find a particular page in a file is quite simple: each internal tnode is selected from by using 3 bits of the page offset in the file. The level 0 page resolves 4 bits.</p>\r\n\r\n<p>For example, finding page 0x235 (ie. the one starting at file position 0x46800 would proceed as follows:</p>\r\n\r\n<p>0x235 is 0000001000110101, partitioned as follows. 000.000.100.011.0101</p>\r\n\r\n<p>Level</p>\r\n\r\n<p>Bits</p>\r\n\r\n<p>Selected value</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>3 or more if they exist</p>\r\n			</td>\r\n			<td>\r\n			<p>&gt;= 10</p>\r\n			</td>\r\n			<td>\r\n			<p>Zero</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>2</p>\r\n			</td>\r\n			<td>\r\n			<p>9 to 7</p>\r\n			</td>\r\n			<td>\r\n			<p>100 binary = 4</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>1</p>\r\n			</td>\r\n			<td>\r\n			<p>6 to 4</p>\r\n			</td>\r\n			<td>\r\n			<p>011 binary = 3</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>0</p>\r\n			</td>\r\n			<td>\r\n			<p>3 to 0</p>\r\n			</td>\r\n			<td>\r\n			<p>0101 binary = 5</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\nFree tnodes are stored in a list. When the list is exhausted, more are allocated.</p>\r\n\r\n<p>Each tnode takes 32 bytes. Each file needs at least one level 0 tnode. How many do we need? A full 16MB file system needs at least 16MB/512/16 = 2000 level zero tnodes. More for internal tnodes. More for files smaller than optimal.</p>\r\n\r\n<p>The tree grows as required. When the file is resized to a smaller size then it is pruned.</p>\r\n\r\n<h3>NAND data</h3>\r\n\r\n<p>Data is stored on NAND in \"chunks\". Currently each chunk is the same size as a NAND flash page (ie. 512 bytes + 16 byte spare). In the future we might decide to allow for different chunk sizes. Chunks can hold either:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>A yaffs_ObjectHeader. This is the way a yaffs_Object gets stored on NAND.</p>\r\n	</li>\r\n	<li>\r\n	<p>A chunk of file data.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>The 16 byte spare area contains:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>8 bytes of tags,</p>\r\n	</li>\r\n	<li>\r\n	<p>6 bytes of ECC data</p>\r\n	</li>\r\n	<li>\r\n	<p>1 byte block status (used to identify damaged blocks)</p>\r\n	</li>\r\n	<li>\r\n	<p>1 byte data status (currently unused).</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>The tags are made up as follows:</p>\r\n\r\n<p>typedef struct</p>\r\n\r\n<p>{</p>\r\n\r\n<p>unsigned chunkId:20; //chunk number in file</p>\r\n\r\n<p>unsigned serialNumber:2; //serial number for chunk</p>\r\n\r\n<p>unsigned byteCount:10; //number of bytes of data used in this chunk</p>\r\n\r\n<p>unsigned objectId:18; //the object id that this chunk belongs to.</p>\r\n\r\n<p>unsigned ecc:12; //ECC on tags</p>\r\n\r\n<p>unsigned unusedStuff:2; //unused</p>\r\n\r\n<p>} yaffs_Tags;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>A chunkId of zero indicates that this chunk holds a yaffs_ObjectHeader. A non zero value indicates that this is a data chunk and the position of the chunk in the file (ie. the first chunk - at offset 0 - has chunkId 1). See yaffs_guts.c:yaffs_Scan () to see how this is done.</p>\r\n\r\n<p>When a chunk is repalced (eg. file details changed or a part of a file was overwritten), the new chunk is written before the old chunk is deleted. This means that we don\'t lose data if there is a power loss after the new chunk is created but before the old one is discarded, but it does mean that we can encounter the situation where we find both the old and the new chunks in flash. The serialNumber is incremented each time the chunk is written. 2 bits is sufficient to resolve any ambiguity.</p>\r\n\r\n<p>bytecount applies only to data chunks and tells how many of the data bytes are valid.</p>\r\n\r\n<p>objectId says which object this chunk belongs to.</p>\r\n\r\n<p>ecc is used to perform error correction on the tags. Another ecc field is used to error correct the data.</p>\r\n\r\n<h3>yaffs_ObjectHeader</h3>\r\n\r\n<p>typedef struct</p>\r\n\r\n<p>{</p>\r\n\r\n<p>yaffs_ObjectType type;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>// Apply to everything</p>\r\n\r\n<p>int parentObjectId;</p>\r\n\r\n<p>__u16 sum; // checksum of name</p>\r\n\r\n<p>char name[YAFFS_MAX_NAME_LENGTH + 1];</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>// Thes following apply to directories, files, symlinks - not hard links</p>\r\n\r\n<p>__u32 st_mode; // protection</p>\r\n\r\n<p>__u32 st_uid; // user ID of owner</p>\r\n\r\n<p>__u32 st_gid; // group ID of owner</p>\r\n\r\n<p>__u32 st_atime; // time of last access</p>\r\n\r\n<p>__u32 st_mtime; // time of last modification</p>\r\n\r\n<p>__u32 st_ctime; // time of last change</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>// File size applies to files only</p>\r\n\r\n<p>int fileSize;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>// Equivalent object id applies to hard links only.</p>\r\n\r\n<p>int equivalentObjectId;</p>\r\n\r\n<p>// alias only applies to symlinks</p>\r\n\r\n<p>char alias[YAFFS_MAX_ALIAS_LENGTH + 1];</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>} yaffs_ObjectHeader;</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>A yaffs_ObjectHeader is stored in NAND for every yaffs_Object.</p>\r\n\r\n<p>type holds the type of yaffs_Object (file,directory,hardlink or symlink).</p>\r\n\r\n<p>parentObject is the objectId of this object\'s parent. name holds the object\'s name. Together these form the directory structure of the file system. Also worth mention is sum. This is a \"checksum\" on the name which speeds directory searching (ie. when searching the directory we only compare the name for those entries where sum matches).</p>\r\n\r\n<p>Obvious stuff skipped....</p>\r\n\r\n<p>equivalentObjectId is used by hardlinks. A hardlink to an object uses this field to specify the object that this links to. This way of doing things is a bit different than the normal Linux way of doing things (ie. keeping the links distinct from the inode) but is simpler and uses less space except for a few corner cases with hardlinks.</p>\r\n\r\n<p>alias is used by symlinks to hold the symlink alias string. This limits the size of the symlink alias. In future we should expand Yaffs1 to use data chunks to store aliases too long to fit into the yaffs_ObjectHeader.</p>\r\n\r\n<h3>NAND Interface</h3>\r\n\r\n<p>All NAND access is performed via four functions pointed to by yaffs_Device. At the moment a chunk is a page.</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>int WriteChunkToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare)</p>\r\n	</li>\r\n	<li>\r\n	<p>int ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);</p>\r\n	</li>\r\n	<li>\r\n	<p>int EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND);</p>\r\n	</li>\r\n	<li>\r\n	<p>int InitialiseNAND(struct yaffs_DeviceStruct *dev);</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>In the Readxxx and Writexxx functions, the data and/or spare pointers may be NULL in which case these data transfers are ignored.</p>\r\n\r\n<p>A quick note about NAND:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>NAND is not random access, but page oriented. Thus, we do all reads &amp; writes in pages.</p>\r\n	</li>\r\n	<li>\r\n	<p>Each NAND page holds 512 bytes of data and 16 \"spare\" bytes. Yaffs structures the spare area with tags used to identify what is stored in the data area. There are 32 such pages to a block.</p>\r\n	</li>\r\n	<li>\r\n	<p>NAND writes will only change 1 bits to 0. eg. if a byte holds 10110011 and you write 11011010 to it you will get the logical and of the two values: 10010010. The only way to get 1s again is to erase the entire block.</p>\r\n	</li>\r\n	<li>\r\n	<p>You may only write to a page a few times before erasing the entire block. Yaffs lives within these limitations. Each page only gets written to twice (once when written and once when discarded).</p>\r\n	</li>\r\n	<li>\r\n	<p>ECC is normally used with NAND to correct for single bit errors. Yaffs1 applies the ECC itself, so the MTD should not do this.</p>\r\n	</li>\r\n	<li>\r\n	<p>The current mtd interfaces are not particularly well suited to Yaffs1 and we will address the issue with the mtd group. (The mtd interface does not support page-oriented read/write which Yaffs1 would prefer).</p>\r\n	</li>\r\n</ul>\r\n\r\n<h3>mkyaffs</h3>\r\n\r\n<p>mkyaffs is the tool to format a NAND mtd to be used for Yaffs1. This is quite simple, just erase all the undamaged blocks. Yaffs1 treats erased blocks as free (empty) space.</p>\r\n\r\n<h2>Expected performance</h2>\r\n\r\n<p>The following numbers should give an indication of the performance we should expect from Yaffs1.</p>\r\n\r\n<p>As an example, I\'ll use the following numbers. Since the hardware is capable of 50ns read/write, these numbers allow for some other ovberheads. Clearly though, the performance can be degraded in various ways.</p>\r\n\r\n<p>Seek</p>\r\n\r\n<p>10uS/page</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Read</p>\r\n			</td>\r\n			<td>\r\n			<p>100nS/byte</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Write</p>\r\n			</td>\r\n			<td>\r\n			<p>100nS/byte</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Program</p>\r\n			</td>\r\n			<td>\r\n			<p>200uS/page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Erase</p>\r\n			</td>\r\n			<td>\r\n			<p>2mS/block</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>From this we can derive some higher-level numbers:</p>\r\n\r\n<p>Operation</p>\r\n\r\n<p>Time</p>\r\n\r\n<p>Calculation</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Read spare</p>\r\n			</td>\r\n			<td>\r\n			<p>12uS</p>\r\n			</td>\r\n			<td>\r\n			<p>seek + 16 * read</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Read page</p>\r\n			</td>\r\n			<td>\r\n			<p>63 uS</p>\r\n			</td>\r\n			<td>\r\n			<p>seek + 528 * read</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Write page</p>\r\n			</td>\r\n			<td>\r\n			<p>326 uS</p>\r\n			</td>\r\n			<td>\r\n			<p>seek + 528 * write + program + read page (for verification)</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Discard page</p>\r\n			</td>\r\n			<td>\r\n			<p>212 uS</p>\r\n			</td>\r\n			<td>\r\n			<p>seek + 16 * write + program</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Overwrite page</p>\r\n			</td>\r\n			<td>\r\n			<p>538 uS</p>\r\n			</td>\r\n			<td>\r\n			<p>write page + discard page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Erase overhead per page</p>\r\n			</td>\r\n			<td>\r\n			<p>63uS</p>\r\n			</td>\r\n			<td>\r\n			<p>erase/32</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p><br />\r\n&nbsp;</p>\r\n\r\n<p>From this we can infer the following flash access times:</p>\r\n\r\n<p>Operation</p>\r\n\r\n<p>Time</p>\r\n\r\n<p>Calculation</p>\r\n\r\n<table>\r\n	<tbody>\r\n		<tr>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Read 1MB file</p>\r\n			</td>\r\n			<td>\r\n			<p>0.13s (about 7.5 MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * read page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Write 1MB (clean system)</p>\r\n			</td>\r\n			<td>\r\n			<p>0.53s (about 1.8 MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * write page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Overwrite 1MB file (no gc)</p>\r\n			</td>\r\n			<td>\r\n			<p>1.08s (about 0.9MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * overwrite page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Overwrite 1MB with 50% gc</p>\r\n			</td>\r\n			<td>\r\n			<p>2.4s (about 0.4 MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * overwrite page + 2000 * page copy (== overwrite page) + 4000 * erase overhead</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Delete 1MB file</p>\r\n			</td>\r\n			<td>\r\n			<p>0.43s (about 2.2 MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * discard page</p>\r\n			</td>\r\n		</tr>\r\n		<tr>\r\n			<td>\r\n			<p>Delete 1MB file with 50% gc</p>\r\n			</td>\r\n			<td>\r\n			<p>0.49s (about 2.0MB/s)</p>\r\n			</td>\r\n			<td>\r\n			<p>2000 * discard page + 1000 * erase overhead</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p>&nbsp;</p>\r\n\";s:7:\"summary\";s:179:\"<p>Notes on how to use Yaffs (Yaffs1) and some details of the internal structures - useful if you want to mess with the code. This document is included in the Yaffs1 download.</p>\";s:6:\"format\";s:9:\"full_html\";}}}s:19:\"field_document_type\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:9:\"target_id\";s:3:\"346\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:4:\"page\";s:2:\"id\";s:2:\"39\";s:8:\"revision\";s:3:\"572\";s:4:\"uuid\";s:36:\"a403e5ec-a8d5-45be-aa0c-7201aabd03f2\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:32:\"Yaffs (Yaffs1) Development Notes\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"572\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510657444.840,1,'entity_field_info node_values','866'),('values:node:390','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:18:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"391\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1330473626\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"390\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"image\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"46ab1fa6-0fc5-4da5-8ea9-bcaca47dde18\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:13:\"Get YAFFS now\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1330473626\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1330473626\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"image\";s:2:\"id\";s:3:\"390\";s:8:\"revision\";s:3:\"391\";s:4:\"uuid\";s:36:\"46ab1fa6-0fc5-4da5-8ea9-bcaca47dde18\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:13:\"Get YAFFS now\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"391\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1512113278.327,1,'entity_field_info node_values','866'),('values:node:391','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:18:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"392\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1330522429\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"391\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"image\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"d2df8049-af19-4ced-80ce-04059782c082\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:13:\"Get YAFFS now\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1330522429\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1330522429\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"image\";s:2:\"id\";s:3:\"391\";s:8:\"revision\";s:3:\"392\";s:4:\"uuid\";s:36:\"d2df8049-af19-4ced-80ce-04059782c082\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:13:\"Get YAFFS now\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"392\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1512113278.316,1,'entity_field_info node_values','866'),('values:node:397','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"398\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1336591220\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"397\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:15:\"yaffs_user_logo\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"73d2bdce-bc12-4215-8b33-d7478f7248a5\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:18:\"Design Electronics\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1336589997\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496412075\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:37:\"<p>Design Electronics use Yaffs</p>\r\n\";s:7:\"summary\";s:28:\"Design Electronics use Yaffs\";s:6:\"format\";s:10:\"basic_html\";}}}s:21:\"field_yaffs_user_logo\";a:1:{s:9:\"x-default\";a:1:{i:0;a:5:{s:9:\"target_id\";s:2:\"40\";s:3:\"alt\";s:0:\"\";s:5:\"title\";s:0:\"\";s:5:\"width\";s:3:\"427\";s:6:\"height\";s:3:\"302\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:15:\"yaffs_user_logo\";s:2:\"id\";s:3:\"397\";s:8:\"revision\";s:3:\"398\";s:4:\"uuid\";s:36:\"73d2bdce-bc12-4215-8b33-d7478f7248a5\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:18:\"Design Electronics\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"398\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.555,1,'entity_field_info node_values','866'),('values:node:398','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"399\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1336605810\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"398\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:15:\"yaffs_user_logo\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"6444ad81-8e37-4969-8a5c-17807309c46b\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:5:\"Eaton\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1336605810\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496412157\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:24:\"<p>Eaton use Yaffs</p>\r\n\";s:7:\"summary\";s:15:\"Eaton use Yaffs\";s:6:\"format\";s:10:\"basic_html\";}}}s:21:\"field_yaffs_user_logo\";a:1:{s:9:\"x-default\";a:1:{i:0;a:5:{s:9:\"target_id\";s:2:\"46\";s:3:\"alt\";s:0:\"\";s:5:\"title\";s:0:\"\";s:5:\"width\";s:3:\"591\";s:6:\"height\";s:3:\"249\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:15:\"yaffs_user_logo\";s:2:\"id\";s:3:\"398\";s:8:\"revision\";s:3:\"399\";s:4:\"uuid\";s:36:\"6444ad81-8e37-4969-8a5c-17807309c46b\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:5:\"Eaton\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"399\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.557,1,'entity_field_info node_values','866'),('values:node:399','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"400\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1336605985\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"399\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:15:\"yaffs_user_logo\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"a5c10bec-5f10-4c54-9cd0-09ca8b4cc0af\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:13:\"LANCOM Sytems\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1336605955\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1494601211\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:34:\"<p>Lancom Systems use Yaffs.</p>\r\n\";s:7:\"summary\";s:0:\"\";s:6:\"format\";s:10:\"basic_html\";}}}s:21:\"field_yaffs_user_logo\";a:1:{s:9:\"x-default\";a:1:{i:0;a:5:{s:9:\"target_id\";s:2:\"43\";s:3:\"alt\";s:0:\"\";s:5:\"title\";s:0:\"\";s:5:\"width\";s:4:\"2118\";s:6:\"height\";s:3:\"531\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:15:\"yaffs_user_logo\";s:2:\"id\";s:3:\"399\";s:8:\"revision\";s:3:\"400\";s:4:\"uuid\";s:36:\"a5c10bec-5f10-4c54-9cd0-09ca8b4cc0af\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:13:\"LANCOM Sytems\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"400\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.559,1,'entity_field_info node_values','866'),('values:node:40','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"551\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1495718291\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:2:\"40\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:4:\"page\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"14126930-0e90-4638-b0bd-2d36a20eb26d\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:32:\"HOWTO incorporate YAFFS in Linux\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1116848477\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1495718291\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:4706:\"<h1>Brief HOWTO on incorporating yaffs as a root fs.</h1>\r\n<h4>By N C Bane &lt;nick@cecomputing.co.uk&gt;</h4>\r\n<h3>Document status</h3>\r\n<p>\r\nThis document is very much work in progress. It currently refers to YAFFS1 and needs updating for YAFFS2. It has been edited by different people with no attempt to keep a consistent style. Beauty will come with age.\r\n</p>\r\n<h2>What is yaffs?</h2>\r\n<p>\r\nYaffs stands for Yet Another Flash Filing System.\r\n</p>\r\n<p>\r\nIt is a journaling filesystem designed to run on NAND flash with special reference to embedded systems.\r\n</p>\r\n<h2>Why would I want to use it?</h2>\r\n<p>\r\nNAND flash (SmartMedia cards are repackaged raw NAND chips) is cheap and has a fast erase time as compared with NOR flash.\r\n</p>\r\n<p>\r\nThe NAND physical interface is very simple.\r\n</p>\r\n<p>\r\nThe small size and low current requirements make it very suitable for embedded systems.\r\n</p>\r\n<p>\r\nHowever, NAND has its problems. These are mainly due to bad block management as blocks of memory can be bad when the device is shipped and further blocks can become unusable over time.\r\n</p>\r\n<p>\r\nPower can die unpredictably in embedded systems leading to data loss and possibly file system corruption.\r\n</p>\r\n<p>\r\nThis is where yaffs comes in; it handles bad blocks and uses formats which are resistant to corruption.\r\n</p>\r\n<h2>What do I need to know?</h2>\r\n<p>\r\nIt is assumed that the reader has a development system with direct access to NAND flash (ie not a CF/SmartMedia adaptor which).\r\n</p>\r\n<p>\r\nThe user should be familiar with building linux kernels and patching build trees.\r\n</p>\r\n<p>\r\nIt is strongly suggested that you also read more about NAND flash on the Linux mtd site.\r\n</p>\r\n<h3>Assumptions:</h3>\r\n<p>\r\nYou have already downloaded the yaffs sources from the cvs at Aleph1.\r\n</p>\r\n<p>\r\nYou have mtd code that exposes NAND as an mtdblock device.\r\n</p>\r\n<h3>Nand interface:</h3>\r\n<p>\r\nFor yaffs to function, it must be able to be the only code that writes to the oob area on the NAND device.\r\n</p>\r\n<p>\r\nThe existing NAND driver in kernel 2.4.19 assumes that it will do the ecc/oob management for the host fs. For yaffs, this is quite wrong.\r\n</p>\r\n<p>\r\nYou can disable ecc/oob calculations either by hand patching the mtd code to bypass ecc calculations or by merging the latest mtd cvs.\r\n</p>\r\n<p>\r\nThe patches at http://www.toby-churchill.org have done the latter.\r\n</p>\r\n<h3>Including yaffs as a kernel fs:</h3>\r\n<p>\r\n1) Create [linux]/fs/yaffs directory in your kernel test source.\r\n</p>\r\n<p>\r\n2) Copy devextras.h yaffs_fs.c yaffs_gets.c yaffs_guts.h yaffs_mtdif.c yaffs_mtdif.h yaffsinterface.h and yportenv.h from the yaffs sources to that directory.\r\n</p>\r\n<p>\r\n3) Copy the Makefile from either the yaffs sources (Makefile.kernel) or the Balloon download site below to [linux]/fs/yaffs/Makefile.\r\n</p>\r\n<p>\r\n4) Modify [linux]/fs/Config.in to include the 3 lines\r\n</p>\r\n<p>\r\n<br />\r\n</p>\r\n<p>\r\nif [ &quot;CONFIG_MTD_NAND&quot; = &quot;y&quot; ]; then\r\n</p>\r\n<p>\r\n    tristate &quot;Yaffs filesystem on NAND&quot; CONFIG_YAFFS_FS\r\n</p>\r\n<p>\r\nfi\r\n</p>\r\n<p>\r\n5) Modify [linux]/fs/Makefile to include the yaffs fs reference\r\n</p>\r\n<p>\r\n<br />\r\n</p>\r\n<p>\r\n subdir-$(CONFIG_YAFFS_FS) +=yaffs\r\n</p>\r\n<p>\r\n<br />\r\n</p>\r\n<p>\r\n6) Configure the kernel to include (not modules) all the mtd nand code (incl nand_ecc and mtdblock device) and yaffs fs.\r\n</p>\r\n<p>\r\nYou should now be able to build a kernel with yaffs as a root fs using the normal tools.\r\n</p>\r\n<h3>Creating a bootable yaffs partition:</h3>\r\n<p>\r\nYou can\r\n</p>\r\n<p>\r\n1) Create the partition by mounting it from a running linux os and copying the data there. The mkyaffs utility in the yaffs source simply erases a NAND mtdblock device without removing bad block data.\r\n</p>\r\n<p>\r\n2) Make and download a filesystem image. The mkyaffsimage utility that came with the sources will create a YAFFS block list in a file from a root tree. This is a list of 512+16 byte blocks that need to be placed (in any order) on a NAND device.\r\n</p>\r\n<p>\r\nYou will need to write code to copy these data blocks and add in the block numbers in the oob areas.\r\n</p>\r\n<p>\r\nExamples of a modified handhelds.org bootldr for the Balloon board can be found on the toby-churchill.org website.\r\n</p>\r\n<h3>Booting into yaffs:</h3>\r\n<p>\r\nModify your bootloader to pass a  command line to linux to specifying the mtdblock/n that refers to the root partition.\r\n</p>\r\n<p>\r\n&nbsp;\r\n</p>\r\n<p>\r\nBalloon page at http://www.toby-churchill.org.uk\r\n</p>\r\n<p>\r\nYaffs mailing list - to join go to http://stoneboat.aleph1.co.uk/cgi-bin/mailman/listinfo/yaffs and enter your email address\r\n\r\n</p>\r\n<p>\r\nLinux MTD http://www.linux-mtd.infradead.org/\r\n</p>\r\n<p>\r\n$Id$\r\n</p>\r\n\";s:7:\"summary\";s:136:\"Simple HOWTO for getting started with YAFFS and using it as a root filesystem. If you just want the <i>quick start</i> info - read this.\";s:6:\"format\";s:9:\"full_html\";}}}s:19:\"field_document_type\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:9:\"target_id\";s:3:\"346\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:4:\"page\";s:2:\"id\";s:2:\"40\";s:8:\"revision\";s:3:\"551\";s:4:\"uuid\";s:36:\"14126930-0e90-4638-b0bd-2d36a20eb26d\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:32:\"HOWTO incorporate YAFFS in Linux\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"551\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655900.849,1,'entity_field_info node_values','866'),('values:node:400','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"401\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1342416153\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"400\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:15:\"yaffs_user_logo\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"fe518988-cfd7-464f-bd0a-941c1ee56307\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:7:\"Bernina\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1336606047\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1494601697\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:27:\"<p>Bernina use Yaffs.</p>\r\n\";s:7:\"summary\";s:0:\"\";s:6:\"format\";s:10:\"basic_html\";}}}s:21:\"field_yaffs_user_logo\";a:1:{s:9:\"x-default\";a:1:{i:0;a:5:{s:9:\"target_id\";s:2:\"45\";s:3:\"alt\";s:0:\"\";s:5:\"title\";s:0:\"\";s:5:\"width\";s:4:\"1024\";s:6:\"height\";s:3:\"153\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:15:\"yaffs_user_logo\";s:2:\"id\";s:3:\"400\";s:8:\"revision\";s:3:\"401\";s:4:\"uuid\";s:36:\"fe518988-cfd7-464f-bd0a-941c1ee56307\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:7:\"Bernina\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"401\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.561,1,'entity_field_info node_values','866'),('values:node:401','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"402\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1336606157\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"401\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:15:\"yaffs_user_logo\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"82fb641c-f24f-4653-a58b-04377a5c1619\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:9:\"Gallagher\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1336606102\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496412218\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:26:\"<p>Used by Gallagher</p>\r\n\";s:7:\"summary\";s:17:\"Used by Gallagher\";s:6:\"format\";s:10:\"basic_html\";}}}s:21:\"field_yaffs_user_logo\";a:1:{s:9:\"x-default\";a:1:{i:0;a:5:{s:9:\"target_id\";s:2:\"47\";s:3:\"alt\";s:0:\"\";s:5:\"title\";s:0:\"\";s:5:\"width\";s:4:\"1796\";s:6:\"height\";s:3:\"580\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:15:\"yaffs_user_logo\";s:2:\"id\";s:3:\"401\";s:8:\"revision\";s:3:\"402\";s:4:\"uuid\";s:36:\"82fb641c-f24f-4653-a58b-04377a5c1619\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:9:\"Gallagher\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"402\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.562,1,'entity_field_info node_values','866'),('values:node:407','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"408\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1344939309\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"407\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"9b644329-6ec6-456a-a931-f6835022e8cd\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:18:\"Booting is fast...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1338515490\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496402093\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:189:\"<p>Being quick to boot was one of the fundamental requirements in Yaffs\' design. Boot-time scanning to build the file structure lists should require just one pass reading NAND memory.</p>\r\n\";s:7:\"summary\";s:122:\"It is important for a Flash filesystem to boot fast, so boot speed was a fundamental consideration in the design of Yaffs.\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:16:\"fa-space-shuttle\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"407\";s:8:\"revision\";s:3:\"408\";s:4:\"uuid\";s:36:\"9b644329-6ec6-456a-a931-f6835022e8cd\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:18:\"Booting is fast...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"408\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.825,1,'entity_field_info node_values','866'),('values:node:408','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"409\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1344936557\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"408\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"75eeebed-ee75-4d5b-b444-1d10280549d1\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:22:\"An active community...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1338515545\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496402147\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:791:\"<p>You can learn from the experience of people and companies who are working with Yaffs. Thousands of developers have used Yaffs successfully, and commercially-licensed Yaffs has many customers that use it repeatedly. Have a look at the mailing list - it\'s a great place to start if you have some questions.<br />\r\n<a href=\"http://stoneboat.aleph1.co.uk/cgi-bin/mailman/listinfo/yaffs\">http://stoneboat.aleph1.co.uk/cgi-bin/mailman/listinfo/yaffs</a></p>\r\n\r\n<p>The searchable archive of postings is at <a href=\"http://lists.aleph1.co.uk/lurker/list/yaffs.html\">http://lists.aleph1.co.uk/lurker/list/yaffs.html&nbsp;&nbsp; </a>Or search online to see the variety of work done with Yaffs as its basis - from research papers through to skunkworks projects for testing particular concepts.</p>\r\n\";s:7:\"summary\";s:112:\"There\'s an active community of people who use Yaffs and who have developed with Yaffs, just a click or two away.\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:8:\"fa-users\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"408\";s:8:\"revision\";s:3:\"409\";s:4:\"uuid\";s:36:\"75eeebed-ee75-4d5b-b444-1d10280549d1\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:22:\"An active community...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"409\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655094.828,1,'entity_field_info node_values','866'),('values:node:409','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:22:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"627\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1498530801\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"409\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"paper\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"7ded725e-366e-4ad5-a9c4-4d97e16adac0\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:15:\"How Yaffs works\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"6\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1338593328\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1498530801\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:239855:\"<p align=\"center\" style=\"margin-top: 0.42cm; orphans: 0; widows: 0; page-break-after: avoid\">\r\n<br/>\r\n<br/>\r\n\r\n</p>\r\n\r\n	<p class=\"western\" align=\"justify\">This document aims to give an explanation of most of the core mechanisms that make\r\n	Yaffs work. \r\n	</p>This document is the starting point for understanding Yaffs.</p>\r\n\r\n<h1 class=\"western\">1 Purpose</h1>\r\n<p class=\"western\">The purpose of this document is to give a\r\nreasonable explanation of most of the core mechanisms that make Yaffs\r\nwork. As of the time of writing this, the Yaffs2 code base includes\r\napproximately 19,000 lines of code making a very detailed discussion\r\nimpractical.</p>\r\n<p class=\"western\">This document should serve as a first port of call\r\nfor understanding Yaffs. Further detailed questions and discussions\r\nare welcomed on the Yaffs discussion list.</p>\r\n<p class=\"western\">This document is updated periodically. Yaffs\r\nmechanism design changes from time to time and this document will not\r\nalways reflect the most up to date code. \r\n</p>\r\n<h1 class=\"western\">2 What is Yaffs?</h1>\r\n<p class=\"western\">Yaffs stands for <i>Yet Another Flash File System</i>,\r\na term coined by Charles Manning in 2001 when suggesting that the\r\nalready cluttered flash file system space could do with yet another\r\noffering – this time a flash file system designed from the ground\r\nup to work with NAND flash.</p>\r\n<p class=\"western\">The first release of Yaffs was developed during\r\nthe end of 2001 and the beginning of 2002. By mid-2002, Yaffs was\r\nbeing trialled in various products.  In May 2002,  Yaffs was\r\nannounced and a few more projects started playing with it. In June,\r\nporting to other OSs started. In September 2002, Yaffs was announced\r\non linuxdevices.com which started a far wider uptake of Yaffs.</p>\r\n<p class=\"western\">Yaffs1, the original version of Yaffs, supported\r\n512-byte page NAND devices with a SmartMedia-like memory layout.</p>\r\n<p class=\"western\">Yaffs2 is a follow-up to Yaffs1 extending Yaffs1\r\nto support larger and different devices with different constraints.</p>\r\n<p class=\"western\">Yaffsis highly portable and has been used in many\r\ndifferent products and applications as varied as sewing machines,\r\npoint of sale, phones and aerospace. Yaffs has been used with\r\nmultiple different operating systems. Native support is available for\r\nLinux, WindowsCE and eCOS while Yaffs Direct Interface provides a\r\nlayer that can be used in other applications such as RTOSs. Yaffs has\r\nbeen used with multiple different CPUs and compilers.</p>\r\n<p class=\"western\">Yaffs has also been used as a NOR file system and\r\neven as a RAM file system.</p>\r\n<h1 class=\"western\">3 Design and coding strategies</h1>\r\n<p class=\"western\">Yaffs is designed to work in multiple environments\r\nwhich drives the need for portability. Portability also improves the\r\ndebugging and testing since it is easier to develop and debug code in\r\nan application environment than within an OS kernel. This generally\r\nallows Yaffs to progress faster with less programming resources and\r\nprovides more varied testing. Primary strategies that improve\r\nportability include:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">No OS-specific features used in main code\r\n	body.</p>\r\n	<li/>\r\n<p class=\"western\">No compiler-specific features used in the\r\n	main code body.</p>\r\n	<li/>\r\n<p class=\"western\">Abstract types and functions used to allow\r\n	Unicode or ASCII operation.</p>\r\n</ul>\r\n\r\n<p class=\"western\" style=\"page-break-before: auto; page-break-after: avoid\">\r\nSimplicity is another key goal. Complexity is limited to those\r\nsituations that provide significant improvements to performance or\r\nutility. Simplicity improves robustness and the ease of integration\r\nand development. Primary strategies that improve simplicity are:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Single threaded model. Yaffs is locked on a\r\n	per-partition basis at a high level. This is simpler than tracking\r\n	lower-level locking. Yaffs Direct Interface uses a single lock for\r\n	all partitions.</p>\r\n</ul>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Log structure makes for a simpler garbage\r\n	collector and allocation methodology.</p>\r\n	<li/>\r\n<p class=\"western\">Abstractions that build layered code which\r\n	is easier to understand, port and debug.</p>\r\n</ul>\r\n<h1 class=\"western\">4 Terminology: Yaffs vs Yaffs1 vs Yaffs2</h1>\r\n<p class=\"western\">Before we embark on our quest to understand what\r\nYaffs is, a terminology explanation is in order.</p>\r\n<p class=\"western\">There are two versions of Yaffs code: the original\r\nYaffs code-base and the current Yaffs2 code-base. The Yaffs2\r\ncode-base supports functionality provided by the Yaffs code-base as\r\nwell as being extended with new functionality to provide extra modes\r\nof operation, most importantly those required to work with larger and\r\nmore modern NAND parts. The Yaffs2 code-base supports the Yaffs1 mode\r\nof operation through a backward compatibility mode.</p>\r\n<p class=\"western\">Unless explicitly mentioned, this text refers to\r\nthe Yaffs2 code-base.</p>\r\n<p class=\"western\">This text uses three terms Yaffs, Yaffs1 and\r\nYaffs2 depending on various modes of operation.</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Yaffs1\r\n	is a simpler mode of operation that uses deletion markers to track\r\n	state. </font>\r\n	</p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Yaffs2\r\n	is a more complex mode of operating that was developed to support\r\n	larger modern flash types, in particular MLC NAND, that cannot used\r\n	deletion markers.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Yaffs\r\n	means operations common to both.</font></p>\r\n</ul>\r\n<p class=\"western\">Yaffs1 originally only worked with 512-byte page\r\ndevices but has been extended to support larger flash pages such as\r\nIntel M18 flash with 1k pages.</p>\r\n<p class=\"western\">Yaffs2 was originally designed for 1k or larger\r\npage sizes but can be used with smaller pages by using in-band tags.</p>\r\n<p class=\"western\">Since the Yaffs1 mode of operation is simpler to\r\nunderstand than the Yaffs2 mode of operation,  Yaffs1 will be\r\ndescribed first and readers interested in Yaffs2 operation should\r\nfirst fully acquaint themselves with the Yaffs1 mode of operation. It\r\nis suggested that this document be read sequentially rather than\r\nbrowsing it.</p>\r\n<h1 class=\"western\">5 Objects</h1>\r\n<p class=\"western\">In Yaffs-speak, an Object is anything that is\r\nstored in the file system. These are:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Regular data files</p>\r\n	<li/>\r\n<p class=\"western\">Directories</p>\r\n	<li/>\r\n<p class=\"western\">Hard-links</p>\r\n	<li/>\r\n<p class=\"western\">Symbolic links</p>\r\n	<li/>\r\n<p class=\"western\">Special objects (pipes, devices etc).</p>\r\n</ul>\r\n<p class=\"western\">All objects are identified by a unique integer\r\nobject id (<i><b>obj_id</b></i><i><b>)</b></i>.</p>\r\n<p class=\"western\">In the standard POSIX model, as used by Linux,\r\nthere are inodes and directory entries (dentries). \r\n</p>\r\n<p class=\"western\">An inode may be a regular file, directory, or\r\nspecial file.</p>\r\n<p class=\"western\">Directory entries provide the naming mechanism\r\nthat is used to locate inodes.</p>\r\n<p class=\"western\">Under POSIX, each inode may have zero, one or many\r\ndentries:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">One dentry per inode is commonly\r\n	understood.</p>\r\n	<li/>\r\n<p class=\"western\">Multiple dentries per inode allow the same\r\n	inode to be accessed via multiple names. This is achieved through\r\n	hard links.</p>\r\n	<li/>\r\n<p class=\"western\">Zero dentries per inode is less often\r\n	understood. This happens when an inode is unlinked while there is\r\n	still a handle open to the inode. The unlinking deletes the dentry\r\n	but the inode still exists. As soon as the handle is closed the\r\n	inode is deleted too.</p>\r\n</ul>\r\n<h1 class=\"western\">6 The Yaffs NAND model</h1>\r\n<p class=\"western\">The memory in NAND flash is arranged in <i><b>pages.</b></i>\r\nA page is the unit of allocation and programming.  In Yaffs, the unit\r\nof allocation is the<i> </i><i><b>chunk</b></i>. Typically a chunk\r\nwill be the same as a NAND page, but there is flexibility to use\r\nchunks which map to multiple pages (eg. A system may have two NAND\r\nchips in parallel requiring 2x2048 = 4096 byte chunks) . This\r\ndistinction gives a lot of flexibility in how the system can be\r\nconfigured.  In this text the term page and chunk are synonymous\r\nunless stated otherwise.</p>\r\n<p class=\"western\">Many, typically 32 to 128 but as many as a few\r\nhundred, chunks form a <i><b>block</b></i>. A block is the unit of\r\nerasure. \r\n</p>\r\n<p class=\"western\">NAND flash may be shipped with bad blocks and\r\nfurther blocks may go bad during the operation of the device. Thus,\r\nYaffs is aware of bad blocks and needs to be able to detect and mark\r\nbad blocks.</p>\r\n<p class=\"western\">NAND flash also typically requires the use of some\r\nsort of error detection and correction code (ECC). Yaffs can either\r\nuse existing ECC logic or provide its own.</p>\r\n<h1 class=\"western\">7 How Yaffs1 stores files</h1>\r\n<p class=\"western\">Yaffs1 has a modified log structure, while Yaffs2\r\n(see below) has a true log structure. A true log structured file\r\nsystem only ever writes sequentially. Yaffs1 uses deletion markers,\r\nwhich breaks the sequential write rule. Yaffs2 does not use deletion\r\nmarkers and is thus a true log structured file system.</p>\r\n<p class=\"western\">Instead of writing data in locations specific to\r\nthe files, the file system data is written in the form of a\r\nsequential log, The entries in the log are all one chunk in size and\r\ncan hold one of two types of chunk:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><i><b>Data chunk</b></i>: A chunk holding\r\n	regular data file contents.</p>\r\n	<li/>\r\n<p class=\"western\"><i><b>Object Header</b></i>: A descriptor\r\n	for an object (directory, regular data file, hard link, soft link,\r\n	special descriptor,...). This holds details such as the identifier\r\n	for the parent directory, object name, etc.</p>\r\n</ul>\r\n<p class=\"western\">Each chunk has <i><b>tags</b></i> associated with\r\nit. The tags comprise the following important fields (others being\r\nignored for now):</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><i><b>Object Id (</b></i><i><b>obj_id</b></i><i><b>)</b></i>:\r\n	Identifies which object the chunk belongs to.</p>\r\n	<li/>\r\n<p class=\"western\"><i><b>Chunk Id (</b></i><i><b>chunk_id</b></i><i><b>)</b></i>:\r\n	Identifies where in the file this chunk belongs. A chunk_id of zero\r\n	signifies that this chunk contains an objectHeader. chunk_id==1\r\n	signifies the first chunk in the file (ie. At file offset 0),\r\n	chunk_id==2  is the next chunk and so on.</p>\r\n	<li/>\r\n<p class=\"western\"><i><b>Deletion Marker (</b></i><i><b>is_deleted</b></i><i><b>)</b></i><i><b>:</b></i>\r\n	(Yaffs1 only)  Shows that this chunk is no longer in use.</p>\r\n	<li/>\r\n<p class=\"western\"><i><b>Byte Count</b></i><b>: </b><b>(n_bytes)</b>:\r\n	Number of bytes of data if this is a data chunk.</p>\r\n	<li/>\r\n<p class=\"western\"><i><b>Serial Number </b></i><i><b>(ser</b></i><i><b>ia</b></i><i><b>l_number)</b></i>:\r\n	 (Yaffs1 only) Serial number used to differentiate chunks with the\r\n	same obj_id and chunk_id.</p>\r\n</ul>\r\n\r\n<p class=\"western\" style=\"page-break-before: always\">Now let\'s bring\r\nthat all together in an explanation. This is a simplified explanation\r\nand skips over issues such as Soft Deletion (mentioned later in the\r\ndocument). For explanation purposes, we shall consider usage of\r\nfictitious NAND type that has 4 chunks per block, starting with an\r\nempty (erased) flash.</p>\r\n\r\n<p class=\"western\">First we\'ll create a file.</p>\r\n\r\n<table width=\"605\" cellpadding=\"4\" cellspacing=\"0\">\r\n	<col width=\"37\">\r\n	<col width=\"56\">\r\n	<col width=\"67\">\r\n	<col width=\"60\">\r\n	<col width=\"64\">\r\n	<col width=\"271\">\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" style=\"font-weight: normal\">Block</p>\r\n		</td>\r\n		<td width=\"56\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" style=\"font-weight: normal\">Chunk</p>\r\n		</td>\r\n		<td width=\"67\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" style=\"font-weight: normal\">obj_id</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" style=\"font-weight: normal\">chunk_id</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" style=\"font-weight: normal\">Deletion</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\" style=\"font-weight: normal\">Comment</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" height=\"26\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"56\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"67\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Object Header for this file (length 0)</p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n\r\n<p class=\"western\">Next we write a few chunks of data to the file.</p>\r\n\r\n<table width=\"605\" cellpadding=\"4\" cellspacing=\"0\">\r\n	<col width=\"37\">\r\n	<col width=\"48\">\r\n	<col width=\"60\">\r\n	<col width=\"64\">\r\n	<col width=\"56\">\r\n	<col width=\"290\">\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Block</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Chunk</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">obj_id</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">chunk_id</p>\r\n		</td>\r\n		<td width=\"56\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deletion</p>\r\n		</td>\r\n		<td width=\"290\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\">Comment</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"56\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"290\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Object Header for t<font size=\"3\" style=\"font-size: 12pt\">his\r\n			file (length 0)</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"56\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"290\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">First chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"56\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"290\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Second chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"56\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"290\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Third chunk of data</p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n\r\n<p class=\"western\">Next we close the file. This writers a new object\r\nheader for the file. Notice how the previous object header is\r\ndeleted.</p>\r\n\r\n<table width=\"605\" cellpadding=\"4\" cellspacing=\"0\">\r\n	<col width=\"37\">\r\n	<col width=\"48\">\r\n	<col width=\"60\">\r\n	<col width=\"68\">\r\n	<col width=\"60\">\r\n	<col width=\"282\">\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Block</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Chunk</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">obj_id</p>\r\n		</td>\r\n		<td width=\"68\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">chunk_id</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deletion</p>\r\n		</td>\r\n		<td width=\"282\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\">Comment</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"68\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"282\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsoleted object header <font size=\"2\" style=\"font-size: 10pt\">(length\r\n			0)</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"68\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"282\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">First chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"68\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"282\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Second chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"68\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"282\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Third chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"68\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"282\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">New object header <font size=\"2\" style=\"font-size: 10pt\">(length\r\n			n)</font></p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n\r\n<p class=\"western\" style=\"page-break-before: always\">Let\'s now open\r\nthe file for read/write, overwrite part of the first chunk in the\r\nfile and close the file. The replaced data and object header chunks\r\nbecome deleted.</p>\r\n\r\n<table width=\"605\" cellpadding=\"4\" cellspacing=\"0\" style=\"page-break-inside: avoid\">\r\n	<col width=\"37\">\r\n	<col width=\"48\">\r\n	<col width=\"64\">\r\n	<col width=\"64\">\r\n	<col width=\"71\">\r\n	<col width=\"271\">\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Block</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Chunk</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">obj_id</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">chunk_id</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deletion</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\">Comment</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsolete object header.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsolete first chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Second chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Third chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsolete object header</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">New first chunk of file</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">New object header</p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n\r\n<p class=\"western\">Now let\'s resize the file to zero by opening the\r\nfile with O_TRUNC and closing the file. This writes a new object\r\nheader with length 0 and the contents are pruned making the data\r\nchunks deleted.</p>\r\n\r\n<table width=\"605\" cellpadding=\"4\" cellspacing=\"0\">\r\n	<col width=\"37\">\r\n	<col width=\"48\">\r\n	<col width=\"64\">\r\n	<col width=\"64\">\r\n	<col width=\"71\">\r\n	<col width=\"271\">\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Block</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Chunk</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">obj_id</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">chunk_id</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deletion</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\">Comment</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsolete object header.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsolete first chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Second chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Third chunk of data</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsolete object header</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Deleted first chunk of file</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Delted</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsoleted object header</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"37\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"48\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"64\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"71\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"271\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">New object header <font size=\"2\" style=\"font-size: 10pt\">(length\r\n			0).</font></p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n\r\n<p class=\"western\">Note how all the pages in block 1 are now marked\r\nas deleted. This means that block 1 no longer contains useful\r\ninformation so we can now erase block 1 and reuse the space.</p>\r\n<p class=\"western\">We will now rename the file. To do this we write a\r\nnew object header for the file</p>\r\n\r\n<table width=\"605\" cellpadding=\"4\" cellspacing=\"0\" style=\"page-break-inside: avoid\">\r\n	<col width=\"38\">\r\n	<col width=\"42\">\r\n	<col width=\"58\">\r\n	<col width=\"60\">\r\n	<col width=\"60\">\r\n	<col width=\"297\">\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Block</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Chunk</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">obj_id</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">chunk_id</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\">Comment</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Erased</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Erased</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Erased</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"1\" sdnum=\"2057;\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\"><br/>\r\n\r\n			</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Erased</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsolete object header</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">1</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Deleted first chunk of file</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsoleted object header</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"2\" sdnum=\"2057;\">\r\n			<p class=\"western\">2</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Deleted</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">Obsolete object header</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"38\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\" sdval=\"3\" sdnum=\"2057;\">\r\n			<p class=\"western\">3</p>\r\n		</td>\r\n		<td width=\"42\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"58\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">500</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">0</p>\r\n		</td>\r\n		<td width=\"60\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Live</p>\r\n		</td>\r\n		<td width=\"297\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">New object header showing new name</p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n\r\n<p class=\"western\">Block 2 now contains only deleted chunks and can\r\nbe erased and reused.</p>\r\n<p class=\"western\">Note how the tags tell us:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Which\r\n	chunks belong to which object</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">The\r\n	position of the chunks within a file,</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Which\r\n	chunks are current</font></p>\r\n</ul>\r\n<ul>\r\n	<p class=\"western\"><font size=\"3\" style=\"font-size: 12pt\">With that\r\n	information we can recreate the state of the files regardless of the\r\n	placement of the chunks in NAND. This means that should the system\r\n	fail (crash, power fail,...) at any point during the sequences\r\n	above, we are still able to recover the file system state up to that\r\n	point.</font></p>\r\n</ul>\r\n<p class=\"western\"><font size=\"3\" style=\"font-size: 12pt\">Note that\r\nthere are no file allocation tables or similar structures stored in\r\nthe flash. This reduces the amount of writing and erasing (improving\r\nwrite performance) while also improving robustness. Corruption of\r\nfile allocation tables and similar structures is a common failure\r\nmechanism for embedded file systems. The lack of such structures\r\nmakes Yaffs more robust. Or, to put it another way, you can\'t corrupt\r\nwhat you don\'t store.</font></p>\r\n<h1 class=\"western\">8 Garbage collection</h1>\r\n<p class=\"western\">As we have shown so far, when a block is made up\r\nonly of deleted chunks, that block can be erased and reused. However,\r\nconsider what will happen if we have many blocks which each have a\r\nfew current chunks in them. Clearly we cannot erase any of the\r\ncurrent blocks or we will destroy data. What we need to do is copy\r\nthe useful data chunks off a block, deleting the originals and\r\nallowing the block to be erased and reused. This process is referred\r\nto as <i><b>garbage collection</b></i>.</p>\r\n<p class=\"western\">The Yaffs garbage collection process works as\r\nfollows:</p>\r\n<ol>\r\n	<li/>\r\n<p class=\"western\">Find a block worth collecting (according\r\n	the the heuristics below). If none found, then exit.</p>\r\n	<li/>\r\n<p class=\"western\">Iterate through the chunks in the block. If\r\n	the chunk is in use then create a new copy and delete the original.\r\n	Fix up the RAM data structures to reflect the change.</p>\r\n</ol>\r\n<p class=\"western\">Once all chunks in this block have been deleted,\r\nthe block can be erased ready for reuse.</p>\r\n<p class=\"western\">Note that although step 2 deletes the original\r\nchunk when it gets copied there is not much point in actually\r\nprogramming the deletion marker (is_deleted flag) in flash since\r\nwe\'re about to erase the block anyway. Thus Yaffs does not program\r\nthe deletion marker in these cases. If power is lost part way through\r\nthe operation we can still tell the difference between the original\r\nand the copy by looking at the serial number (not that it really\r\nmatters anyway since the two have the same contents so either can be\r\nused).</p>\r\n<p class=\"western\">The heuristics to determine whether a block is\r\nworth collecting are as follows:</p>\r\n<ol>\r\n	<li/>\r\n<p class=\"western\">If there are many erased blocks available,\r\n	then Yaffs does not need to work hard, but will instead only attempt\r\n	to perform garbage collection of blocks with very few chunks in use.\r\n	This is termed <i><b>passive</b></i> garbage collection.</p>\r\n	<li/>\r\n<p class=\"western\">If, however, there are very few erased\r\n	blocks, Yaffs will work much harder to recover more space and will\r\n	garbage collect blocks with more chunks in use. This is termed\r\n	<i><b>aggressive</b></i> garbage collection.</p>\r\n</ol>\r\n<p class=\"western\">OK, the passive/aggressive names are a bit silly,\r\nbut they were contrived around midnight... give me a break!</p>\r\n<p class=\"western\">If garbage collection is aggressive, we need\r\nerased space urgency and the whole block is collected in a single\r\ngarbage collection cycle. If the collection is passive then only a\r\nfew chunks are collected at a time thus spreading the effort over\r\nmany garbage collection cycles. This is done to reduce garbage\r\ncollection load and improve responsiveness.</p>\r\n<p class=\"western\">The rationale behind the above heuristics is to\r\ndelay garbage collection when possible to reduce the amount of\r\ncollection that needs to be performed, thus increasing average system\r\nperformance. Yet there is a conflicting goal of trying to spread the\r\ngarbage collection so that it does not all happen at the same causing\r\nfluctuations in file system throughput. These conflicting goals make\r\ngarbage tuning quite challenging.</p>\r\n<p class=\"western\">All flash file systems need some sort of garbage\r\ncollector to reclaim space. The garbage collector is often a\r\ndetermining factor in the performance of the flash file system. Many\r\nfile systems have to do a significant amount of effort in a single\r\ncollection sweep.</p>\r\n<p class=\"western\">Yaffs only deals with one block at a time which\r\nconstrains the amount of effort in a garbage collection cycle, thus\r\nreducing the “stall time”.  Under normal conditions that garbage\r\ncollection is performed a few chunks at a time, further reducing\r\n“stall time”.</p>\r\n<h1 class=\"western\">9 Yaffs1 serial numbers</h1>\r\n<p class=\"western\">In Yaffs1, each chunk is marked with a 2-bit\r\nserial number that is incremented every time a chunk with the same\r\ntags value is replaced (eg. When a chunk is overwritten or when\r\ncopied by garbage collection).</p>\r\n<p class=\"western\">Now let\'s suppose first that we did not have a\r\nserial number. \r\n</p>\r\n<p class=\"western\">Let\'s consider a rename where an object header\r\nchunk must be replaced with a new one with the new name. Yaffs could\r\ndo the following:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Delete\r\n	the old chunk.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Write\r\n	the new chunk. </font>\r\n	</p>\r\n</ul>\r\n<p class=\"western\">If the system fails after the delete, the system\r\ncould end up with no chunks matching the relevant tags values. This\r\ncould cause files to be lost (end up in the lost+found directory).\r\nThus, we have to write the new chunk before deleting the old chunk.</p>\r\n<p class=\"western\">But now consider what might happen if we did this:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">W<font face=\"Liberation Serif, serif\">rite\r\n	new chunk.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Delete\r\n	old chunk.</font></p>\r\n</ul>\r\n<p class=\"western\">If the system failed after the write we now have\r\ntwo chunks that match the tags. How can we tell which one is current?</p>\r\n<p class=\"western\">The current chunk is determined by inspecting the\r\nserial number.  Since the serial number is only incremented by one\r\nbefore the old chunk is deleted, a 2-bit serial number is sufficient.\r\nValid pairs are:</p>\r\n<table width=\"86\" cellpadding=\"4\" cellspacing=\"0\">\r\n	<col width=\"35\">\r\n	<col width=\"33\">\r\n	<tr valign=\"top\">\r\n		<td width=\"35\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">Old</p>\r\n		</td>\r\n		<td width=\"33\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\">New</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"35\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">00</p>\r\n		</td>\r\n		<td width=\"33\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">01</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"35\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">01</p>\r\n		</td>\r\n		<td width=\"33\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">10</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"35\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">10</p>\r\n		</td>\r\n		<td width=\"33\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">11</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"35\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">11</p>\r\n		</td>\r\n		<td width=\"33\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">00</p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n\r\n<p class=\"western\">Thus, by inspecting the serial number attached to\r\nthe old and new tags the current chunk can be determined and the old\r\nchunk can be deleted.</p>\r\n<h1 class=\"western\">10 Yaffs2 NAND model</h1>\r\n<p class=\"western\">Yaffs2 is an extension of Yaffs designed to\r\nfulfill a new set of objectives to work with newer NAND types\r\nincluding:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Zero overwrites. Yaffs1 only ever\r\n	overwrites a single byte in the spare area of the chunks to set the\r\n	deletion marker. More modern NAND devices are less tolerant of\r\n	overwrites and Yaffs2 performs no overwrites at all.</p>\r\n	<li/>\r\n<p class=\"western\">Sequential chunk writing within a block.\r\n	More modern NAND reliability specifications tend to assume\r\n	sequential writing. Since Yaffs2 does not write deletion markers,\r\n	the writing of chunks within a block is strictly sequential.</p>\r\n	<li/>\r\n<p class=\"western\">Some flash technologies – such as MLC –\r\n	only work properly if pages are written sequentially. This is a\r\n	fundamental requirement of how many MLC types perform the bit\r\n	overlaying.</p>\r\n</ul>\r\n<p class=\"western\">Since Yaffs2 performs less writes, there is\r\npotential for Yaffs2 to have improved write performance.</p>\r\n<p class=\"western\">Yaffs2 cannot use a deletion marker because that\r\nwould violate the zero overwrites mandate and alternate mechanisms\r\nare provided to determine which chunks are current and which are\r\ndeleted. These mechanisms are:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><i><b>Sequence Number </b></i><i><b>(seq_number)</b></i>:\r\n	As each block is allocated, the file system\'s sequence number is\r\n	incremented and each chunk in the block is marked with that sequence\r\n	number. The sequence number thus provides a way of organising the\r\n	log in chronological order.</p>\r\n	<li/>\r\n<p class=\"western\"><i><b>Shrink Header Marker </b></i><i><b>(shrink_header)</b></i>:\r\n	The shrink header marker is used to mark object headers that are\r\n	written to shrink the size of a data file. This is explained more in\r\n	the accompanying text.</p>\r\n</ul>\r\n\r\n<p class=\"western\" align=\"center\"><i><b>Note: The Yaffs2 sequence\r\nnumber is not the same as the Yaffs1 serial number!</b></i></p>\r\n\r\n<p class=\"western\">Note: We still refer to chunk deletion in Yaffs2.\r\nThe chunks are marked as deleted in the RAM data structures used by\r\ngarbage collection etc, but there is no deletion marker written to\r\nflash.</p>\r\n<h2 class=\"western\">10.1 Sequence Number</h2>\r\n<ul>\r\n	<p class=\"western\">The sequence number allows the chronological\r\n	order to be determined which allows Yaffs to determine the sequence\r\n	of events and restore the file system state. This is achieved by\r\n	scanning <i><b>backwards</b></i> chronologically (ie. From the\r\n	highest sequence number backwards to the lowest sequence number).\r\n	Thus:</p>\r\n	<li/>\r\n<p class=\"western\">Since we\'re scanning backwards, the most\r\n	recently written – and thus current – chunk matching an\r\n	obj_id:chunk_id pair will be encountered first and all subsequent\r\n	matching chunks must be obsolete and treated as deleted.</p>\r\n	<li/>\r\n<p class=\"western\">The file length in object headers are used\r\n	to trim back resized files. If an object header is encountered, then\r\n	subsequent data chunks that lie beyond that file length are clearly\r\n	obsolete and treated as deleted. Note that both current and obsolete\r\n	object header sizes must be used to obtain an accurate\r\n	reconstruction.</p>\r\n</ul>\r\n<h2 class=\"western\">10.2 Shrink Header</h2>\r\n<p class=\"western\">Explaining the purpose of the shrink header marker\r\nis a bit convoluted. The purpose of a shrink header marker is to show\r\nthat this object header indicates that a file has shrunken in size,\r\nand to prevent those object headers from being deleted by garbage\r\ncollection.  To understand this, it is easiest to consider what would\r\nhappen if the shrink header markers did not exist.</p>\r\n<p class=\"western\">For simplification we\'ll assume no garbage\r\ncollection happens during this part of the exercise. It is safe to\r\nmake that assumption since it does not alter the reasoning.</p>\r\n<p class=\"western\">Consider a file that has been through the\r\nfollowing:</p>\r\n<p class=\"code-western\"><font face=\"Liberation Mono, monospace\"><font size=\"2\" style=\"font-size: 10pt\"><b>#define\r\nMB (1024 * 1024)<br/>\r\n</b></font></font><br/>\r\n\r\n</p>\r\n<p class=\"code-western\"><code class=\"western\"><font face=\"Liberation Mono, monospace\"><font size=\"2\" style=\"font-size: 9pt\">h\r\n= open(“foo”,O_CREAT| O_RDWR, S_IREAD|S_IWRITE); /* create file\r\n*/</font></font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 9pt\"><br/>\r\nwrite(h,data,5*</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 9pt\">MB</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 9pt\">);\r\n/* write 5 MB of data /<br/>\r\ntruncate(h,1*</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 9pt\">MB</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 9pt\">);\r\n /* truncate to 1MB */<br/>\r\nlseek(h,2*</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 9pt\">MB</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 9pt\">,\r\nSEEK_SET); /* set the file access position to 2MB\r\n*/<br/>\r\nwrite(h,data,1*</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 9pt\">MB</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 9pt\">);\r\n/* write 1MB of data */<br/>\r\nclose(h);</font></code><br/>\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\">The file will now be 3MB in length, but there will\r\nbe a “hole” between 1MB and 2MB. According to POSIX (and to aid\r\nsecurity etc) that “hole” should always read back as zeros.</p>\r\n<p class=\"western\">Yaffs2 would represent that in NAND with the\r\nfollowing sequence of chunks:</p>\r\n<ol>\r\n	<li/>\r\n<p class=\"western\">Object header for file creation (file\r\n	length = 0)</p>\r\n	<li/>\r\n<p class=\"western\">5MB worth of data chunks (0 to 5MB)</p>\r\n	<li/>\r\n<p class=\"western\">Object header for truncation (file length =\r\n	1MB)</p>\r\n	<li/>\r\n<p class=\"western\">1MB worth of data chunks (2MB to 3MB)</p>\r\n	<li/>\r\n<p class=\"western\">Object header for close (file length = 3MB)</p>\r\n	<p class=\"western\">At this stage, only the the following data chunks\r\n	are current:</p>\r\n</ol>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">The first 1MB of data created in step 2\r\n	above.</p>\r\n	<li/>\r\n<p class=\"western\">The 1MB of data created in step 4 above.</p>\r\n	<li/>\r\n<p class=\"western\">The object header created in step 5 above.</p>\r\n</ul>\r\n<p class=\"western\">But Yaffs must remember the truncation that\r\nhappened in step 3, otherwise Yaffs will “forget”  that there is\r\na hole, which would cause the old data to be visible again. Thus, if\r\nYaffs creates a hole it first writes a shrink header to indicate the\r\nstart of the hole and a regular object header to mark the end of the\r\nhole. \r\n</p>\r\n<p class=\"western\">The shrink header modifies the behavior of the\r\ngarbage collector to ensure that  these shrink headers are not erased\r\nuntil it is safe to do so. This unfortunately has a negative impact\r\non garbage collection in systems which make extensive use of files\r\nwith holes.</p>\r\n<p class=\"western\">Shrink headers are also used to indicate that a\r\nfile has been deleted and that the record of the file deletion is not\r\nlost.</p>\r\n<h2 class=\"western\">10.3 Yaffs2 extended tags</h2>\r\n<p class=\"western\">Yaffs2 extends the tags in object headers with\r\nextra fields to improve mount scanning performance. The operation of\r\nextended tags is described later in this document.</p>\r\n<h1 class=\"western\">11 Bad block handling NAND error handling</h1>\r\n<p class=\"western\">NAND flash is designed to be very low cost and\r\nvery high density. In order to get high yields, and thus keep costs\r\ndown, NAND flash is typically shipped with a few bad blocks and some\r\nfurther blocks are expected to go bad during the use of the device.\r\nThus, any flash file system without an effective bad block handling\r\npolicy is unsuitable for NAND flash.</p>\r\n<p class=\"western\">Yaffs1 uses the Smart-Media style of bad block\r\nmarking. This checks the sixth byte (byte 5) of the spare area. In a\r\ngood block this should be 0xFF. A factory-marked bad block should be\r\n0x00. If Yaffs1 determines that a block has gone bad it is marked bad\r\nwith 0x59 (\'Y\'). Using a distinctive marker allows Yaffs-marked bad\r\nblocks to be differentiated from factory-marked bad blocks.</p>\r\n<p class=\"western\">Yaffs2 mode is designed to support a wider range\r\nof devices and spare-area layouts. Thus, Yaffs2 does not decide which\r\nbytes to mark but instead calls driver functions to determine whether\r\nthe block is bad, or to mark it bad.</p>\r\n<p class=\"western\">So, when does Yaffs mark a block bad? Yaffs will\r\nmark a block bad if a read or write operation fails or if three ECC\r\nerrors are detected. A block that is marked bad is retired from use,\r\nthus improving the robustness of the file system. This policy is\r\nsuitable for SLC flash. MLC policies are under development.</p>\r\n<p class=\"western\">Further, NAND flash cells can sometimes be\r\ndisturbed (corrupted) by NAND activity and charge loss.  These errors\r\nare corrected by error correction codes (ECC) which may be\r\nimplemented in hardware, software drivers, or within Yaffs itself.\r\nAgain, any flash file system lacking effective ECC handling is\r\nunsuitable for NAND flash.</p>\r\n<p class=\"western\">Yaffs1 mode can use either the built in ECC or use\r\nECC provided by the driver or hardware.</p>\r\n<p class=\"western\">Since Yaffs2 mode is designed for a wider range of\r\ndevices, it does not provide ECC internally but requires that the\r\ndriver provide the ECC.</p>\r\n<p class=\"western\">The ECC code supplied with Yaffs (yaffs_ecc.c) is\r\nthe fastest C code implementation of a Smart Media compatible ECC\r\nalgorithm that we are aware of. This code will correct any single bit\r\nerror within a 256-byte data block and detect 2 errors per 256-byte\r\ndata block. This is sufficient error correction to provide very high\r\nreliability on most SLC-type NAND flash.</p>\r\n<p class=\"western\">For a more complete description of failure\r\nhandling, please refer to the Yaffs error mitigation document.</p>\r\n<h1 class=\"western\">12 RAM structures</h1>\r\n<p class=\"western\">While it is theoretically possible to use a log\r\nstructured file system with very few RAM structures, this would\r\nprovide reduce performance. Thus, significant RAM data structures are\r\nrequired to store enough information to provide sufficiently high\r\nperformance. \r\n</p>\r\n<p class=\"western\">Before we jump in, it is a good idea to first\r\nfigure out what purpose the RAM structures serve. The main structures\r\nare defined in yaffs_guts.h and their main purposes, are :</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Device/partition: This is named <i><b>yaffs_dev</b></i><span style=\"font-style: normal\"><span style=\"font-weight: normal\">.\r\n	</span></span>This is required to hold information relating to a\r\n	Yaffs “partition” or “mount point”. Using these, rather than\r\n	globals, allows Yaffs to simultaneously support multiple partitions\r\n	and partitions of different types. In fact, almost other data\r\n	structures mentioned here are part of, or accessed via, the\r\n	structure.</p>\r\n	<li/>\r\n<p class=\"western\">NAND Block Information: This is named\r\n	<i><b>yaffs_block_info </b></i>and holds the current state of the\r\n	NAND blocks. Each yaffs_dev has an array of these.</p>\r\n	<li/>\r\n<p class=\"western\">NAND Chunk Information: This is a bitfield\r\n	attached to the yaffs_dev that holds the current in-use state of\r\n	each chunk in the system. There is one bit per chunk in the\r\n	partition.</p>\r\n	<li/>\r\n<p class=\"western\">Object: This is named <i><b>yaffs_obj</b></i>\r\n	and holds the state of an object (see section 3). There is one of\r\n	these for each object in the file system, where an object is one of\r\n	a regular file, directory, hard link, symbolic link or special link.\r\n	There are different variants of yaffs_Objects to reflect the\r\n	different data required for these different object types. Each\r\n	object is uniquely identified by an obj_id.</p>\r\n	<li/>\r\n<p class=\"western\">File structure: For each file object, Yaffs\r\n	holds a tree which provides the mechanism to find the data chunks in\r\n	a file. The tree consists of nodes called <i><b>yaffs_tnode</b></i>\r\n	(tree nodes).</p>\r\n	<li/>\r\n<p class=\"western\">Directory structure: The directory\r\n	structure allows objects to be found by name. The directory\r\n	structure is built from a doubly-linked list that is rooted in the\r\n	directory and binds together the sibling objects within a directory.</p>\r\n	<li/>\r\n<p class=\"western\">Object number hash table: The object number\r\n	hash table provides a mechanism to find an object from its obj_id.\r\n	The obj_id is hashed to select a hash bucket. Each hash bucket has a\r\n	doubly-linked list of objects that belong in this hash bucket, as\r\n	well as a count of the objects in the bucket.</p>\r\n	<li/>\r\n<p class=\"western\">Cache: Yaffs provides a read/write cache\r\n	that significantly improves performance for short operations. The\r\n	size of the cache can be set at run-time.</p>\r\n</ul>\r\n<p class=\"western\">The usage of these structures is described in more\r\ndetail below.</p>\r\n<p class=\"western\">Yaffs makes significant use of doubly-linked\r\nlists. These data structures are very useful because they provide\r\nrapid insertion, removal and traversal. They do however come at the\r\nexpense of requiring two pointers rather than just one that would be\r\nrequired by a singly-linked list.</p>\r\n<h2 class=\"western\">12.1 Yaffs objects (struct yaffs_obj)</h2>\r\n<p class=\"western\">Each object (file, directory,...) in the system is\r\nrepresented by a yaffs_obj structure \r\n</p>\r\n<p class=\"western\">The yaffs_obj\'s main function is to store most of\r\nthe object metadata and type-specific information. This means that\r\nalmost all the information about an object can be accessed\r\nimmediately without reading flash.</p>\r\n<p class=\"western\">The metadata includes, amongst others:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">obj_id:\r\n	The number used to identify the object.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">parent:\r\n	A pointer to the parent directory. Not all objects have a parent.\r\n	The root director and special directories for unlinked and deleted\r\n	files do not have parents so this is NULL.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">short_name:\r\n	If the name is short enough to fit in a small fixed-sized array\r\n	(default 16 characters) then it is stored here otherwise it must be\r\n	fetched from flash each time it is requested.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">type:\r\n	Type of object.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Permissions,\r\n	time, ownership and other attributes</font></p>\r\n</ul>\r\n<p class=\"western\"><font size=\"3\" style=\"font-size: 12pt\">Depending\r\non the object type, yaffs_obj also stores:</font></p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">A\r\n	tnode tree, file extents etc for data files</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">A\r\n	directory chain for directories</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">An\r\n	equivalent object for hard links</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">A\r\n	string for symbolic links</font></p>\r\n</ul>\r\n<h2 class=\"western\">12.2 Look-up by obj_id</h2>\r\n<p class=\"western\">The purpose of this mechanism is to rapidly access\r\nan object by its device and obj_id. This is required during garbage\r\ncollection, scanning and similar operations.</p>\r\n<p class=\"western\">Each yaffs_dev uses a hash table for this purpose.\r\nThe hash table has 256 “buckets” (tunable), each holding a\r\ndoubly-linked list of the yaffs_objs in that bucket.</p>\r\n<p class=\"western\">The hash table\'s hash function is just masking the\r\nleast significant bits of the obj_id. This is a very cheap function\r\nthat provides reasonable “spread”.</p>\r\n<p class=\"western\">Yaffs makes an attempt to assign obj_ids in a way\r\nthat keeps the number of objects in each hash bucket quite low, thus\r\npreventing any one hash entry getting too long.</p>\r\n<p class=\"western\">This mechanism is also charged with assigning new\r\n(unique) obj_id values.</p>\r\n<h2 class=\"western\">12.3 Directory structure</h2>\r\n<p class=\"western\">The purpose of the directory structure is to\r\nrapidly access an object by name. This is required to perform file\r\noperations such as opening, renaming etc.</p>\r\n<p class=\"western\"><font size=\"3\" style=\"font-size: 12pt\">The Yaffs\r\ndirectory structure is formed by a tree of objects of type\r\nYAFFS_OBJECT_TYPE_DIRECTORY. These objects have a doubly linked node\r\nof children.</font></p>\r\n<p class=\"western\">Each yaffs_obj also has a doubly linked list node\r\ncalled sibling which chain together the siblings in a directory.</p>\r\n<p class=\"western\">Each Yaffs partition has a root directory.</p>\r\n<p class=\"western\">Each yaffs partition also has some special purpose\r\n“fake” directories which are not stored in NAND but are instead\r\ncreated on mounting:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">lost+found: This directory is used as a\r\n	place to store any lost file parts that cannot be placed in the\r\n	normal directory tree.</p>\r\n	<li/>\r\n<p class=\"western\">Unlinked and deleted: These are\r\n	pseudo-directories that are not in the directory tree. Placing\r\n	objects in these directories gives them a status of being unlinked\r\n	or deleted.</p>\r\n</ul>\r\n<p class=\"western\" align=\"left\">Each object has a name that is used\r\nto look up the object within the directory, Thus, each name within a\r\ndirectory must be unique. This rule does not apply to objects in the\r\nunlinked and deleted pseudo-directories since we never use names to\r\nlook up unlinked/deleted files and there may be many files of the\r\nsame name that have been deleted.</p>\r\n<p class=\"western\">Name resolution is sped up by two mechanisms:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">short_names\r\n	are stored directly in the yaffs_obj so that they don\'t have to be\r\n	loaded from flash.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Each\r\n	object has a “name sum”. This is a simple hashing of the name\r\n	which speeds up the matching process because it is cheaper to\r\n	compare the hash than compare the whole name string.</font></p>\r\n</ul>\r\n<p class=\"western\"><img src=\"data:image/png;base64,[encoded data, 22776 characters]\" name=\"Object2\" align=\"left\" width=\"412\" height=\"355\">\r\n  <br clear=\"left\"/>\r\n</img>\r\n<br/>\r\n<br/>\r\n\r\n</p>\r\n\r\n<p class=\"western\">The above directory structure represents the\r\nfollowing directory tree</p>\r\n<table width=\"605\" cellpadding=\"4\" cellspacing=\"0\">\r\n	<col width=\"119\">\r\n	<col width=\"468\">\r\n	<tr valign=\"top\">\r\n		<td width=\"119\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font face=\"Courier, monospace\"><font size=\"3\" style=\"font-size: 12pt\">/</font></font></p>\r\n		</td>\r\n		<td width=\"468\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Root directory</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"119\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font face=\"Courier, monospace\"><font size=\"3\" style=\"font-size: 12pt\">/a</font></font></p>\r\n		</td>\r\n		<td width=\"468\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Directory containing c,d,e</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"119\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font face=\"Courier, monospace\"><font size=\"3\" style=\"font-size: 12pt\">/b</font></font></p>\r\n		</td>\r\n		<td width=\"468\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Empty directory</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"119\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font face=\"Courier, monospace\"><font size=\"3\" style=\"font-size: 12pt\">/lost+found</font></font></p>\r\n		</td>\r\n		<td width=\"468\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Empty directory</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"119\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font face=\"Courier, monospace\"><font size=\"3\" style=\"font-size: 12pt\">/a/c</font></font></p>\r\n		</td>\r\n		<td width=\"468\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Directory</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"119\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font face=\"Courier, monospace\"><font size=\"3\" style=\"font-size: 12pt\">/a/d</font></font></p>\r\n		</td>\r\n		<td width=\"468\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Data file</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"119\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font face=\"Courier, monospace\"><font size=\"3\" style=\"font-size: 12pt\">/a/e</font></font></p>\r\n		</td>\r\n		<td width=\"468\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Data file</font></p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n<p class=\"western\" align=\"left\" style=\"margin-bottom: 0cm; orphans: 0; widows: 0; page-break-before: auto\">\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\">If a Yaffs partition has been somehow corrupted\r\nthen it is possible for an object to be created during scanning but\r\nwith no object header (which contains the object name) being found.\r\nThe object would then not have a name. In these cases, Yaffs creates\r\na pseudonym from the object number of the form objnnnn so that the\r\nobject can be placed in the directory structure. \r\n</p>\r\n\r\n<h2 class=\"western\" style=\"page-break-before: always\">12.4 Hard links</h2>\r\n<p class=\"western\">In POSIX file systems, the objects (inodes in\r\nLinux terminology, vnode in BSD-speak) and the object names (dentry\r\nin Linux terminology)  are independent in that an object can have\r\nzero, one or more names.</p>\r\n<p class=\"western\">Having files with zero links is caused by\r\nconstructs such as:</p>\r\n<p class=\"western\" align=\"left\" style=\"margin-left: 1.25cm; margin-bottom: 0cm; orphans: 0; widows: 0; page-break-before: auto\">\r\n<font face=\"Courier 10 Pitch\"><font size=\"1\" style=\"font-size: 8pt\"><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">h\r\n= open(“foo”,O_CREAT | O_RDWR, S_IREAD | S_IWRITE); /* create\r\nfile “foo” */</font></code></font></font></p>\r\n<p class=\"western\" align=\"left\" style=\"margin-left: 1.25cm; margin-bottom: 0cm; orphans: 0; widows: 0; page-break-before: auto\">\r\n<font face=\"Courier 10 Pitch\"><font size=\"1\" style=\"font-size: 8pt\"><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">unlink(“foo”);	/*\r\nunlink it </font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">to\r\nremove</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">\r\ndirectory </font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">entry\r\n</font></code><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">*/</font></code></font></font></p>\r\n<p class=\"western\" align=\"left\" style=\"margin-left: 1.25cm; margin-bottom: 0cm; orphans: 0; widows: 0; page-break-before: auto\">\r\n<font face=\"Courier 10 Pitch\"><font size=\"1\" style=\"font-size: 8pt\"><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">/*\r\nwe still have a handle to the file so can still access it via the\r\nhandle */</font></code></font></font></p>\r\n<p class=\"western\" align=\"left\" style=\"margin-left: 1.25cm; margin-bottom: 0cm; orphans: 0; widows: 0; page-break-before: auto\">\r\n<font face=\"Courier 10 Pitch\"><font size=\"1\" style=\"font-size: 8pt\"><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">read(h,buffer,100);	</font></code></font></font></p>\r\n<p class=\"western\" align=\"left\" style=\"margin-left: 1.25cm; margin-bottom: 0cm; orphans: 0; widows: 0; page-break-before: auto\">\r\n<font face=\"Courier 10 Pitch\"><font size=\"1\" style=\"font-size: 8pt\"><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">write(h,buffer,100);</font></code></font></font></p>\r\n<p class=\"western\" align=\"left\" style=\"margin-left: 1.25cm; margin-bottom: 0cm; orphans: 0; widows: 0; page-break-before: auto\">\r\n<font face=\"Courier 10 Pitch\"><font size=\"1\" style=\"font-size: 8pt\"><code class=\"western\"><font size=\"2\" style=\"font-size: 10pt\">close(h);\r\n/* as soon as the handle is closed the file is deleted */</font></code></font></font></p>\r\n<p class=\"western\" align=\"left\" style=\"margin-left: 1.25cm; margin-bottom: 0cm; orphans: 0; widows: 0; page-break-before: auto\">\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\">Yaffs does not store separate object and name\r\nrecords because that would waste space and incur extra\r\nreading/writing. Instead, Yaffs is optimised for the most typical\r\ncase of one name per object. That is, Yaffs stores one name per\r\nyaffs_obj and uses “cheats” to achieve other behavior:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Objects that have zero names (ie unlinked\r\n	objects) are handled by renaming the object into a fake directory\r\n	that is used to designate unlinked objects.</p>\r\n	<li/>\r\n<p class=\"western\">Multiple names object are handled by\r\n	designating one of the objects the main object and having multiple\r\n	hard link pseudo-objects that refer to it.</p>\r\n	<li/>\r\n<p class=\"western\">The inode number (vnid in BSD-speak) is a\r\n	per-file system unique number that identifies the object. The Yaffs\r\n	obj_id of the main object is presented to the user. That is, if the\r\n	inode number is queried from a hardlink object then the obj_id of\r\n	the equivalent object is returned.</p>\r\n</ul>\r\n<p class=\"western\">The linkage between hard link pseudo-objects and\r\ntheir equivalent object is through two fields:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Each object has a hard_links doubly linked\r\n	list node that links the list of hard links to that object.</p>\r\n	<li/>\r\n<p class=\"western\">Each hard link has a equiv_obj pointer to\r\n	the “equivalent object”.</p>\r\n</ul>\r\n\r\n<p class=\"western\" style=\"page-break-before: always\">The usage of\r\nthis structure is straight forward except for one interesting case\r\nwhen hard links are being deleted. Consider the following sequence of\r\nevents:</p>\r\n<table width=\"605\" cellpadding=\"4\" cellspacing=\"0\">\r\n	<col width=\"50\">\r\n	<col width=\"80\">\r\n	<col width=\"449\">\r\n	<tr valign=\"top\">\r\n		<td width=\"50\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">1</font></p>\r\n		</td>\r\n		<td width=\"80\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\"># touch a</font></p>\r\n		</td>\r\n		<td width=\"449\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Create file a</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"50\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">2</font></p>\r\n		</td>\r\n		<td width=\"80\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\"># ln a b</font></p>\r\n		</td>\r\n		<td width=\"449\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Create a hard link b with\r\n			equivalent object a.</font></p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"50\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">3</font></p>\r\n		</td>\r\n		<td width=\"80\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\"># rm a</font></p>\r\n		</td>\r\n		<td width=\"449\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\" align=\"left\" style=\"orphans: 0; widows: 0; page-break-before: auto\">\r\n			<font size=\"3\" style=\"font-size: 12pt\">Remove a. The object must\r\n			still exist under the name b</font></p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n<p class=\"western\" align=\"left\" style=\"margin-bottom: 0cm; orphans: 0; widows: 0; page-break-before: auto\">\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\">In step 3, Yaffs cannot just delete the equivalent\r\nobject since that would leave a “hanging” hard link with no\r\nequivalent object. \r\n</p>\r\n<p class=\"western\">We also cannot just change the type of one of the\r\nhardlink objects because that would cause the object\'s obj_id to\r\nchange. This would be unacceptable since it would break any mechanism\r\nthat use the obj_id (of which there are many within and outside of\r\nYaffs).</p>\r\n<p class=\"western\">Thus, if an object is deleted and it has hard\r\nlinks to it then we do the following:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Select one of the object\'s hard links.</p>\r\n	<li/>\r\n<p class=\"western\">Rename the object to the name in the hard\r\n	link.</p>\r\n	<li/>\r\n<p class=\"western\">Delete the hard link pseudo-object.</p>\r\n</ul>\r\n<h2 class=\"western\">12.5 Symbolic links and special objects</h2>\r\n<p class=\"western\">These object types just store values that are\r\nneeded to provide a full POSIX file system.</p>\r\n<p class=\"western\">A symbolic link object saves a symbolic link\r\nstring that is used to provide the POSIX symbolic string mechanism.</p>\r\n<p class=\"western\">A special object is used to store entries for\r\ndevice numbers, pipes and other similar special objects.</p>\r\n<h2 class=\"western\">12.6 File objects</h2>\r\n<p class=\"western\">The yaffs_Objects have a type and a variant\r\nportion which is a union of different data required to hold the state\r\nof different object types.</p>\r\n<p class=\"western\">The file objects have type YAFFS_OBJECT_TYPE_FILE,\r\nand an associated file variant. This stores the following main\r\nvalues:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">file_size:\r\n	file size</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">top_level:\r\n	depth of the Tnode tree</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">top:\r\n	pointer to top of Tnode tree</font></p>\r\n</ul>\r\n<p class=\"western\">The meaning of the file size is quite obvious.\r\nThis is the current length of the file. Note that a file might have\r\nholes in it caused by seeking forward past the extents of the file.</p>\r\n<p class=\"western\">The top and top_level work together to control the\r\nTnode trees. \r\n</p>\r\n<h3 class=\"western\" style=\"page-break-before: always\">12.6.1 Tnode\r\ntree</h3>\r\n<p class=\"western\">Each file has a tnode tree to provide the mapping\r\nfrom file position to actual NAND chunk address. top is a pointer to\r\nthe top of the tnode tree</p>\r\n\r\n<p class=\"western\"><img src=\"data:image/png;base64,[encoded data, 20236 characters]\" name=\"Object1\" align=\"left\" width=\"385\" height=\"378\">\r\n  <br clear=\"left\"/>\r\n</img>\r\n<br/>\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\">The tnode tree is made up of tnodes (tree nodes)\r\narranged in levels, each of which holds either:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">At levels greater than 0, a tnode has 8\r\n	pointers to other tnodes in the next level down.</p>\r\n	<li/>\r\n<p class=\"western\">At level 0, a tnode has 16 NAND chunk Ids\r\n	which identify the chunk\'s location in RAM.</p>\r\n</ul>\r\n<p class=\"western\">These numbers are powers of 2 which makes for\r\nsimple look-ups by just applying bitmasks. The code that traverses\r\nthis tree is in yaffs_find_tnode_0().</p>\r\n<p class=\"western\">As the file size grows, more tnodes are added and\r\nas the levels fill, more levels are added. If the file is truncated\r\nor resized downwards, then the tree is pruned. If a chunk in a file\r\nis replaced (eg. data is overwritten or copied by garbage collection)\r\nthen the tnode tree must be updated to reflect the change.</p>\r\n<p class=\"western\">Tnodes typically make up the bulk of the Yaffs\'\r\nRAM usage.</p>\r\n<h1 class=\"western\">13 How various mechanisms work</h1>\r\n<p class=\"western\">Having looked at the Yaffs data structures, we now\r\nconsider how some of the mechanisms in Yaffs operates. This is most\r\neasily done by walking through some operations that Yaffs performs.</p>\r\n<h2 class=\"western\">13.1 Block and chunk management</h2>\r\n<h3 class=\"western\">13.1.1 Block states</h3>\r\n<p class=\"western\">Yaffs tracks the state of each block and chunk in\r\nthe partition. This information is first built up during scanning (or\r\nrecovered from a checkpoint). A block may be in one of the following\r\nstates (see definition of  enum yaffs_block_state):</p>\r\n\r\n<table width=\"605\" cellpadding=\"4\" cellspacing=\"0\">\r\n	<col width=\"146\">\r\n	<col width=\"441\">\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0.1cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">UNKNOWN</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border: 1px solid #000000; padding: 0.1cm\">\r\n			<p class=\"western\">The block state is not yet known.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">NEEDS_SCANNING</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">During pre-scanning it has been determined that\r\n			this block has something on it and needs scanning.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">SCANNING</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">This block is currently being scanned.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">EMPTY</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">This block has nothing in it (is erased) and\r\n			may be used for allocation. The block can get to this state by\r\n			being erased.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">ALLOCATING</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">This is the block currently being used for\r\n			allocation by the chunk allocator.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">FULL</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">All the chunks in this block have been\r\n			allocated and at least one chunk contains useful information that\r\n			has not yet been deleted.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">DIRTY</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">All the chunks in this block have been\r\n			allocated and all have been deleted. The block might have been in\r\n			the FULL or COLLECTING state before this. This block can now be\r\n			erased and returned to EMPTY state.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">CHECKPOINT</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">This block has checkpoint data in it. When the\r\n			checkpoint is invalidated this block will be erased and returned\r\n			to the EMPTY state.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">COLLECTING</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">This block is being garbage collected. As soon\r\n			as all live data has been inspected this block becomes DIRTY.</p>\r\n		</td>\r\n	</tr>\r\n	<tr valign=\"top\">\r\n		<td width=\"146\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm\">\r\n			<p class=\"western\">DEAD</p>\r\n		</td>\r\n		<td width=\"441\" style=\"border-top: none; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding-top: 0cm; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm\">\r\n			<p class=\"western\">This block has been retired or was marked bad.\r\n			This is a terminal state.</p>\r\n		</td>\r\n	</tr>\r\n</table>\r\n<p class=\"western\"><img src=\"data:image/png;base64,[encoded data, 42088 characters]\" name=\"Object3\" align=\"left\" width=\"575\" height=\"510\">\r\n  <br clear=\"left\"/>\r\n</img>\r\n<br/>\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\">The regular runtime states are; EMPTY, ALLOCATING,\r\nFULL, COLLECTING and DIRTY.</p>\r\n<p class=\"western\">The checkpoint state is used for checkpoint\r\nblocks.</p>\r\n<p class=\"western\">The DEAD state is the terminal state for blocks\r\nthat were retired because they were either marked bad or an error was\r\ndetected.</p>\r\n<h3 class=\"western\">13.1.2 Block and chunk allocation</h3>\r\n<p class=\"western\">An available chunk must be allocated before it can\r\nbe written. The chunk allocation mechanism is provided by\r\nyaffs_alloc_chunk() and is very simple. Each yaffs_dev has a current\r\nblock that it is allocating from. This is termed the <i><b>allocation\r\nblock </b></i><i><b>(alloc_block)</b></i>. Chunks are allocated\r\nsequentially from the allocation block. As the chunks are allocated,\r\nblock and chunk management information is updated, including the\r\nblock\'s pages_in_use count and the chunk use bitmap.</p>\r\n<p class=\"western\">When the block is fully allocated, another empty\r\nblock is selected to become the allocation block. The blocks are\r\nselected by searching upwards from the previous allocation block.</p>\r\n<p class=\"western\">In older versions of Yaffs, the Yaffs scanning\r\nwould identify the allocation block being used when the file system\r\nwas last shut down and would continue allocation from that point.\r\nThis had the benefit of continuing to use the same block and slightly\r\nreduce garbage creation. However, doing this could potentially cause\r\nproblems due to attempting to write a block that had been in the\r\nmiddle of a write when power was lost. Thus Yaffs now always starts\r\nallocation on a new block after a mount. This slightly increases the\r\namount of garbage (typically by an insignificant amount) but improves\r\nrobustness.</p>\r\n<h3 class=\"western\">13.1.3 A word about wear leveling</h3>\r\n<p class=\"western\">Since flash memory blocks can only endure a\r\nlimited number of writes and erases ( termed the flash endurance), a\r\nflash file system needs to ensure that the same few blocks are not\r\noverwritten continuously causing those blocks to wear out while the\r\nother blocks are hardly used at all.. Instead it is important that\r\nthe file system spreads out the wear.</p>\r\n<p class=\"western\">This is extremely important in a file system such\r\nas FAT which uses a limited set of logical blocks to store the file\r\nallocation table entries which get modified frequently. If FAT is\r\nused with a static logical to physical block mapping then the file\r\nallocation table blocks will wear out far before other blocks causing\r\npremature device failure. Thus, for FAT, it is very important that\r\nthe logical to physical mapping gets stirred up a bit to cause the\r\nfile allocation tables to be written to different physical blocks,\r\nthus leveling out the wear.</p>\r\n<p class=\"western\">Wear leveling is far less of a concern in a log\r\nstructured file system such as Yaffs since we always write to the end\r\nof the log and thus don\'t keep on overwriting the same blocks.</p>\r\n<p class=\"western\">There are basically two ways to achieve wear\r\nleveling:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Use a\r\n	specifically written set of functions that actively perform wear\r\n	leveling.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Allow\r\n	a degree of wear leveling to happen as a side effect of other\r\n	activity.</font></p>\r\n</ul>\r\n<p class=\"western\">Yaffs takes the second approach.</p>\r\n<p class=\"western\">Firstly, being log structured, Yaffs inherently\r\nspreads out the wear by performing all writes in sequence. That means\r\nthat we don\'t single out a few blocks for a specific purpose and\r\nwrite them more than others.</p>\r\n<p class=\"western\">Secondly, blocks are allocated serially from the\r\nerased blocks in the partition. Thus the process of erasing (after\r\ndeletion of garbage collection) and then allocating blocks does tend\r\nto spread the block use and provides a level of wear leveling.</p>\r\n<p class=\"western\">Thus, even though there is no code to specifically\r\nperform wear leveling it does happen as a side effect of other\r\nactivity.</p>\r\n<p class=\"western\">This strategy performs well and has survived many\r\naccelerated lifetime tests in both simulations and on real NAND-based\r\nproducts.</p>\r\n<h3 class=\"western\">13.1.4 Management of yaffs_tnode and yaffs_obj\r\nstructures</h3>\r\n<p class=\"western\">yaffs_tnodes and yaffs_objs are dynamically\r\ncreated and released as they are needed. \r\n</p>\r\n<p class=\"western\">The allocation and management could be done by\r\njust using the standard memory allocator (malloc, kmalloc etc), but\r\nthis could cause performance problems, particularly in embedded\r\nsystems which tend to have rather simplistic memory allocators. \r\n</p>\r\n<p class=\"western\">The allocation and deletion of many small\r\nstructures can cause memory fragmentation causing out-of-memory and\r\nslowdown problems.</p>\r\n<p class=\"western\">To prevent these problems, Yaffs manages these\r\nobjects internally. Yaffs creates many structures (100 or so) at a\r\ntime and then allocates them singly from a free list. When structures\r\nare released they are placed on the free list for reuse.</p>\r\n<h2 class=\"western\">13.2 Internal cache</h2>\r\n<p class=\"western\">This describes the standard Yaffs internal cache\r\nimplementation. Alternative caches have been devised for other\r\npurposes and at some future point Yaffs might be extended to support\r\npluggable cache policies.</p>\r\n<p class=\"western\">The main purpose of the internal cache is to\r\nreduce NAND access for  badly behaved applications which perform many\r\nsmall reads and writes. Believe it or not, but there are applications\r\nout there that read or write files a few bytes at a time:</p>\r\n<p class=\"code-western\"><code class=\"western\">while(...)<br/>\r\n	write(h,buf,1);</code></p>\r\n<p class=\"western\" style=\"margin-left: 1.25cm\"><br/>\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\">This sort of behavior would be terrible for\r\nperformance and flash memory life if each read or write operation\r\nresulted in a flash access. Yaffs provides an internal cache to\r\nmitigate against this sort of behaviour.</p>\r\n<p class=\"western\">The Yaffs internal cache is called a “Short Op\r\nCache” (short operation cache) and only comes in to play for\r\noperations which are not chunk aligned. The caching mechanism is very\r\nsimple and was primarily written for less sophisticated OSs that lack\r\ntheir own file caching layer. The cache is still beneficial in OSs\r\nlike Linux, which provide a caching layer, because it caches both the\r\nread and write path. Thus, while short reads will be serviced by the\r\nLinux page cache, the short op cache does address non-chunk aligned\r\nwrites.</p>\r\n<p class=\"western\">Page aligned reads/writes bypass the cache unless\r\nthat chunk is already in the cache, except when inband tags are used.\r\nInband tags always require the cache because the cache is used to\r\nbuild up the buffer where the tags are attached to the data chunk\r\nbeing written.</p>\r\n<p class=\"western\">The cache is stored in an array of cache entries.\r\nThe number of cache entries is set in the yaffs_dev parameters\r\nn_caches and the cache is configured during initialisation. n_caches\r\nof zero disables the cache. The cache management algorithms are\r\nsimplistic and probably don\'t scale well to very large numbers. This\r\nmeans that it is probably best to stick with around 5 to 20 cache\r\nentries.</p>\r\n<p class=\"western\">Each cache entry holds:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">obj_id, chunk id, nbytes (the tag info of\r\n	the chunk being cached)</p>\r\n	<li/>\r\n<p class=\"western\">The actual data bytes</p>\r\n	<li/>\r\n<p class=\"western\">Cache slot status (last used counter,\r\n	dirty,...)</p>\r\n</ul>\r\n<p class=\"western\">Finding an unused cache entry is a simple\r\noperation. We just iterate through the cache entries searching for\r\none that is not assigned. If all cache entries are busy then a cache\r\npush-out is performed to free up a cahce entry.</p>\r\n<p class=\"western\">Whenever a cache entry is accessed (read or\r\nwritten) the last-use counter is is set to an incrementing number.\r\nThis counter value is used to drive the least-recently-used (LRU)\r\nalgorithm.</p>\r\n<p class=\"western\">Cache entries which have been modified and not yet\r\nwritten back to flash are marked with a dirty flag. This is tells us\r\nwhether we need to write out the data during a flush or push-out.</p>\r\n<p class=\"western\">A push-out happens whenever the cache is full and\r\nwe need to push an entry out of the cache to make space to load a new\r\nentry. Yaffs uses the LRU algorithm to select the LRU cache entry,\r\nwrite it out if needed and then assign that for use.</p>\r\n<p class=\"western\">Whenever a file is flushed (file flush or close),\r\nthe file\'s dirty entries are written out. At certain times (eg.\r\nbefore an unmount or at sync()) the entire cache is flushed.</p>\r\n<p class=\"western\">This caching policy is gives a useful performance\r\nimprovement with very simple algorithms (ie good bang-for-bucks).</p>\r\n<p class=\"western\">Apart from its normal caching function, the short\r\nop cache also does much of the heavy lifting for inband tags support\r\nsince all the inband tags accesses are not chunk aligned and must\r\ntypically be re-aligned. The cache  makes this easy.</p>\r\n<h2 class=\"western\">13.3 Scanning</h2>\r\n<p class=\"western\">Scanning is the process whereby file system state\r\nis rebuilt from scratch. This happens on mounting a Yaffs partition\r\nif no checkpoint data is available or if the mounting was told to\r\nignore the checkpoint data.</p>\r\n<p class=\"western\">Scanning involves reading the tags from all the\r\nactive chunks in the system so can take quite a while, but probably\r\nless time than you\'d expect.</p>\r\n<p class=\"western\">The scanning process is different for Yaffs1 vs\r\nYaffs2 because of the differences mentioned before.</p>\r\n<h3 class=\"western\">13.3.1 Yaffs1 scanning</h3>\r\n<p class=\"western\">Yaffs1 scanning is rather straight forward because\r\nYaffs1 uses deletion markers.</p>\r\n<p class=\"western\">All we really need to do is read the tags off all\r\nthe chunks in the partition and determine if the chunk is active.\r\nOrder is not important and blocks could be read in any order. If the\r\ndeletion marker has not been set then it is active and we need to add\r\nthe chunk to the file system state as follows:</p>\r\n<p class=\"western\">If the chunk is a data chunk (chunk_id &gt; 0)\r\nthen the chunk must be added to the relevant file\'s tnode tree. If\r\nthe object does not exist, then we create it in lost+found, although\r\nit has no name and other file details yet.</p>\r\n<p class=\"western\">If the chunk is an object header (chunk_id == 0)\r\nthen the object must be created (or it might already exist in lost +\r\nfound and we need to fix up its details and slot it into the correct\r\npart of the directory tree.</p>\r\n<p class=\"western\">If at any time during scanning we find that we are\r\nreading a second chunk with the same obj_id:chunk_id as a previously\r\nencountered chunk then the 2-bit serial number is used to resolve the\r\ndispute.</p>\r\n<p class=\"western\">Once the scanning is complete we still need to fix\r\nup a few things: \r\n</p>\r\n<p class=\"western\">Hard links must be connected up properly (it is\r\nmore efficient to defer this until after the scanning has completed).</p>\r\n<p class=\"western\">Also, objects which were marked as unlinked must\r\nbe deleted since there are no longer handles open to these objects.</p>\r\n<h3 class=\"western\">13.3.2 Yaffs2 scanning</h3>\r\n<p class=\"western\">Yaffs2 has no deletion markers which makes the\r\nscanning significantly more complex.</p>\r\n<p class=\"western\">The first thing that needs to be done is to\r\npre-scan the blocks to determine the sequence number for the blocks.\r\nThe list of blocks and sequence numbers is then sorted to make a\r\nchronologically ordered list.</p>\r\n<p class=\"western\">Yaffs then scans <i><b>backwards</b></i> through\r\nthese blocks (ie in reverse chronological order). Thus, the first\r\nencountered  obj_id:chunk_id pair is the current one and subsequent\r\nchunks with those tags are out of date.</p>\r\n<p class=\"western\" style=\"margin-left: 1.25cm\">We read the tags for\r\neach chunk in each block. \r\n</p>\r\n<p class=\"western\" style=\"margin-left: 1.25cm\">If it is a data chunk\r\n( ie. chunk_id &gt; 0) then:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">If a chunk with the same obj_id:chunk_id\r\n	has already been found then this is not the current chunk. Delete\r\n	this one.</p>\r\n	<li/>\r\n<p class=\"western\">Else if the object is marked as deleted, or\r\n	corrupted, then delete it.</p>\r\n	<li/>\r\n<p class=\"western\">Else if the object does not yet exist then\r\n	this chunk was written since the last object header write for this\r\n	object so this chunk must be the last written chunk in the file and\r\n	must have happened just before an unclean shutdown with the file\r\n	still open. We can create the file and use the chunk_id and nbytes\r\n	to set the file extents.</p>\r\n	<li/>\r\n<p class=\"western\">Else if the object does exist and the chunk\r\n	lies beyond the object\'s file scan size (extents) then it is a\r\n	truncated chunk and can be deleted.</p>\r\n	<li/>\r\n<p class=\"western\">Else it is placed into the file\'s tnode\r\n	tree.</p>\r\n</ul>\r\n<p class=\"western\" style=\"margin-left: 1.25cm\">If it is an object\r\nheader (ie. chunk_id == 0) then:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">If the object is in the deleted directory\r\n	then mark the object as deleted and set the object\'s shrink size to\r\n	zero.</p>\r\n	<li/>\r\n<p class=\"western\">Else if an object header has not yet been\r\n	found for this object, then this is the most current object header\r\n	and holds the most current name etc.  If no data chunks have yet\r\n	been found for this chunk then the size in the object header is also\r\n	the file extents. The file size is used to set the file scan size\r\n	since at the time it was written the file did not extend past that\r\n	point and we can safely ignore further data chunks for that file\r\n	that extend past that point.</p>\r\n	<li/>\r\n<p class=\"western\">Else just use the file size as the scan\r\n	size if it is smaller than the current file scan size.</p>\r\n	<li/>\r\n<p class=\"western\">Else this an obsolete object header. It is\r\n	deleted.</p>\r\n</ul>\r\n<p class=\"western\">A bit more explanation is probably needed to\r\ndescribe the file scan size. The whole purpose of this is to\r\ndetermine data chunks that should be ignored due to the file being\r\ntruncated.</p>\r\n<h2 class=\"western\">13.4 Checkpoint</h2>\r\n<p class=\"western\">Mount scanning takes quite a lot of time and slows\r\nmounting, though perhaps by less than you\'d think. Checkpointing is a\r\nmechanism to speed the mounting by taking a snapshot of the Yaffs\r\nruntime state at unmount or sync() and then reconstituting the\r\nruntime state on re-mounting. The speed up is dramatic.</p>\r\n<p class=\"western\">The actual checkpoint mechanism is quite simple. A\r\n“stream” of data is written to a set of blocks which are marked\r\nas holding checkpoint data and the important runtime state is written\r\nto the stream.</p>\r\n<p class=\"western\">Not all state needs to be saved, only the state\r\nneeded to reconstitute the structure of the runtime data. For\r\nexample, file metadata need not be saved since it is very easy to\r\nload that through lazy-loading.</p>\r\n<p class=\"western\">The checkpoint stores data in the following order:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Start\r\n	marker, including checkpoint format id.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">yaffs_dev\r\n	information</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Block\r\n	information</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Chunk\r\n	flags</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Objects,\r\n	including file structure</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">End\r\n	marker</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Checksum</font></p>\r\n</ul>\r\n<p class=\"western\">The checkpoint validity is ensured by the\r\nfollowing mechanisms:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">The\r\n	data is stored using whatever ECC mechanisms are in place.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">The\r\n	start marker includes a checkpoint version so that an obsolete\r\n	checkpoint will not be read if the checkpoint code changes.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Data\r\n	is written to the stream as structured records, each with a type and\r\n	size.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">The\r\n	end marker must be read when expected.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">Two\r\n	checksums are maintained across the whole checkpoint data set.</font></p>\r\n</ul>\r\n<p class=\"western\">If any checks fail, the checkpoint is ignored and\r\nthe state is re-scanned.</p>\r\n<p class=\"western\">The astute reader might notice that block state\r\nchanges as we\'re writing checkpoint blocks, so how do we manage to\r\nre-constitute the block states correctly? This is achieved by the\r\nfollowing:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">As we\r\n	write the checkpoint, the checkpoint block allocation selects EMPTY\r\n	blocks. We don\'t change the state as we\'re writing the checkpoint so\r\n	their state is written to the checkpoint as EMPTY or CHECKPOINT, it\r\n	does not really matter which.</font></p>\r\n	<li/>\r\n<p class=\"western\"><font face=\"Liberation Serif, serif\">After\r\n	reading the checkpoint, we know which blocks have been used to store\r\n	checkpoint data. We update those blocks to reflect the CHECKPOINT\r\n	state.</font></p>\r\n</ul>\r\n<p class=\"western\">A checkpoint is invalidated by any modifications\r\n(writes, erases,...) thus any modification path also checks to see if\r\nthere is a checkpoint and erases it.</p>\r\n<p class=\"western\">The regular Yaffs block allocator and garbage\r\ncollection logic also needs to be aware of the approximate size of\r\nthe checkpoint so that these can ensure enough spare space is\r\nreserved to store a checkpoint. There is a calculation that updates\r\nthe value whenever the number of objects etc changes.</p>\r\n<h2 class=\"western\">13.5 Extended tags and packed tags</h2>\r\n<p class=\"western\">Extended tags is an abstraction of a way to store\r\nmore information in the tags, allowing for faster scan times. Packed\r\nTags is a physical implementation of the storage of extended tags.</p>\r\n<p class=\"western\">When we\'re scanning we really only need to build\r\nup the structure of the file system. In other words, rebuild the\r\ndirectory relationships, tnode trees and such. Much of the detail\r\nsuch as file names, permissions etc can be lazy loaded if and when\r\nneeded.</p>\r\n<p class=\"western\">This required storing extra information, such as\r\nthe parent directory and object type, in the tags of object headers.\r\nBut how do we do this without enlarging the tags size?</p>\r\n<p class=\"western\">Object headers always have a chunk_id of zero and\r\nn_bytes has no meaning because it is not a data chunk. By using a\r\nsingle bit to identify object headers we suddenly open up a whole lot\r\nof space that we can stuff full of useful data. By being clever as to\r\nwhat data we use, we can pack in the important data in most\r\ncircumstances.</p>\r\n<p class=\"western\">Sometimes, for example very large files, the\r\npacking will not work because there are insufficient bits to hold the\r\nfield so we just write regular tags instead. That\'s OK since there\r\ncan only be few such files in the system so the performance reduction\r\nonly impacts very few files and the system level impact is\r\nunnoticeable. A simple, cheap, strategy that gives speed up 99% of\r\nthe time is a very handy one.</p>\r\n<p class=\"western\">Other details are lazy-loaded on demand. This will\r\nhappen when the object is looked up (eg. by a file open or searching\r\nfor the file in the directory).</p>\r\n<h2 class=\"western\">13.6 Block summaries</h2>\r\n<p class=\"western\">Scanning requires that the tags for each chunk are\r\nread so that they can be inspected. Reading the tags from each chunk\r\ncan be time consuming. Thus, block summaries were added in 2011.</p>\r\n<p class=\"western\">Block summaries write all the tags data for chunks\r\nin the block into the last few (typically only one) chunk in a block.\r\nThis allows all the tags for chunks in that block to be read in one\r\nhit. Depending on the system throughput (CPU, RAM and flash speeds),\r\nthis can speed up mount time dramatically.</p>\r\n<p class=\"western\">Note that the block summary does not replace the\r\ntags attached to each chunk. Both are written. Thus, if the whole\r\nblock is not written (and the block summary is thus not written), the\r\nchunk tags can still be read and used.</p>\r\n<p class=\"western\">If a block summary is not available for a block,\r\nthen the old mechanism is still used to scan the tags on each chunk.</p>\r\n<h2 class=\"western\">13.7 Inband tags</h2>\r\n<p class=\"western\">Thus far we have considered chunks where there are\r\nsufficient unallocated bytes in the spare (or out of band) area to\r\nstore the tags. \r\n</p>\r\n<p class=\"western\">But what happens if we don\'t have enough space in\r\nthe spare area to store the tags? Inband tags to the rescue! \r\n</p>\r\n<p class=\"western\">With inband tags we store the tags in the flash\r\ndata area alongside the data. This gives us far more flexibility in\r\nthe types of storage that Yaffs can support.</p>\r\n<p class=\"western\">There are three major penalties with inband tags:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Due to the loss of chunk alignment, all\r\n	transactions must pass through the short op cache. This costs an\r\n	extra memcpy().</p>\r\n	<li/>\r\n<p class=\"western\"></p>\r\n	<li/>\r\n<p class=\"western\">Reading tags during scanning etc can\r\n	involve reading the whole page, making this slower. The impact is\r\n	minimised by using checkpointing or block summaries.</p>\r\n</ul>\r\n<p class=\"western\">Thus, it is better, performance wise, to only use\r\ninband tags when regular tags will not work.</p>\r\n<h2 class=\"western\">13.8 Soft deletion</h2>\r\n<p class=\"western\">Soft deletion is a mechanism that was added to\r\nspeed up file deletion in Yaffs1 mode.</p>\r\n<p class=\"western\">Looking back to the description of how files are\r\nstored in Yaffs1, you can see that deleting a file involves writing\r\nthe deletion marker of every data chunk in the file. This can take\r\nquite some time for large files.</p>\r\n<p class=\"western\">The soft deletion mechanism was added to avoid\r\nwriting all those deletion markers. Instead of writing the deletion\r\nmarkers, soft deletion instead tracks the number of chunks in each\r\nblock that belong to deleted files and leaves the clean up to the\r\ngarbage collector.</p>\r\n<p class=\"western\">When the garbage collector looks at a block it can\r\nsee what current chunks (ie chunks not yet deleted) belong to deleted\r\nfiles and does not copy those, thus effectively deleting the chunk.\r\nOnce all the chunks associated with a deleted file have cleaned up by\r\nthe garbage collector the file header object can also be deleted.</p>\r\n<p class=\"western\">Yaffs2 mode does not write deletion markers and\r\nthus does not use soft deletion.</p>\r\n\";s:7:\"summary\";s:378:\"This document gives an explanation of most of the core mechanisms that make Yaffs work. As of the time of writing this, the Yaffs2 code base includes approximately 19,000 lines of code making a very detailed discussion impractical. This document is the starting point for understanding Yaffs. Further detailed questions and discussions are welcomed on the Yaffs discussion list.\";s:6:\"format\";s:8:\"raw_html\";}}}s:19:\"field_document_type\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:9:\"target_id\";s:3:\"344\";}}}s:6:\"upload\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:9:\"target_id\";s:2:\"76\";s:7:\"display\";s:1:\"1\";s:11:\"description\";s:0:\"\";}}}s:18:\"field_teaser_image\";a:1:{s:9:\"x-default\";a:1:{i:0;a:5:{s:9:\"target_id\";s:3:\"108\";s:3:\"alt\";s:28:\"Preview of HowYaffsWorks.pdf\";s:5:\"title\";s:0:\"\";s:5:\"width\";s:3:\"150\";s:6:\"height\";s:3:\"194\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"paper\";s:2:\"id\";s:3:\"409\";s:8:\"revision\";s:3:\"627\";s:4:\"uuid\";s:36:\"7ded725e-366e-4ad5-a9c4-4d97e16adac0\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:15:\"How Yaffs works\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"6\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"627\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655095.022,1,'entity_field_info node_values','866'),('values:node:41','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"567\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1496142831\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:2:\"41\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:4:\"page\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"d0453baf-7f75-451c-8711-b9c8d9efb201\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:20:\"JFFS2 and NAND study\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1149597275\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496142831\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";N;}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:10986:\"<p>For the purposes of this discussion, the term NAND will mean both AND and NAND type flash memories, both sharing similar properties from a system perspective.</p>\r\n\r\n<h3>A bit of history -</h3>\r\n\r\n<p>History on my perspective, not the history of JFFS2.</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>Some years ago I wrote a flash file system for Trimble. Trimble patented this system. This FFS runs on NOR flash and uses a concepts very similar to JFFS to overcome problems associated with Flash Translation Layers, FTLs and flash. This FFS was rigorously tested for block failure, stress tested in various ways and deliberately crashed with an emulator at critical stages to attempt to damage data integrity. The FFS held up to all this.</p>\r\n\r\n<p>Thus, when looking at JFFS2 I can immediately understand why certain things are being done and various benefits of this approach over FTLs.</p>\r\n\r\n<p>At first I thought that using an FTL would be better than JFFS2 for NAND because NAND has a different set of constraints. After a bit of analysis, I came around to thinking that using JFFS2 would still be better than an FTL mainly because JFFS2 dispenses with the need for a logical to physical translation layer.</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<h3>NOR and NAND</h3>\r\n\r\n<p>The following table highlights some of the important properties of NOR and NAND flash. This table holds true for most devices, though there are some odd-ball devices out there.</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<table border=\"1\" cellpadding=\"1\" cellspacing=\"0\" width=\"568\">\r\n	<tbody>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p><strong>NOR</strong></p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p><strong>NAND</strong></p>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>Cost $HIGHER</p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Cost LOWER</p>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>Low density (approx 8MB max device size)</p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Higher density (approx 256MB max device size)</p>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>Linear random access:</p>\r\n\r\n			<ul>\r\n				<li>\r\n				<p>Like RAM</p>\r\n				</li>\r\n				<li>\r\n				<p>Can be used for XIP</p>\r\n				</li>\r\n			</ul>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Sector read/write:</p>\r\n\r\n			<ul>\r\n				<li>\r\n				<p>Almost like a disk.</p>\r\n				</li>\r\n				<li>\r\n				<p>Can\'t be used for XIP</p>\r\n				</li>\r\n			</ul>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>Structured as erasable blocks of 8kB to 128kB typical.</p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Structured as erasable blocks of 32x512-byte pages. Each page has 16-bytes of extra management data.</p>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>Endurance 100k to 1M erasures</p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Endurance 100k to 1M erasures</p>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>Erase time 1second/erasable block</p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Erase time 2ms</p>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>Designed as ROM replacements</p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Designed as mass storage replacements</p>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>Byte-by-byte programming allowing single-bit modification. Any single bit can be modified from a 1 to a 0 by programming that byte. However, the only way to modify a 0 to a 1 is to erase the entire erasable block.</p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Page or partial-page programming. A page may be programmed a maximum number of times. After that number of times, the erasable block must be erased to allow further programming. Write operations can only modify 1s to 0s. Changing 0s to 1s requires an erasure.</p>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>Random access programming.</p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Pages must be written sequentially within a block.</p>\r\n			</td>\r\n		</tr>\r\n		<tr valign=\"top\">\r\n			<td width=\"281\">\r\n			<p>No bad blocks when delivered, but the devices wear out. Thus file systems should be fault tolerant.</p>\r\n			</td>\r\n			<td width=\"281\">\r\n			<p>Bad blocks are expected when the devices are delivered. Further degradation is expected with use. Thus fault tolerance is an absolute necessity.</p>\r\n			</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>It is important to note the various differences between NOR and NAND flash, because these are material in choosing the appropriate file systems for each. In particular:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>The erasure times are very different. This impacts on the selection of appropriate garbage collection and erasure strategies. NOR\'s 1 second erasure time is significant and needs to be considered; NAND\'s 2msec erasure time is virtually insignificant.</p>\r\n	</li>\r\n</ul>\r\n\r\n<ul>\r\n	<li>\r\n	<p>The programming access restrictions that apply to NAND do not apply to NOR.</p>\r\n	</li>\r\n	<li>\r\n	<p>Errors are far more likely in NAND devices, therefore error detection and correction is highly desirable.</p>\r\n	</li>\r\n	<li>\r\n	<p>NAND flash is arranged in pages/sectors of 512b and is inherently block structured.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>Both families of flash technology have significant usage restrictions which require special consideration when using the devices for file storage:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>All flash memory blocks can only endure a limited number of erasure cycles. Some wear levelling strategy is required to prevent often-used sectors wearing out faster.</p>\r\n	</li>\r\n	<li>\r\n	<p>Sectors, are smaller than an erasable block. Thus, some garbage collection strategy is required to reclaim deleted/dirty sectors. To accomplish this, the \"good data\" must be copied off the selected block so that the whole block can be erased without losing data.</p>\r\n	</li>\r\n	<li>\r\n	<p>If a part of a file needs to be overwritten, it is a limitation of flash memory that the new data cannot just overwrite the data at the same physical location. Instead the data must be written at a new location. Thus, some sort of logical to physical mapping layer (ie. FTL) or alternative data storage approach is required (eg. JFFS2). Such logical to physical decoupling is also required to perform garbage collection.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<h3>Flash file systems in general</h3>\r\n\r\n<p>Flash file systems can essentially be implemented in two possible ways:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Custom-built file system. ie. the whole file system is designed so as to operate with flash memory. An example of this is JFFS2 or Microsoft FFS2.</p>\r\n	</li>\r\n	<li>\r\n	<p>Use a standard file system with a custom block driver (ie Flash Translation Layer - FTL).</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>Each of these approaches have their pros and cons. FTLs are particularly suited to situations where the file system is pre-ordained; a custom file system is able to be more \"flash friendly\".</p>\r\n\r\n<h3>An appraisal of the JFFS2 file system</h3>\r\n\r\n<p>JFFS, and JFFS2, achieve the logical decoupling between logical file positions and physical memory by using journaling. For this to work, the entire file system must be designed to support journaling - as appropriate to flash memory. This is not excessively restrictive with non-removable media and embedded systems since there is no need to conform to a legacy file system layout.</p>\r\n\r\n<p>JFFS2 is designed to support NOR flash, but is currently not suited to NAND flash since it does not handle bad blocks. If this deficiency was addressed would it be a better choice for NAND than an FTL? Probably not directly, some other tweaks would be needed.</p>\r\n\r\n<p>Journaling is particularly useful: Garbage collection, bad block handling and the restrictions which prevent flash sectors being overwritten mean that data in flash file systems is forever being moved around. For FTLs this means storing logical to physical mappings. Journaling neatly sidesteps this overhead.</p>\r\n\r\n<p>One of the most thorny issues with flash file systems is that there are many patents covering both FTL-like block drivers and various approaches to custom file systems.</p>\r\n\r\n<p>These patents are particularly restrictive in FTL-like block drivers (especially the M-Systems patents). JFFS2 does not violate any patents I am aware of, but it probably comes quite close to some - particularly the Trimble one. Thus it is highly beneficial to have a GPL\'ed system that can be extended.</p>\r\n\r\n<h3>Work needed</h3>\r\n\r\n<p>The following effort is required to make JFFS2 work with NAND:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>New MTDs for NAND flash. A new interface is probably required for NAND since many of the functions for NOR make no sense on NAND.</p>\r\n	</li>\r\n</ul>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Bad block handling. This could be handled in a NOR-specific layer, although it should really be generically supported since NOR can fail too.</p>\r\n	</li>\r\n	<li>\r\n	<p>ECC for data security. Code available from Samsung www. This can be handled as part of the write and read. When a journaling node is written, it should be verified. If the data cannot be retrieved, then a new node is created.</p>\r\n	</li>\r\n	<li>\r\n	<p>Fixed size journaling nodes (since NAND is page oriented with limited writes per page). This might make compression challenging - maybe compression can\'t be used with NAND? Anyway, fixed-size journaling nodes probably reduce fragmentation too (since there\'s an integer number of these per erasable block).</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>The following are possible improvements:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Tuning garbage collection/erasure strategies to suite NAND (eg. NAND erasure time is much faster). Using fixed-size nodes will probably strip out a chunk of code too.</p>\r\n	</li>\r\n	<li>\r\n	<p>Attempting to use the spare 16 bytes per page for journalling tags (if there\'s a useful amount of space left after ECC and bad block management).</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>Thus, my preliminary suggestion would be to add a NAND sub-system to JFFS2. This subsystem would use the same journaling file system core. Fixing the size of journaling nodes to \"pages\" of 512 bytes quite likely simplifies the interfaces, node management and garbage collection.</p>\r\n\r\n<p>Error handling would fit within the NAND subsystem. Since NOR fails too, bad block handling is really required for NOR too. Whether the same management is appropriate for both is TBD. ECC is only required for NAND.</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p align=\"center\"><a name=\"_1065327724\"></a><a name=\"_1065291949\"> <img align=\"bottom\" border=\"0\" height=\"190\" src=\"/sites/yaffs.net/files/sv9379380.gif\" width=\"227\" /></a></p>\r\n\r\n<p><a name=\"_1065291949\"> </a></p>\r\n\r\n<h3><a name=\"_1065291949\">References</a></h3>\r\n\r\n<p><a name=\"_1065291949\">Samsung and Toshiba NAND part data sheets and www. Samsung in particular has useful applications notes and code.</a></p>\r\n\r\n<p><a name=\"_1065291949\">JFFS2 presentation materials. http://sources.redhat.com/jffs2/</a></p>\r\n\";s:7:\"summary\";s:190:\"Discussion of the characteristics of NAND and NOR flash and how those interact with JFFS2 to produce significant boot-time delays and high RAM consumption, especially with large flash chips.\";s:6:\"format\";s:9:\"full_html\";}}}s:19:\"field_document_type\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:9:\"target_id\";s:3:\"346\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:4:\"page\";s:2:\"id\";s:2:\"41\";s:8:\"revision\";s:3:\"567\";s:4:\"uuid\";s:36:\"d0453baf-7f75-451c-8711-b9c8d9efb201\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:20:\"JFFS2 and NAND study\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"567\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510659012.612,1,'entity_field_info node_values','866'),('values:node:414','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"415\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1430391217\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"414\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"796983fd-b8b0-48f9-9c95-377d7227350d\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:47:\"Suitable for open and closed source projects...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1339010643\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496402329\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:875:\"<p>If you want to use Yaffs on an Open Source project, then go ahead and <a href=\"/downloads\">download</a> the GNU General Public Licence v.2 now. You can get it straight away from the link on the right of the page.</p>\r\n\r\n<p>Yaffs is also available under a Commercial Licence&nbsp;for projects that don\'t want to disclose their source code.&nbsp; This Licence does not have the obligations of GPL, but is perpetual, world-wide, non-exclusive and carries no continuing royalty.</p>\r\n\r\n<p>You can use the Open Source code to investigate and evaluate Yaffs, then before shipping your product to anyone outside of your organisation you buy a licence from Aleph One which does not have the GNU GPL obligation to release your Source Code.&nbsp; Contact&nbsp; sales@aleph1.co.uk&nbsp; for more information or have a look at our <a href=\"/downloads\">licensing information</a>.</p>\r\n\";s:7:\"summary\";s:260:\"If you want to use Yaffs on an Open Source project, then go ahead and <a href=\"/downloads\">download</a> the GNU General Public Licence, version 2 form now. It is also available under a commercial Licence without the obligations entailed in the GNU GPL version.\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:7:\"fa-cogs\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"414\";s:8:\"revision\";s:3:\"415\";s:4:\"uuid\";s:36:\"796983fd-b8b0-48f9-9c95-377d7227350d\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:47:\"Suitable for open and closed source projects...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"415\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674600.739,1,'entity_field_info node_values','866'),('values:node:415','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"416\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1430391377\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"415\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"434a5659-0edd-45b9-a53f-d255b5a35cbe\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:50:\"For closed source projects - try before you buy...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1339066508\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496402417\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:597:\"<p>When shopping for a software component, it\'s always useful to be able to try it out before buying.</p>\r\n\r\n<p>For your proprietary projects, the GPL version of Yaffs lets you do just that - download it, examine the code and test it out. Check out our documentation and videos.</p>\r\n\r\n<p>It\'s perfectly acceptable and safe to use the GNU GPL code inside your company, providing you don\'t ship a binary to anyone beyond it.&nbsp;That\'s when code disclosure and licensing provisions of the GNU GPL kick in.&nbsp;So before you do that, you\'ll want to talk to us about acquiring a paid Licence.</p>\r\n\";s:7:\"summary\";s:89:\"If you think that Yaffs might be what you need, you can test it without buying a licence.\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:14:\"fa-credit-card\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"415\";s:8:\"revision\";s:3:\"416\";s:4:\"uuid\";s:36:\"434a5659-0edd-45b9-a53f-d255b5a35cbe\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:50:\"For closed source projects - try before you buy...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"416\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674600.742,1,'entity_field_info node_values','866'),('values:node:416','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"417\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1430392039\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"416\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"1b9479c8-dfea-4726-aa1a-32e112b26879\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:25:\"Yaffs is a safe choice...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1339071522\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496402459\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:1266:\"<p>Having started in 2002 Yaffs embodies more than ten years of experience with Flash memory and its specialised needs, coupled with continued growth in the number of people and companies using Yaffs.</p>\r\n\r\n<p>Since its inception numerous features and refinements have been added. The code continues to evolve, growing in value to users whilst retaining backward compatibility. The community of users continues to grow as more and more people and companies opt to use Yaffs, providing a pool of knowledge which is accessible to new users.&nbsp;</p>\r\n\r\n<p>The availability of the GNU General Public Licence version means that there\'s always an exit route for open source projects, and since it\'s open-source, existing commercial projects will at the very least always have the source code and the licence to continue to use it, and likely much more. Plus commercial projects benefit from the open source experience in Yaffs - both with respect to developers and knowledge.&nbsp;</p>\r\n\r\n<p>Yaffs is a safe choice for any project needing a Flash file system: it has well over ten years of history, proven sustainability, a continuously improving codebase, a growing user base, and exit routes, since it&nbsp;will continue to be available regardless of Yaffs.net.</p>\r\n\";s:7:\"summary\";s:161:\"Yaffs has a long history, coupled with continuing development. There are thousands of developers who have used it, and it\'s deployed in many millions of devices.\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:11:\"fa-bullseye\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"416\";s:8:\"revision\";s:3:\"417\";s:4:\"uuid\";s:36:\"1b9479c8-dfea-4726-aa1a-32e112b26879\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:25:\"Yaffs is a safe choice...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"417\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674600.744,1,'entity_field_info node_values','866'),('values:node:417','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"418\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1341880534\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"417\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"c7610495-b4fb-4573-9fd2-db3c881fd503\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:27:\"Yaffs is fully supported...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1339095743\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496407318\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:541:\"<p>Yaffs support is available through the Yaffs community - primarily via the mail list - with help coming from our key developers as well as other people who use Yaffs. For those times when you don\'t feel comfortable asking a question in a public forum, perhaps because the project is sensitive, we will normally answer a few questions off-list before we offer you the opportunity of consultancy and direct access to our developers. And of course we are always willing to discuss other forms of support for customers who buy licences.</p>\r\n\";s:7:\"summary\";s:177:\"Yaffs support is available through the Yaffs community but for those problems that aren\'t suitable for a public forum, we offer consultancy with direct access to our developers.\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:12:\"fa-map-signs\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"417\";s:8:\"revision\";s:3:\"418\";s:4:\"uuid\";s:36:\"c7610495-b4fb-4573-9fd2-db3c881fd503\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:27:\"Yaffs is fully supported...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"418\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674600.746,1,'entity_field_info node_values','866'),('values:node:418','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"419\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1344939735\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"418\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"2cdd1a43-8da4-4267-b769-46f663b3a333\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:26:\"Data is safe with Yaffs...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1339097688\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496407385\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:997:\"<p>Yaffs provides bad block handling and ECC algorithms to handle deficiencies in NAND flash.</p>\r\n\r\n<p>It is a log-structured file system which makes it very robust to corruptions caused by power failures.</p>\r\n\r\n<p>We spend about 60% of development time on testing Yaffs, and our test harness is available for download so you can check the testing and perform some yourself.</p>\r\n\r\n<p>We\'ve performed hundreds of thousands of tests to make sure that Yaffs is as safe as we can make it, even in the even of a power failure during a firmware update.</p>\r\n\r\n<p>You can find full details of the Yaffs testing regime in our paper <a href=\"http://www.yaffs.net/documents/yaffs-robustness-and-testing\">http://www.yaffs.net/documents/yaffs-robustness-and-testing</a>&nbsp; including all the details on the power-fail stress tests, the Yaffs Direct API tests for commercial RTOSs, Linux testing, and fuzz testing where we deliberately corrupt Yaffs file systems to check that Yaffs can still mount.</p>\r\n\";s:7:\"summary\";s:178:\"Yaffs is designed for data safety and rigorously tested to ensure it does the best possible to keep users\' data safe. It\'s been crash-tested it hundreds of thousands of times ...\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:7:\"fa-lock\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"418\";s:8:\"revision\";s:3:\"419\";s:4:\"uuid\";s:36:\"2cdd1a43-8da4-4267-b769-46f663b3a333\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:26:\"Data is safe with Yaffs...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"419\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674600.748,1,'entity_field_info node_values','866'),('values:node:42','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"573\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1496365989\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:2:\"42\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:4:\"page\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"1561b774-226c-4c3f-96ff-6f08e210b3f9\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:44:\"State of NAND MTD driver at start of project\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1116849036\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496365989\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:5890:\"<h3>Current state of NAND MTD</h3>\r\n\r\n<p>The current NAND MTD supports basic read/write functions. The code is hard-wired to support the NAND devices on a SPIA board. The ECC code supports 256 byte sectors.</p>\r\n\r\n<p>There are 3 files:</p>\r\n\r\n<p>nand.c: nand support algorithms. Unfortunately there is no hardware abstraction (ie. the hardware is assumed to be the SPIA board). but this is relatively easy to add.</p>\r\n\r\n<p>spia.c: this initialises the spia hardware to set up the addresses for the hardware access.</p>\r\n\r\n<p>ecc.c: ECC for 256 byte pages.</p>\r\n\r\n<p>What needs to be done at this level:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Hardware abstraction of nand.c. This allows this code to be used with different hardware configurations.</p>\r\n	</li>\r\n	<li>\r\n	<p>The larger memory sizes use 512 byte pages. The memory sizes supported by 256-byte pages are obsolete. 512-byte pages are treated as two sub-pages of 256 bytes each. The Samsung code is calculation based (ie. maybe slow). The Toshiba code is table based and probably faster. Check if they are equivalent.</p>\r\n	</li>\r\n	<li>\r\n	<p>Write a software emulation for a NAND device. The purpose of the software emulator is:</p>\r\n\r\n	<ul>\r\n		<li>\r\n		<p>Allow debugging without the need for hardware.</p>\r\n		</li>\r\n		<li>\r\n		<p>NAND file systems need to be fault tolerant. The hardware can\'t be forced to fail to test out bad block detection/handling etc. A software emulator can be forced to fail.</p>\r\n		</li>\r\n	</ul>\r\n	</li>\r\n</ul>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<h3>Overall flash system diagram<img alt=\"\" height=\"402\" src=\"/sites/yaffs.net/sv16516600.gif\" width=\"399\" /></h3>\r\n\r\n<p>A diagrammatic representation of support for SmartMedia, NAND and NOR as well as both FAT16 and JFFS2 might look like the above.</p>\r\n\r\n<p>The NAND flash sub-system uses common layers for:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>hardware access</p>\r\n	</li>\r\n	<li>\r\n	<p>ECC, bad block handling and low-level formatting. (based on Smart Media low-level specs). By using the same low level formatting and ECC as much as possible we gain some benefit in testing, reuse etc. The low-level formatting would differ in that fields used to store the LBA and reserved fields might be used for something else (??journaling tags??)</p>\r\n	</li>\r\n</ul>\r\n\r\n<h3>Concerns with using JFFS2 on NAND</h3>\r\n\r\n<p>There are some reasons why JFFS and NAND might not work together that well.</p>\r\n\r\n<p>Two particular concerns re booting</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>NAND devices are typically much larger than NOR (eg. 128MB is currently a large NAND chip while 16MB would be considered a large NOR chip), thus the data structures associated with flash management are likely to be much larger. Also, JFFS2 scans the media on boot to build data structures representing the nodes in the system. This increases the boot time.</p>\r\n	</li>\r\n	<li>\r\n	<p>NAND is not random access but must be read serially. This means that the scanning routine can\'t just merrily skip through the flash, instead the whole flash must be read and ECC\'d first. This slows scanning and hence booting.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>Thus booting a 128MB NAND-based JFFS2 is likely to look something like this:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Read and ECC every last byte on the device even if we only need a few bytes per page for journaling headers and digest the contents. At say 5MB/second this will take ~25 seconds.</p>\r\n	</li>\r\n	<li>\r\n	<p>Each node requires a 16-byte structure (struct jffs2_raw_node_ref). If nodes were 512-bytes then that\'s 4MB of RAM!</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>These are probably unacceptable for the product being used. We therefore need to run something better than this.</p>\r\n\r\n<p>Two approaches spring to mind:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>Just run FAT16. ie. Just treat all NAND as SmartMedia. Benefits: one code base. Down-side: reliability.</p>\r\n	</li>\r\n	<li>\r\n	<p>I\'m reluctant to store critical files in a FAT16 file system because these can be so unreliable. I\'m convinced that a journaling file system is superior. Maybe what we need is a light weight journaling file system (using common code with JFFS) modified in such a way as sidestep some of the nasty issues raised above.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<h3>What I\'m working towards</h3>\r\n\r\n<p>Right now I\'m investigating the idea of trying to do something more appropriate. My current avenue of exploration is to use a journaling approach as follows:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>The journaling records are stored in fixed-size 512-byte pages.</p>\r\n	</li>\r\n	<li>\r\n	<p>The journaling tags are stored in the 16-byte-per-page \"management space\", semi-consistent with SmartMedia, using the 8 bytes of reserved space and LBA space to store journaling tags. ie something like:</p>\r\n	</li>\r\n	<li>\r\n	<p>20 bits of page id within inode</p>\r\n	</li>\r\n	<li>\r\n	<p>20 bits of inode id</p>\r\n	</li>\r\n	<li>\r\n	<p>9 bits length (bytes used in this page).</p>\r\n	</li>\r\n	<li>\r\n	<p>7 bits flags etc.</p>\r\n	</li>\r\n	<li>\r\n	<p>8 bits of hamming code on this area.</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>Each page id identifies where the page fits into the file. When a page is replaced (ie file data is overwritten) a new page with the same page id is written and the old one is wiped out. During garbage collection, the pages containing valid data are copied and the wiped out data is discarded.</p>\r\n\r\n<p>The benefits of this approach are:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>NAND-friendly since it works within the write limitations of NAND.</p>\r\n	</li>\r\n	<li>\r\n	<p>Less stuff to read to reconstruct file structures (only read management data).</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>Down sides:</p>\r\n\r\n<ul>\r\n	<li>\r\n	<p>No compression. But is that an issue considering the target data is already compressed and NAND is far less precious than NOR (thanks to higher densities and lower price).</p>\r\n	</li>\r\n</ul>\r\n\r\n<p>Still need to see if a new data structure is going to reduce the overhead of jffs2_raw_node_ref somewhat.</p>\r\n\";s:7:\"summary\";s:251:\"<p>Details of Dec 2001 state of nand driver, and overview of how drivers fit together for use with different hardware and filesystems. Not really intended for public consumption, but a useful backgrounder and explanation of the evolution of YAFFS.</p>\";s:6:\"format\";s:9:\"full_html\";}}}s:19:\"field_document_type\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:9:\"target_id\";s:3:\"346\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:4:\"page\";s:2:\"id\";s:2:\"42\";s:8:\"revision\";s:3:\"573\";s:4:\"uuid\";s:36:\"1561b774-226c-4c3f-96ff-6f08e210b3f9\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:44:\"State of NAND MTD driver at start of project\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"573\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510657515.065,1,'entity_field_info node_values','866'),('values:node:420','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:22:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"605\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1496873154\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"420\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:5:\"paper\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"c3d49866-ddb0-41b9-9505-630fed1d93f4\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:28:\"YAFFS Robustness and Testing\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"6\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1339119318\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496873154\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:61826:\"\r\n\r\n	<p class=\"western\">Many embedded systems need to store critical\r\n	data, making reliable file systems an important part of modern\r\n	embedded system design. That robustness is not achieved through\r\n	chance. Robustness is only achieved through design and extensive\r\n	testing to verify that the file system functions correctly and is\r\n	resistant to power failure.</p>\r\n	<p class=\"western\">This document describes some of the important\r\n	design criteria and design features used to achieve a robust design.</p>\r\n	\r\n<p class=\"western\" style=\"page-break-before: always\"><h1 class=\"western\">1 Background</h1>\r\n<p class=\"western\">Cheaper CPUs and flash have driven up embedded\r\nsystem functionality. These increased functions often require file\r\nsystem storage.</p>\r\n<p class=\"western\">The original flash file storage mechanisms were\r\nthe use of a flash translation layer (FTL) – a driver model which\r\nmakes flash memory appear as a disk drive – in conjunction with a\r\ndisk-oriented file system such as FAT. This storage methodology has\r\nvarious performance and robustness limitations, leading to the\r\ndevelopment of file systems designed specifically for flash memory.\r\nThese are known as flash file systems.</p>\r\n<p class=\"western\">Flash memory has various limitations when compared\r\nwith a disk. For example, flash memory pages cannot be individually\r\nre-written but instead the whole block must be  erased and rewritten\r\nwith the modified page. Typical FTL achieve this with various logical\r\nto physical mapping schemes. Thus emulating disk-like behaviour on\r\nflash memory adds an extra layer of software which slows down write\r\nperformance. Worse still, it adds extra state which is prone to\r\ncorruption due to power failure.</p>\r\n<p class=\"western\">A typical FTL-based solution will use a file\r\nsystem such as FAT. FAT always stores tables in the same disk blocks\r\nand must thus change the same blocks often. Since flash memory blocks\r\ncan endure a limited number of write/erasure cycles, the FTL must\r\nmove the physical location of the block around to prevent  the high\r\ntraffic blocks from wearing out. This requires wear levelling – a\r\nfurther burden.</p>\r\n<p class=\"western\">Some systems try to mitigate against the\r\nperformance penalties by caching a lot of data to reduce writes.\r\nWhile this can go some way towards reducing the apparent write time,\r\nit does make the solution prone to data loss in the event of a power\r\nfailure.</p>\r\n<p class=\"western\">As well as limitations, flash memory also has\r\ncertain advantages when compared to rotating media. There is no spin\r\nup time, making it more responsive. There is no read head so there is\r\nno read penalty if data is fragmented. Flash file systems can be\r\ndesigned to exploit these advantages.</p>\r\n<p class=\"western\">True flash file systems<a class=\"sdfootnoteanc\" name=\"sdfootnote1anc\" href=\"#sdfootnote1sym\"><sup>1</sup></a>,\r\non the other hand, are a single code body designed to take the\r\nfeatures and limitations of flash into consideration. Flash file\r\nsystems can thus be far more “flash friendly”. Well designed\r\nflash file systems will avoid using “flash unfriendly” techniques\r\nsuch as allocation tables and in-place rewriting.</p>\r\n<p class=\"western\">Yaffs is a flash file system, originally designed\r\nspecifically for NAND flash though also used with great success on\r\nNOR flash too. Yaffs development started in 2001 when 32Mbytes of\r\nflash was considered large. Since then, Yaffs has been expanded to\r\nwork properly with different flash types and far larger memory arrays\r\n(many GBytes).</p>\r\n<p class=\"western\">Yaffs was originally deployed in Linux, but was\r\nwritten in an OS neutral way, mainly to facilitate modular\r\ndevelopment and testing. This turned out to be useful when we had\r\nrequests to port Yaffs to other operating systems. Since then, Yaffs\r\nhas been used in many different products in a wide variety of\r\napplications from consumer products such as cell phones and sewing\r\nmachines to aerospace, industrial and medical applications including\r\nprocess control, building management, communications infrastructure\r\nand many others.</p>\r\n<p class=\"western\">Yaffs is not tied to any endian ordering and has\r\nbeen used on a wide variety of architectures including ARM, MIPS,\r\nPowerPC, x86, some DSPs. Yaffs has been deployed using a wide variety\r\nof compilers from many different vendors.</p>\r\n<p class=\"western\">Nor is Yaffs tied to any particular operating\r\nsystem. Yaffs has been used with Linux, eCOS, Windows Embedded\r\nCompact (previously Windows CE), VxWorks and others.</p>\r\n<h1 class=\"western\">2 Flash File System considerations</h1>\r\n<p class=\"western\">There are many criteria that are important when\r\nselecting a flash file system. These are some that out customers have\r\nfound to be most important:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">Robustness: It really is not worth having a\r\n	file system that loses or corrupts data and prevents the system from\r\n	working properly. Some flash file systems are only robust when\r\n	synced (flushed) after files have been written. That requires extra\r\n	code, slows the system and leaves the file system in a\r\n	non-deterministic state until the sync has been completed. Some file\r\n	systems need to perform disk repair operations (eg. check disk) in\r\n	the event of a power failure. This can add considerable time to the\r\n	start up, preventing the system from being operational.</p>\r\n	<li/>\r\n<p class=\"western\">Performance: In many embedded system\r\n	designs, slow read/write performance can delay tasks and cause\r\n	system degradation or even failure. It is thus important that\r\n	read/write performance be acceptable. Note that many flash file\r\n	systems need to perform extra actions such as garbage collection. In\r\n	some cases these actions can cause the file system to stall for a\r\n	long time. It is thus important that these factors be taken into\r\n	consideration. Performance can sometimes be improved by adding a\r\n	write caching layer. These caching layers make the file system calls\r\n	(write etc) proceed quickly, without actually writing the data to\r\n	flash. This is a two-edged sword as data in the cache will be lost\r\n	on a power failure and syncing the file system will take a long\r\n	time. Thus, most flash file systems offer either speed or robustness\r\n	– not both.</p>\r\n	<li/>\r\n<p class=\"western\">Proven: It is very easy for a file system\r\n	vendor to provide a list of claims saying “100% power safe” or\r\n	similar, but what evidence do they have to back this up? All file\r\n	systems, including flash file systems, are complex bodies of\r\n	software with extremely complex state. They need very significant\r\n	testing to prove that they work correctly.</p>\r\n	<li/>\r\n<p class=\"western\">Portable: Software is a huge investment and\r\n	it is increasingly important to be able to port the software between\r\n	OSs and CPU architectures. Most flash file systems are limited to a\r\n	single operating system which makes it difficult to migrate software\r\n	between different platforms. In Yaffs\' case portability extends to\r\n	being able to seamlessly migrate the core Yaffs code into a test\r\n	framework which enhances testing.</p>\r\n</ul>\r\n<h1 class=\"western\">3 How Yaffs achieves robustness and performance</h1>\r\n<p class=\"western\">Yaffs was designed from the ground up specifically\r\nto work well with NAND flash. The author had already developed\r\nanother flash file system, so was already familiar with the  design\r\nchallenges of flash.</p>\r\n<p class=\"western\">As Yaffs is not just adapting a disk-oriented file\r\nsystem to work with flash it is not surprising that Yaffs is very\r\ndifferent in design to most other file systems. The key difference is\r\nthat Yaffs is a log-structured. file system<a class=\"sdfootnoteanc\" name=\"sdfootnote2anc\" href=\"#sdfootnote2sym\"><sup>2</sup></a>.</p>\r\n<p class=\"western\">In essence, a log structured file system writes\r\nfile system changes as a sequential log.  The log structure is\r\nparticularly suitable for various reasons including:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">All writes are at the end of the log. When\r\n	a file is modified, there is no need to erase and rewrite a part of\r\n	the flash. Changes are just appended to the log. Thus there is no\r\n	need to erase and copy old data just to change some existing pages\r\n	in a file. This tends to make writes much faster. There is no need\r\n	to do a lot of caching to achieve performance. Data can be written\r\n	to the log immediately meaning that sync time is very low. Data\r\n	robustness is improved dramatically.</p>\r\n	<li/>\r\n<p class=\"western\">There are no allocation tables or similar.\r\n	This reduces the amount of data being written to the flash, and that\r\n	there are no tables to corrupt.</p>\r\n	<li/>\r\n<p class=\"western\">Since all writes are to the end of the log\r\n	there are no “high traffic” blocks. This means Yaffs only needs\r\n	a simpler wear leveling strategy.</p>\r\n	<li/>\r\n<p class=\"western\">In the event of a power failure, the file\r\n	system state is easily re-created from the log. This means there is\r\n	no need to perform disk repair operations to correct for an unclean\r\n	shutdown.</p>\r\n</ul>\r\n<p class=\"western\">So why don\'t we see many log structured file\r\nsystems for disk file systems? The answer to this is that log file\r\nsystems tend to spread the writes around on the media. That is\r\ntypically very problematic for mechanical storage which must\r\nphysically move the read/write head from one location to another\r\nmaking the access time very slow. Of course that does not apply for\r\nflash memory. By designing specifically for flash, Yaffs can ignore\r\nthis issue and write fast.</p>\r\n<p class=\"western\">Many flash file systems need make a compromise\r\nbetween robustness against performance. Thanks to the log structure,\r\nYaffs does not need to. Yaffs can provide high performance without\r\ngiving up on robustness.</p>\r\n<p class=\"western\">Those familiar with log structured file system\r\ndesign will know that some log structured file systems have problems\r\nwith garbage collection<a class=\"sdfootnoteanc\" name=\"sdfootnote3anc\" href=\"#sdfootnote3sym\"><sup>3</sup></a>.\r\nGarbage collection is used to clean up the log and make more free\r\nspace available. Some log structured file system designs did not pay\r\nenough attention to garbage collection and can stall for a\r\nconsiderable time while garbage collection happens. Yaffs was\r\ndesigned differently. The potential impact of garbage collection was\r\nconsidered throughout the Yaffs design process. As a result, Yaffs\r\nhas a very simple garbage collection model that allows a lot of\r\nflexibility in garbage collection scheduling. This prevents the\r\ngarbage collection from making the file system unresponsive.</p>\r\n<p class=\"western\">Most file systems are developed within the\r\ncontext, and framework of, a single operating system. This typically\r\nmakes the code difficult to explore, debug and port. Yaffs on the\r\nother hand was developed from the start inside a portable\r\ndevelopment/testing framework. Yaffs is then ported to various\r\noperating systems through the addition of glue code.</p>\r\n<p class=\"western\"><br/>\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\"><img src=\"data:image/png;base64,[encoded data, 38784 characters]\" name=\"Object1\" align=\"left\" width=\"552\" height=\"524\"/>\r\n<br/>\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\">There are many benefits to this approach:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">A development framework runs in user space\r\n	which provides a richer development environment than inside an OS\r\n	kernel. It is much easier to attach debuggers and perform logging\r\n	and create reproducible testing.</p>\r\n	<li/>\r\n<p class=\"western\">The code is structured to be portable. That\r\n	makes it relatively easy to port to a new OS or RTOS with a high\r\n	level of confidence.</p>\r\n	<li/>\r\n<p class=\"western\">There is a choice of porting interfaces\r\n	allowing more flexibility to determine which porting method will be\r\n	simpler. For example, the Linux wrapper accesses the Yaffs core\r\n	directly while the Windows CE wrapper access the Yaffs Direct\r\n	Interface<a class=\"sdfootnoteanc\" name=\"sdfootnote4anc\" href=\"#sdfootnote4sym\"><sup>4</sup></a>.</p>\r\n	<li/>\r\n<p class=\"western\">Each different environment provides\r\n	different test tools. For example, Linux provides a raft of file\r\n	system test tools that do different kinds of testing to the power\r\n	fail test harness. Since the vast majority of the code is in the\r\n	portable Yaffs core, that code gets the advantage of all test\r\n	methods combined. The many millions of Android phone users that use\r\n	Yaffs-based devices are helping test the core code that is also used\r\n	on a wide variety of different operating systems and a wide range of\r\n	different device types.</p>\r\n	<li/>\r\n<p class=\"western\">Its Open Source status means any interested\r\n	person can take a version from git and test it to make sure that it\r\n	meets their needs.</p>\r\n</ul>\r\n<h1 class=\"western\">4 Testing</h1>\r\n<p class=\"western\">It is all very well to design software to be\r\nrobust, but it needs thorough testing to build confidence in the\r\nsoftware and in the code authors and supplier.</p>\r\n<p class=\"western\">File systems have incredibly complex state so it\r\nis not at all surprising that operating system designers find file\r\nsystems some of the most challenging code to test.</p>\r\n<p class=\"western\">There is no single test methodology that can test\r\nall cases, and exhaustive state testing is impossible. The best we\r\ncan do is to have a suite of test methodologies that combine to\r\nprovide thorough testing.</p>\r\n<p class=\"western\">Approximately 60% of Yaffs development effort is\r\ndirected towards testing and improving the test environment. We are\r\nconstantly researching new methodologies.</p>\r\n<p class=\"western\">The following are descriptions of the most\r\nimportant test strategies used in Yaffs.</p>\r\n<h2 class=\"western\">4.1 Power Fail Stress Testing</h2>\r\n<p class=\"western\">By far the most important consideration in Yaffs\r\ntesting is that it is robust to corruptions caused by power failure.\r\nWe want Yaffs to provide the basis for reliable products in typical\r\nembedded system environments.</p>\r\n<p class=\"western\">The first power fail testing was done by companies\r\nintegrating Yaffs into their products. Some of these built test jigs\r\nwhich would automatically interrupt power while running a real\r\nhardware device. This approach is better than nothing, but has some\r\nlimitations:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">It is relatively costly to set up. Flash\r\n	has a limited lifetime meaning that test devices wear out with time\r\n	and must be replaced.</p>\r\n	<li/>\r\n<p class=\"western\">It is relatively slow since each cycle\r\n	takes many seconds to boot, run the application for a while and then\r\n	reboot.</p>\r\n	<li/>\r\n<p class=\"western\">Many, and perhaps most, of the power\r\n	interruptions will happen at times when the file system is inactive\r\n	and thus be wasted cycles.</p>\r\n</ul>\r\n<p class=\"western\">In 2008 we developed a simulated power-fail-test\r\nenvironment. This simulates power failures using simulated flash\r\nmemory while running various consistency checks.</p>\r\n<p class=\"western\">The benefits of a software-based test harness are\r\nnumerous:</p>\r\n<ul>\r\n	<li/>\r\n<p class=\"western\">The test harness controls the point at\r\n	which the simulated power failures happen. That means every test\r\n	cycle counts.</p>\r\n	<li/>\r\n<p class=\"western\">No special hardware is required.</p>\r\n	<li/>\r\n<p class=\"western\">Test loops run faster. A quad-core computer\r\n	can simulate ten to twenty power failures per second. That means\r\n	about a million power failure simulations per day.</p>\r\n</ul>\r\n<p class=\"western\">The effectiveness of the new software based\r\ntesting is dramatic.. A few times we have tested some user-suggested\r\nchanges that had passed a week or more of real-world power fail\r\ntesting only to have problems caught by the software simulation in a\r\nmatter of minutes.</p>\r\n<p class=\"western\">We regularly run the power fail simulation test\r\nover a weekend, testing millions of power fail cycles.</p>\r\n<h2 class=\"western\">4.2 Testing the Yaffs Direct Interface API</h2>\r\n<p class=\"western\">Yaffs Direct Interface (YDI) is a POSIX-like\r\nwrapper around the Yaffs core. This provides a set of function calls,\r\nyaffs_open(), yaffs_write() and the like.</p>\r\n<p class=\"western\">Each function can return numerous error codes and\r\nhas to handle numerous different parameters.</p>\r\n<p class=\"western\">Although there were already significant tests for\r\nthe YDI, an extensive test harness was developed in 2010 to\r\ncomprehensively test each of the error paths and generate all of the\r\nrequired errors.</p>\r\n<p class=\"western\">This provides a high level of confidence that the\r\ntest interfaces do what they should and that POSIX-like functionality\r\nprovides relatively clean porting of existing code.</p>\r\n<h2 class=\"western\">4.3 Linux Testing</h2>\r\n<p class=\"western\">The main purpose of the Linux testing is to test\r\nthe Linux wrapper code. It does, however, still exercise the Yaffs\r\ncore code differently to other testing and thus adds to the test\r\nfabric.</p>\r\n<p class=\"western\">The Linux testing does not do power fail testing\r\nbut instead tests other aspects such as clean shutdowns, cache\r\nintegrity and write performance. This gives a useful way to assess\r\nthe effects of modifications.</p>\r\n<p class=\"western\">Linux testing is done on both real hardware and on\r\nsimulated hardware using the Linux mtd nand simulator.</p>\r\n<p class=\"western\">As with the Power Fail Stress Testing described\r\nabove, the simulated testing is done using a scrippted environment\r\nwhich is typically run for a few days at a time.</p>\r\n<h2 class=\"western\">4.4 Fuzz Testing</h2>\r\n<p class=\"western\">Fuzz testing deliberately corrupts the flash image\r\nand ensures that Yaffs still mounts. This is done to ensure that\r\nYaffs does not crash on corrupted data.</p>\r\n<p class=\"western\">Clearly fuzz testing can corrupt the contents of\r\nindividual files (that\'s its job), but the file system integrity\r\nshould not be compromised. \r\n</p>\r\n<h2 class=\"western\">4.5 Software checking</h2>\r\n<p class=\"western\">Although code checking is  not actual testing per\r\nse, it does help to verify code changes.</p>\r\n<p class=\"western\">The Yaffs code has been checked with Coverity<a class=\"sdfootnoteanc\" name=\"sdfootnote5anc\" href=\"#sdfootnote5sym\"><sup>5</sup></a>\r\n– a market leader in code checking.</p>\r\n<p class=\"western\">We are investigating the use of KLEE and other\r\ntools.</p>\r\n<h2 class=\"western\">4.6 Open Source Usage</h2>\r\n<p class=\"western\">Open Source usage of Yaffs opens it up to testing\r\nby the many different projects. Many of these participate in some way\r\nwith the Yaffs mailing list, helping to uncover issues and generally\r\nprovide feedback.</p>\r\n<p class=\"western\">Each different project uses Yaffs in a different\r\nway, meaning that a wider range of operation sequences are tested.</p>\r\n<h2 class=\"western\">4.7 Universities</h2>\r\n<p class=\"western\">Over its lifetime, Yaffs has been used as a\r\nteaching framework for various university course in many different\r\ncounties around the world.</p>\r\n<p class=\"western\">For example, Oregon State and Utah State\r\nUniversities have used Yaffs as a test bench for their post-graduate\r\nsoftware testing courses. They essentially test the test tools by\r\ninjecting errors into the Yaffs code and seeing if these are\r\ndiscovered by the test tools they are testing. Of course this has the\r\nside effect of running these tests over the original Yaffs code too. \r\n</p>\r\n<p class=\"western\">Those interested in test methods are encouraged to\r\nread some of the university papers in the references of this\r\ndocument.</p>\r\n<p class=\"western\">We expect to adopt and extend some of the Oregon\r\nState ideas and use these to extend our in-house test suite.</p>\r\n<h1 class=\"western\">5 Conclusions</h1>\r\n<p class=\"western\">Software development is an iterative process of\r\ndesign and testing. Robust software solutions are only possible with\r\nextensive testing.</p>\r\n<p class=\"western\">Embedded systems increasingly need to store data\r\nin file systems as a critical part of their operation. It is thus\r\nimportant to have a file system that is predictable and robust to\r\npower failure and similar interruptions.</p>\r\n<p class=\"western\">Yaffs has been designed from scratch to be robust\r\nto power failure and that robustness has been verified with a\r\nmulti-pronged test strategy that is continuously being improved.</p>\r\n<h1 class=\"western\" style=\"page-break-before: always\">6References</h1>\r\n<p class=\"western\" align=\"left\">Charles Manning, “How Yaffs\r\nWorks”.<br/>\r\n<a href=\"http://users.actrix.co.nz/manningc/yaffs-docs/HowYaffsWorks.pdf\">http://users.actrix.co.nz/manningc/yaffs-docs/HowYaffsWorks.pdf</a></p>\r\n<p class=\"western\" align=\"left\"><br/>\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\" align=\"left\">A. Groce et al, “Swarm Testing”\r\nfrom Oregon State University, School of EE and Computer Science and\r\nUtah State University, School of Computing,\r\n2011.<br/>\r\n<a href=\"http://www.ct.utah.edu/~regehr/papers/swarm12.pdf\">http://</a><a href=\"http://www.ct.utah.edu/~regehr/papers/swarm12.pdf\">www.ct.utah.edu/~regehr/papers/swarm12.pdf</a></p>\r\n<p class=\"western\" align=\"left\"><br/>\r\n<br/>\r\n\r\n</p>\r\n<p class=\"western\" align=\"left\"><em>Wu CH, “Efficient\r\nInitialization and Crash Recovery</em> for. <em>Log</em>-<em>based\r\nFile Systems</em> over Flash Memory” from National Taiwan\r\nUniversity, Dept of Computer Science,<span style=\"font-style: normal\">\r\n2006.<br/>\r\nhttp://</span><cite>www.cis.nctu.edu.tw/~lpchang/papers/SAC_wu_sac06.pdf</cite></p>\r\n<p class=\"western\" align=\"left\" style=\"font-style: normal\"><br/>\r\n<br/>\r\n\r\n</p>\r\n<div id=\"sdfootnote1\">\r\n	<p class=\"sdfootnote-western\"><a class=\"sdfootnotesym\" name=\"sdfootnote1sym\" href=\"#sdfootnote1anc\">1</a>Note\r\n	that flash translation layers (FTLs) are erroneously refered to as\r\n	flash file systems. For example, despite the name, M-Systems TrueFFS\r\n	is not a flash file system but a flash translation layer (FTL).</p>\r\n</div>\r\n<div id=\"sdfootnote2\">\r\n	<p class=\"sdfootnote-western\"><a class=\"sdfootnotesym\" name=\"sdfootnote2sym\" href=\"#sdfootnote2anc\">2</a>This\r\n	document only provides a brief overview of the Yaffs architecture\r\n	and design. The “How Yaffs Works” document provides an in-depth\r\n	explanation of the Yaffs design and architecture.</p>\r\n</div>\r\n<div id=\"sdfootnote3\">\r\n	<p class=\"sdfootnote-western\"><a class=\"sdfootnotesym\" name=\"sdfootnote3sym\" href=\"#sdfootnote3anc\">3</a>Refer\r\n	to the “How Yaffs Works” document to understand the need for\r\n	garbage collection and how Yaffs does garbage collection.</p>\r\n</div>\r\n<div id=\"sdfootnote4\">\r\n	<p class=\"sdfootnote-western\"><a class=\"sdfootnotesym\" name=\"sdfootnote4sym\" href=\"#sdfootnote4anc\">4</a>For\r\n	more information on Yaffs Direct Interface, please read the various\r\n	documents on the subject.</p>\r\n</div>\r\n<div id=\"sdfootnote5\">\r\n	<p class=\"sdfootnote-western\"><a class=\"sdfootnotesym\" name=\"sdfootnote5sym\" href=\"#sdfootnote5anc\">5</a>http://www.coverity.com</p>\r\n</div>\r\n\";s:7:\"summary\";s:241:\"<p>This document describes some of the important design criteria and design features used to achieve a robust design suitable for modern embedded systems which need to store critical data.&nbsp; The test methodologies are also described.</p>\";s:6:\"format\";s:8:\"raw_html\";}}}s:19:\"field_document_type\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:9:\"target_id\";s:3:\"345\";}}}s:18:\"field_teaser_image\";a:1:{s:9:\"x-default\";a:1:{i:0;a:5:{s:9:\"target_id\";s:2:\"79\";s:3:\"alt\";s:40:\"Preview of YaffsRobustnessAndTesting.pdf\";s:5:\"title\";N;s:5:\"width\";N;s:6:\"height\";N;}}}s:6:\"upload\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:9:\"target_id\";s:2:\"78\";s:7:\"display\";s:1:\"1\";s:11:\"description\";s:0:\"\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:5:\"paper\";s:2:\"id\";s:3:\"420\";s:8:\"revision\";s:3:\"605\";s:4:\"uuid\";s:36:\"c3d49866-ddb0-41b9-9505-630fed1d93f4\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:28:\"YAFFS Robustness and Testing\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"6\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"605\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655746.080,1,'entity_field_info node_values','866'),('values:node:426','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"427\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1344939996\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"426\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"815de3d9-836e-47f9-b906-a5616f636a1c\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:32:\"High and low level interfaces...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1339875040\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496407743\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:961:\"<p>We provide a high level interface with the GPL version of Yaffs, so it\'s easy to use with Linux and other OS\'s that support POSIX.&nbsp; This support includes directories, symbolic and hard links, through standard file system interface calls.</p>\r\n\r\n<p>But when you want to integrate Yaffs directly into your OS or your code, you\'ll most likely want to make use of the Yaffs Direct Interface or other low-level interfaces:</p>\r\n\r\n<ul>\r\n	<li>Application Interface: This is the interface that the application code uses to access the YAFFS file system.</li>\r\n	<li>RTOS Integration Interface: These are the functions that much be provided for YAFFS to access the RTOS system resources.</li>\r\n	<li>NAND Configuration and Access Interface: These are the functions that must be provided for YAFFS to access the NAND flash.</li>\r\n</ul>\r\n\r\n<p>Have a look at the guides in the Documents section, to find out more about <a href=\"/documents\">integrating Yaffs</a>.</p>\r\n\";s:7:\"summary\";s:138:\"Yaffs has high and low level interfaces, for Posix compliance and more direct use, making it easy to integrate with Linux and other RTOSs.\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:14:\"fa-stethoscope\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"426\";s:8:\"revision\";s:3:\"427\";s:4:\"uuid\";s:36:\"815de3d9-836e-47f9-b906-a5616f636a1c\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:32:\"High and low level interfaces...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"427\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510674600.750,1,'entity_field_info node_values','866'),('values:node:427','O:23:\"Drupal\\node\\Entity\\Node\":25:{s:10:\"in_preview\";N;s:9:\"\0*\0values\";a:20:{s:3:\"vid\";a:1:{s:9:\"x-default\";s:3:\"428\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:18:\"revision_timestamp\";a:1:{s:9:\"x-default\";s:10:\"1354548179\";}s:12:\"revision_uid\";a:1:{s:9:\"x-default\";s:1:\"4\";}s:12:\"revision_log\";a:1:{s:9:\"x-default\";N;}s:3:\"nid\";a:1:{s:9:\"x-default\";s:3:\"427\";}s:4:\"type\";a:1:{s:9:\"x-default\";s:27:\"what_is_special_about_yaffs\";}s:4:\"uuid\";a:1:{s:9:\"x-default\";s:36:\"36ba10da-e473-4dcb-9a8b-93bff1aa5352\";}s:17:\"isDefaultRevision\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:5:\"title\";a:1:{s:9:\"x-default\";s:30:\"Cross-platform and portable...\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:7:\"created\";a:1:{s:9:\"x-default\";s:10:\"1339875620\";}s:7:\"changed\";a:1:{s:9:\"x-default\";s:10:\"1496408088\";}s:7:\"promote\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:6:\"sticky\";a:1:{s:9:\"x-default\";s:1:\"0\";}s:29:\"revision_translation_affected\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:4:\"body\";a:1:{s:9:\"x-default\";a:1:{i:0;a:3:{s:5:\"value\";s:1073:\"<p>Yaffs is easy to port. It is written in C, with particular attention paid to making it portable.&nbsp;It\'s CPU independent, high/low bit independent (endian neutral)&nbsp;and doesn\'t rely on any particular operating system.&nbsp; Look at the schematic in the <a href=\"/yaffs-overview\">Yaffs Overview</a>&nbsp;to see the relationship of the different elements.</p>\r\n\r\n<p>It\'s already been used under Linux, eCos, VxWorks, Win CE and more.&nbsp;</p>\r\n\r\n<p>Yaffs has been used successfully with many different 32-bit and 64-bit CPUs including MIPS, 68000, many from ARM, ColdFire, PowerPC and x86 variants. Yaffs works with 16-bit CPUs too, but this is less tested and might need some tuning, depending on compiler options.&nbsp;</p>\r\n\r\n<p>We\'ve found it easy to move to different processor architectures because it was designed to do this; as long as your processor is greater than 8-bit, Yaffs should run without needing much work.</p>\r\n\r\n<p>Read&nbsp; <a href=\"http://www.yaffs.net/yaffs-porting-guide\">http://www.yaffs.net/yaffs-porting-guide</a> for more detail.</p>\r\n\";s:7:\"summary\";s:130:\"Yaffs is OS- and CPU- and Endian-independent. It\'s been designed to be easy to port, and has been ported repeatedly by many users.\";s:6:\"format\";s:10:\"basic_html\";}}}s:15:\"field_icon_text\";a:1:{s:9:\"x-default\";a:1:{i:0;a:1:{s:5:\"value\";s:8:\"fa-truck\";}}}}s:9:\"\0*\0fields\";a:0:{}s:19:\"\0*\0fieldDefinitions\";N;s:12:\"\0*\0languages\";N;s:14:\"\0*\0langcodeKey\";s:8:\"langcode\";s:21:\"\0*\0defaultLangcodeKey\";s:16:\"default_langcode\";s:17:\"\0*\0activeLangcode\";s:9:\"x-default\";s:18:\"\0*\0defaultLangcode\";s:3:\"und\";s:15:\"\0*\0translations\";a:1:{s:9:\"x-default\";a:1:{s:6:\"status\";i:1;}}s:24:\"\0*\0translationInitialize\";b:0;s:14:\"\0*\0newRevision\";b:0;s:20:\"\0*\0isDefaultRevision\";s:1:\"1\";s:13:\"\0*\0entityKeys\";a:4:{s:6:\"bundle\";s:27:\"what_is_special_about_yaffs\";s:2:\"id\";s:3:\"427\";s:8:\"revision\";s:3:\"428\";s:4:\"uuid\";s:36:\"36ba10da-e473-4dcb-9a8b-93bff1aa5352\";}s:25:\"\0*\0translatableEntityKeys\";a:6:{s:5:\"label\";a:1:{s:9:\"x-default\";s:30:\"Cross-platform and portable...\";}s:8:\"langcode\";a:1:{s:9:\"x-default\";s:3:\"und\";}s:6:\"status\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:9:\"published\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:3:\"uid\";a:1:{s:9:\"x-default\";s:1:\"1\";}s:16:\"default_langcode\";a:1:{s:9:\"x-default\";s:1:\"1\";}}s:12:\"\0*\0validated\";b:0;s:21:\"\0*\0validationRequired\";b:0;s:19:\"\0*\0loadedRevisionId\";s:3:\"428\";s:15:\"\0*\0entityTypeId\";s:4:\"node\";s:15:\"\0*\0enforceIsNew\";N;s:12:\"\0*\0typedData\";N;s:16:\"\0*\0cacheContexts\";a:0:{}s:12:\"\0*\0cacheTags\";a:0:{}s:14:\"\0*\0cacheMaxAge\";i:-1;s:14:\"\0*\0_serviceIds\";a:0:{}}',-1,1510655746.057,1,'entity_field_info node_values','866'),