Discard the tail of the target partitions when updating.
The partition is normally way bigger than the data it holds and the
remainder of the partition is often ignored by the system. This patch
discards the tail of the partition, past the end of the updated data.
This would ensure that the unused blocks in these partitions can be
reallocated by the SSD controller to other blocks, and that data from
previous updates does not interfere with the current version.
Bug: 28744609
TEST=strace -e trace=file,ioctl shows the device discarding the end of the updated partitions.
Change-Id: Ie6135ee1aef2fa594c40d84af4d1d46a8f53cc3a
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 5ad1d46..687f903 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -130,6 +130,35 @@
*err = 0;
return fd;
}
+
+// Discard the tail of the block device referenced by |fd|, from the offset
+// |data_size| until the end of the block device. Returns whether the data was
+// discarded.
+bool DiscardPartitionTail(FileDescriptorPtr fd, uint64_t data_size) {
+ uint64_t part_size = fd->BlockDevSize();
+ if (!part_size || part_size <= data_size)
+ return false;
+
+ const vector<int> requests = {
+ BLKSECDISCARD,
+ BLKDISCARD,
+#ifdef BLKZEROOUT
+ BLKZEROOUT,
+#endif
+ };
+ for (int request : requests) {
+ int error = 0;
+ if (fd->BlkIoctl(request, data_size, part_size - data_size, &error) &&
+ error == 0) {
+ return true;
+ }
+ LOG(WARNING) << "Error discarding the last "
+ << (part_size - data_size) / 1024 << " KiB using ioctl("
+ << request << ")";
+ }
+ return false;
+}
+
} // namespace
@@ -325,6 +354,15 @@
<< ", file " << target_path_;
return false;
}
+
+ LOG(INFO) << "Applying " << partition.operations().size()
+ << " operations to partition \"" << partition.partition_name()
+ << "\"";
+
+ // Discard the end of the partition, but ignore failures.
+ DiscardPartitionTail(
+ target_fd_, install_plan_->partitions[current_partition_].target_size);
+
return true;
}