ブログネタ
Android に参加中!
Galaxy Nexus を使用して Android で F2FS を導入するのに必要なことを調べてみたので、
そのメモ。

Android(Galaxy Nexus)で F2FS を使用するのに必要なこと
  • Linux Kernle で F2FS を有効にする
  • マウントの設定を F2FS に変更する
  • パーティションタイプに F2FS を追加する
  • SELinux のポリシーを変更する
Linux Kernle で F2FS を有効にする
kernel config で次の4つを有効にします。
CONFIG_F2FS_FS=y
CONFIG_F2FS_STAT_FS=y
CONFIG_F2FS_FS_XATTR=y
CONFIG_F2FS_FS_SECURITY=y

kernel のバージョンが 3.8 未満で F2FS が入ってない場合、kernel のバージョンが 3.0 以降であればバックポートして使うことが可能。
https://github.com/nowcomputing/f2fs-backports
AOSP で公開されている Galaxy Nexus の kernel は 3.0 なので、使用可能。
実際に F2FS のバックポートを行い、動作するのを確認したものは Github で公開済み。
https://github.com/JCROM-Android/jcrom_kernel_omap
F2FS の確認をしたのは android-omap-tuna-3.0-f2fs ブランチ。

マウントの設定を F2FS に変更する
fstab file を変更する。
Galaxy Nexus の場合、fstab.tuna を変更する。
変更したのは system、data、cache の3つ。ext4 だったものを f2fs に変更。
/dev/block/platform/omap/omap_hsmmc.0/by-name/system    /system             f2fs      ro,noatime,nodiratime,background_gc=off,inline_xattr,active_logs=2    wait
/dev/block/platform/omap/omap_hsmmc.0/by-name/efs /factory ext4 ro wait
/dev/block/platform/omap/omap_hsmmc.0/by-name/cache /cache f2fs noatime,nosuid,nodev,nodiratime,background_gc=off,inline_xattr,active_logs=2 wait,check
/dev/block/platform/omap/omap_hsmmc.0/by-name/userdata /data f2fs noatime,nosuid,nodev,nodiratime,background_gc=off,inline_xattr,active_logs=2 wait,check,encryptable=/dev/block/platform/omap/omap_hsmmc.0/by-name/metadata
/dev/block/platform/omap/omap_hsmmc.0/by-name/misc /misc emmc defaults defaults
/dev/block/platform/omap/omap_hsmmc.0/by-name/boot /boot emmc defaults defaults
/dev/block/platform/omap/omap_hsmmc.0/by-name/recovery /recovery emmc defaults defaults
/dev/block/platform/omap/omap_hsmmc.0/by-name/sbl /sbl emmc defaults defaults
/dev/block/platform/omap/omap_hsmmc.0/by-name/xloader /xloader emmc defaults defaults
/dev/block/platform/omap/omap_hsmmc.0/by-name/radio /radio emmc defaults defaults

パーティションタイプに F2FS を追加する
make otapackage でリカバリから書き込むファイルを作成するので、そのための修正を行う。
変更しないと ext4 でフォーマットされてしまうので、そうしないようにした。
  • device/samsung/tuna
  • --- a/BoardConfig.mk
    +++ b/BoardConfig.mk
    @@ -63,6 +63,7 @@ TARGET_RELEASETOOLS_EXTENSIONS := device/samsung/tuna

    TARGET_RECOVERY_FSTAB = device/samsung/tuna/fstab.tuna
    TARGET_USERIMAGES_USE_EXT4 := true
    +TARGET_USERIMAGES_USE_F2FS := true
    BOARD_SYSTEMIMAGE_PARTITION_SIZE := 685768704
    BOARD_USERDATAIMAGE_PARTITION_SIZE := 14539537408
    BOARD_FLASH_BLOCK_SIZE := 4096
  • bootable/recovery
  • --- a/updater/Android.mk
    +++ b/updater/Android.mk
    @@ -27,6 +27,10 @@ LOCAL_STATIC_LIBRARIES += \
    libz
    endif

    +ifeq ($(TARGET_USERIMAGES_USE_F2FS), true)
    +LOCAL_CFLAGS += -DUSE_F2FS
    +endif
    +
    LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
    LOCAL_STATIC_LIBRARIES += libapplypatch libedify libmtdutils libminzip libz
    LOCAL_STATIC_LIBRARIES += libmincrypt libbz

    --- a/updater/install.c
    +++ b/updater/install.c
    @@ -275,6 +275,10 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
    }
    result = location;
    #endif
    +#ifdef USE_F2FS
    + } else if (strcmp(fs_type, "f2fs") == 0) {
    + result = location;
    +#endif
    } else {
    printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"",
    name, fs_type, partition_type);
  • build
  • --- a/tools/releasetools/common.py
    +++ b/tools/releasetools/common.py
    @@ -946,7 +946,7 @@ def ComputeDifferences(diffs):

    # map recovery.fstab's fs_types to mount/format "partition types"
    PARTITION_TYPES = { "yaffs2": "MTD", "mtd": "MTD",
    - "ext4": "EMMC", "emmc": "EMMC" }
    + "ext4": "EMMC", "emmc": "EMMC", "f2fs": "EMMC" }

    def GetTypeAndDevice(mount_point, info):
    fstab = info["fstab"]
今回は f2fs へのフォーマットはリカバリから手動で行うので、make_f2fs の組み込み等は行わない。

SELinux のポリシーを変更する
Android 4.4 から SELinux が(そこそこ)真面目に仕事をするようになったので、AOSP のままだと F2FS は(仮に root 権限を用いても)弾かれる。
以下は root になって mount コマンドを実行した時のログ。
<5>[ 61.754425] type=1400 audit(1402206823.503:14): avc: denied { mount } for pid=1466 comm="mount" name="/" dev=mmcblk0p11 ino=3 scontext=u:r:su:s0 tcontext=u:object_r:unlabeled:s0 tclass=filesystem
mount はログ出るだけで実際は出来るけど、書き込みは不可。
root になって echo > /data/test を実行しても書き込めない。
<5>[ 220.597137] type=1400 audit(1402206982.347:18): avc: denied { associate } for pid=1495 comm="sh" name="test" scontext=u:object_r:unlabeled:s0 tcontext=u:object_r:unlabeled:s0 tclass=filesystem

これを解決するために、SELinux のポリシー定義に f2fs も扱う事を追記してあげる必要がある。
変更するファイルは external/sepolicy/fs_use
--- a/fs_use
+++ b/fs_use
@@ -4,6 +4,7 @@ fs_use_xattr jffs2 u:object_r:labeledfs:s0;
fs_use_xattr ext2 u:object_r:labeledfs:s0;
fs_use_xattr ext3 u:object_r:labeledfs:s0;
fs_use_xattr ext4 u:object_r:labeledfs:s0;
+fs_use_xattr f2fs u:object_r:labeledfs:s0;
fs_use_xattr xfs u:object_r:labeledfs:s0;
fs_use_xattr btrfs u:object_r:labeledfs:s0;

Android での SELinux やポリシーファイルの定義について知らなければ、横浜PF部で使用した資料で少し分かるかもしれない。
Yokohama-PF-2014-05-androidsola

以上の変更で F2FS を使用することが出来るようになる。


ビルド済みイメージと書き込み手順

JCROM ベースだが、Galaxy Nexus 向けにビルドしたイメージを用意したので、これを使用して試すことは可能。
F2FS-GalaxyNexus.tar.bz2
書き込みには F2FS に対応したリカバリーが必要。
今回は TWRP ベースで作成してる人がいたので、それを同梱した。

書き込み手順
  • Advanced → f2fs/ext4 switch と選択し、System、Cache、Data を f2fs でフォーマット
  • JCROM-2.4.0-f2fs_maguro.zip と jcrom-gapps-kitkat-20140604.zip を adb コマンドで端末に転送する
  • JCROM-2.4.0-f2fs_maguro.zip と jcrom-gapps-kitkat-20140604.zip を書き込む
  • 書き込み完了後、再起動

ベンチマーク結果

F2FS に変更する前後で Quadrant を使用して比較してみた。
F2FS に変更する前(ext4) が左、F2FS へ変更した後が右。
EXT4-ARTF2FS-ART

既に Nexus 7 等で試してる人の結果同様、I/O の結果で明確が差が出た。
AOSP の master ブランチには F2FS 関連のリポジトリが出来ているので、もしかしたら今後使用されるケースが増えるかもしれない。
https://android.googlesource.com/platform/external/f2fs-tools


F2FS を使用した JCROM(Galaxy Nexus)をビルドする手順

「F2FS を使用するのに必要なこと」を反映したものを登録したので、以下の手順で作成可。

作業ディレクトリの準備
$ mkdir -p ~/android_f2fs/android
$ export JCROM_ROOT=~/android_f2fs
$ export ANDROID_ROOT=~/android_f2fs/android
ソースコードのダウンロード
$ cd $ANDROID_ROOT
$ repo init -u https://github.com/JCROM-Android/jcrom_manifest -m jcrom_kitkat-f2fs.xml
$ repo sync
$ cd $ANDROID_ROOT/device/samsung/maguro
$ ./download-blobs.sh
$ cd $ANDROID_ROOT/jcrom/samsung/maguro/proprietary
$ ./extract-files.sh
Kernel のビルド
$ cd $JCROM_ROOT
$ git clone https://android.googlesource.com/platform/prebuilt kernel/toolchain
$ export ARCH=arm
$ export CROSS_COMPILE=$JCROM_ROOT/kernel/toolchain/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
$ git clone https://github.com/JCROM-Android/jcrom_kernel_omap.git -b android-omap-tuna-3.0-f2fs kernel/gnexus
$ cd kernel/gnexus
$ make tuna_f2fs_defconfig
$ make -j4
$ cp arch/arm/boot/zImage $ANDROID_ROOT/device/samsung/tuna/kernel
Android のビルド
$ cd $ANDROID_ROOT
$ source build/envsetup.sh
$ lunch aosp_maguro-user
$ make otapackage -j4