]> www.infradead.org Git - mtd-www.git/commitdiff
UBIFS: describe while holes appear in the end of files
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Thu, 10 Sep 2009 15:00:53 +0000 (18:00 +0300)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Thu, 10 Sep 2009 15:02:22 +0000 (18:02 +0300)
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
doc/ubifs.xml
faq/ubifs.xml

index a11e10f2fbe14457c6c089a46c478b815aa673a2..38e6e59dfe01a0463407020bb22565435626d035 100644 (file)
@@ -21,6 +21,7 @@
        <li><a href="ubifs.html#L_writeback">Write-back support</a></li>
        <li><a href="ubifs.html#L_wb_knobs">Write-back knobs in Linux</a></li>
        <li><a href="ubifs.html#L_writebuffer">UBIFS write-buffer</a></li>
+       <li><a href="ubifs.html#L_sync_semantics">UBIFS in synchronous mode vs JFFS2</a></li>
        <li><a href="ubifs.html#L_sync_exceptions">Synchronization exceptions for buggy applications</a></li>
        <li><a href="ubifs.html#L_compression">Compression</a></li>
        <li><a href="ubifs.html#L_checksumming">Checksumming</a></li>
@@ -395,7 +396,9 @@ following is a list of useful hints and advices.</p>
 <ul>
        <li>If you want to switch into synchronous mode, use the
        <code>-o sync</code> option when mounting UBIFS; however, the file
-       system performance will drop - be careful;</li>
+       system performance will drop - be careful; Also remember that UBIFS
+       mounted in synchronous mode provides less guarantees than JFFS2 - refer
+       <a href="ubi.html#L_sync_semantics">this</a> section for details.</li>
 
        <li>Always keep in mind the above statement from the manual pages and
        run <code>fsync()</code> for all important files you change; of
@@ -575,6 +578,88 @@ write-buffers are small, only few data are delayed.</p>
 
 
 
+<h2><a name="L_sync_semantics"></a>UBIFS in synchronous mode vs JFFS2</h2>
+
+<p>When UBIFS is mounted in synchronous mode (<code>-o sync</code> mount
+options) - all file system operations become synchronous. This means that all
+data are written to flash <i>before</i> the file-system operations return.</p>
+
+<p>For example, if you write 10MiB of data to a file <code>f.dat</code> using
+the <code>write()</code> call, and UBIFS is in synchronous mode, then UBIFS
+guarantees that all 10MiB of data and the meta-data (file size and date changes)
+will reach the flash media before <code>write()</code> returns. And if a
+power cut happens after the <code>write()</code> call returns, the file will
+contain the written data.</p>
+
+<p>The same is true for situations when <code>f.dat</code> has was opened
+with <code>O_SYNC</code> or has the <code>sync</code> flag (see
+<code>man 2 chattr</code>).</p>
+
+<p>It is well-known that the JFFS2 file-system is synchronous (except a small
+write-buffer). However, UBIFS in synchronous mode is not the same as JFFS2 and
+provides somewhat less guarantees that JFFS2 does with respect to sudden power
+cuts.</p>
+
+<p>In JFFS2 all the meta-data (like inode
+<code>atime</code>/<code>mtime</code>/<code>ctime</code>, inode size, UID/GID,
+etc) are stored in the data node headers. Data nodes carry 4KiB of (compressed)
+data. This means that the meta-data information is duplicated in many places,
+but this also means that every time JFFS2 writes a data node to the flash
+media, it updates inode size as well.</p>
+
+<p>In practice this means that JFFS2 will write these 10MiB of data
+sequentially, from the beginning to the end. And if you have a power cut, you
+will just loose some amount of data at the end of the inode. For example, if
+JFFS2 starts writing those 10MiB of data, write 5MiB, and a power cut happens,
+you will end up with a 5MiB <code>f.dat</code> file. You loose only the last
+5MiB.</p>
+
+<p>Things are a little bit more complex in case of UBIFS, where data are stored
+in data nodes and meta-data are stored in (separate) inode nodes. The meta-data
+are not duplicated in each data node, like in JFFS2. Lets consider an
+example.</p>
+
+<ul>
+       <li>User creates an empty file <code>f.dat</code>. The file is
+       synchronous, or UBIFS is mounted in synchronous mode. User calls the
+       <code>write()</code> function with a 10MiB buffer.</li>
+
+       <li>The kernel first copies all 10MiB of the data to the page cache.
+       Inode size is changed to 10MiB as well and the inode is marked as
+       dirty. Nothing has been written to the flash media so far. If a power
+       cut happens at this point, the user will end up with an empty
+       <code>f.dat</code> file.</li>
+
+       <li>UBIFS sees that the I/O has to be synchronous, and starts
+       synchronizing the inode. First of all, it writes the inode node to the
+       flash media. If a power cut happens at this moment, the user will end
+       up with a 10MiB file which contains no data (hole), and if he read
+       this file, he will get 10MiB of zeroes.</li>
+
+       <li>UBIFS starts writing the data. If a power cut happens at this
+       point, the user will end up with a 10MiB file containing a hole at the
+       end.</li>
+</ul>
+
+<p>Note, if the I/O was not synchronous, UBIFS would skip the last step and
+would just return. And the actual write-back would then happen in back-ground.
+But power cuts during write-back could anyway lead to files with holes at the
+end.</p>
+
+<p>Thus, synchronous I/O in UBIFS provides less guarantees than JFFS2 I/O -
+UBIFS has an effect of holes at the end of files. In ideal world applications
+should not assume anything about the contents of files which were not
+synchronized before a power-cut has happened. And "mainstream" file-systems
+like <code>ext3</code> do not provide JFSS2-like guarantees.</p>
+
+<p>However, UBIFS is sometimes used as a JFFS2 replacement and people may
+want it to behave the same way as JFFS2 if it is mounted synchronously. This is
+doable, but needs some non-trivial development, so this was not implemented so
+far. On the other hand, there was no strong demand. You may implement this as
+an excercise, or you may try to convince UBIFS authors to do this.</p>
+
+
+
 <h2><a name="L_sync_exceptions"></a>Synchronization exceptions for buggy applications</h2>
 
 <p>As <a href="ubifs.html#L_writeback">this</a> section describes, UBIFS is
index 10a31a160b07d0f920611475ac41e47a94799096..783d016b2b9a94b79ab614eeb3470910a8aaa652 100644 (file)
@@ -33,6 +33,7 @@
        <li><a href="ubifs.html#L_powercut">Is UBIFS tolerant to power-cuts?</a></li>
        <li><a href="ubifs.html#L_smaller_jrn">I need more space - should I make UBIFS journal smaller?</a></li>
        <li><a href="ubifs.html#L_empty_file">Why my file is empty after an unclean reboot?</a></li>
+       <li><a href="ubifs.html#L_end_hole">Why my file has zeroes at the end after an unclean reboot?</a></li>
        <li><a href="ubifs.html#L_bgt_thread">What does the "ubifs_bgt0_0" thread do?</a></li>
        <li><a href="ubifs.html#L_sudden_ro">UBIFS suddenly became read-only - what is this?</a></li>
        <li><a href="ubifs.html#L_lebsz_mismatch">I see this UBIFS error: "validate_sb: LEB size mismatch: 129024 in superblock, 126976 real"</a></li>
@@ -936,7 +937,7 @@ the data are lost.</p>
 
 <p>Zero-length files also appear when an application creates a new file, then
 writes to the file, and a power cut happens. The reason is similar - file
-creation is a synchronous operation, data writing is not.</p>
+creation is a synchronous operation, data writing is not. </p>
 
 <p>Well, the description is a bit simplified. Actually, when a file is
 created or truncated, the creation/truncation UBIFS information is written to
@@ -960,7 +961,11 @@ real.</p>
 
        <li>If you gave up fixing all your applications, you may mount UBIFS in
        synchronous mode - use "<code>-o sync</code>" mount option. But this
-       make UBIFS perform worse.</li>
+       makes UBIFS perform worse. And unfortunatelly, this also does not save
+       you from all possible corruptions - you may still end up with holes
+       (zeroes) at the end of files. See
+       <a href="../doc/ubifs.html#L_sync_semantics">this</a> section for more
+       information.</li>
 
        <li>You may use the well-known atomic file update technique - see
        <a href="ubifs.html#L_atomic_change">this</a> section.</li>
@@ -978,6 +983,20 @@ to implement it.</p>
 
 
 
+<h2><a name="L_end_hole">Why my file has zeroes at the end after an unclean reboot?</a></h2>
+
+<p>Power cuts often lead to holes at the end of files. Holes are areas of
+the file which contain no data. For example, if you truncate a file to a lagrer
+size and synchronize it - you end up with a hole. Holes are read as zeroes.
+Often files with holes are referred to as sparce files. People sometimes
+deliberately create sparse files in order to save space - this is sometimes
+better than filling files with lots of zeroes.</p>
+
+<p>Please, read more information about how unclean reboots relult in holes
+in <a href="../doc/ubifs.html#L_sync_semantics">this</a> section.</p>
+
+
+
 <h2><a name="L_bgt_thread">What does the "ubifs_bgt0_0" thread do?</a></h2>
 
 <p>The UBIFS background thread is created for every mounted file-system and