Use ordered data mode & disable delayed allocation when /config is ext4

Issues were observed on Chimera (gfch100) devices with zero-length files
in /config, believed to have occurred due to power being pulled on the
first boot after a factory reset when the system would be creating many
new files in /config since the partition would have just been recreated.

ext4's writeback data mode does not journal data at all and does not
guarantee any ordering between data and metadata writes. As the ext4
documentation states, "A crash+recovery can cause incorrect data to
appear in files which were written shortly before the crash." Ordered
data mode ensures that data blocks are written before metadata.
However, even if ordered data mode is used, ext4's delayed allocation
feature can still result in empty files after a crash since new data
blocks whose allocation is deferred can still be written after metadata.

Data integrity is more critical than performance on /config in
particular. This change shifts from writeback to ordered data mode and
also disables delayed allocation to ensure that all data blocks are
written before metadata.

Also adds an fsync to utils.sh's atomic() function for another layer of
protection against this same issue.

Change-Id: Idd1f96c6e6bf53df562a315d1c3f537b347a6fe5
diff --git a/fs/skeleton/etc/init.d/S08volcheck.platform_gfibertv b/fs/skeleton/etc/init.d/S08volcheck.platform_gfibertv
index 10c5ab1..554a6cd 100755
--- a/fs/skeleton/etc/init.d/S08volcheck.platform_gfibertv
+++ b/fs/skeleton/etc/init.d/S08volcheck.platform_gfibertv
@@ -245,14 +245,17 @@
 
 mount_ext4fs()
 {
-  mount -t ext4 -o defaults,noatime,discard,data=writeback $1 /user || return 1
+  # Use ordered mode & disable delayed allocation to enable metadata journaling
+  # and ensure data blocks are always written before metadata. Avoids issues
+  # with power loss or crashes resulting in zero length files.
+  mount -t ext4 -o defaults,noatime,discard,nodelalloc,data=ordered $1 /user || return 1
   [ ! -d /user/config ] && mkdir -p /user/config
   mount --bind /user/config /config || return 1
 }
 
 mount_atv_ext4fs()
 {
-  mount -t ext4 -o defaults,noatime,discard,data=writeback $1 /atv_userdata || return 1
+  mount -t ext4 -o defaults,noatime,discard,nodelalloc,data=ordered $1 /atv_userdata || return 1
   mkdir -p /atv_userdata/gfiber/user
   mount --bind /atv_userdata/gfiber/user /user || return 1
   mkdir -p /user/config
diff --git a/fs/skeleton/etc/utils.sh b/fs/skeleton/etc/utils.sh
index e4f4b9c..6d6341a 100644
--- a/fs/skeleton/etc/utils.sh
+++ b/fs/skeleton/etc/utils.sh
@@ -9,8 +9,12 @@
   shift
 
   if [ ! -e $filename ] || [ "$(cat $filename)" != "$newval" ]; then
+    # fsync after writing the temp file to avoid the potential for ending up
+    # with a zero length file at $filename on ext4 partitions due to ext4's
+    # delayed allocation.
     rm -f $filename.new
     echo "$@" >$filename.new
+    fsync $filename.new
     mv $filename.new $filename
   fi
 }
diff --git a/package/toybox/toybox.config b/package/toybox/toybox.config
index b01f19b..2b09397 100644
--- a/package/toybox/toybox.config
+++ b/package/toybox/toybox.config
@@ -206,7 +206,7 @@
 CONFIG_FREE=y
 # CONFIG_FREERAMDISK is not set
 # CONFIG_FSFREEZE is not set
-# CONFIG_FSYNC is not set
+CONFIG_FSYNC=y
 # CONFIG_HELP is not set
 # CONFIG_HELP_EXTRAS is not set
 # CONFIG_HEXEDIT is not set