Merge changes Idb791187,Iad926450 into main
* changes:
libprefetch: Remove `start` command
libprefetch: replay/record checks if they can run on its own
diff --git a/init/libprefetch/prefetch/prefetch.rc b/init/libprefetch/prefetch/prefetch.rc
index dee37bb..bdcbbc6 100644
--- a/init/libprefetch/prefetch/prefetch.rc
+++ b/init/libprefetch/prefetch/prefetch.rc
@@ -1,28 +1,36 @@
-on init && property:ro.prefetch_boot.enabled=true
- start prefetch
-
-service prefetch /system/bin/prefetch start
- class main
- user root
- group root system
- disabled
- oneshot
-
-on property:prefetch_boot.record=true
- start prefetch_record
+# Reads data from disk in advance and populates page cache
+# to speed up subsequent disk access.
+#
+# Record:
+# start by `start prefetch_record` at appropriate timing.
+# stop by setting `prefetch_boot.record_stop` to 1.
+# set --duration to only capture for a certain duration instead.
+#
+# Replay:
+# start by `start prefetch_replay` at appropriate timing.
+# it will depend on several files generated from record.
+#
+# replay is I/O intensive. make sure you pick appropriate
+# timing to run each, so that you can maximize the page cache
+# hit for subsequent disk access.
+#
+# Example:
+# on early-init && property:ro.prefetch_boot.enabled=true
+# start prefetch_replay
+#
+# on init && property:ro.prefetch_boot.enabled=true
+# start prefetch_record
+#
+# on property:sys.boot_completed=1 && property:ro.prefetch_boot.enabled=true
+# setprop prefetch_boot.record_stop 1
service prefetch_record /system/bin/prefetch record --duration ${ro.prefetch_boot.duration_s:-0}
- class main
user root
group root system
disabled
oneshot
-on property:prefetch_boot.replay=true
- start prefetch_replay
-
service prefetch_replay /system/bin/prefetch replay --io-depth ${ro.prefetch_boot.io_depth:-2} --max-fds ${ro.prefetch_boot.max_fds:-128}
- class main
user root
group root system
disabled
diff --git a/init/libprefetch/prefetch/src/arch/android.rs b/init/libprefetch/prefetch/src/arch/android.rs
index a11767e..a87502d 100644
--- a/init/libprefetch/prefetch/src/arch/android.rs
+++ b/init/libprefetch/prefetch/src/arch/android.rs
@@ -1,18 +1,15 @@
use crate::Error;
use crate::RecordArgs;
-use crate::StartArgs;
-use log::info;
use log::warn;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::Write;
+use std::path::Path;
use std::time::Duration;
use rustutils::system_properties::error::PropertyWatcherError;
use rustutils::system_properties::PropertyWatcher;
-const PREFETCH_RECORD_PROPERTY: &str = "prefetch_boot.record";
-const PREFETCH_REPLAY_PROPERTY: &str = "prefetch_boot.replay";
const PREFETCH_RECORD_PROPERTY_STOP: &str = "prefetch_boot.record_stop";
fn wait_for_property_true(
@@ -31,68 +28,41 @@
});
}
-fn start_prefetch_service(property_name: &str) -> Result<(), Error> {
- match rustutils::system_properties::write(property_name, "true") {
- Ok(_) => {}
- Err(_) => {
- return Err(Error::Custom { error: "Failed to start prefetch service".to_string() });
- }
- }
- Ok(())
-}
-
-/// Start prefetch service
-///
-/// 1: Check the presence of the file 'prefetch_ready'. If it doesn't
-/// exist then the device is booting for the first time after wipe.
-/// Thus, we would just create the file and exit as we do not want
-/// to initiate the record after data wipe primiarly because boot
-/// after data wipe is long and the I/O pattern during first boot may not actually match
-/// with subsequent boot.
-///
-/// 2: If the file 'prefetch_ready' is present:
-///
-/// a: Compare the build-finger-print of the device with the one record format
-/// is associated with by reading the file 'build_finger_print'. If they match,
-/// start the prefetch_replay.
-///
-/// b: If they don't match, then the device was updated through OTA. Hence, start
-/// a fresh record and delete the build-finger-print file. This should also cover
-/// the case of device rollback.
-///
-/// c: If the build-finger-print file doesn't exist, then just restart the record
-/// from scratch.
-pub fn start_prefetch(args: &StartArgs) -> Result<(), Error> {
- if !args.path.exists() {
- match File::create(args.path.clone()) {
- Ok(_) => {}
- Err(_) => {
- return Err(Error::Custom { error: "File Creation failed".to_string() });
- }
- }
- return Ok(());
+/// Checks if we can perform replay phase.
+/// Ensure that the pack file exists and is up-to-date, returns false otherwise.
+pub fn can_perform_replay(pack_path: &Path, fingerprint_path: &Path) -> Result<bool, Error> {
+ if !pack_path.exists() || !fingerprint_path.exists() {
+ return Ok(false);
}
- if args.build_fingerprint_path.exists() {
- let device_build_fingerprint = rustutils::system_properties::read("ro.build.fingerprint")
- .map_err(|e| Error::Custom {
+ let saved_fingerprint = std::fs::read_to_string(fingerprint_path)?;
+
+ let current_device_fingerprint = rustutils::system_properties::read("ro.build.fingerprint")
+ .map_err(|e| Error::Custom {
error: format!("Failed to read ro.build.fingerprint: {}", e),
})?;
- let pack_build_fingerprint = std::fs::read_to_string(&args.build_fingerprint_path)?;
- if pack_build_fingerprint.trim() == device_build_fingerprint.as_deref().unwrap_or_default()
- {
- info!("Start replay");
- start_prefetch_service(PREFETCH_REPLAY_PROPERTY)?;
- } else {
- info!("Start record");
- std::fs::remove_file(&args.build_fingerprint_path)?;
- start_prefetch_service(PREFETCH_RECORD_PROPERTY)?;
- }
- } else {
- info!("Start record");
- start_prefetch_service(PREFETCH_RECORD_PROPERTY)?;
+
+ Ok(current_device_fingerprint.is_some_and(|fp| fp == saved_fingerprint.trim()))
+}
+
+/// Checks if we can perform record phase.
+/// Ensure that following conditions hold:
+/// - File specified in ready_path exists. otherwise, create a new file and return false.
+/// - can_perform_replay is false.
+pub fn ensure_record_is_ready(
+ ready_path: &Path,
+ pack_path: &Path,
+ fingerprint_path: &Path,
+) -> Result<bool, Error> {
+ if !ready_path.exists() {
+ File::create(ready_path)
+ .map_err(|_| Error::Custom { error: "File Creation failed".to_string() })?;
+
+ return Ok(false);
}
- Ok(())
+
+ let can_replay = can_perform_replay(pack_path, fingerprint_path)?;
+ Ok(!can_replay)
}
/// Write build finger print to associate prefetch pack file
diff --git a/init/libprefetch/prefetch/src/args.rs b/init/libprefetch/prefetch/src/args.rs
index e534210..4c1e689 100644
--- a/init/libprefetch/prefetch/src/args.rs
+++ b/init/libprefetch/prefetch/src/args.rs
@@ -25,8 +25,6 @@
pub use args_internal::OutputFormat;
pub use args_internal::ReplayArgs;
-#[cfg(target_os = "android")]
-pub use args_internal::StartArgs;
pub use args_internal::TracerType;
pub use args_internal::{DumpArgs, MainArgs, RecordArgs, SubCommands};
use serde::Deserialize;
@@ -68,8 +66,6 @@
SubCommands::Dump(arg) => {
ensure_path_exists(&arg.path)?;
}
- #[cfg(target_os = "android")]
- SubCommands::Start(_arg) => return Ok(()),
}
Ok(())
}
diff --git a/init/libprefetch/prefetch/src/args/args_argh.rs b/init/libprefetch/prefetch/src/args/args_argh.rs
index 65084ee..d2251e6 100644
--- a/init/libprefetch/prefetch/src/args/args_argh.rs
+++ b/init/libprefetch/prefetch/src/args/args_argh.rs
@@ -40,12 +40,6 @@
Replay(ReplayArgs),
/// Dump prefetch data in human readable format
Dump(DumpArgs),
- /// Start prefetch service if possible
- /// If the pack file is present, then prefetch replay is started
- /// If the pack file is absent or if the build fingerprint
- /// of the current pack file is different, then prefetch record is started.
- #[cfg(target_os = "android")]
- Start(StartArgs),
}
#[cfg(target_os = "android")]
@@ -58,22 +52,6 @@
PathBuf::from("/metadata/prefetch/build_finger_print")
}
-#[cfg(target_os = "android")]
-#[derive(Eq, PartialEq, Debug, Default, FromArgs)]
-/// Start prefetch service based on if pack file is present.
-#[argh(subcommand, name = "start")]
-pub struct StartArgs {
- /// file path to check if prefetch_ready is present.
- ///
- /// A new file is created at the given path if it's not present.
- #[argh(option, default = "default_ready_path()")]
- pub path: PathBuf,
-
- /// file path where build fingerprint is stored
- #[argh(option, default = "default_build_finger_print_path()")]
- pub build_fingerprint_path: PathBuf,
-}
-
impl Default for SubCommands {
fn default() -> Self {
Self::Dump(DumpArgs::default())
@@ -147,6 +125,13 @@
/// store build_finger_print to tie the pack format
#[argh(option, default = "default_build_finger_print_path()")]
pub build_fingerprint_path: PathBuf,
+
+ #[cfg(target_os = "android")]
+ /// file path to check if prefetch_ready is present.
+ ///
+ /// A new file is created at the given path if it's not present.
+ #[argh(option, default = "default_ready_path()")]
+ pub ready_path: PathBuf,
}
/// Type of tracing subsystem to use.
@@ -204,6 +189,11 @@
/// file path from where the prefetch config file will be read
#[argh(option, default = "PathBuf::new()")]
pub config_path: PathBuf,
+
+ #[cfg(target_os = "android")]
+ /// store build_finger_print to tie the pack format
+ #[argh(option, default = "default_build_finger_print_path()")]
+ pub build_fingerprint_path: PathBuf,
}
/// dump records file in given format
diff --git a/init/libprefetch/prefetch/src/lib.rs b/init/libprefetch/prefetch/src/lib.rs
index 6564c4b..ea84c59 100644
--- a/init/libprefetch/prefetch/src/lib.rs
+++ b/init/libprefetch/prefetch/src/lib.rs
@@ -42,8 +42,6 @@
pub use args::args_from_env;
use args::OutputFormat;
pub use args::ReplayArgs;
-#[cfg(target_os = "android")]
-pub use args::StartArgs;
pub use args::{DumpArgs, MainArgs, RecordArgs, SubCommands};
pub use error::Error;
pub use format::FileId;
@@ -59,6 +57,13 @@
/// Records prefetch data for the given configuration
pub fn record(args: &RecordArgs) -> Result<(), Error> {
+ #[cfg(target_os = "android")]
+ if !ensure_record_is_ready(&args.ready_path, &args.path, &args.build_fingerprint_path)? {
+ info!("Cannot perform record -- skipping");
+ return Ok(());
+ }
+
+ info!("Starting record.");
let (mut tracer, exit_tx) = tracer::Tracer::create(
args.trace_buffer_size_kib,
args.tracing_subsystem.clone(),
@@ -109,6 +114,13 @@
/// Replays prefetch data for the given configuration
pub fn replay(args: &ReplayArgs) -> Result<(), Error> {
+ #[cfg(target_os = "android")]
+ if !can_perform_replay(&args.path, &args.build_fingerprint_path)? {
+ info!("Cannot perform replay -- exiting.");
+ return Ok(());
+ }
+
+ info!("Starting replay.");
let replay = Replay::new(args)?;
replay.replay()
}
diff --git a/init/libprefetch/prefetch/src/main.rs b/init/libprefetch/prefetch/src/main.rs
index eab826f..046e07e 100644
--- a/init/libprefetch/prefetch/src/main.rs
+++ b/init/libprefetch/prefetch/src/main.rs
@@ -22,8 +22,6 @@
use prefetch_rs::init_logging;
use prefetch_rs::record;
use prefetch_rs::replay;
-#[cfg(target_os = "android")]
-use prefetch_rs::start_prefetch;
use prefetch_rs::LogLevel;
use prefetch_rs::MainArgs;
use prefetch_rs::SubCommands;
@@ -35,8 +33,6 @@
SubCommands::Record(args) => record(args),
SubCommands::Replay(args) => replay(args),
SubCommands::Dump(args) => dump(args),
- #[cfg(target_os = "android")]
- SubCommands::Start(args) => start_prefetch(args),
};
if let Err(err) = ret {