Loading fs_mgr/libfiemap_writer/fiemap_writer.cpp +18 −3 Original line number Diff line number Diff line Loading @@ -220,7 +220,7 @@ static bool PerformFileChecks(const std::string& file_path, uint64_t file_size, } static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz, uint64_t file_size) { uint64_t file_size, std::function<bool(uint64_t, uint64_t)> on_progress) { // Reserve space for the file on the file system and write it out to make sure the extents // don't come back unwritten. Return from this function with the kernel file offset set to 0. // If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks Loading @@ -245,12 +245,22 @@ static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blo return false; } int permille = -1; for (; offset < file_size; offset += blocksz) { if (!::android::base::WriteFully(file_fd, buffer.get(), blocksz)) { PLOG(ERROR) << "Failed to write" << blocksz << " bytes at offset" << offset << " in file " << file_path; return false; } // Don't invoke the callback every iteration - wait until a significant // chunk (here, 1/1000th) of the data has been processed. int new_permille = (static_cast<uint64_t>(offset) * 1000) / file_size; if (new_permille != permille) { if (on_progress && !on_progress(offset, file_size)) { return false; } permille = new_permille; } } if (lseek64(file_fd, 0, SEEK_SET) < 0) { Loading @@ -264,6 +274,10 @@ static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blo return false; } // Send one last progress notification. if (on_progress && !on_progress(file_size, file_size)) { return false; } return true; } Loading Loading @@ -412,7 +426,8 @@ static bool ReadFiemap(int file_fd, const std::string& file_path, return last_extent_seen; } FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create) { FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create, std::function<bool(uint64_t, uint64_t)> progress) { // if 'create' is false, open an existing file and do not truncate. int open_flags = O_RDWR | O_CLOEXEC; if (create) { Loading Loading @@ -474,7 +489,7 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s } if (create) { if (!AllocateFile(file_fd, abs_path, blocksz, file_size)) { if (!AllocateFile(file_fd, abs_path, blocksz, file_size, std::move(progress))) { LOG(ERROR) << "Failed to allocate file: " << abs_path << " of size: " << file_size << " bytes"; cleanup(abs_path, create); Loading fs_mgr/libfiemap_writer/fiemap_writer_test.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,25 @@ TEST_F(FiemapWriterTest, CheckFilePath) { EXPECT_EQ(access(testfile.c_str(), F_OK), 0); } TEST_F(FiemapWriterTest, CheckProgress) { std::vector<uint64_t> expected{ 0, 4096, }; size_t invocations = 0; auto callback = [&](uint64_t done, uint64_t total) -> bool { EXPECT_LT(invocations, expected.size()); EXPECT_EQ(done, expected[invocations]); EXPECT_EQ(total, 4096); invocations++; return true; }; auto ptr = FiemapWriter::Open(testfile, 4096, true, std::move(callback)); EXPECT_NE(ptr, nullptr); EXPECT_EQ(invocations, 2); } TEST_F(FiemapWriterTest, CheckBlockDevicePath) { FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 4096); EXPECT_EQ(fptr->size(), 4096); Loading fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h +7 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <sys/types.h> #include <unistd.h> #include <functional> #include <string> #include <vector> Loading @@ -36,9 +37,13 @@ class FiemapWriter final { public: // Factory method for FiemapWriter. // The method returns FiemapUniquePtr that contains all the data necessary to be able to write // to the given file directly using raw block i/o. // to the given file directly using raw block i/o. The optional progress callback will be // invoked, if create is true, while the file is being initialized. It receives the bytes // written and the number of total bytes. If the callback returns false, the operation will // fail. static FiemapUniquePtr Open(const std::string& file_path, uint64_t file_size, bool create = true); bool create = true, std::function<bool(uint64_t, uint64_t)> progress = {}); // Syncs block device writes. bool Flush() const; Loading Loading
fs_mgr/libfiemap_writer/fiemap_writer.cpp +18 −3 Original line number Diff line number Diff line Loading @@ -220,7 +220,7 @@ static bool PerformFileChecks(const std::string& file_path, uint64_t file_size, } static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz, uint64_t file_size) { uint64_t file_size, std::function<bool(uint64_t, uint64_t)> on_progress) { // Reserve space for the file on the file system and write it out to make sure the extents // don't come back unwritten. Return from this function with the kernel file offset set to 0. // If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks Loading @@ -245,12 +245,22 @@ static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blo return false; } int permille = -1; for (; offset < file_size; offset += blocksz) { if (!::android::base::WriteFully(file_fd, buffer.get(), blocksz)) { PLOG(ERROR) << "Failed to write" << blocksz << " bytes at offset" << offset << " in file " << file_path; return false; } // Don't invoke the callback every iteration - wait until a significant // chunk (here, 1/1000th) of the data has been processed. int new_permille = (static_cast<uint64_t>(offset) * 1000) / file_size; if (new_permille != permille) { if (on_progress && !on_progress(offset, file_size)) { return false; } permille = new_permille; } } if (lseek64(file_fd, 0, SEEK_SET) < 0) { Loading @@ -264,6 +274,10 @@ static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blo return false; } // Send one last progress notification. if (on_progress && !on_progress(file_size, file_size)) { return false; } return true; } Loading Loading @@ -412,7 +426,8 @@ static bool ReadFiemap(int file_fd, const std::string& file_path, return last_extent_seen; } FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create) { FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create, std::function<bool(uint64_t, uint64_t)> progress) { // if 'create' is false, open an existing file and do not truncate. int open_flags = O_RDWR | O_CLOEXEC; if (create) { Loading Loading @@ -474,7 +489,7 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s } if (create) { if (!AllocateFile(file_fd, abs_path, blocksz, file_size)) { if (!AllocateFile(file_fd, abs_path, blocksz, file_size, std::move(progress))) { LOG(ERROR) << "Failed to allocate file: " << abs_path << " of size: " << file_size << " bytes"; cleanup(abs_path, create); Loading
fs_mgr/libfiemap_writer/fiemap_writer_test.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,25 @@ TEST_F(FiemapWriterTest, CheckFilePath) { EXPECT_EQ(access(testfile.c_str(), F_OK), 0); } TEST_F(FiemapWriterTest, CheckProgress) { std::vector<uint64_t> expected{ 0, 4096, }; size_t invocations = 0; auto callback = [&](uint64_t done, uint64_t total) -> bool { EXPECT_LT(invocations, expected.size()); EXPECT_EQ(done, expected[invocations]); EXPECT_EQ(total, 4096); invocations++; return true; }; auto ptr = FiemapWriter::Open(testfile, 4096, true, std::move(callback)); EXPECT_NE(ptr, nullptr); EXPECT_EQ(invocations, 2); } TEST_F(FiemapWriterTest, CheckBlockDevicePath) { FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 4096); EXPECT_EQ(fptr->size(), 4096); Loading
fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h +7 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <sys/types.h> #include <unistd.h> #include <functional> #include <string> #include <vector> Loading @@ -36,9 +37,13 @@ class FiemapWriter final { public: // Factory method for FiemapWriter. // The method returns FiemapUniquePtr that contains all the data necessary to be able to write // to the given file directly using raw block i/o. // to the given file directly using raw block i/o. The optional progress callback will be // invoked, if create is true, while the file is being initialized. It receives the bytes // written and the number of total bytes. If the callback returns false, the operation will // fail. static FiemapUniquePtr Open(const std::string& file_path, uint64_t file_size, bool create = true); bool create = true, std::function<bool(uint64_t, uint64_t)> progress = {}); // Syncs block device writes. bool Flush() const; Loading