-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
387 additions
and
0 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,24 @@ | ||
TARGETS = libublkdev.so ublkdev-s3 | ||
CPPFLAGS = -I. -I../../src | ||
CXXFLAGS = -std=c++11 -fPIC | ||
|
||
LIB_SRCS = ublkdev.cc | ||
LIB_OBJS = $(LIB_SRCS:%.cc=%.o) | ||
LIB_LD = g++ | ||
LIB_LDFLAGS = -shared | ||
|
||
S3_SRCS = s3.cc | ||
S3_OBJS = $(S3_SRCS:%.cc=%.o) | ||
S3_LD = g++ | ||
S3_LDFLAGS = -L. | ||
S3_LIBS = -lublkdev | ||
|
||
all: $(TARGETS) | ||
libublkdev.so: $(LIB_OBJS) | ||
$(LIB_LD) $(LIB_LDFLAGS) -o $@ $(LIB_OBJS) | ||
|
||
ublkdev-s3: $(S3_OBJS) | ||
$(S3_LD) $(S3_LDFLAGS) -o $@ $(S3_OBJS) $(S3_LIBS) | ||
|
||
%.o: %.c | ||
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $< |
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,43 @@ | ||
#include <ublkdev.hh> | ||
#include <aws/core/Aws.h> | ||
#include "s3.hh" | ||
|
||
UBDS3Volume::UBDS3Volume( | ||
std::string const &bucket_name, | ||
std::string const &devname, | ||
std::string const ®ion, | ||
uint32_t thread_count) : | ||
m_ubd(NULL), | ||
m_bucket_name(bucket_name), | ||
m_devname(devname), | ||
m_region(region), | ||
m_thread_count(thread_count), | ||
m_block_size(-1), | ||
m_encryption(Aws::S3::Model::ServerSideEncryption::NOT_SET), | ||
m_policy(Aws::S3::Model::ObjectCannedACL::private_), | ||
m_storage_class(Aws::S3::Model::StorageClass::STANDARD), | ||
m_suffix(), | ||
m_size(0ull), | ||
m_major(0), | ||
m_stop_requested(false) | ||
{ | ||
return; | ||
} | ||
|
||
UBDS3Volume::~UBDS3Volume() { | ||
delete m_ubd; | ||
return; | ||
} | ||
|
||
void UBDS3Volume::registerVolume() { | ||
uint64_t n_sectors = m_size / 512; | ||
|
||
m_ubd = new UserBlockDevice(); | ||
auto ui = m_ubd->registerEndpoint(m_devname.c_str(), n_sectors, false); | ||
m_major = ui.ubd_major; | ||
return; | ||
} | ||
|
||
void UBDS3Volume::readVolumeInfo() { | ||
|
||
} |
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,109 @@ | ||
#pragma once | ||
#include <stdint.h> | ||
#include <string> | ||
|
||
#include <aws/s3/S3Client.h> | ||
#include <aws/s3/model/ObjectCannedACL.h> | ||
#include <aws/s3/model/ServerSideEncryption.h> | ||
#include <aws/s3/model/StorageClass.h> | ||
|
||
class UBDS3Volume { | ||
public: | ||
UBDS3Volume( | ||
std::string const &bucket_name, | ||
std::string const &devname, | ||
std::string const ®ion, | ||
uint32_t thread_count); | ||
|
||
virtual ~UBDS3Volume(); | ||
|
||
virtual void registerVolume(); | ||
virtual void run(); | ||
virtual void readVolumeInfo(); | ||
virtual void createVolume( | ||
uint32_t blockSize, | ||
Aws::S3::Model::ServerSideEncryption encryption = | ||
Aws::S3::Model::ServerSideEncryption::NOT_SET, | ||
Aws::S3::Model::ObjectCannedACL policy = | ||
Aws::S3::Model::ObjectCannedACL::private_, | ||
Aws::S3::Model::StorageClass storage_class = | ||
Aws::S3::Model::StorageClass::STANDARD, | ||
std::string const &suffix = ""); | ||
virtual void read( | ||
uint64_t offset, | ||
void *buffer /* OUT */, | ||
uint32_t length); | ||
virtual void write( | ||
uint64_t offset, | ||
void const *buffer, | ||
uint32_t length); | ||
virtual void trim( | ||
uint64_t offset, | ||
uint32_t length); | ||
|
||
static std::string blockToPrefix(uint64_t block_index); | ||
|
||
protected: | ||
virtual void readBlock( | ||
uint64_t block_id, | ||
void *buffer); | ||
|
||
virtual void writeBlock( | ||
uint64_t block_id, | ||
void *buffer); | ||
|
||
virtual void trimBlock( | ||
uint64_t block_id); | ||
|
||
private: | ||
UserBlockDevice *m_ubd; | ||
std::string m_bucket_name; | ||
std::string m_devname; | ||
std::string m_region; | ||
uint32_t m_thread_count; | ||
uint32_t m_block_size; | ||
Aws::S3::Model::ServerSideEncryption m_encryption; | ||
Aws::S3::Model::ObjectCannedACL m_policy; | ||
Aws::S3::Model::StorageClass m_storage_class; | ||
std::string m_suffix; | ||
uint64_t m_size; | ||
uint32_t m_major; | ||
volatile bool m_stop_requested; | ||
}; | ||
|
||
class S3Pool; | ||
class S3PoolConnection; | ||
|
||
class S3Pool { | ||
public: | ||
S3Pool( | ||
std::string region, | ||
uint32_t size, | ||
std::string bucket_name); | ||
|
||
private: | ||
Aws::S3::S3Client *getConnection(); | ||
void returnConnection(Aws::S3::S3Client *client); | ||
|
||
Aws::Utils::Array<Aws::S3::S3Client *> m_connections; | ||
|
||
friend class S3PoolConnection; | ||
}; | ||
|
||
class S3PoolConnection { | ||
public: | ||
S3PoolConnection(S3Pool *pool) : | ||
m_pool(pool), | ||
m_client(pool->getConnection()) { } | ||
|
||
~S3PoolConnection() { | ||
m_pool->returnConnection(m_client); | ||
} | ||
|
||
Aws::S3::S3Client *operator ->() { return m_client; } | ||
|
||
private: | ||
S3Pool *m_pool; | ||
Aws::S3::S3Client *m_client; | ||
}; | ||
|
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,125 @@ | ||
#include <string> | ||
|
||
#include <sys/ioctl.h> | ||
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
#include <fcntl.h> | ||
|
||
#include <ublkdev.hh> | ||
|
||
using std::string; | ||
|
||
UserBlockDevice::UserBlockDevice( | ||
char const *control_endpoint) | ||
{ | ||
m_control = open(control_endpoint, O_RDWR | O_SYNC | O_NONBLOCK); | ||
|
||
if (m_control < 0) { | ||
string msg("Unable to open "); | ||
|
||
msg += control_endpoint; | ||
msg += ": "; | ||
msg += strerror(errno); | ||
|
||
throw UBDError(msg, errno); | ||
} | ||
|
||
m_poll.fd = m_control; | ||
m_poll.events = POLLIN; | ||
return; | ||
} | ||
|
||
UserBlockDevice::~UserBlockDevice() | ||
{ | ||
close(m_control); | ||
return; | ||
} | ||
|
||
struct ubd_info UserBlockDevice::registerEndpoint( | ||
const char *name, | ||
ssize_t n_sectors, | ||
bool read_only) | ||
{ | ||
struct ubd_info ui; | ||
strncpy(ui.ubd_name, name, UBD_DISK_NAME_LEN); | ||
ui.ubd_flags = (read_only ? UBD_FL_READ_ONLY : 0u); | ||
ui.ubd_major = 0u; | ||
ui.ubd_nsectors = n_sectors; | ||
|
||
if (ioctl(m_control, UBD_IOCREGISTER, &ui) != 0) { | ||
throw UBDError(errno); | ||
} | ||
|
||
return ui; | ||
} | ||
|
||
void UserBlockDevice::unregisterEndpoint( | ||
uint32_t major) | ||
{ | ||
if (ioctl(m_control, UBD_IOCUNREGISTER, major) != 0) { | ||
throw UBDError(errno); | ||
} | ||
|
||
return; | ||
} | ||
|
||
int UserBlockDevice::getCount() { | ||
int result = ioctl(m_control, UBD_IOCGETCOUNT); | ||
if (result < 0) { | ||
throw UBDError(errno); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
struct ubd_info UserBlockDevice::describe( | ||
uint32_t index) | ||
{ | ||
struct ubd_describe desc; | ||
desc.ubd_index = index; | ||
|
||
if (ioctl(m_control, UBD_IOCDESCRIBE, &desc) != 0) { | ||
throw UBDError(errno); | ||
} | ||
|
||
return desc.ubd_info; | ||
} | ||
|
||
void UserBlockDevice::tie( | ||
uint32_t major) | ||
{ | ||
if (ioctl(m_control, UBD_IOCTIE, major) != 0) { | ||
throw UBDError(errno); | ||
} | ||
|
||
return; | ||
} | ||
|
||
void UserBlockDevice::getRequest( | ||
struct ubd_message *result) | ||
{ | ||
if (ioctl(m_control, UBD_IOCGETREQUEST, result) != 0) { | ||
throw UBDError(errno); | ||
} | ||
|
||
return; | ||
} | ||
|
||
void UserBlockDevice::putReply( | ||
struct ubd_message const *reply) | ||
{ | ||
if (ioctl(m_control, UBD_IOCPUTREPLY, reply) != 0) { | ||
throw UBDError(errno); | ||
} | ||
|
||
return; | ||
} | ||
|
||
void UserBlockDevice::debug() | ||
{ | ||
if (ioctl(m_control, UBD_IOCDEBUG) != 0) { | ||
throw UBDError(errno); | ||
} | ||
|
||
return; | ||
} |
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,86 @@ | ||
#ifndef UBLKDEV_HH | ||
#define UBLKDEV_HH | ||
|
||
#include <cstring> | ||
#include <stdexcept> | ||
#include <string> | ||
|
||
#include <poll.h> | ||
#include <stdint.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
|
||
extern "C" { | ||
#include <ublkdev.h> | ||
} | ||
|
||
#ifndef UBD_IOC_MAGIC | ||
#error No UBD_IOC_MAGIC defined | ||
#endif | ||
|
||
class UBDError : public std::runtime_error { | ||
public: | ||
inline UBDError(std::string const &what_arg) : | ||
std::runtime_error(what_arg), m_error(0) { } | ||
|
||
inline UBDError(std::string const &what_arg, int error) : | ||
std::runtime_error(what_arg), m_error(error) { } | ||
|
||
inline UBDError(int error) : | ||
std::runtime_error(std::string(std::strerror(error))), | ||
m_error(error) { } | ||
|
||
#if __cplusplus >= 201103L /* C++11 */ | ||
inline UBDError(char const *what_arg) : | ||
std::runtime_error(what_arg), m_error(0) { } | ||
|
||
inline UBDError(char const *what_arg, int error) : | ||
std::runtime_error(what_arg), m_error(error) { } | ||
#endif /* C++11 */ | ||
|
||
inline int getError() { return m_error; } | ||
|
||
private: | ||
const int m_error; | ||
}; | ||
|
||
class UserBlockDevice { | ||
public: | ||
explicit UserBlockDevice( | ||
char const *control_endpoint="/dev/ubdctl"); | ||
|
||
virtual ~UserBlockDevice(); | ||
|
||
virtual struct ubd_info registerEndpoint( | ||
const char *name, | ||
ssize_t n_sectors, | ||
bool read_only); | ||
|
||
virtual void unregisterEndpoint( | ||
uint32_t major); | ||
|
||
virtual int getCount(); | ||
|
||
virtual struct ubd_info describe( | ||
uint32_t index); | ||
|
||
virtual void tie( | ||
uint32_t major); | ||
|
||
virtual void getRequest( | ||
struct ubd_message *result /* IN/OUT */); | ||
|
||
virtual void putReply( | ||
struct ubd_message const *reply /* IN */); | ||
|
||
virtual void debug(); | ||
|
||
private: | ||
UserBlockDevice(UserBlockDevice const &); | ||
UserBlockDevice operator = (UserBlockDevice const &); | ||
|
||
int m_control; | ||
struct pollfd m_poll; | ||
}; | ||
|
||
#endif /* UBLKDEV_HH */ |