Skip to content

Commit 56850e1

Browse files
dvandercorpGerrit Code Review
authored and
Gerrit Code Review
committed
Merge "libsnapshot: Add an open /dev/null mode for CowWriter."
2 parents f2609b2 + 1b9ab3f commit 56850e1

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

fs_mgr/libsnapshot/cow_writer.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,28 @@ bool CowWriter::ParseOptions() {
110110
return true;
111111
}
112112

113+
bool CowWriter::SetFd(android::base::borrowed_fd fd) {
114+
if (fd.get() < 0) {
115+
owned_fd_.reset(open("/dev/null", O_RDWR | O_CLOEXEC));
116+
if (owned_fd_ < 0) {
117+
PLOG(ERROR) << "open /dev/null failed";
118+
return false;
119+
}
120+
fd_ = owned_fd_;
121+
is_dev_null_ = true;
122+
} else {
123+
fd_ = fd;
124+
}
125+
return true;
126+
}
127+
113128
bool CowWriter::Initialize(unique_fd&& fd, OpenMode mode) {
114129
owned_fd_ = std::move(fd);
115130
return Initialize(borrowed_fd{owned_fd_}, mode);
116131
}
117132

118133
bool CowWriter::Initialize(borrowed_fd fd, OpenMode mode) {
119-
fd_ = fd;
120-
121-
if (!ParseOptions()) {
134+
if (!SetFd(fd) || !ParseOptions()) {
122135
return false;
123136
}
124137

@@ -139,9 +152,7 @@ bool CowWriter::InitializeAppend(android::base::unique_fd&& fd, uint64_t label)
139152
}
140153

141154
bool CowWriter::InitializeAppend(android::base::borrowed_fd fd, uint64_t label) {
142-
fd_ = fd;
143-
144-
if (!ParseOptions()) {
155+
if (!SetFd(fd) || !ParseOptions()) {
145156
return false;
146157
}
147158

@@ -304,7 +315,7 @@ bool CowWriter::EmitLabel(uint64_t label) {
304315
CowOperation op = {};
305316
op.type = kCowLabelOp;
306317
op.source = label;
307-
return WriteOperation(op) && !fsync(fd_.get());
318+
return WriteOperation(op) && Sync();
308319
}
309320

310321
std::basic_string<uint8_t> CowWriter::Compress(const void* data, size_t length) {
@@ -383,7 +394,7 @@ bool CowWriter::Finalize() {
383394
PLOG(ERROR) << "lseek ops failed";
384395
return false;
385396
}
386-
return !fsync(fd_.get());
397+
return Sync();
387398
}
388399

389400
uint64_t CowWriter::GetCowSize() {
@@ -424,5 +435,16 @@ bool CowWriter::WriteRawData(const void* data, size_t size) {
424435
return true;
425436
}
426437

438+
bool CowWriter::Sync() {
439+
if (is_dev_null_) {
440+
return true;
441+
}
442+
if (fsync(fd_.get()) < 0) {
443+
PLOG(ERROR) << "fsync failed";
444+
return false;
445+
}
446+
return true;
447+
}
448+
427449
} // namespace snapshot
428450
} // namespace android

fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ class CowWriter : public ICowWriter {
9090
// If opening for write, the file starts from the beginning.
9191
// If opening for append, if the file has a footer, we start appending to the last op.
9292
// If the footer isn't found, the last label is considered corrupt, and dropped.
93+
//
94+
// If fd is < 0, the CowWriter will be opened against /dev/null. This is for
95+
// computing COW sizes without using storage space.
9396
bool Initialize(android::base::unique_fd&& fd, OpenMode mode = OpenMode::WRITE);
9497
bool Initialize(android::base::borrowed_fd fd, OpenMode mode = OpenMode::WRITE);
9598
// Set up a writer, assuming that the given label is the last valid label.
@@ -119,13 +122,17 @@ class CowWriter : public ICowWriter {
119122
void AddOperation(const CowOperation& op);
120123
std::basic_string<uint8_t> Compress(const void* data, size_t length);
121124

125+
bool SetFd(android::base::borrowed_fd fd);
126+
bool Sync();
127+
122128
private:
123129
android::base::unique_fd owned_fd_;
124130
android::base::borrowed_fd fd_;
125131
CowHeader header_{};
126132
CowFooter footer_{};
127133
int compression_ = 0;
128134
uint64_t next_op_pos_ = 0;
135+
bool is_dev_null_ = false;
129136

130137
// :TODO: this is not efficient, but stringstream ubsan aborts because some
131138
// bytes overflow a signed char.

0 commit comments

Comments
 (0)