问题描述
Android设备突然断电,文件未及时写入到文件系统,重新开机文件未更新,读写文件使用sync()/flush()后,仍未及时写入文件,写入到内存中
修改方案
data分区挂载参数fsync_mode=nobarrier
修改为fsync_mode=strict
关于Android文件系统
- fstab.qcom编译文件
device/qcom/trinket/AndroidBoard.mk
ifeq ($(strip $(BOARD_DYNAMIC_PARTITION_ENABLE)),true)
include $(CLEAR_VARS)
LOCAL_MODULE := fstab.qcom
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
ifeq ($(ENABLE_AB), true)
LOCAL_SRC_FILES := fstab_AB_dynamic_partition.qti
else
LOCAL_SRC_FILES := fstab_non_AB_dynamic_partition.qti
endif
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)
include $(BUILD_PREBUILT)
else
include $(CLEAR_VARS)
LOCAL_MODULE := fstab.qcom
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
ifeq ($(ENABLE_AB), true)
LOCAL_SRC_FILES := fstab_AB_variant.qti
else
LOCAL_SRC_FILES := fstab_non_AB_variant.qti
endif
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)
include $(BUILD_PREBUILT)
endif
编译到系统路径下的文件:/vendor/etc/fstab.qcom
- 关于fstab
这个文件描述系统中各种文件系统的信息,在这个文件中,每个文件系统用一行来描述,在每一行中,用空格或TAB符号来分隔各个字段,文件中以#开头的行是注释信息。Fstab文件中的纪录的排序十分重要。因为fsck,mount或umount等程序在做它们的工作时会按此顺序进行。
device/qcom/trinket/fstab_AB_variant.qti
# Copyright (c) 2018, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of The Linux Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Android fstab file.
# The filesystem that contains the filesystem checker binary (typically /system) cannot
# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
#TODO: Add 'check' as fs_mgr_flags with data partition.
# Currently we dont have e2fsck compiled. So fs check would failed.
#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
/dev/block/bootdevice/by-name/system / ext4 ro,barrier=1,discard wait,slotselect,avb
/dev/block/bootdevice/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,formattable,wrappedkey
/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,fsync_mode=nobarrier latemount,wait,check,fileencryption=ice,wrappedkey,keydirectory=/metadata/vold/metadata_encryption,quota,reservedsize=128M
/devices/platform/soc/4784000.sdhci/mmc_host* /storage/sdcard1 vfat nosuid,nodev wait,voldmanaged=sdcard1:auto,encryptable=footer
/devices/platform/soc/1da4000.ufshc_card/host* /storage/sdcard1 vfat nosuid,nodev wait,voldmanaged=sdcard1:auto,encryptable=footer
/dev/block/bootdevice/by-name/modem /vendor/firmware_mnt vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait,slotselect
/dev/block/bootdevice/by-name/dsp /vendor/dsp ext4 ro,nosuid,nodev,barrier=1 wait,slotselect
/dev/block/bootdevice/by-name/persist /mnt/vendor/persist ext4 noatime,nosuid,nodev,barrier=1 wait
/dev/block/bootdevice/by-name/bluetooth /vendor/bt_firmware vfat ro,shortname=lower,uid=1002,gid=3002,dmask=227,fmask=337,context=u:object_r:bt_firmware_file:s0 wait,slotselect
/devices/platform/soc/*.ssusb/*.dwc3/xhci-hcd.0.auto* /storage/usbotg vfat nosuid,nodev wait,voldmanaged=usbotg:auto
# Need to have this entry in here even though the mount point itself is no longer needed.
# The update_engine code looks for this entry in order to determine the boot device address
# and fails if it does not find it.
/dev/block/bootdevice/by-name/misc /misc emmc defaults defaults
/dev/block/zram0 none swap defaults zramsize=1073741824
- fstab参数
fstab文件系统参数说明
kernel/msm-4.9/Documentation/filesystems/ext4.txt
kernel/msm-4.19/Documentation/filesystems/f2fs.txt
相关参数示例:
<src> 磁盘设备文件或者该设备的Label或者UUID
<mount point> 设备的挂载点,就是你要挂载到哪个目录下
<filesystem type> 磁盘文件系统的格式,包括ext2、ext3、reiserfs、nfs、vfat等
<mount flags parameters> 文件系统的参数
<fs_mgr_flags>
- 解析fstab.qcom文件配置流程
system/core/init/builtins.cpp
/* mount_all <fstab> [ <path> ]* [--<options>]*
*
* This function might request a reboot, in which case it will
* not return.
*/
static Result<Success> do_mount_all(const BuiltinArguments& args) {
std::size_t na = 0;
bool import_rc = true;
bool queue_event = true;
int mount_mode = MOUNT_MODE_DEFAULT;
const auto& fstabfile = args[1];
std::size_t path_arg_end = args.size();
const char* prop_post_fix = "default";
for (na = args.size() - 1; na > 1; --na) {
if (args[na] == "--early") {
path_arg_end = na;
queue_event = false;
mount_mode = MOUNT_MODE_EARLY;
prop_post_fix = "early";
} else if (args[na] == "--late") {
path_arg_end = na;
import_rc = false;
mount_mode = MOUNT_MODE_LATE;
prop_post_fix = "late";
}
}
std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix;
android::base::Timer t;
auto mount_fstab_return_code = mount_fstab(fstabfile, mount_mode);
if (!mount_fstab_return_code) {
return Error() << "mount_fstab() failed " << mount_fstab_return_code.error();
}
property_set(prop_name, std::to_string(t.duration().count()));
if (import_rc) {
/* Paths of .rc files are specified at the 2nd argument and beyond */
import_late(args.args, 2, path_arg_end);
}
if (queue_event) {
/* queue_fs_event will queue event based on mount_fstab return code
* and return processed return code*/
auto queue_fs_result = queue_fs_event(*mount_fstab_return_code);
if (!queue_fs_result) {
return Error() << "queue_fs_event() failed: " << queue_fs_result.error();
}
}
return Success();
}
相关参考
https://blog.csdn.net/u014770862/article/details/54583157/
https://blog.csdn.net/zhangshaoye998/article/details/50461825