Merge changes from topic "fastbootd-reset-fd"
* changes: fastbootd: reset file descriptor on unaligned writes fastbootd: add support to reset fd by handle fastbootd: pass handle in place of fd
This commit is contained in:
commit
04a4a10ee1
3 changed files with 66 additions and 23 deletions
|
@ -76,7 +76,7 @@ void WipeOverlayfsForPartition(FastbootDevice* device, const std::string& partit
|
|||
|
||||
} // namespace
|
||||
|
||||
int FlashRawDataChunk(int fd, const char* data, size_t len) {
|
||||
int FlashRawDataChunk(PartitionHandle* handle, const char* data, size_t len) {
|
||||
size_t ret = 0;
|
||||
const size_t max_write_size = 1048576;
|
||||
void* aligned_buffer;
|
||||
|
@ -91,7 +91,15 @@ int FlashRawDataChunk(int fd, const char* data, size_t len) {
|
|||
while (ret < len) {
|
||||
int this_len = std::min(max_write_size, len - ret);
|
||||
memcpy(aligned_buffer_unique_ptr.get(), data, this_len);
|
||||
int this_ret = write(fd, aligned_buffer_unique_ptr.get(), this_len);
|
||||
// In case of non 4KB aligned writes, reopen without O_DIRECT flag
|
||||
if (this_len & 0xFFF) {
|
||||
if (handle->Reset(O_WRONLY) != true) {
|
||||
PLOG(ERROR) << "Failed to reset file descriptor";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int this_ret = write(handle->fd(), aligned_buffer_unique_ptr.get(), this_len);
|
||||
if (this_ret < 0) {
|
||||
PLOG(ERROR) << "Failed to flash data of len " << len;
|
||||
return -1;
|
||||
|
@ -102,8 +110,8 @@ int FlashRawDataChunk(int fd, const char* data, size_t len) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int FlashRawData(int fd, const std::vector<char>& downloaded_data) {
|
||||
int ret = FlashRawDataChunk(fd, downloaded_data.data(), downloaded_data.size());
|
||||
int FlashRawData(PartitionHandle* handle, const std::vector<char>& downloaded_data) {
|
||||
int ret = FlashRawDataChunk(handle, downloaded_data.data(), downloaded_data.size());
|
||||
if (ret < 0) {
|
||||
return -errno;
|
||||
}
|
||||
|
@ -111,30 +119,30 @@ int FlashRawData(int fd, const std::vector<char>& downloaded_data) {
|
|||
}
|
||||
|
||||
int WriteCallback(void* priv, const void* data, size_t len) {
|
||||
int fd = reinterpret_cast<long long>(priv);
|
||||
PartitionHandle* handle = reinterpret_cast<PartitionHandle*>(priv);
|
||||
if (!data) {
|
||||
return lseek64(fd, len, SEEK_CUR) >= 0 ? 0 : -errno;
|
||||
return lseek64(handle->fd(), len, SEEK_CUR) >= 0 ? 0 : -errno;
|
||||
}
|
||||
return FlashRawDataChunk(fd, reinterpret_cast<const char*>(data), len);
|
||||
return FlashRawDataChunk(handle, reinterpret_cast<const char*>(data), len);
|
||||
}
|
||||
|
||||
int FlashSparseData(int fd, std::vector<char>& downloaded_data) {
|
||||
int FlashSparseData(PartitionHandle* handle, std::vector<char>& downloaded_data) {
|
||||
struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(),
|
||||
downloaded_data.size(), true, false);
|
||||
if (!file) {
|
||||
// Invalid sparse format
|
||||
return -EINVAL;
|
||||
}
|
||||
return sparse_file_callback(file, false, false, WriteCallback, reinterpret_cast<void*>(fd));
|
||||
return sparse_file_callback(file, false, false, WriteCallback, reinterpret_cast<void*>(handle));
|
||||
}
|
||||
|
||||
int FlashBlockDevice(int fd, std::vector<char>& downloaded_data) {
|
||||
lseek64(fd, 0, SEEK_SET);
|
||||
int FlashBlockDevice(PartitionHandle* handle, std::vector<char>& downloaded_data) {
|
||||
lseek64(handle->fd(), 0, SEEK_SET);
|
||||
if (downloaded_data.size() >= sizeof(SPARSE_HEADER_MAGIC) &&
|
||||
*reinterpret_cast<uint32_t*>(downloaded_data.data()) == SPARSE_HEADER_MAGIC) {
|
||||
return FlashSparseData(fd, downloaded_data);
|
||||
return FlashSparseData(handle, downloaded_data);
|
||||
} else {
|
||||
return FlashRawData(fd, downloaded_data);
|
||||
return FlashRawData(handle, downloaded_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,7 +189,7 @@ int Flash(FastbootDevice* device, const std::string& partition_name) {
|
|||
if (android::base::GetProperty("ro.system.build.type", "") != "user") {
|
||||
WipeOverlayfsForPartition(device, partition_name);
|
||||
}
|
||||
int result = FlashBlockDevice(handle.fd(), data);
|
||||
int result = FlashBlockDevice(&handle, data);
|
||||
sync();
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -90,14 +90,7 @@ bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHan
|
|||
return false;
|
||||
}
|
||||
|
||||
flags |= (O_EXCL | O_CLOEXEC | O_BINARY);
|
||||
unique_fd fd(TEMP_FAILURE_RETRY(open(handle->path().c_str(), flags)));
|
||||
if (fd < 0) {
|
||||
PLOG(ERROR) << "Failed to open block device: " << handle->path();
|
||||
return false;
|
||||
}
|
||||
handle->set_fd(std::move(fd));
|
||||
return true;
|
||||
return handle->Open(flags);
|
||||
}
|
||||
|
||||
std::optional<std::string> FindPhysicalPartition(const std::string& name) {
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <android/hardware/boot/1.0/IBootControl.h>
|
||||
#include <fstab/fstab.h>
|
||||
|
@ -44,11 +46,51 @@ class PartitionHandle {
|
|||
}
|
||||
const std::string& path() const { return path_; }
|
||||
int fd() const { return fd_.get(); }
|
||||
void set_fd(android::base::unique_fd&& fd) { fd_ = std::move(fd); }
|
||||
bool Open(int flags) {
|
||||
flags |= (O_EXCL | O_CLOEXEC | O_BINARY);
|
||||
|
||||
// Attempts to open a second device can fail with EBUSY if the device is already open.
|
||||
// Explicitly close any previously opened devices as unique_fd won't close them until
|
||||
// after the attempt to open.
|
||||
fd_.reset();
|
||||
|
||||
fd_ = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path_.c_str(), flags)));
|
||||
if (fd_ < 0) {
|
||||
PLOG(ERROR) << "Failed to open block device: " << path_;
|
||||
return false;
|
||||
}
|
||||
flags_ = flags;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Reset(int flags) {
|
||||
if (fd_.ok() && (flags | O_EXCL | O_CLOEXEC | O_BINARY) == flags_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
off_t offset = fd_.ok() ? lseek(fd_.get(), 0, SEEK_CUR) : 0;
|
||||
if (offset < 0) {
|
||||
PLOG(ERROR) << "Failed lseek on block device: " << path_;
|
||||
return false;
|
||||
}
|
||||
|
||||
sync();
|
||||
|
||||
if (Open(flags) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lseek(fd_.get(), offset, SEEK_SET) != offset) {
|
||||
PLOG(ERROR) << "Failed lseek on block device: " << path_;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
std::string path_;
|
||||
android::base::unique_fd fd_;
|
||||
int flags_;
|
||||
std::function<void()> closer_;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue