Add UnownedCacheFileDescriptor
Since we switched to raw pointers in a subset of fs verfication
functions, EncodeFEC no longer have a shared ptr, and can no longer use
CacheFileDescriptor. Add a variant of CacheFileDescriptor that works
with raw pointer.
Test: th
Bug: 216391325
Change-Id: Id71880a4f8f97e4549dcc96d53e9af00ae45168c
diff --git a/payload_consumer/cached_file_descriptor.cc b/payload_consumer/cached_file_descriptor.cc
index 7f2515e..aa0dbcd 100644
--- a/payload_consumer/cached_file_descriptor.cc
+++ b/payload_consumer/cached_file_descriptor.cc
@@ -26,7 +26,7 @@
namespace chromeos_update_engine {
-off64_t CachedFileDescriptor::Seek(off64_t offset, int whence) {
+off64_t CachedFileDescriptorBase::Seek(off64_t offset, int whence) {
// Only support SEEK_SET and SEEK_CUR. I think these two would be enough. If
// we want to support SEEK_END then we have to figure out the size of the
// underlying file descriptor each time and it may not be a very good idea.
@@ -40,7 +40,7 @@
return -1;
}
// Then we have to seek there.
- if (fd_->Seek(next_offset, SEEK_SET) < 0) {
+ if (GetFd()->Seek(next_offset, SEEK_SET) < 0) {
return -1;
}
offset_ = next_offset;
@@ -48,7 +48,7 @@
return offset_;
}
-ssize_t CachedFileDescriptor::Write(const void* buf, size_t count) {
+ssize_t CachedFileDescriptorBase::Write(const void* buf, size_t count) {
auto bytes = static_cast<const uint8_t*>(buf);
size_t total_bytes_wrote = 0;
while (total_bytes_wrote < count) {
@@ -72,19 +72,20 @@
return total_bytes_wrote;
}
-bool CachedFileDescriptor::Flush() {
- return FlushCache() && fd_->Flush();
+bool CachedFileDescriptorBase::Flush() {
+ return FlushCache() && GetFd()->Flush();
}
-bool CachedFileDescriptor::Close() {
+bool CachedFileDescriptorBase::Close() {
offset_ = 0;
- return FlushCache() && fd_->Close();
+ return FlushCache() && GetFd()->Close();
}
-bool CachedFileDescriptor::FlushCache() {
+bool CachedFileDescriptorBase::FlushCache() {
size_t begin = 0;
while (begin < bytes_cached_) {
- auto bytes_wrote = fd_->Write(cache_.data() + begin, bytes_cached_ - begin);
+ auto bytes_wrote =
+ GetFd()->Write(cache_.data() + begin, bytes_cached_ - begin);
if (bytes_wrote < 0) {
PLOG(ERROR) << "Failed to flush cached data!";
return false;
diff --git a/payload_consumer/cached_file_descriptor.h b/payload_consumer/cached_file_descriptor.h
index ada112b..1193455 100644
--- a/payload_consumer/cached_file_descriptor.h
+++ b/payload_consumer/cached_file_descriptor.h
@@ -29,45 +29,66 @@
namespace chromeos_update_engine {
-class CachedFileDescriptor : public FileDescriptor {
+class CachedFileDescriptorBase : public FileDescriptor {
public:
- CachedFileDescriptor(FileDescriptorPtr fd, size_t cache_size)
- : fd_(fd), cache_(cache_size) {}
- ~CachedFileDescriptor() override = default;
+ CachedFileDescriptorBase(size_t cache_size) : cache_(cache_size) {}
+ ~CachedFileDescriptorBase() override = default;
bool Open(const char* path, int flags, mode_t mode) override {
- return fd_->Open(path, flags, mode);
+ return GetFd()->Open(path, flags, mode);
}
bool Open(const char* path, int flags) override {
- return fd_->Open(path, flags);
+ return GetFd()->Open(path, flags);
}
ssize_t Read(void* buf, size_t count) override {
- return fd_->Read(buf, count);
+ return GetFd()->Read(buf, count);
}
ssize_t Write(const void* buf, size_t count) override;
off64_t Seek(off64_t offset, int whence) override;
- uint64_t BlockDevSize() override { return fd_->BlockDevSize(); }
+ uint64_t BlockDevSize() override { return GetFd()->BlockDevSize(); }
bool BlkIoctl(int request,
uint64_t start,
uint64_t length,
int* result) override {
- return fd_->BlkIoctl(request, start, length, result);
+ return GetFd()->BlkIoctl(request, start, length, result);
}
bool Flush() override;
bool Close() override;
- bool IsSettingErrno() override { return fd_->IsSettingErrno(); }
- bool IsOpen() override { return fd_->IsOpen(); }
+ bool IsSettingErrno() override { return GetFd()->IsSettingErrno(); }
+ bool IsOpen() override { return GetFd()->IsOpen(); }
+
+ protected:
+ virtual FileDescriptor* GetFd() = 0;
private:
// Internal flush without the need to call |fd_->Flush()|.
bool FlushCache();
- FileDescriptorPtr fd_;
brillo::Blob cache_;
size_t bytes_cached_{0};
off64_t offset_{0};
- DISALLOW_COPY_AND_ASSIGN(CachedFileDescriptor);
+ DISALLOW_COPY_AND_ASSIGN(CachedFileDescriptorBase);
+};
+
+class CachedFileDescriptor final : public CachedFileDescriptorBase {
+ public:
+ CachedFileDescriptor(FileDescriptorPtr fd, size_t cache_size)
+ : CachedFileDescriptorBase(cache_size), fd_(fd) {}
+
+ protected:
+ virtual FileDescriptor* GetFd() { return fd_.get(); }
+ FileDescriptorPtr fd_;
+};
+
+class UnownedCachedFileDescriptor final : public CachedFileDescriptorBase {
+ public:
+ UnownedCachedFileDescriptor(FileDescriptor* fd, size_t cache_size)
+ : CachedFileDescriptorBase(cache_size), fd_(fd) {}
+
+ protected:
+ virtual FileDescriptor* GetFd() { return fd_; }
+ FileDescriptor* fd_;
};
} // namespace chromeos_update_engine
diff --git a/payload_consumer/partition_writer.cc b/payload_consumer/partition_writer.cc
index 4625a7a..b94f8c7 100644
--- a/payload_consumer/partition_writer.cc
+++ b/payload_consumer/partition_writer.cc
@@ -86,8 +86,6 @@
} // namespace
-using google::protobuf::RepeatedPtrField;
-
// Opens path for read/write. On success returns an open FileDescriptor
// and sets *err to 0. On failure, sets *err to errno and returns nullptr.
FileDescriptorPtr OpenFile(const char* path,
diff --git a/payload_consumer/verity_writer_android.cc b/payload_consumer/verity_writer_android.cc
index b233b58..b669b4d 100644
--- a/payload_consumer/verity_writer_android.cc
+++ b/payload_consumer/verity_writer_android.cc
@@ -161,6 +161,11 @@
std::unique_ptr<void, decltype(&free_rs_char)> rs_char(
init_rs_char(FEC_PARAMS(fec_roots)), &free_rs_char);
TEST_AND_RETURN_FALSE(rs_char != nullptr);
+ // Cache at most 1MB of fec data, in VABC, we need to re-open fd if we
+ // perform a read() operation after write(). So reduce the number of writes
+ // can save unnecessary re-opens.
+ UnownedCachedFileDescriptor cache_fd(write_fd, 1 * (1 << 20));
+ write_fd = &cache_fd;
for (size_t i = 0; i < rounds; i++) {
// Encodes |block_size| number of rs blocks each round so that we can read