Merge "adb: Retry io in case of interrupt"
diff --git a/daemon/remount_service.cpp b/daemon/remount_service.cpp
index 7876368..eb46903 100644
--- a/daemon/remount_service.cpp
+++ b/daemon/remount_service.cpp
@@ -21,6 +21,7 @@
#include <errno.h>
#include <fcntl.h>
#include <mntent.h>
+#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -106,6 +107,41 @@
return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
}
+static bool can_unshare_blocks(int fd, const char* dev) {
+ const char* E2FSCK_BIN = "/system/bin/e2fsck";
+ if (access(E2FSCK_BIN, X_OK)) {
+ WriteFdFmt(fd, "e2fsck is not available, cannot undo deduplication on %s\n", dev);
+ return false;
+ }
+
+ pid_t child;
+ char* env[] = {nullptr};
+ const char* argv[] = {E2FSCK_BIN, "-n", "-E", "unshare_blocks", dev, nullptr};
+ if (posix_spawn(&child, E2FSCK_BIN, nullptr, nullptr, const_cast<char**>(argv), env)) {
+ WriteFdFmt(fd, "failed to e2fsck to check deduplication: %s\n", strerror(errno));
+ return false;
+ }
+ int status = 0;
+ int ret = TEMP_FAILURE_RETRY(waitpid(child, &status, 0));
+ if (ret < 0) {
+ WriteFdFmt(fd, "failed to get e2fsck status: %s\n", strerror(errno));
+ return false;
+ }
+ if (!WIFEXITED(status)) {
+ WriteFdFmt(fd, "e2fsck exited abnormally with status %d\n", status);
+ return false;
+ }
+ int rc = WEXITSTATUS(status);
+ if (rc != 0) {
+ WriteFdFmt(fd,
+ "%s is deduplicated, and an e2fsck check failed. It might not "
+ "have enough free-space to be remounted as writable.\n",
+ dev);
+ return false;
+ }
+ return true;
+}
+
static bool remount_partition(int fd, const char* dir, std::vector<std::string>& dedup) {
if (!directory_exists(dir)) {
return true;
@@ -133,6 +169,9 @@
}
if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) {
if (errno == EROFS && fs_has_shared_blocks(dev.c_str())) {
+ if (!can_unshare_blocks(fd, dev.c_str())) {
+ return false;
+ }
// We return true so remount_service() can detect that the only
// failure was deduplicated filesystems.
dedup.push_back(dev);
diff --git a/daemon/usb.cpp b/daemon/usb.cpp
index 263303f..c724b11 100644
--- a/daemon/usb.cpp
+++ b/daemon/usb.cpp
@@ -234,6 +234,10 @@
for (unsigned i = 0; i < USB_FFS_NUM_BUFS; i++) {
aiob->iocbs[i] = &aiob->iocb[i];
}
+ memset(&aiob->ctx, 0, sizeof(aiob->ctx));
+ if (io_setup(USB_FFS_NUM_BUFS, &aiob->ctx)) {
+ D("[ aio: got error on io_setup (%d) ]", errno);
+ }
}
static int getMaxPacketSize(int ffs_fd) {
@@ -312,13 +316,6 @@
goto err;
}
- memset(&h->read_aiob.ctx, 0, sizeof(h->read_aiob.ctx));
- memset(&h->write_aiob.ctx, 0, sizeof(h->write_aiob.ctx));
- if (io_setup(USB_FFS_NUM_BUFS, &h->read_aiob.ctx) ||
- io_setup(USB_FFS_NUM_BUFS, &h->write_aiob.ctx)) {
- D("[ aio: got error on io_setup (%d) ]", errno);
- }
-
h->read_aiob.fd = h->bulk_out;
h->write_aiob.fd = h->bulk_in;
return true;
@@ -500,8 +497,6 @@
h->kicked = false;
adb_close(h->bulk_out);
adb_close(h->bulk_in);
- io_destroy(h->read_aiob.ctx);
- io_destroy(h->write_aiob.ctx);
// Notify usb_adb_open_thread to open a new connection.
h->lock.lock();