forked from westerndigitalcorporation/zenfs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
util: Move utility functions for test infrastructure access
Signed-off-by: Andreas Hindborg <andreas.hindborg@wdc.com>
- Loading branch information
Showing
4 changed files
with
204 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.