Loading fs_mgr/libfiemap_writer/fiemap_writer.cpp +1 −121 Original line number Diff line number Diff line Loading @@ -374,14 +374,6 @@ bool FiemapWriter::HasPinnedExtents(const std::string& file_path) { return IsFilePinned(fd, file_path, sfs.f_type); } static void LogExtent(uint32_t num, const struct fiemap_extent& ext) { LOG(INFO) << "Extent #" << num; LOG(INFO) << " fe_logical: " << ext.fe_logical; LOG(INFO) << " fe_physical: " << ext.fe_physical; LOG(INFO) << " fe_length: " << ext.fe_length; LOG(INFO) << " fe_flags: 0x" << std::hex << ext.fe_flags; } static bool ReadFiemap(int file_fd, const std::string& file_path, std::vector<struct fiemap_extent>* extents) { uint64_t fiemap_size = Loading Loading @@ -473,7 +465,7 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s } ::android::base::unique_fd bdev_fd( TEMP_FAILURE_RETRY(open(bdev_path.c_str(), O_RDWR | O_CLOEXEC))); TEMP_FAILURE_RETRY(open(bdev_path.c_str(), O_RDONLY | O_CLOEXEC))); if (bdev_fd < 0) { PLOG(ERROR) << "Failed to open block device: " << bdev_path; cleanup(file_path, create); Loading Loading @@ -530,7 +522,6 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s fmap->file_path_ = abs_path; fmap->bdev_path_ = bdev_path; fmap->file_fd_ = std::move(file_fd); fmap->bdev_fd_ = std::move(bdev_fd); fmap->file_size_ = file_size; fmap->bdev_size_ = bdevsz; fmap->fs_type_ = fs_type; Loading @@ -541,120 +532,9 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s return fmap; } bool FiemapWriter::Flush() const { if (fsync(bdev_fd_)) { PLOG(ERROR) << "Failed to flush " << bdev_path_ << " with fsync"; return false; } return true; } // TODO: Test with fs block_size > bdev block_size bool FiemapWriter::Write(off64_t off, uint8_t* buffer, uint64_t size) { if (!size || size > file_size_) { LOG(ERROR) << "Failed write: size " << size << " is invalid for file's size " << file_size_; return false; } if (off + size > file_size_) { LOG(ERROR) << "Failed write: Invalid offset " << off << " or size " << size << " for file size " << file_size_; return false; } if ((off & (block_size_ - 1)) || (size & (block_size_ - 1))) { LOG(ERROR) << "Failed write: Unaligned offset " << off << " or size " << size << " for block size " << block_size_; return false; } if (!IsFilePinned(file_fd_, file_path_, fs_type_)) { LOG(ERROR) << "Failed write: file " << file_path_ << " is not pinned"; return false; } // find extents that must be written to and then write one at a time. uint32_t num_extent = 1; uint32_t buffer_offset = 0; for (auto& extent : extents_) { uint64_t e_start = extent.fe_logical; uint64_t e_end = extent.fe_logical + extent.fe_length; // Do we write in this extent ? if (off >= e_start && off < e_end) { uint64_t written = WriteExtent(extent, buffer + buffer_offset, off, size); if (written == 0) { return false; } buffer_offset += written; off += written; size -= written; // Paranoid check to make sure we are done with this extent now if (size && (off >= e_start && off < e_end)) { LOG(ERROR) << "Failed to write extent fully"; LogExtent(num_extent, extent); return false; } if (size == 0) { // done break; } } num_extent++; } return true; } bool FiemapWriter::Read(off64_t off, uint8_t* buffer, uint64_t size) { return false; } // private helpers // WriteExtent() Returns the total number of bytes written. It will always be multiple of // block_size_. 0 is returned in one of the two cases. // 1. Any write failed between logical_off & logical_off + length. // 2. The logical_offset + length doesn't overlap with the extent passed. // The function can either partially for fully write the extent depending on the // logical_off + length. It is expected that alignment checks for size and offset are // performed before calling into this function. uint64_t FiemapWriter::WriteExtent(const struct fiemap_extent& ext, uint8_t* buffer, off64_t logical_off, uint64_t length) { uint64_t e_start = ext.fe_logical; uint64_t e_end = ext.fe_logical + ext.fe_length; if (logical_off < e_start || logical_off >= e_end) { LOG(ERROR) << "Failed write extent, invalid offset " << logical_off << " and size " << length; LogExtent(0, ext); return 0; } off64_t bdev_offset = ext.fe_physical + (logical_off - e_start); if (bdev_offset >= bdev_size_) { LOG(ERROR) << "Failed write extent, invalid block # " << bdev_offset << " for block device " << bdev_path_ << " of size " << bdev_size_ << " bytes"; return 0; } if (TEMP_FAILURE_RETRY(lseek64(bdev_fd_, bdev_offset, SEEK_SET)) == -1) { PLOG(ERROR) << "Failed write extent, seek offset for " << bdev_path_ << " offset " << bdev_offset; return 0; } // Determine how much we want to write at once. uint64_t logical_end = logical_off + length; uint64_t write_size = (e_end <= logical_end) ? (e_end - logical_off) : length; if (!android::base::WriteFully(bdev_fd_, buffer, write_size)) { PLOG(ERROR) << "Failed write extent, write " << bdev_path_ << " at " << bdev_offset << " size " << write_size; return 0; } return write_size; } } // namespace fiemap_writer } // namespace android fs_mgr/libfiemap_writer/fiemap_writer_test.cpp +19 −131 Original line number Diff line number Diff line Loading @@ -138,36 +138,31 @@ TEST_F(FiemapWriterTest, CheckFileExtents) { EXPECT_GT(fptr->extents().size(), 0); } TEST_F(FiemapWriterTest, CheckWriteError) { FiemapUniquePtr fptr = FiemapWriter::Open(testfile, testfile_size); ASSERT_NE(fptr, nullptr); // prepare buffer for writing the pattern - 0xa0 uint64_t blocksize = fptr->block_size(); auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksize), free); ASSERT_NE(buffer, nullptr); memset(buffer.get(), 0xa0, blocksize); uint8_t* p = static_cast<uint8_t*>(buffer.get()); for (off64_t off = 0; off < testfile_size; off += blocksize) { ASSERT_TRUE(fptr->Write(off, p, blocksize)); } EXPECT_TRUE(fptr->Flush()); } class TestExistingFile : public ::testing::Test { protected: void SetUp() override { std::string exec_dir = ::android::base::GetExecutableDirectory(); std::string unaligned_file = exec_dir + "/testdata/unaligned_file"; std::string file_4k = exec_dir + "/testdata/file_4k"; std::string file_32k = exec_dir + "/testdata/file_32k"; fptr_unaligned = FiemapWriter::Open(unaligned_file, 4097, false); fptr_4k = FiemapWriter::Open(file_4k, 4096, false); fptr_32k = FiemapWriter::Open(file_32k, 32768, false); unaligned_file_ = exec_dir + "/testdata/unaligned_file"; file_4k_ = exec_dir + "/testdata/file_4k"; file_32k_ = exec_dir + "/testdata/file_32k"; CleanupFiles(); fptr_unaligned = FiemapWriter::Open(unaligned_file_, 4097); fptr_4k = FiemapWriter::Open(file_4k_, 4096); fptr_32k = FiemapWriter::Open(file_32k_, 32768); } void TearDown() { CleanupFiles(); } void CleanupFiles() { unlink(unaligned_file_.c_str()); unlink(file_4k_.c_str()); unlink(file_32k_.c_str()); } std::string unaligned_file_; std::string file_4k_; std::string file_32k_; FiemapUniquePtr fptr_unaligned; FiemapUniquePtr fptr_4k; FiemapUniquePtr fptr_32k; Loading @@ -184,33 +179,6 @@ TEST_F(TestExistingFile, ErrorChecks) { EXPECT_GT(fptr_32k->extents().size(), 0); } TEST_F(TestExistingFile, CheckWriteError) { ASSERT_NE(fptr_4k, nullptr); // prepare buffer for writing the pattern - 0xa0 uint64_t blocksize = fptr_4k->block_size(); auto buff_4k = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksize), free); ASSERT_NE(buff_4k, nullptr); memset(buff_4k.get(), 0xa0, blocksize); uint8_t* p = static_cast<uint8_t*>(buff_4k.get()); for (off64_t off = 0; off < 4096; off += blocksize) { ASSERT_TRUE(fptr_4k->Write(off, p, blocksize)); } EXPECT_TRUE(fptr_4k->Flush()); ASSERT_NE(fptr_32k, nullptr); // prepare buffer for writing the pattern - 0xa0 blocksize = fptr_32k->block_size(); auto buff_32k = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksize), free); ASSERT_NE(buff_32k, nullptr); memset(buff_32k.get(), 0xa0, blocksize); p = static_cast<uint8_t*>(buff_32k.get()); for (off64_t off = 0; off < 4096; off += blocksize) { ASSERT_TRUE(fptr_32k->Write(off, p, blocksize)); } EXPECT_TRUE(fptr_32k->Flush()); } class VerifyBlockWritesExt4 : public ::testing::Test { // 2GB Filesystem and 4k block size by default static constexpr uint64_t block_size = 4096; Loading Loading @@ -253,46 +221,6 @@ class VerifyBlockWritesExt4 : public ::testing::Test { std::string fs_path; }; TEST_F(VerifyBlockWritesExt4, CheckWrites) { EXPECT_EQ(access(fs_path.c_str(), F_OK), 0); std::string file_path = mntpoint + "/testfile"; uint64_t file_size = 100 * 1024 * 1024; auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free); ASSERT_NE(buffer, nullptr); memset(buffer.get(), 0xa0, getpagesize()); { // scoped fiemap writer FiemapUniquePtr fptr = FiemapWriter::Open(file_path, file_size); ASSERT_NE(fptr, nullptr); uint8_t* p = static_cast<uint8_t*>(buffer.get()); for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) { ASSERT_TRUE(fptr->Write(off, p, getpagesize())); } EXPECT_TRUE(fptr->Flush()); } // unmount file system here to make sure we invalidated all page cache and // remount the filesystem again for verification ASSERT_EQ(umount(mntpoint.c_str()), 0); LoopDevice loop_dev(fs_path); ASSERT_TRUE(loop_dev.valid()); ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "ext4", 0, nullptr), 0) << "failed to mount: " << loop_dev.device() << " on " << mntpoint << ": " << strerror(errno); ::android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_SYNC)); ASSERT_NE(fd, -1); auto filebuf = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free); ASSERT_NE(filebuf, nullptr); for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) { memset(filebuf.get(), 0x00, getpagesize()); ASSERT_EQ(pread64(fd, filebuf.get(), getpagesize(), off), getpagesize()); ASSERT_EQ(memcmp(filebuf.get(), buffer.get(), getpagesize()), 0) << "Invalid pattern at offset: " << off << " size " << getpagesize(); } } class VerifyBlockWritesF2fs : public ::testing::Test { // 2GB Filesystem and 4k block size by default static constexpr uint64_t block_size = 4096; Loading Loading @@ -335,46 +263,6 @@ class VerifyBlockWritesF2fs : public ::testing::Test { std::string fs_path; }; TEST_F(VerifyBlockWritesF2fs, CheckWrites) { EXPECT_EQ(access(fs_path.c_str(), F_OK), 0); std::string file_path = mntpoint + "/testfile"; uint64_t file_size = 100 * 1024 * 1024; auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free); ASSERT_NE(buffer, nullptr); memset(buffer.get(), 0xa0, getpagesize()); { // scoped fiemap writer FiemapUniquePtr fptr = FiemapWriter::Open(file_path, file_size); ASSERT_NE(fptr, nullptr); uint8_t* p = static_cast<uint8_t*>(buffer.get()); for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) { ASSERT_TRUE(fptr->Write(off, p, getpagesize())); } EXPECT_TRUE(fptr->Flush()); } // unmount file system here to make sure we invalidated all page cache and // remount the filesystem again for verification ASSERT_EQ(umount(mntpoint.c_str()), 0); LoopDevice loop_dev(fs_path); ASSERT_TRUE(loop_dev.valid()); ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "f2fs", 0, nullptr), 0) << "failed to mount: " << loop_dev.device() << " on " << mntpoint << ": " << strerror(errno); ::android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_SYNC)); ASSERT_NE(fd, -1); auto filebuf = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free); ASSERT_NE(filebuf, nullptr); for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) { memset(filebuf.get(), 0x00, getpagesize()); ASSERT_EQ(pread64(fd, filebuf.get(), getpagesize(), off), getpagesize()); ASSERT_EQ(memcmp(filebuf.get(), buffer.get(), getpagesize()), 0) << "Invalid pattern at offset: " << off << " size " << getpagesize(); } } int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); if (argc <= 1) { Loading fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h +0 −13 Original line number Diff line number Diff line Loading @@ -57,15 +57,6 @@ class FiemapWriter final { // FiemapWriter::Open). static bool HasPinnedExtents(const std::string& file_path); // Syncs block device writes. bool Flush() const; // Writes the file by using its FIEMAP and performing i/o on the raw block device. // The return value is success / failure. This will happen in particular if the // kernel write returns errors, extents are not writeable or more importantly, if the 'size' is // not aligned to the block device's block size. bool Write(off64_t off, uint8_t* buffer, uint64_t size); // The counter part of Write(). It is an error for the offset to be unaligned with // the block device's block size. // In case of error, the contents of buffer MUST be discarded. Loading Loading @@ -93,7 +84,6 @@ class FiemapWriter final { // File descriptors for the file and block device ::android::base::unique_fd file_fd_; ::android::base::unique_fd bdev_fd_; // Size in bytes of the file this class is writing uint64_t file_size_; Loading @@ -112,9 +102,6 @@ class FiemapWriter final { std::vector<struct fiemap_extent> extents_; FiemapWriter() = default; uint64_t WriteExtent(const struct fiemap_extent& ext, uint8_t* buffer, off64_t logical_off, uint64_t length); }; } // namespace fiemap_writer Loading Loading
fs_mgr/libfiemap_writer/fiemap_writer.cpp +1 −121 Original line number Diff line number Diff line Loading @@ -374,14 +374,6 @@ bool FiemapWriter::HasPinnedExtents(const std::string& file_path) { return IsFilePinned(fd, file_path, sfs.f_type); } static void LogExtent(uint32_t num, const struct fiemap_extent& ext) { LOG(INFO) << "Extent #" << num; LOG(INFO) << " fe_logical: " << ext.fe_logical; LOG(INFO) << " fe_physical: " << ext.fe_physical; LOG(INFO) << " fe_length: " << ext.fe_length; LOG(INFO) << " fe_flags: 0x" << std::hex << ext.fe_flags; } static bool ReadFiemap(int file_fd, const std::string& file_path, std::vector<struct fiemap_extent>* extents) { uint64_t fiemap_size = Loading Loading @@ -473,7 +465,7 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s } ::android::base::unique_fd bdev_fd( TEMP_FAILURE_RETRY(open(bdev_path.c_str(), O_RDWR | O_CLOEXEC))); TEMP_FAILURE_RETRY(open(bdev_path.c_str(), O_RDONLY | O_CLOEXEC))); if (bdev_fd < 0) { PLOG(ERROR) << "Failed to open block device: " << bdev_path; cleanup(file_path, create); Loading Loading @@ -530,7 +522,6 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s fmap->file_path_ = abs_path; fmap->bdev_path_ = bdev_path; fmap->file_fd_ = std::move(file_fd); fmap->bdev_fd_ = std::move(bdev_fd); fmap->file_size_ = file_size; fmap->bdev_size_ = bdevsz; fmap->fs_type_ = fs_type; Loading @@ -541,120 +532,9 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s return fmap; } bool FiemapWriter::Flush() const { if (fsync(bdev_fd_)) { PLOG(ERROR) << "Failed to flush " << bdev_path_ << " with fsync"; return false; } return true; } // TODO: Test with fs block_size > bdev block_size bool FiemapWriter::Write(off64_t off, uint8_t* buffer, uint64_t size) { if (!size || size > file_size_) { LOG(ERROR) << "Failed write: size " << size << " is invalid for file's size " << file_size_; return false; } if (off + size > file_size_) { LOG(ERROR) << "Failed write: Invalid offset " << off << " or size " << size << " for file size " << file_size_; return false; } if ((off & (block_size_ - 1)) || (size & (block_size_ - 1))) { LOG(ERROR) << "Failed write: Unaligned offset " << off << " or size " << size << " for block size " << block_size_; return false; } if (!IsFilePinned(file_fd_, file_path_, fs_type_)) { LOG(ERROR) << "Failed write: file " << file_path_ << " is not pinned"; return false; } // find extents that must be written to and then write one at a time. uint32_t num_extent = 1; uint32_t buffer_offset = 0; for (auto& extent : extents_) { uint64_t e_start = extent.fe_logical; uint64_t e_end = extent.fe_logical + extent.fe_length; // Do we write in this extent ? if (off >= e_start && off < e_end) { uint64_t written = WriteExtent(extent, buffer + buffer_offset, off, size); if (written == 0) { return false; } buffer_offset += written; off += written; size -= written; // Paranoid check to make sure we are done with this extent now if (size && (off >= e_start && off < e_end)) { LOG(ERROR) << "Failed to write extent fully"; LogExtent(num_extent, extent); return false; } if (size == 0) { // done break; } } num_extent++; } return true; } bool FiemapWriter::Read(off64_t off, uint8_t* buffer, uint64_t size) { return false; } // private helpers // WriteExtent() Returns the total number of bytes written. It will always be multiple of // block_size_. 0 is returned in one of the two cases. // 1. Any write failed between logical_off & logical_off + length. // 2. The logical_offset + length doesn't overlap with the extent passed. // The function can either partially for fully write the extent depending on the // logical_off + length. It is expected that alignment checks for size and offset are // performed before calling into this function. uint64_t FiemapWriter::WriteExtent(const struct fiemap_extent& ext, uint8_t* buffer, off64_t logical_off, uint64_t length) { uint64_t e_start = ext.fe_logical; uint64_t e_end = ext.fe_logical + ext.fe_length; if (logical_off < e_start || logical_off >= e_end) { LOG(ERROR) << "Failed write extent, invalid offset " << logical_off << " and size " << length; LogExtent(0, ext); return 0; } off64_t bdev_offset = ext.fe_physical + (logical_off - e_start); if (bdev_offset >= bdev_size_) { LOG(ERROR) << "Failed write extent, invalid block # " << bdev_offset << " for block device " << bdev_path_ << " of size " << bdev_size_ << " bytes"; return 0; } if (TEMP_FAILURE_RETRY(lseek64(bdev_fd_, bdev_offset, SEEK_SET)) == -1) { PLOG(ERROR) << "Failed write extent, seek offset for " << bdev_path_ << " offset " << bdev_offset; return 0; } // Determine how much we want to write at once. uint64_t logical_end = logical_off + length; uint64_t write_size = (e_end <= logical_end) ? (e_end - logical_off) : length; if (!android::base::WriteFully(bdev_fd_, buffer, write_size)) { PLOG(ERROR) << "Failed write extent, write " << bdev_path_ << " at " << bdev_offset << " size " << write_size; return 0; } return write_size; } } // namespace fiemap_writer } // namespace android
fs_mgr/libfiemap_writer/fiemap_writer_test.cpp +19 −131 Original line number Diff line number Diff line Loading @@ -138,36 +138,31 @@ TEST_F(FiemapWriterTest, CheckFileExtents) { EXPECT_GT(fptr->extents().size(), 0); } TEST_F(FiemapWriterTest, CheckWriteError) { FiemapUniquePtr fptr = FiemapWriter::Open(testfile, testfile_size); ASSERT_NE(fptr, nullptr); // prepare buffer for writing the pattern - 0xa0 uint64_t blocksize = fptr->block_size(); auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksize), free); ASSERT_NE(buffer, nullptr); memset(buffer.get(), 0xa0, blocksize); uint8_t* p = static_cast<uint8_t*>(buffer.get()); for (off64_t off = 0; off < testfile_size; off += blocksize) { ASSERT_TRUE(fptr->Write(off, p, blocksize)); } EXPECT_TRUE(fptr->Flush()); } class TestExistingFile : public ::testing::Test { protected: void SetUp() override { std::string exec_dir = ::android::base::GetExecutableDirectory(); std::string unaligned_file = exec_dir + "/testdata/unaligned_file"; std::string file_4k = exec_dir + "/testdata/file_4k"; std::string file_32k = exec_dir + "/testdata/file_32k"; fptr_unaligned = FiemapWriter::Open(unaligned_file, 4097, false); fptr_4k = FiemapWriter::Open(file_4k, 4096, false); fptr_32k = FiemapWriter::Open(file_32k, 32768, false); unaligned_file_ = exec_dir + "/testdata/unaligned_file"; file_4k_ = exec_dir + "/testdata/file_4k"; file_32k_ = exec_dir + "/testdata/file_32k"; CleanupFiles(); fptr_unaligned = FiemapWriter::Open(unaligned_file_, 4097); fptr_4k = FiemapWriter::Open(file_4k_, 4096); fptr_32k = FiemapWriter::Open(file_32k_, 32768); } void TearDown() { CleanupFiles(); } void CleanupFiles() { unlink(unaligned_file_.c_str()); unlink(file_4k_.c_str()); unlink(file_32k_.c_str()); } std::string unaligned_file_; std::string file_4k_; std::string file_32k_; FiemapUniquePtr fptr_unaligned; FiemapUniquePtr fptr_4k; FiemapUniquePtr fptr_32k; Loading @@ -184,33 +179,6 @@ TEST_F(TestExistingFile, ErrorChecks) { EXPECT_GT(fptr_32k->extents().size(), 0); } TEST_F(TestExistingFile, CheckWriteError) { ASSERT_NE(fptr_4k, nullptr); // prepare buffer for writing the pattern - 0xa0 uint64_t blocksize = fptr_4k->block_size(); auto buff_4k = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksize), free); ASSERT_NE(buff_4k, nullptr); memset(buff_4k.get(), 0xa0, blocksize); uint8_t* p = static_cast<uint8_t*>(buff_4k.get()); for (off64_t off = 0; off < 4096; off += blocksize) { ASSERT_TRUE(fptr_4k->Write(off, p, blocksize)); } EXPECT_TRUE(fptr_4k->Flush()); ASSERT_NE(fptr_32k, nullptr); // prepare buffer for writing the pattern - 0xa0 blocksize = fptr_32k->block_size(); auto buff_32k = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksize), free); ASSERT_NE(buff_32k, nullptr); memset(buff_32k.get(), 0xa0, blocksize); p = static_cast<uint8_t*>(buff_32k.get()); for (off64_t off = 0; off < 4096; off += blocksize) { ASSERT_TRUE(fptr_32k->Write(off, p, blocksize)); } EXPECT_TRUE(fptr_32k->Flush()); } class VerifyBlockWritesExt4 : public ::testing::Test { // 2GB Filesystem and 4k block size by default static constexpr uint64_t block_size = 4096; Loading Loading @@ -253,46 +221,6 @@ class VerifyBlockWritesExt4 : public ::testing::Test { std::string fs_path; }; TEST_F(VerifyBlockWritesExt4, CheckWrites) { EXPECT_EQ(access(fs_path.c_str(), F_OK), 0); std::string file_path = mntpoint + "/testfile"; uint64_t file_size = 100 * 1024 * 1024; auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free); ASSERT_NE(buffer, nullptr); memset(buffer.get(), 0xa0, getpagesize()); { // scoped fiemap writer FiemapUniquePtr fptr = FiemapWriter::Open(file_path, file_size); ASSERT_NE(fptr, nullptr); uint8_t* p = static_cast<uint8_t*>(buffer.get()); for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) { ASSERT_TRUE(fptr->Write(off, p, getpagesize())); } EXPECT_TRUE(fptr->Flush()); } // unmount file system here to make sure we invalidated all page cache and // remount the filesystem again for verification ASSERT_EQ(umount(mntpoint.c_str()), 0); LoopDevice loop_dev(fs_path); ASSERT_TRUE(loop_dev.valid()); ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "ext4", 0, nullptr), 0) << "failed to mount: " << loop_dev.device() << " on " << mntpoint << ": " << strerror(errno); ::android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_SYNC)); ASSERT_NE(fd, -1); auto filebuf = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free); ASSERT_NE(filebuf, nullptr); for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) { memset(filebuf.get(), 0x00, getpagesize()); ASSERT_EQ(pread64(fd, filebuf.get(), getpagesize(), off), getpagesize()); ASSERT_EQ(memcmp(filebuf.get(), buffer.get(), getpagesize()), 0) << "Invalid pattern at offset: " << off << " size " << getpagesize(); } } class VerifyBlockWritesF2fs : public ::testing::Test { // 2GB Filesystem and 4k block size by default static constexpr uint64_t block_size = 4096; Loading Loading @@ -335,46 +263,6 @@ class VerifyBlockWritesF2fs : public ::testing::Test { std::string fs_path; }; TEST_F(VerifyBlockWritesF2fs, CheckWrites) { EXPECT_EQ(access(fs_path.c_str(), F_OK), 0); std::string file_path = mntpoint + "/testfile"; uint64_t file_size = 100 * 1024 * 1024; auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free); ASSERT_NE(buffer, nullptr); memset(buffer.get(), 0xa0, getpagesize()); { // scoped fiemap writer FiemapUniquePtr fptr = FiemapWriter::Open(file_path, file_size); ASSERT_NE(fptr, nullptr); uint8_t* p = static_cast<uint8_t*>(buffer.get()); for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) { ASSERT_TRUE(fptr->Write(off, p, getpagesize())); } EXPECT_TRUE(fptr->Flush()); } // unmount file system here to make sure we invalidated all page cache and // remount the filesystem again for verification ASSERT_EQ(umount(mntpoint.c_str()), 0); LoopDevice loop_dev(fs_path); ASSERT_TRUE(loop_dev.valid()); ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "f2fs", 0, nullptr), 0) << "failed to mount: " << loop_dev.device() << " on " << mntpoint << ": " << strerror(errno); ::android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_SYNC)); ASSERT_NE(fd, -1); auto filebuf = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free); ASSERT_NE(filebuf, nullptr); for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) { memset(filebuf.get(), 0x00, getpagesize()); ASSERT_EQ(pread64(fd, filebuf.get(), getpagesize(), off), getpagesize()); ASSERT_EQ(memcmp(filebuf.get(), buffer.get(), getpagesize()), 0) << "Invalid pattern at offset: " << off << " size " << getpagesize(); } } int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); if (argc <= 1) { Loading
fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h +0 −13 Original line number Diff line number Diff line Loading @@ -57,15 +57,6 @@ class FiemapWriter final { // FiemapWriter::Open). static bool HasPinnedExtents(const std::string& file_path); // Syncs block device writes. bool Flush() const; // Writes the file by using its FIEMAP and performing i/o on the raw block device. // The return value is success / failure. This will happen in particular if the // kernel write returns errors, extents are not writeable or more importantly, if the 'size' is // not aligned to the block device's block size. bool Write(off64_t off, uint8_t* buffer, uint64_t size); // The counter part of Write(). It is an error for the offset to be unaligned with // the block device's block size. // In case of error, the contents of buffer MUST be discarded. Loading Loading @@ -93,7 +84,6 @@ class FiemapWriter final { // File descriptors for the file and block device ::android::base::unique_fd file_fd_; ::android::base::unique_fd bdev_fd_; // Size in bytes of the file this class is writing uint64_t file_size_; Loading @@ -112,9 +102,6 @@ class FiemapWriter final { std::vector<struct fiemap_extent> extents_; FiemapWriter() = default; uint64_t WriteExtent(const struct fiemap_extent& ext, uint8_t* buffer, off64_t logical_off, uint64_t length); }; } // namespace fiemap_writer Loading