動的パーティショニングは、Linux カーネルの dm-linear device-mapper モジュールを使用して実装されます。super
パーティションには、super
にある動的パーティションの名前とブロック範囲を示すメタデータが格納されます。第 1 ステージ init
では、このメタデータが解析および検証され、各動的パーティションを表す仮想ブロック デバイスが作成されます。
OTA を適用すると、必要に応じて動的パーティションが自動的に作成、サイズ変更、削除されます。A/B デバイスの場合、メタデータのコピーは 2 つあり、変更はターゲット スロットとなるコピーにのみ適用されます。
動的パーティションはユーザー空間に実装されているため、ブートローダーに必要なパーティションを動的に作成することはできません。たとえば、boot
、dtbo
、vbmeta
はブートローダーが読み取るため、物理パーティションとして残す必要があります。
動的パーティションはそれぞれアップデート グループに属します。アップデート グループは、そのグループ内のパーティションが消費できる最大の容量を制限します。
たとえば system
と vendor
は、system
と vendor
の合計サイズを制限するグループに属します。
新しいデバイスへの動的パーティションの実装
このセクションでは、Android 10 以降でリリースする新しいデバイスに動的パーティションを実装する方法について説明します。既存のデバイスをアップグレードする方法については、Android デバイスのアップグレードをご覧ください。
パーティショニングの変更
Android 10 でリリースするデバイスの場合は、super
というパーティションを作成します。super
パーティションは内部で A/B スロットを処理するため、A/B デバイスは区別された super_a
と super_b
パーティションを必要としません。
ブートローダーで使用されない読み取り専用の AOSP パーティションはすべて動的である必要があり、GUID パーティション テーブル(GPT)から削除する必要があります。
ベンダー固有のパーティションは動的でなくても GPT に配置できます。
super
のサイズを見積もる際には、GPT から削除するパーティションのサイズを追加します。A/B デバイスの場合は、両方のスロットのサイズを含めます。図 1 は、動的パーティションへ変換する前後のパーティション テーブルの例を示しています。
サポートされている動的パーティションは次のとおりです。
- System
- Vendor
- Product
- System Ext
- ODM
Android 10 でリリースするデバイスの場合、カーネル コマンドライン オプション androidboot.super_partition
を空にして、コマンド sysprop ro.boot.super_partition
が空になるようにします。
パーティションの配置
super
パーティションが正しく配置されていないと、device-mapper モジュールが効率的に動作しない場合があります。super
パーティションは、ブロックレイヤによって決定される I/O リクエストの最小サイズに従って配置する必要があります。デフォルトでは、super
パーティション イメージを生成する lpmake
を経由するビルドシステムは、すべての動的パーティションが 1 MiB の配置で十分であると想定しています。ただし、ベンダーは super
パーティションが適切に配置されていることを確認する必要があります。
ブロック デバイスの最小リクエスト サイズは、sysfs
を検査することで測定できます。次に例を示します。
# ls -l /dev/block/by-name/super lrwxrwxrwx 1 root root 16 1970-04-05 01:41 /dev/block/by-name/super -> /dev/block/sda17 # cat /sys/block/sda/queue/minimum_io_size 786432
super
パーティションの配置も同様に確認できます。
# cat /sys/block/sda/sda17/alignment_offset
アライメント オフセットは 0 にする必要があります。
デバイス設定の変更
動的パーティショニングを有効にするには、次のフラグを device.mk
に追加します。
PRODUCT_USE_DYNAMIC_PARTITIONS := true
ボード設定の変更
super
パーティションのサイズを設定する必要があります。
BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>
A/B デバイスでは、動的パーティション イメージの合計サイズが super
パーティション サイズの半分を超えると、ビルドシステムがエラーをスローします。
動的パーティションのリストは次のように設定できます。アップデート グループを使用するデバイスの場合は、BOARD_SUPER_PARTITION_GROUPS
変数にそのグループを指定します。各グループ名には、BOARD_group_SIZE
変数と BOARD_group_PARTITION_LIST
変数が含まれます。
A/B デバイスの場合、グループ名には内部的にスロット名が接尾辞として付されているため、グループの最大サイズは 1 スロットのみになります。
次の例では、すべてのパーティションを example_dynamic_partitions
というグループに配置するデバイスを示します。
BOARD_SUPER_PARTITION_GROUPS := example_dynamic_partitions BOARD_EXAMPLE_DYNAMIC_PARTITIONS_SIZE := 6442450944 BOARD_EXAMPLE_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product
次の例では、システムとプロダクト サービスを group_foo
に、vendor
、product
、odm
を group_bar
に配置するデバイスを示します。
BOARD_SUPER_PARTITION_GROUPS := group_foo group_bar BOARD_GROUP_FOO_SIZE := 4831838208 BOARD_GROUP_FOO_PARTITION_LIST := system product_services BOARD_GROUP_BAR_SIZE := 1610612736 BOARD_GROUP_BAR_PARTITION_LIST := vendor product odm
-
仮想 A/B リリース デバイスの場合、全グループの最大サイズの合計は次のようになります。
BOARD_SUPER_PARTITION_SIZE
- オーバーヘッド
仮想 A/B の実装をご覧ください。 -
A/B リリース デバイスの場合、全グループの最大サイズの合計は次のようになります。
BOARD_SUPER_PARTITION_SIZE
/ 2 - オーバーヘッド -
A/B 以外のデバイスとレトロフィット A/B デバイスの場合、全グループの最大サイズの合計は次のようになります。
BOARD_SUPER_PARTITION_SIZE
- オーバーヘッド - ビルド時、アップデート グループ内の各パーティションに含まれるイメージの合計サイズは、グループの最大サイズを超えることはできません。
- オーバーヘッドの計算には、メタデータ、配置などを考慮する必要があります。オーバーヘッドは 4 MiB 程度ですが、必要に応じてデバイスのオーバーヘッドを大きくすることもできます。
動的パーティションのサイズ設定
動的パーティションが行われる前は、将来のアップデートに十分な空き領域を確保するためパーティションのサイズが過剰に割り当てられていました。実際のサイズは現在と同じでしたが、ほとんどの読み取り専用パーティションにはファイル システムに空き領域がありました。動的パーティションでは、この空き領域は使用されないため、OTA 中にパーティションを拡張するために使用できます。 パーティションがスペースを浪費せず、最小限のサイズで割り当てられるようにすることが重要です。
読み取り専用の ext4 イメージでは、ハードコーディングされたパーティション サイズが指定されていない場合、最小サイズが自動的に割り当てられます。ビルドシステムは、ファイル システムに未使用の領域ができるだけ少なくなるようにイメージを収めます。これにより、デバイスで OTA に使用できるスペースが無駄になることはありません。
さらに、ブロックレベルでの重複排除を有効にすると、ext4 イメージをさらに圧縮できます。これを有効にするには、次の設定を使用します。
BOARD_EXT4_SHARE_DUP_BLOCKS := true
パーティションの最小サイズの自動割り当てが望ましくない場合、パーティション サイズを制御するには 2 つの方法があります。BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE
を使用して空き領域の最小サイズを指定するか、または BOARD_partitionIMAGE_PARTITION_SIZE
を指定して動的パーティションを特定のサイズになるよう強制します。どちらも、必要のない限りおすすめしません。
例:
BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800
これにより、product.img
のファイル システムの使用されていない領域が 50 MiB になります。
system-as-root の変更
Android 10 でリリースするデバイスでは、system-as-root を使用しないでください。
動的パーティションを持つ(リリース時からかレトロフィットかにかかわらず)デバイスは、system-as-root を使用しないでください。Linux カーネルは super
パーティションを解釈できないため、自身で system
をマウントできません。system
は RAM ディスクにある第 1 ステージ init
によりマウントされます。
BOARD_BUILD_SYSTEM_ROOT_IMAGE
は設定しないでください。Android 10 では、BOARD_BUILD_SYSTEM_ROOT_IMAGE
フラグが使用されるのは、システムがカーネルによってマウントされるか、RAM ディスクの第 1 ステージ init
でマウントされるかを区分するためです。
BOARD_BUILD_SYSTEM_ROOT_IMAGE
を true
に設定すると、PRODUCT_USES_DYNAMIC_PARTITIONS
も true
の場合にビルドエラーが発生します。
BOARD_USES_RECOVERY_AS_BOOT
が true に設定されている場合、リカバリ イメージは boot.img として作成され、リカバリの RAM ディスクが含まれます。これまで、ブートローダーはカーネル コマンドライン パラメータ skip_initramfs
を使用してブートするモードを決定していました。Android 10 デバイスの場合、ブートローダーが skip_initramfs
をカーネルのコマンドラインに渡さないようにします。代わりに、ブートローダーは androidboot.force_normal_boot=1
を渡してリカバリをスキップし、通常の Android を起動します。Android 12 以降でリリースするデバイスでは、bootconfig を使用して androidboot.force_normal_boot=1
を渡す必要があります。
AVB 設定の変更
Android Verified Boot 2.0 を使用している場合、デバイスがチェーン パーティション記述子を使用していなければ、変更の必要はありません。ただし、チェーン パーティションを使用しており、確認済みのパーティションの 1 つが動的な場合は、変更が必要です。
system
パーティションと vendor
パーティションの vbmeta
をチェーンするデバイスの設定例は次のとおりです。
BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048 BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1 BOARD_AVB_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VENDOR_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION := 1
この設定では、ブートローダーは system
パーティションと vendor
パーティションの最後に vbmeta フッターがあることを想定しています。これらのパーティションは super
にあり、ブートローダーから見えなくなったため、以下の 2 つの変更が必要です。
-
vbmeta_system
パーティションとvbmeta_vendor
パーティションをデバイスのパーティション テーブルに追加します。A/B デバイスの場合は、vbmeta_system_a
、vbmeta_system_b
、vbmeta_vendor_a
、vbmeta_vendor_b
を追加します。1 つ以上のパーティションを追加する場合は、vbmeta
パーティションと同じサイズにする必要があります。 -
VBMETA_
を追加し、チェーンが継がれていくパーティションを指定することで設定フラグの名前を変更します。BOARD_AVB_VBMETA_SYSTEM := system BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1 BOARD_AVB_VBMETA_VENDOR := vendor BOARD_AVB_VBMETA_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VBMETA_VENDOR_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION := 1
デバイスは、これらのパーティションの片方のみ使用している場合もあれば、両方を使用またはいずれも使用していない場合もあります。変更は、論理パーティションにチェーンする場合にのみ必要です。
AVB ブートローダーの変更
ブートローダーに libavb が埋め込まれている場合は、次のパッチを追加します。
- 818cf56740775446285466eda984acedd4baeac0 - libavb: cmdline で必要な場合のみ、パーティション GUID をクエリします。
- 5abd6bc2578968d24406d834471adfd995a0c2e9 - system パーティションがないことを許容します。
- 9ba3b6613b4e5130fa01a11d984c6b5f0eb3af05 - AvbSlotVerifyData-> cmdline が NULL になるのを修正しました。
チェーン パーティションを使用する場合は、次のパッチを追加します。
- 49936b4c0109411fdd38bd4ba3a32a01c40439a9 - libavb: パーティションの先頭で vbmeta blob をサポートします。
カーネルのコマンドラインの変更
新しいパラメータである androidboot.boot_devices
をカーネルのコマンドラインに追加する必要があります。これは init
が /dev/block/by-name
シンボリック リンクの有効化に使用します。ueventd
により作成された by-name シンボリック リンクへのデバイスパス コンポーネントである必要があります。つまり /dev/block/platform/device-path/by-name/partition-name
です。
Android 12 以降でリリースするデバイスでは、bootconfig を使用して androidboot.boot_devices
を init
に渡す必要があります。
たとえば、super パーティションの by-name シンボリック リンクが /dev/block/platform/soc/100000.ufshc/by-name/super
の場合、BoardConfig.mk ファイルにコマンドライン パラメータを次のように追加できます。
BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshcBoardConfig.mk ファイルに bootconfig パラメータを次のように追加できます。
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc
fstab の変更
デバイスツリーとデバイスツリー オーバーレイに fstab エントリを含めることはできません。RAM ディスクの一部となる fstab ファイルを使用します。
論理パーティションについて、fstab ファイルに次の変更を行う必要があります。
-
fs_mgr フラグ フィールドに、Android 10 で導入された、パーティションが第 1 ステージでマウントされることを示す
logical
フラグとfirst_stage_mount
フラグを含める必要があります。 -
1 つのパーティションは、
avb=vbmeta partition name
をfs_mgr
フラグとして指定できます。指定されたvbmeta
パーティションは、デバイスのマウントを試みるより先に第 1 ステージinit
によって初期化されます。 dev
フィールドにはパーティション名を指定してください。
次の fstab エントリでは、上記のルールに従って system、vendor、product を論理パーティションとして設定しています。
#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags> system /system ext4 ro,barrier=1 wait,slotselect,avb=vbmeta,logical,first_stage_mount vendor /vendor ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount product /product ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount
fstab ファイルを第 1 ステージ RAM ディスクにコピーします。
SELinux の変更
super パーティション ブロック デバイスには super_block_device
のラベルを付ける必要があります。たとえば、super パーティションの by-name シンボリック リンクが /dev/block/platform/soc/100000.ufshc/by-name/super
の場合、次の行を file_contexts
に追加します。
/dev/block/platform/soc/10000\.ufshc/by-name/super u:object_r:super_block_device:s0
fastbootd
ブートローダーやユーザー空間以外のフラッシング ツールは、動的パーティションを認識しないため、フラッシュできません。これに対処するには、fastbootd と呼ばれる fastboot プロトコルのユーザー空間への実装をデバイスが使用する必要があります。
fastbootd の実装方法の詳細については、Fastboot をユーザー空間に移動するをご覧ください。
adb の再マウント
eng や userdebug ビルドを使用するデベロッパーの場合、adb remount
は迅速な反復処理に非常に役立ちます。動的パーティションが原因で adb remount
に問題が発生するのは、各ファイル システム内に空き領域がなくなるためです。これに対処するため、デバイスは overlayfs を有効にできます。super パーティション内に空き領域がある限り、adb remount
は自動的に一時的な動的パーティションを作成し、overlayfs を書き込みに使用します。一時パーティションには scratch
という名前が付きますので、他のパーティションにはこの名前を使用しないでください。
overlayfs を有効にする方法の詳細については、AOSP の overlayfs の README をご覧ください。
Android デバイスのアップグレード
Android 10 にデバイスをアップグレードし、OTA で動的パーティションのサポートを追加する場合、組み込みパーティション テーブルを変更する必要はありません。追加の設定がいくつか必要になります。
デバイス設定の変更
動的パーティショニングをレトロフィットするには、device.mk
に次のフラグを追加します。
PRODUCT_USE_DYNAMIC_PARTITIONS := true PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true
ボード設定の変更
次のボード変数を設定する必要があります。
- 動的パーティションのエクステントの格納に使用するブロック デバイスのリストに
BOARD_SUPER_PARTITION_BLOCK_DEVICES
を設定します。これは、デバイス上もあり既存の物理パーティションの名前をリストにしたものです。 BOARD_SUPER_PARTITION_partition_DEVICE_SIZE
をBOARD_SUPER_PARTITION_BLOCK_DEVICES
の各ブロック デバイスのサイズに設定します。 これは、デバイス上にある既存の物理パーティションのサイズをリストにしたものです。通常既存のボード設定ではBOARD_partitionIMAGE_PARTITION_SIZE
とされています。BOARD_SUPER_PARTITION_BLOCK_DEVICES
のすべてのパーティションに対して既存のBOARD_partitionIMAGE_PARTITION_SIZE
の設定を解除します。BOARD_SUPER_PARTITION_SIZE
をBOARD_SUPER_PARTITION_partition_DEVICE_SIZE
の合計に設定します。- 動的パーティション メタデータが格納されているブロック デバイスを
BOARD_SUPER_PARTITION_METADATA_DEVICE
に設定します。BOARD_SUPER_PARTITION_BLOCK_DEVICES
のいずれかである必要があります。通常、system
に設定されています。 BOARD_SUPER_PARTITION_GROUPS
、BOARD_group_SIZE
、BOARD_group_PARTITION_LIST
をそれぞれ設定します。詳しくは新しいデバイスでのボード設定の変更をご覧ください。
たとえば、デバイスにすでに system パーティションと vendor パーティションがあり、更新中に動的パーティションに転換し、新しく product パーティションを追加する場合は、次のようにボード設定を行います。
BOARD_SUPER_PARTITION_BLOCK_DEVICES := system vendor BOARD_SUPER_PARTITION_METADATA_DEVICE := system # Rename BOARD_SYSTEMIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE. BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := <size-in-bytes> # Rename BOARD_VENDORIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := <size-in-bytes> # This is BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE + BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE BOARD_SUPER_PARTITION_SIZE := <size-in-bytes> # Configuration for dynamic partitions. For example: BOARD_SUPER_PARTITION_GROUPS := group_foo BOARD_GROUP_FOO_SIZE := <size-in-bytes> BOARD_GROUP_FOO_PARTITION_LIST := system vendor product
SELinux の変更
super パーティション ブロック デバイスには super_block_device_type
属性を指定する必要があります。たとえば、デバイスに system
パーティションと vendor
パーティションがある場合、次のように動的パーティションのエクステントを保存するブロック デバイスとして使用し、by-name シンボリック リンクを system_block_device
とします。
/dev/block/platform/soc/10000\.ufshc/by-name/system u:object_r:system_block_device:s0 /dev/block/platform/soc/10000\.ufshc/by-name/vendor u:object_r:system_block_device:s0
次に、以下の行を device.te
に追加します。
typeattribute system_block_device super_block_device_type;
他の設定については、新しいデバイスに動的パーティションを実装するをご覧ください。
レトロフィット アップデートの詳細については、動的パーティションのない A/B デバイスの OTA をご覧ください。
ファクトリー イメージ
動的パーティションをサポートしてリリースするデバイスでは、ユーザー空間 fastboot を使用してファクトリ イメージをフラッシュしないでください。ユーザー空間での起動はほかのフラッシュ方法に比べ速度が遅くなります。
これに対処するため、make dist
は追加の super.img
イメージをビルドし、super パーティションに直接フラッシュできます。このイメージは論理パーティションのコンテンツを自動的にバンドルします。つまり、super
パーティション メタデータに加えて、system.img
、vendor.img
なども含んでいます。このイメージは、追加のツールや fastbootd を使用せずに、直接 super
パーティションにフラッシュできます。ビルド後、super.img
は ${ANDROID_PRODUCT_OUT}
に配置されます。
動的パーティションを使用してリリースする A/B デバイスの場合、super.img
には A スロットにイメージが含まれています。super イメージを直接フラッシュした後、A スロットを起動可能にしてからデバイスを再起動します。
レトロフィット デバイスの場合、make dist
は一連の super_*.img
イメージをビルドし、これは対応する物理パーティションに直接フラッシュできます。たとえば、BOARD_SUPER_PARTITION_BLOCK_DEVICES
が system vendor のとき、make dist
は super_system.img
と super_vendor.img
をビルドします。これらのイメージは、target_files.zip
内の OTA フォルダに置かれます。
デバイス マッパーのストレージとデバイスの調整
動的パーティショニングは、決定性のない各種デバイス マッパー オブジェクトに対応しています。これらは想定どおりにインスタンス化されない場合があるため、すべてのマウントをトラッキングし、関連付けられているすべてのパーティションの Android プロパティで基盤となるストレージ デバイスを更新する必要があります。
init
内のメカニズムはマウントをトラッキングし、Android プロパティを非同期で更新します。更新にかかる時間が所定の時間内に収まることは保証されません。そのため、すべての on property
トリガーが応答するのに十分な時間を確保する必要があります。プロパティは dev.mnt.blk.<partition>
です(<partition>
はたとえば、root
、system
、data
、vendor
)。次の例のように、各プロパティは基本ストレージ デバイス名に関連付けられます。
taimen:/ % getprop | grep dev.mnt.blk [dev.mnt.blk.data]: [sda] [dev.mnt.blk.firmware]: [sde] [dev.mnt.blk.metadata]: [sde] [dev.mnt.blk.persist]: [sda] [dev.mnt.blk.root]: [dm-0] [dev.mnt.blk.vendor]: [dm-1] blueline:/ $ getprop | grep dev.mnt.blk [dev.mnt.blk.data]: [dm-4] [dev.mnt.blk.metadata]: [sda] [dev.mnt.blk.mnt.scratch]: [sda] [dev.mnt.blk.mnt.vendor.persist]: [sdf] [dev.mnt.blk.product]: [dm-2] [dev.mnt.blk.root]: [dm-0] [dev.mnt.blk.system_ext]: [dm-3] [dev.mnt.blk.vendor]: [dm-1] [dev.mnt.blk.vendor.firmware_mnt]: [sda]
init.rc
言語を使用すると、ルールの一部として Android プロパティを拡張できます。また、次のようなコマンドで、必要に応じてストレージ デバイスをプラットフォームで調整することもできます。
write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb 128 write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb 128
コマンド処理が第 2 ステージ init
で開始されると、epoll loop
がアクティブになり、値の更新が開始されます。ただし、プロパティのトリガーは後期 init
までアクティブでないため、初期ブートステージでの root
、system
、vendor
の処理には使用できません。init.rc
スクリプトが early-fs
でオーバーライドするまで(このとき各種デーモンやファシリティが開始される)、カーネル デフォルト read_ahead_kb
は十分であると想定されます。このため、on property
機能を init.rc
が管理するプロパティ(sys.read_ahead_kb
など)と組み合わせて使用することをおすすめします。これにより、下の例のように、タイミングを合わせて競合状態を防ぐことができます。
on property:dev.mnt.blk.root=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.system=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.system}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.vendor=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.vendor}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.product=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.system_ext}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.oem=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.oem}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.data=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on early-fs: setprop sys.read_ahead_kb ${ro.read_ahead_kb.boot:-2048} on property:sys.boot_completed=1 setprop sys.read_ahead_kb ${ro.read_ahead_kb.bootcomplete:-128}