Skip to content

Commit

Permalink
util: Move utility functions for test infrastructure access
Browse files Browse the repository at this point in the history
Signed-off-by: Andreas Hindborg <andreas.hindborg@wdc.com>
  • Loading branch information
metaspace committed Jun 9, 2022
1 parent a0ced69 commit 6d62965
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 140 deletions.
153 changes: 153 additions & 0 deletions fs/util.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@

#include "util.h"

#include <dirent.h>
#include <libzbd/zbd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstdint>
#include <filesystem>
#include <memory>
#include <system_error>

#include "fs_zenfs.h"

namespace ROCKSDB_NAMESPACE {

std::unique_ptr<ZonedBlockDevice> zbd_open(std::string const &zbd_path,
bool readonly, bool exclusive) {
std::unique_ptr<ZonedBlockDevice> zbd{
new ZonedBlockDevice(zbd_path, nullptr)};
IOStatus open_status = zbd->Open(readonly, exclusive);

if (!open_status.ok()) {
fprintf(stderr, "Failed to open zoned block device: %s, error: %s\n",
zbd_path.c_str(), open_status.ToString().c_str());
zbd.reset();
}

return zbd;
}

// Here we pass 'zbd' by non-const reference to be able to pass its ownership
// to 'zenFS'
Status zenfs_mount(std::unique_ptr<ZonedBlockDevice> &zbd,
std::unique_ptr<ZenFS> *zenFS, bool readonly) {
Status s;

std::unique_ptr<ZenFS> localZenFS{
new ZenFS(zbd.release(), FileSystem::Default(), nullptr)};
s = localZenFS->Mount(readonly);
if (!s.ok()) {
localZenFS.reset();
}
*zenFS = std::move(localZenFS);

return s;
}

static int is_dir(const char *path) {
struct stat st;
if (stat(path, &st) != 0) {
fprintf(stderr, "Failed to stat %s\n", path);
return 1;
}
return S_ISDIR(st.st_mode);
}

// Create or check pre-existing aux directory and fail if it is
// inaccessible by current user and if it has previous data
static int create_aux_dir(const char *path) {
struct dirent *dent;
size_t nfiles = 0;
int ret = 0;

errno = 0;
ret = mkdir(path, 0750);
if (ret < 0 && EEXIST != errno) {
fprintf(stderr, "Failed to create aux directory %s: %s\n", path,
strerror(errno));
return 1;
}
// The aux_path is now available, check if it is a directory infact
// and is empty and the user has access permission

if (!is_dir(path)) {
fprintf(stderr, "Aux path %s is not a directory\n", path);
return 1;
}

errno = 0;

auto closedirDeleter = [](DIR *d) {
if (d != nullptr) closedir(d);
};
std::unique_ptr<DIR, decltype(closedirDeleter)> aux_dir{
opendir(path), std::move(closedirDeleter)};
if (errno) {
fprintf(stderr, "Failed to open aux directory %s: %s\n", path,
strerror(errno));
return 1;
}

// Consider the directory as non-empty if any files/dir other
// than . and .. are found.
while ((dent = readdir(aux_dir.get())) != NULL && nfiles <= 2) ++nfiles;
if (nfiles > 2) {
fprintf(stderr, "Aux directory %s is not empty.\n", path);
return 1;
}

if (access(path, R_OK | W_OK | X_OK) < 0) {
fprintf(stderr,
"User does not have access permissions on "
"aux directory %s\n",
path);
return 1;
}

return 0;
}

int zenfs_mkfs(std::string const &zbd_path, std::string const &aux_path,
int finish_threshold, bool force) {
Status s;

if (create_aux_dir(aux_path.c_str())) return 1;

std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(zbd_path, false, true);
if (!zbd) return 1;

std::unique_ptr<ZenFS> zenFS;
s = zenfs_mount(zbd, &zenFS, false);
if ((s.ok() || !s.IsNotFound()) && !force) {
fprintf(
stderr,
"Existing filesystem found, use --force if you want to replace it.\n");
return 1;
}

zenFS.reset();

zbd = zbd_open(zbd_path, false, true);
ZonedBlockDevice *zbdRaw = zbd.get();
zenFS.reset(new ZenFS(zbd.release(), FileSystem::Default(), nullptr));

std::string aux_path_patched = aux_path;
if (aux_path_patched.back() != '/') aux_path_patched.append("/");

s = zenFS->MkFS(aux_path_patched, finish_threshold);
if (!s.ok()) {
fprintf(stderr, "Failed to create file system, error: %s\n",
s.ToString().c_str());
return 1;
}

fprintf(stdout, "ZenFS file system created. Free space: %lu MB\n",
zbdRaw->GetFreeSpace() / (1024 * 1024));

return 0;
}
} // namespace ROCKSDB_NAMESPACE
19 changes: 19 additions & 0 deletions fs/util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <cstdint>
#include <filesystem>

#include "fs_zenfs.h"
#include "rocksdb/status.h"

namespace ROCKSDB_NAMESPACE {

std::unique_ptr<ZonedBlockDevice> zbd_open(std::string const& zbd_path,
bool readonly, bool exclusive);

Status zenfs_mount(std::unique_ptr<ZonedBlockDevice>& zbd,
std::unique_ptr<ZenFS>* zenFS, bool readonly);

int zenfs_mkfs(std::string const& zbd_path, std::string const& aux_path,
int finish_threshold, bool force);
} // namespace ROCKSDB_NAMESPACE
Loading

0 comments on commit 6d62965

Please sign in to comment.