core: add support for file classes

Intended to allow different file classes to implement their own
file operations; currently supporting regular and block device
files. This support would also be required for a native file
system, for example.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
This commit is contained in:
Raphael S. Carvalho
2014-10-14 14:14:24 -03:00
committed by Avi Kivity
parent a85baa4e8f
commit f3e429bc43
2 changed files with 77 additions and 40 deletions

View File

@@ -160,9 +160,9 @@ void reactor::process_io(size_t count)
}
future<size_t>
reactor::write_dma(file& f, uint64_t pos, const void* buffer, size_t len) {
return submit_io([&f, pos, buffer, len] (iocb& io) {
io_prep_pwrite(&io, f._fd, const_cast<void*>(buffer), len, pos);
posix_file_impl::write_dma(uint64_t pos, const void* buffer, size_t len) {
return engine.submit_io([this, pos, buffer, len] (iocb& io) {
io_prep_pwrite(&io, _fd, const_cast<void*>(buffer), len, pos);
}).then([] (io_event ev) {
throw_kernel_error(long(ev.res));
return make_ready_future<size_t>(size_t(ev.res));
@@ -170,9 +170,9 @@ reactor::write_dma(file& f, uint64_t pos, const void* buffer, size_t len) {
}
future<size_t>
reactor::write_dma(file& f, uint64_t pos, std::vector<iovec> iov) {
return submit_io([&f, pos, iov = std::move(iov)] (iocb& io) {
io_prep_pwritev(&io, f._fd, iov.data(), iov.size(), pos);
posix_file_impl::write_dma(uint64_t pos, std::vector<iovec> iov) {
return engine.submit_io([this, pos, iov = std::move(iov)] (iocb& io) {
io_prep_pwritev(&io, _fd, iov.data(), iov.size(), pos);
}).then([] (io_event ev) {
throw_kernel_error(long(ev.res));
return make_ready_future<size_t>(size_t(ev.res));
@@ -180,9 +180,9 @@ reactor::write_dma(file& f, uint64_t pos, std::vector<iovec> iov) {
}
future<size_t>
reactor::read_dma(file& f, uint64_t pos, void* buffer, size_t len) {
return submit_io([&f, pos, buffer, len] (iocb& io) {
io_prep_pread(&io, f._fd, buffer, len, pos);
posix_file_impl::read_dma(uint64_t pos, void* buffer, size_t len) {
return engine.submit_io([this, pos, buffer, len] (iocb& io) {
io_prep_pread(&io, _fd, buffer, len, pos);
}).then([] (io_event ev) {
throw_kernel_error(long(ev.res));
return make_ready_future<size_t>(size_t(ev.res));
@@ -190,9 +190,9 @@ reactor::read_dma(file& f, uint64_t pos, void* buffer, size_t len) {
}
future<size_t>
reactor::read_dma(file& f, uint64_t pos, std::vector<iovec> iov) {
return submit_io([&f, pos, iov = std::move(iov)] (iocb& io) {
io_prep_preadv(&io, f._fd, iov.data(), iov.size(), pos);
posix_file_impl::read_dma(uint64_t pos, std::vector<iovec> iov) {
return engine.submit_io([this, pos, iov = std::move(iov)] (iocb& io) {
io_prep_preadv(&io, _fd, iov.data(), iov.size(), pos);
}).then([] (io_event ev) {
throw_kernel_error(long(ev.res));
return make_ready_future<size_t>(size_t(ev.res));
@@ -210,9 +210,9 @@ reactor::open_file_dma(sstring name) {
}
future<>
reactor::flush(file& f) {
return _thread_pool.submit<syscall_result<int>>([&f] {
return wrap_syscall<int>(::fsync(f._fd));
posix_file_impl::flush(void) {
return engine._thread_pool.submit<syscall_result<int>>([this] {
return wrap_syscall<int>(::fsync(_fd));
}).then([] (syscall_result<int> sr) {
sr.throw_if_error();
return make_ready_future<>();
@@ -220,10 +220,10 @@ reactor::flush(file& f) {
}
future<struct stat>
reactor::stat(file& f) {
return _thread_pool.submit<struct stat>([&f] {
posix_file_impl::stat(void) {
return engine._thread_pool.submit<struct stat>([this] {
struct stat st;
auto ret = ::fstat(f._fd, &st);
auto ret = ::fstat(_fd, &st);
throw_system_error_on(ret == -1);
return (st);
});

View File

@@ -427,8 +427,9 @@ public:
future<size_t> write_all(pollable_fd_state& fd, const void* buffer, size_t size);
future<file> open_file_dma(sstring name);
future<> flush(file& f);
future<struct stat> stat(file& f);
template <typename Func>
future<io_event> submit_io(Func prepare_io);
int run();
void exit(int ret);
@@ -441,14 +442,6 @@ public:
private:
future<size_t> write_all_part(pollable_fd_state& fd, const void* buffer, size_t size, size_t completed);
future<size_t> read_dma(file& f, uint64_t pos, void* buffer, size_t len);
future<size_t> read_dma(file& f, uint64_t pos, std::vector<iovec> iov);
future<size_t> write_dma(file& f, uint64_t pos, const void* buffer, size_t len);
future<size_t> write_dma(file& f, uint64_t pos, std::vector<iovec> iov);
template <typename Func>
future<io_event> submit_io(Func prepare_io);
void process_io(size_t count);
void add_timer(timer* tmr);
@@ -580,41 +573,85 @@ public:
private:
};
class file {
int _fd;
private:
explicit file(int fd) : _fd(fd) {}
class file_impl {
public:
~file() {
virtual ~file_impl() {}
virtual future<size_t> write_dma(uint64_t pos, const void* buffer, size_t len) = 0;
virtual future<size_t> write_dma(uint64_t pos, std::vector<iovec> iov) = 0;
virtual future<size_t> read_dma(uint64_t pos, void* buffer, size_t len) = 0;
virtual future<size_t> read_dma(uint64_t pos, std::vector<iovec> iov) = 0;
virtual future<> flush(void) = 0;
virtual future<struct stat> stat(void) = 0;
friend class reactor;
};
class posix_file_impl : public file_impl {
public:
int _fd;
posix_file_impl(int fd) : _fd(fd) {}
~posix_file_impl() {
if (_fd != -1) {
::close(_fd);
}
}
file(file&& x) : _fd(x._fd) { x._fd = -1; }
future<size_t> write_dma(uint64_t pos, const void* buffer, size_t len);
future<size_t> write_dma(uint64_t pos, std::vector<iovec> iov);
future<size_t> read_dma(uint64_t pos, void* buffer, size_t len);
future<size_t> read_dma(uint64_t pos, std::vector<iovec> iov);
future<> flush(void);
future<struct stat> stat(void);
};
class blockdev_file_impl : public posix_file_impl {
public:
blockdev_file_impl(int fd) : posix_file_impl(fd) {}
};
inline
std::unique_ptr<file_impl>
make_file_impl(int fd) {
struct stat st;
::fstat(fd, &st);
if (S_ISBLK(st.st_mode)) {
return std::unique_ptr<file_impl>(new blockdev_file_impl(fd));
} else {
return std::unique_ptr<file_impl>(new posix_file_impl(fd));
}
}
class file {
std::unique_ptr<file_impl> _file_impl;
private:
explicit file(int fd) : _file_impl(make_file_impl(fd)) {}
public:
file(file&& x) : _file_impl(std::move(x._file_impl)) {}
template <typename CharType>
future<size_t> dma_read(uint64_t pos, CharType* buffer, size_t len) {
return engine.read_dma(*this, pos, buffer, len);
return _file_impl->read_dma(pos, buffer, len);
}
future<size_t> dma_read(uint64_t pos, std::vector<iovec> iov) {
return engine.read_dma(*this, pos, std::move(iov));
return _file_impl->read_dma(pos, std::move(iov));
}
template <typename CharType>
future<size_t> dma_write(uint64_t pos, const CharType* buffer, size_t len) {
return engine.write_dma(*this, pos, buffer, len);
return _file_impl->write_dma(pos, buffer, len);
}
future<size_t> dma_write(uint64_t pos, std::vector<iovec> iov) {
return engine.write_dma(*this, pos, std::move(iov));
return _file_impl->write_dma(pos, std::move(iov));
}
future<> flush() {
return engine.flush(*this);
return _file_impl->flush();
}
future<struct stat> stat() {
return engine.stat(*this);
return _file_impl->stat();
}
friend class reactor;