Skip to content

Commit

Permalink
common,msg,kv: Use Windows or portable function alternatives
Browse files Browse the repository at this point in the history
Some functions are unavailable on Windows. We'll add some platform
checks, using either portable functions, either the Windows specific
ones:

* utimes -> utime
* strerror_r -> strerror_s
* poll -> WSAPoll
* sendmsg -> WSASend
* switch to portable time format specifiers
* fcntl -> ioctlsocket, when setting up non-blocking sockets
* /dev/urandom -> BCryptGenRandom
* sysconf(_SC_PAGESIZE) -> GetSystemInfo()
* define compat_mkdir, handling the fact that mkdir doesn't accept
  the mode argument on Windows

Signed-off-by: Lucian Petrut <[email protected]>
  • Loading branch information
petrutlucian94 committed Jul 8, 2020
1 parent 8cd9278 commit 4ba0c2f
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ if(WITH_DPDK)
endif()

if(WIN32)
list(APPEND ceph_common_deps ws2_32 mswsock)
list(APPEND ceph_common_deps ws2_32 mswsock bcrypt)
list(APPEND ceph_common_deps dlfcn_win32)
endif()

Expand Down
20 changes: 19 additions & 1 deletion src/auth/Crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,26 @@ void CryptoRandom::get_bytes(char *buf, int len)
}
}

#else // !HAVE_GETENTROPY
#elif defined(_WIN32) // !HAVE_GETENTROPY

#include <bcrypt.h>

CryptoRandom::CryptoRandom() : fd(0) {}
CryptoRandom::~CryptoRandom() = default;

void CryptoRandom::get_bytes(char *buf, int len)
{
auto ret = BCryptGenRandom (
NULL,
(unsigned char*)buf,
len,
BCRYPT_USE_SYSTEM_PREFERRED_RNG);
if (ret != 0) {
throw std::system_error(ret, std::system_category());
}
}

#else // !HAVE_GETENTROPY && !_WIN32
// open /dev/urandom once on construction and reuse the fd for all reads
CryptoRandom::CryptoRandom()
: fd{open_urandom()}
Expand Down
3 changes: 2 additions & 1 deletion src/common/HeartbeatMap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*
*/

#include <utime.h>
#include <signal.h>

#include "HeartbeatMap.h"
Expand Down Expand Up @@ -173,7 +174,7 @@ void HeartbeatMap::check_touch_file()
if (path.length() && is_healthy()) {
int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_CLOEXEC, 0644);
if (fd >= 0) {
::utimes(path.c_str(), NULL);
::utime(path.c_str(), NULL);
::close(fd);
} else {
ldout(m_cct, 0) << "unable to touch " << path << ": "
Expand Down
5 changes: 4 additions & 1 deletion src/common/compat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,10 @@ int sched_setaffinity(pid_t pid, size_t cpusetsize,

char *ceph_strerror_r(int errnum, char *buf, size_t buflen)
{
#ifdef STRERROR_R_CHAR_P
#ifdef _WIN32
strerror_s(buf, buflen, errnum);
return buf;
#elif defined(STRERROR_R_CHAR_P)
return strerror_r(errnum, buf, buflen);
#else
if (strerror_r(errnum, buf, buflen)) {
Expand Down
14 changes: 14 additions & 0 deletions src/common/page.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#include <unistd.h>

#ifdef _WIN32
#include <windows.h>
#endif

namespace ceph {

// page size crap, see page.h
Expand All @@ -12,7 +16,17 @@ namespace ceph {
return n;
}

#ifdef _WIN32
unsigned _get_page_size() {
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
return system_info.dwPageSize;
}

unsigned _page_size = _get_page_size();
#else
unsigned _page_size = sysconf(_SC_PAGESIZE);
#endif
unsigned long _page_mask = ~(unsigned long)(_page_size - 1);
unsigned _page_shift = _get_bits_of(_page_size - 1);

Expand Down
6 changes: 6 additions & 0 deletions src/include/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,19 @@ int lchown(const char *path, uid_t owner, gid_t group);

#ifdef __cplusplus
}

// Windows' mkdir doesn't accept a mode argument.
#define compat_mkdir(pathname, mode) mkdir(pathname)

#endif

// O_CLOEXEC is not defined on Windows. Since handles aren't inherited
// with subprocesses unless explicitly requested, we'll define this
// flag as a no-op.
#define O_CLOEXEC 0

#define compat_mkdir(pathname, mode) mkdir(pathname, mode)

#endif /* WIN32 */

#endif /* !CEPH_COMPAT_H */
4 changes: 2 additions & 2 deletions src/include/utime.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,12 +485,12 @@ class utime_t {

if (out_date) {
char buf[32];
strftime(buf, sizeof(buf), "%F", &tm);
strftime(buf, sizeof(buf), "%Y-%m-%d", &tm);
*out_date = buf;
}
if (out_time) {
char buf[32];
strftime(buf, sizeof(buf), "%T", &tm);
strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
*out_time = buf;
}

Expand Down
2 changes: 1 addition & 1 deletion src/kv/MemDB.cc
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ int MemDB::_init(bool create)
int r;
dout(1) << __func__ << dendl;
if (create) {
r = ::mkdir(m_db_path.c_str(), 0700);
r = compat_mkdir(m_db_path.c_str(), 0700);
if (r < 0) {
r = -errno;
if (r != -EEXIST) {
Expand Down
2 changes: 1 addition & 1 deletion src/kv/RocksDBStore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ int RocksDBStore::create_db_dir()
unique_ptr<rocksdb::Directory> dir;
env->NewDirectory(path, &dir);
} else {
int r = ::mkdir(path.c_str(), 0755);
int r = compat_mkdir(path.c_str(), 0755);
if (r < 0)
r = -errno;
if (r < 0 && r != -EEXIST) {
Expand Down
45 changes: 45 additions & 0 deletions src/msg/async/PosixStack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class PosixConnectedSocketImpl final : public ConnectedSocketImpl {

// return the sent length
// < 0 means error occurred
#ifndef _WIN32
static ssize_t do_sendmsg(int fd, struct msghdr &msg, unsigned len, bool more)
{
size_t sent = 0;
Expand Down Expand Up @@ -150,6 +151,50 @@ class PosixConnectedSocketImpl final : public ConnectedSocketImpl {

return static_cast<ssize_t>(sent_bytes);
}
#else
ssize_t send(bufferlist &bl, bool more) override
{
size_t total_sent_bytes = 0;
auto pb = std::cbegin(bl.buffers());
uint64_t left_pbrs = bl.get_num_buffers();
while (left_pbrs) {
WSABUF msgvec[IOV_MAX];
uint64_t size = std::min<uint64_t>(left_pbrs, IOV_MAX);
left_pbrs -= size;
unsigned msglen = 0;
for (auto iov = msgvec; iov != msgvec + size; iov++) {
iov->buf = const_cast<char*>(pb->c_str());
iov->len = pb->length();
msglen += pb->length();
++pb;
}
DWORD sent_bytes = 0;
DWORD flags = 0;
if (more)
flags |= MSG_PARTIAL;

int ret_val = WSASend(_fd, msgvec, size, &sent_bytes, flags, NULL, NULL);
if (ret_val)
return -ret_val;

total_sent_bytes += sent_bytes;
if (static_cast<unsigned>(sent_bytes) < msglen)
break;
}

if (total_sent_bytes) {
bufferlist swapped;
if (total_sent_bytes < bl.length()) {
bl.splice(total_sent_bytes, bl.length()-total_sent_bytes, &swapped);
bl.swap(swapped);
} else {
bl.clear();
}
}

return static_cast<ssize_t>(total_sent_bytes);
}
#endif
void shutdown() override {
::shutdown(_fd, SHUT_RDWR);
}
Expand Down
9 changes: 9 additions & 0 deletions src/msg/async/net_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ int NetHandler::set_nonblock(int sd)
int flags;
int r = 0;

#ifdef _WIN32
ULONG mode = 1;
r = ioctlsocket(sd, FIONBIO, &mode);
if (r) {
lderr(cct) << __func__ << " ioctlsocket(FIONBIO) failed: " << r << dendl;
return -r;
}
#else
/* Set the socket nonblocking.
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
* interrupted by a signal. */
Expand All @@ -80,6 +88,7 @@ int NetHandler::set_nonblock(int sd)
lderr(cct) << __func__ << " fcntl(F_SETFL,O_NONBLOCK): " << cpp_strerror(r) << dendl;
return -r;
}
#endif

return 0;
}
Expand Down

0 comments on commit 4ba0c2f

Please sign in to comment.