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 <[email protected]>
  • Loading branch information
metaspace committed Mar 30, 2022
1 parent ca8b1b1 commit 4633176
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 136 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
146 changes: 12 additions & 134 deletions util/zenfs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@

#ifdef WITH_TERARKDB
#include <fs/fs_zenfs.h>
#include <fs/util.h>
#include <fs/version.h>
#else
#include <rocksdb/plugin/zenfs/fs/fs_zenfs.h>
#include <rocksdb/plugin/zenfs/fs/util.h>
#include <rocksdb/plugin/zenfs/fs/version.h>
#endif

Expand Down Expand Up @@ -53,100 +55,6 @@ void AddDirSeparatorAtEnd(std::string &path) {
if (path.back() != '/') path = path + "/";
}

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

if (!open_status.ok()) {
fprintf(stderr, "Failed to open zoned block device: %s, error: %s\n",
FLAGS_zbd.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;
}

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
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_tool_mkfs() {
Status s;

Expand All @@ -155,39 +63,9 @@ int zenfs_tool_mkfs() {
return 1;
}

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

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

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

zenFS.reset();

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

if (FLAGS_aux_path.back() != '/') FLAGS_aux_path.append("/");

s = zenFS->MkFS(FLAGS_aux_path, FLAGS_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;
return zenfs_mkfs(std::filesystem::path(FLAGS_zbd),
std::filesystem::path(FLAGS_aux_path),
FLAGS_finish_threshold, FLAGS_force);
}

void list_children(const std::unique_ptr<ZenFS> &zenFS,
Expand Down Expand Up @@ -231,7 +109,7 @@ void list_children(const std::unique_ptr<ZenFS> &zenFS,

int zenfs_tool_list() {
Status s;
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(true, false);
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(FLAGS_zbd, true, false);
if (!zbd) return 1;

std::unique_ptr<ZenFS> zenFS;
Expand All @@ -249,7 +127,7 @@ int zenfs_tool_list() {

int zenfs_tool_df() {
Status s;
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(true, false);
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(FLAGS_zbd, true, false);
if (!zbd) return 1;
ZonedBlockDevice *zbdRaw = zbd.get();

Expand Down Expand Up @@ -469,14 +347,14 @@ int zenfs_tool_backup() {
IOStatus io_status;
IOOptions opts;
IODebugContext dbg;
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(true, true);
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(FLAGS_zbd, true, true);

if (!zbd) {
if (FLAGS_force) {
fprintf(stderr,
"WARNING: attempting to back up a zoned block device in use! "
"Expect data loss and corruption.\n");
zbd = zbd_open(true, false);
zbd = zbd_open(FLAGS_zbd, true, false);
}
}

Expand Down Expand Up @@ -680,7 +558,7 @@ int zenfs_tool_restore() {
AddDirSeparatorAtEnd(FLAGS_path);
ReadWriteLifeTimeHints();

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

std::unique_ptr<ZenFS> zenFS;
Expand Down Expand Up @@ -710,7 +588,7 @@ int zenfs_tool_restore() {

int zenfs_tool_dump() {
Status s;
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(true, false);
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(FLAGS_zbd, true, false);
if (!zbd) return 1;
ZonedBlockDevice *zbdRaw = zbd.get();

Expand All @@ -734,7 +612,7 @@ int zenfs_tool_dump() {

int zenfs_tool_fsinfo() {
Status s;
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(true, false);
std::unique_ptr<ZonedBlockDevice> zbd = zbd_open(FLAGS_zbd, true, false);
if (!zbd) return 1;

std::unique_ptr<ZenFS> zenFS;
Expand Down
Loading

0 comments on commit 4633176

Please sign in to comment.