blob: 657b0f53b4fe8d87d79e992ef3d082f4f6a58f4f [file] [log] [blame]
// 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