| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <fcntl.h> |
| #include <limits.h> |
| #include <stdint.h> |
| |
| #include <utility> |
| |
| namespace { |
| |
| enum class FsTestType { |
| // The partition may appear as any generic block device |
| kNormal, |
| |
| // The partition should appear on top of a resizable |
| // FVM device |
| kFvm, |
| }; |
| |
| enum class FsTestState { |
| kInit, // Just created, waiting to be initialized. |
| kMinimal, // Initialized in a minimal state, i.e. ramdisk only. |
| kRunning, // Initialized and ready to start testing. |
| kComplete, // Indicates that the test has completed. |
| kError, // Indicates that an error has occurred. |
| }; |
| |
| struct BlobfsUsage { |
| uint64_t used_bytes; |
| uint64_t total_bytes; |
| uint64_t used_nodes; |
| uint64_t total_nodes; |
| }; |
| |
| class BlobfsTest { |
| public: |
| BlobfsTest(FsTestType type) : type_(type) {} |
| ~BlobfsTest(); |
| |
| // Creates a ramdisk, formats it, and mounts it at a mount point. |
| // |state| indicates the intended state once initialization is complete. |
| // This value must be either kMinimal or kRunning. |
| // If |state| is kMinimal, the mkfs and mount methods will be skipped. |
| bool Init(FsTestState state = FsTestState::kRunning); |
| |
| // Unmounts and remounts the blobfs partition. |
| bool Remount(); |
| |
| // Forcibly unmounts and remounts the blobfs partition, regardless of the current test state. |
| // If the partition is successfully remounted, the test is restored to a kRunning state. |
| // If |fsck_result| is not nullptr, fsck is run before remount and |fsck_result| is set to |
| // the result. |
| bool ForceRemount(zx_status_t* fsck_result = nullptr); |
| |
| // Unmounts a blobfs, runs fsck, and removes the backing ramdisk device. |
| // If the state_ is not kRunning, the umount and fsck methods will be skipped. |
| bool Teardown(); |
| |
| FsTestType GetType() const { |
| return type_; |
| } |
| |
| int GetFd() const { |
| return open(device_path_, O_RDWR); |
| } |
| |
| off_t GetDiskSize() const { |
| return blk_size_ * blk_count_; |
| } |
| |
| uint64_t GetBlockSize() const { |
| return blk_size_; |
| } |
| |
| uint64_t GetBlockCount() const { |
| return blk_count_; |
| } |
| |
| // Returns the full device path of blobfs. |
| bool GetDevicePath(char* path, size_t len) const; |
| |
| // Given a new disk size, updates the block count. Block size doesn't change. |
| bool SetBlockCount(uint64_t block_count) { |
| BEGIN_HELPER; |
| ASSERT_EQ(state_, FsTestState::kInit); |
| blk_count_ = block_count; |
| END_HELPER; |
| } |
| |
| // Sets readonly to |readonly|, defaulting to true. |
| void SetReadOnly(bool read_only) { |
| read_only_ = read_only; |
| } |
| |
| // Determine if the mounted filesystem should have output to stdio. |
| void SetStdio(bool stdio) { |
| stdio_ = stdio; |
| } |
| |
| // Reset to initial state, given that the test was successfully torn down. |
| bool Reset() { |
| BEGIN_HELPER; |
| ASSERT_EQ(state_, FsTestState::kComplete); |
| state_ = FsTestState::kInit; |
| END_HELPER; |
| } |
| |
| // Forcibly resets a running test by destroying and recreating the Blobfs partition. |
| bool ForceReset(); |
| |
| // Sleeps or wakes the ramdisk underlying the blobfs partition, depending on its current state. |
| bool ToggleSleep(uint64_t blk_count = 0); |
| |
| // Returns the current total transaction block count from the underlying ramdisk. |
| bool GetRamdiskCount(uint64_t* blk_count) const; |
| |
| // Checks info of mounted blobfs. |
| // |
| // Returns total and used byte and node counts in |usage| if it is supplied. |
| bool CheckInfo(BlobfsUsage* usage = nullptr); |
| |
| private: |
| // Mounts the blobfs partition. |
| bool Mount(); |
| |
| FsTestType type_; |
| FsTestState state_ = FsTestState::kInit; |
| uint64_t blk_size_ = 512; |
| uint64_t blk_count_ = 1 << 20; |
| ramdisk_client_t* ramdisk_ = nullptr; |
| char device_path_[PATH_MAX]; |
| char fvm_path_[PATH_MAX]; |
| bool read_only_ = false; |
| bool asleep_ = false; |
| bool stdio_ = true; |
| }; |
| |
| } // namespace |