diff --git a/core/reactor.cc b/core/reactor.cc index d662eaeb29..1bec4c9335 100644 --- a/core/reactor.cc +++ b/core/reactor.cc @@ -160,9 +160,9 @@ void reactor::process_io(size_t count) } future -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(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(buffer), len, pos); }).then([] (io_event ev) { throw_kernel_error(long(ev.res)); return make_ready_future(size_t(ev.res)); @@ -170,9 +170,9 @@ reactor::write_dma(file& f, uint64_t pos, const void* buffer, size_t len) { } future -reactor::write_dma(file& f, uint64_t pos, std::vector 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 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(ev.res)); @@ -180,9 +180,9 @@ reactor::write_dma(file& f, uint64_t pos, std::vector iov) { } future -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(ev.res)); @@ -190,9 +190,9 @@ reactor::read_dma(file& f, uint64_t pos, void* buffer, size_t len) { } future -reactor::read_dma(file& f, uint64_t pos, std::vector 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 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(ev.res)); @@ -210,9 +210,9 @@ reactor::open_file_dma(sstring name) { } future<> -reactor::flush(file& f) { - return _thread_pool.submit>([&f] { - return wrap_syscall(::fsync(f._fd)); +posix_file_impl::flush(void) { + return engine._thread_pool.submit>([this] { + return wrap_syscall(::fsync(_fd)); }).then([] (syscall_result sr) { sr.throw_if_error(); return make_ready_future<>(); @@ -220,10 +220,10 @@ reactor::flush(file& f) { } future -reactor::stat(file& f) { - return _thread_pool.submit([&f] { +posix_file_impl::stat(void) { + return engine._thread_pool.submit([this] { struct stat st; - auto ret = ::fstat(f._fd, &st); + auto ret = ::fstat(_fd, &st); throw_system_error_on(ret == -1); return (st); }); diff --git a/core/reactor.hh b/core/reactor.hh index b3b8142b44..2da3b9a857 100644 --- a/core/reactor.hh +++ b/core/reactor.hh @@ -427,8 +427,9 @@ public: future write_all(pollable_fd_state& fd, const void* buffer, size_t size); future open_file_dma(sstring name); - future<> flush(file& f); - future stat(file& f); + + template + future submit_io(Func prepare_io); int run(); void exit(int ret); @@ -441,14 +442,6 @@ public: private: future write_all_part(pollable_fd_state& fd, const void* buffer, size_t size, size_t completed); - future read_dma(file& f, uint64_t pos, void* buffer, size_t len); - future read_dma(file& f, uint64_t pos, std::vector iov); - future write_dma(file& f, uint64_t pos, const void* buffer, size_t len); - future write_dma(file& f, uint64_t pos, std::vector iov); - - template - future 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 write_dma(uint64_t pos, const void* buffer, size_t len) = 0; + virtual future write_dma(uint64_t pos, std::vector iov) = 0; + virtual future read_dma(uint64_t pos, void* buffer, size_t len) = 0; + virtual future read_dma(uint64_t pos, std::vector iov) = 0; + virtual future<> flush(void) = 0; + virtual future 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 write_dma(uint64_t pos, const void* buffer, size_t len); + future write_dma(uint64_t pos, std::vector iov); + future read_dma(uint64_t pos, void* buffer, size_t len); + future read_dma(uint64_t pos, std::vector iov); + future<> flush(void); + future stat(void); +}; + +class blockdev_file_impl : public posix_file_impl { +public: + blockdev_file_impl(int fd) : posix_file_impl(fd) {} +}; + +inline +std::unique_ptr +make_file_impl(int fd) { + struct stat st; + ::fstat(fd, &st); + if (S_ISBLK(st.st_mode)) { + return std::unique_ptr(new blockdev_file_impl(fd)); + } else { + return std::unique_ptr(new posix_file_impl(fd)); + } +} + +class file { + std::unique_ptr _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 future 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 dma_read(uint64_t pos, std::vector iov) { - return engine.read_dma(*this, pos, std::move(iov)); + return _file_impl->read_dma(pos, std::move(iov)); } template future 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 dma_write(uint64_t pos, std::vector 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 stat() { - return engine.stat(*this); + return _file_impl->stat(); } friend class reactor;