AU: Pass opened device fd from update engine to bspatch.
Whenever a device is written and closes, some processing happens
(involving udev, devicekit-disks, udev, and even
chrome). Historically, bspatch called open, write, close on the raw
device, thus causing much CPU usage every time bspatch was called,
which can be many times per second for delta updates.
This CL causes us to pass /dev/fd/## and the file descriptor to
bspatch. A corresponding CL causes bspatch to detect this and skip
open/close calls. Together, these CLs dramatically reduce resource
usage on clients performing delta updates.
BUG=7636
TEST=unittests; tested delta update on device
Review URL: http://codereview.chromium.org/3723005
diff --git a/delta_performer.cc b/delta_performer.cc
index 7ee9d4f..d111015 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -446,7 +446,7 @@
}
int fd = is_kernel_partition ? kernel_fd_ : fd_;
- const string& path = is_kernel_partition ? kernel_path_ : path_;
+ const string& path = StringPrintf("/dev/fd/%d", fd);
// If this is a non-idempotent operation, request a delayed exit and clear the
// update state in case the operation gets interrupted. Do this as late as
@@ -464,7 +464,10 @@
cmd.push_back(input_positions);
cmd.push_back(output_positions);
int return_code = 0;
- TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &return_code));
+ TEST_AND_RETURN_FALSE(
+ Subprocess::SynchronousExecFlags(cmd,
+ &return_code,
+ G_SPAWN_LEAVE_DESCRIPTORS_OPEN));
TEST_AND_RETURN_FALSE(return_code == 0);
if (operation.dst_length() % block_size_) {
diff --git a/subprocess.cc b/subprocess.cc
index 28b895c..49fc4c3 100755
--- a/subprocess.cc
+++ b/subprocess.cc
@@ -135,8 +135,9 @@
}
}
-bool Subprocess::SynchronousExec(const std::vector<std::string>& cmd,
- int* return_code) {
+bool Subprocess::SynchronousExecFlags(const std::vector<std::string>& cmd,
+ int* return_code,
+ GSpawnFlags flags) {
GError* err = NULL;
scoped_array<char*> argv(new char*[cmd.size() + 1]);
for (unsigned int i = 0; i < cmd.size(); i++) {
@@ -157,16 +158,17 @@
char* child_stdout;
- bool success = g_spawn_sync(NULL, // working directory
- argv.get(),
- argp,
- G_SPAWN_STDERR_TO_DEV_NULL, // flags
- GRedirectStderrToStdout, // child setup function
- NULL, // data for child setup function
- &child_stdout,
- NULL,
- return_code,
- &err);
+ bool success = g_spawn_sync(
+ NULL, // working directory
+ argv.get(),
+ argp,
+ static_cast<GSpawnFlags>(G_SPAWN_STDERR_TO_DEV_NULL | flags), // flags
+ GRedirectStderrToStdout, // child setup function
+ NULL, // data for child setup function
+ &child_stdout,
+ NULL,
+ return_code,
+ &err);
FreeArgv(argv.get());
if (err)
LOG(INFO) << "err is: " << err->code << ", " << err->message;
diff --git a/subprocess.h b/subprocess.h
index 8f97c5d..bf1e7ea 100644
--- a/subprocess.h
+++ b/subprocess.h
@@ -37,8 +37,13 @@
void CancelExec(uint32_t tag);
// Executes a command synchronously. Returns true on success.
+ static bool SynchronousExecFlags(const std::vector<std::string>& cmd,
+ int* return_code,
+ GSpawnFlags flags);
static bool SynchronousExec(const std::vector<std::string>& cmd,
- int* return_code);
+ int* return_code) {
+ return SynchronousExecFlags(cmd, return_code, static_cast<GSpawnFlags>(0));
+ }
// Gets the one instance
static Subprocess& Get() {