libsnapshot: Don't try to truncate block devices

When we're writing to a block device, we can't truncate. Ignore those
commands. Truncate mostly just saves time in the read phase by chopping
off unused data in the event finalize wasn't called.

Bug: 172026020
Test: cow_api_test
Change-Id: I3befc71fa9597edf8243d0f9e17440db91409aea
This commit is contained in:
Daniel Rosenberg 2020-11-09 17:45:28 -08:00 committed by David Anderson
parent 99ed2152de
commit ce69f2985b
2 changed files with 23 additions and 4 deletions

View File

@ -122,6 +122,13 @@ bool CowWriter::SetFd(android::base::borrowed_fd fd) {
is_dev_null_ = true;
} else {
fd_ = fd;
struct stat stat;
if (fstat(fd.get(), &stat) < 0) {
PLOG(ERROR) << "fstat failed";
return false;
}
is_block_device_ = S_ISBLK(stat.st_mode);
}
return true;
}
@ -217,12 +224,11 @@ bool CowWriter::OpenForAppend(uint64_t label) {
// Free reader so we own the descriptor position again.
reader = nullptr;
// Position for new writing
if (ftruncate(fd_.get(), next_op_pos_) != 0) {
PLOG(ERROR) << "Failed to trim file";
// Remove excess data
if (!Truncate(next_op_pos_)) {
return false;
}
if (lseek(fd_.get(), 0, SEEK_END) < 0) {
if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
PLOG(ERROR) << "lseek failed";
return false;
}
@ -445,5 +451,16 @@ bool CowWriter::CommitMerge(int merged_ops) {
return Sync();
}
bool CowWriter::Truncate(off_t length) {
if (is_dev_null_ || is_block_device_) {
return true;
}
if (ftruncate(fd_.get(), length) < 0) {
PLOG(ERROR) << "Failed to truncate.";
return false;
}
return true;
}
} // namespace snapshot
} // namespace android

View File

@ -123,6 +123,7 @@ class CowWriter : public ICowWriter {
bool SetFd(android::base::borrowed_fd fd);
bool Sync();
bool Truncate(off_t length);
private:
android::base::unique_fd owned_fd_;
@ -133,6 +134,7 @@ class CowWriter : public ICowWriter {
uint64_t next_op_pos_ = 0;
bool is_dev_null_ = false;
bool merge_in_progress_ = false;
bool is_block_device_ = false;
// :TODO: this is not efficient, but stringstream ubsan aborts because some
// bytes overflow a signed char.