summaryrefslogtreecommitdiffstats
path: root/updater
diff options
context:
space:
mode:
authorTianjie Xu <xunchang@google.com>2016-05-31 18:29:49 +0200
committerTianjie Xu <xunchang@google.com>2016-06-03 21:12:50 +0200
commit7ce287d432dd3a4dc8841fc59e11ee1a0b7808a1 (patch)
tree9e1a3f6c63abe5ceb130b93699fb0d7df43ec0ec /updater
parentMerge "Allow recovery to return error codes" into nyc-dev (diff)
downloadandroid_bootable_recovery-7ce287d432dd3a4dc8841fc59e11ee1a0b7808a1.tar
android_bootable_recovery-7ce287d432dd3a4dc8841fc59e11ee1a0b7808a1.tar.gz
android_bootable_recovery-7ce287d432dd3a4dc8841fc59e11ee1a0b7808a1.tar.bz2
android_bootable_recovery-7ce287d432dd3a4dc8841fc59e11ee1a0b7808a1.tar.lz
android_bootable_recovery-7ce287d432dd3a4dc8841fc59e11ee1a0b7808a1.tar.xz
android_bootable_recovery-7ce287d432dd3a4dc8841fc59e11ee1a0b7808a1.tar.zst
android_bootable_recovery-7ce287d432dd3a4dc8841fc59e11ee1a0b7808a1.zip
Diffstat (limited to 'updater')
-rw-r--r--updater/blockimg.cpp59
-rw-r--r--updater/updater.cpp10
2 files changed, 61 insertions, 8 deletions
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 2efa1cd47..f7955566d 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -70,6 +70,7 @@ struct RangeSet {
};
static CauseCode failure_type = kNoCause;
+static bool is_retry = false;
static std::map<std::string, RangeSet> stash_map;
static void parse_range(const std::string& range_text, RangeSet& rs) {
@@ -179,6 +180,21 @@ static int write_all(int fd, const std::vector<uint8_t>& buffer, size_t size) {
return write_all(fd, buffer.data(), size);
}
+static bool discard_blocks(int fd, off64_t offset, uint64_t size) {
+ // Don't discard blocks unless the update is a retry run.
+ if (!is_retry) {
+ return true;
+ }
+
+ uint64_t args[2] = {static_cast<uint64_t>(offset), size};
+ int status = ioctl(fd, BLKDISCARD, &args);
+ if (status == -1) {
+ fprintf(stderr, "BLKDISCARD ioctl failed: %s\n", strerror(errno));
+ return false;
+ }
+ return true;
+}
+
static bool check_lseek(int fd, off64_t offset, int whence) {
off64_t rc = TEMP_FAILURE_RETRY(lseek64(fd, offset, whence));
if (rc == -1) {
@@ -238,10 +254,15 @@ static ssize_t RangeSinkWrite(const uint8_t* data, ssize_t size, void* token) {
rss->p_remain = (rss->tgt.pos[rss->p_block * 2 + 1] -
rss->tgt.pos[rss->p_block * 2]) * BLOCKSIZE;
- if (!check_lseek(rss->fd, (off64_t)rss->tgt.pos[rss->p_block*2] * BLOCKSIZE,
- SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(rss->tgt.pos[rss->p_block*2]) * BLOCKSIZE;
+ if (!discard_blocks(rss->fd, offset, rss->p_remain)) {
+ break;
+ }
+
+ if (!check_lseek(rss->fd, offset, SEEK_SET)) {
break;
}
+
} else {
// we can't write any more; return how many bytes have
// been written so far.
@@ -347,11 +368,15 @@ static int WriteBlocks(const RangeSet& tgt, const std::vector<uint8_t>& buffer,
size_t p = 0;
for (size_t i = 0; i < tgt.count; ++i) {
- if (!check_lseek(fd, (off64_t) tgt.pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(tgt.pos[i * 2]) * BLOCKSIZE;
+ size_t size = (tgt.pos[i * 2 + 1] - tgt.pos[i * 2]) * BLOCKSIZE;
+ if (!discard_blocks(fd, offset, size)) {
return -1;
}
- size_t size = (tgt.pos[i * 2 + 1] - tgt.pos[i * 2]) * BLOCKSIZE;
+ if (!check_lseek(fd, offset, SEEK_SET)) {
+ return -1;
+ }
if (write_all(fd, data + p, size) == -1) {
return -1;
@@ -1104,7 +1129,13 @@ static int PerformCommandZero(CommandParameters& params) {
if (params.canwrite) {
for (size_t i = 0; i < tgt.count; ++i) {
- if (!check_lseek(params.fd, (off64_t) tgt.pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(tgt.pos[i * 2]) * BLOCKSIZE;
+ size_t size = (tgt.pos[i * 2 + 1] - tgt.pos[i * 2]) * BLOCKSIZE;
+ if (!discard_blocks(params.fd, offset, size)) {
+ return -1;
+ }
+
+ if (!check_lseek(params.fd, offset, SEEK_SET)) {
return -1;
}
@@ -1143,7 +1174,12 @@ static int PerformCommandNew(CommandParameters& params) {
rss.p_block = 0;
rss.p_remain = (tgt.pos[1] - tgt.pos[0]) * BLOCKSIZE;
- if (!check_lseek(params.fd, (off64_t) tgt.pos[0] * BLOCKSIZE, SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(tgt.pos[0]) * BLOCKSIZE;
+ if (!discard_blocks(params.fd, offset, tgt.size * BLOCKSIZE)) {
+ return -1;
+ }
+
+ if (!check_lseek(params.fd, offset, SEEK_SET)) {
return -1;
}
@@ -1221,7 +1257,12 @@ static int PerformCommandDiff(CommandParameters& params) {
rss.p_block = 0;
rss.p_remain = (tgt.pos[1] - tgt.pos[0]) * BLOCKSIZE;
- if (!check_lseek(params.fd, (off64_t) tgt.pos[0] * BLOCKSIZE, SEEK_SET)) {
+ off64_t offset = static_cast<off64_t>(tgt.pos[0]) * BLOCKSIZE;
+ if (!discard_blocks(params.fd, offset, rss.p_remain)) {
+ return -1;
+ }
+
+ if (!check_lseek(params.fd, offset, SEEK_SET)) {
return -1;
}
@@ -1340,6 +1381,10 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
params.canwrite = !dryrun;
fprintf(stderr, "performing %s\n", dryrun ? "verification" : "update");
+ if (state->is_retry) {
+ is_retry = true;
+ fprintf(stderr, "This update is a retry.\n");
+ }
Value* blockdev_filename = nullptr;
Value* transfer_list_value = nullptr;
diff --git a/updater/updater.cpp b/updater/updater.cpp
index b5db71e2a..e956dd557 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -48,7 +48,7 @@ int main(int argc, char** argv) {
setbuf(stdout, NULL);
setbuf(stderr, NULL);
- if (argc != 4) {
+ if (argc != 4 && argc != 5) {
printf("unexpected number of arguments (%d)\n", argc);
return 1;
}
@@ -142,6 +142,14 @@ int main(int argc, char** argv) {
state.script = script;
state.errmsg = NULL;
+ if (argc == 5) {
+ if (strcmp(argv[4], "retry") == 0) {
+ state.is_retry = true;
+ } else {
+ printf("unexpected argument: %s", argv[4]);
+ }
+ }
+
char* result = Evaluate(&state, root);
if (have_eio_error) {