]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common,msg,kv: Use Windows or portable function alternatives
authorLucian Petrut <lpetrut@cloudbasesolutions.com>
Fri, 11 Oct 2019 15:38:52 +0000 (18:38 +0300)
committerLucian Petrut <lpetrut@cloudbasesolutions.com>
Wed, 8 Jul 2020 06:38:39 +0000 (06:38 +0000)
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 <lpetrut@cloudbasesolutions.com>
src/CMakeLists.txt
src/auth/Crypto.cc
src/common/HeartbeatMap.cc
src/common/compat.cc
src/common/page.cc
src/include/compat.h
src/include/utime.h
src/kv/MemDB.cc
src/kv/RocksDBStore.cc
src/msg/async/PosixStack.cc
src/msg/async/net_handler.cc

index dfce966222f7313006cf38dc547e7d4083efd725..c3f7e4016f4448ccf48abeb9c5715cd63d484f4e 100644 (file)
@@ -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()
 
index 1827b5a7de857bc18d3d98f8ae11e7516839de53..2dda80e2b04b54f58e80ab9bfe6d4586ec3a5fd2 100644 (file)
@@ -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()}
index 7e5b8140632756ea2bd344dc125ce21578a13ee2..aef9677d9fac3530110a994e68976dd69b735003 100644 (file)
@@ -12,6 +12,7 @@
  * 
  */
 
+#include <utime.h>
 #include <signal.h>
 
 #include "HeartbeatMap.h"
@@ -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 << ": "
index 23fe2fa0e9def0c72926d78f982248ca4891d7ad..a8d57bd7758f53bf1f14096ad97f51d0f56213bd 100644 (file)
@@ -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)) {
index 7a252a60ba17bd66e4939cce9478d18177d5306b..e3dc34a43c136dc6a72bdc2ee90d6e0d40349373 100644 (file)
@@ -1,5 +1,9 @@
 #include <unistd.h>
 
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
 namespace ceph {
 
   // page size crap, see page.h
@@ -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);
 
index 334d60eeace7933a99f68c45325f41b82b1c127a..8a855c188110cff8c4d2ba5a961bc8363054d49a 100644 (file)
@@ -280,6 +280,10 @@ 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
@@ -287,6 +291,8 @@ int lchown(const char *path, uid_t owner, gid_t group);
 // flag as a no-op.
 #define O_CLOEXEC 0
 
+#define compat_mkdir(pathname, mode) mkdir(pathname, mode)
+
 #endif /* WIN32 */
 
 #endif /* !CEPH_COMPAT_H */
index ab053433e2a039438f151082ecdc59e19e738bc1..512149db03e3aa1be9451b7928a73a9bf528df53 100644 (file)
@@ -485,12 +485,12 @@ public:
 
     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;
     }
 
index 1f5740a34a592e5dada24eedf6c8e8577b04528b..1618b2551acc62e15ee560e3fbf12f63f343b928 100644 (file)
@@ -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) {
index 030ca7fed8ab995e8eaa4719650393419d2aa79a..f4956b649fb08dadc0e45f96a3604bc0205e373b 100644 (file)
@@ -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) {
index a7a7fc41dd0f6a152a20d827e2a7daea0ef5c8af..be6c617383b97b020c702ba63e632d77ef5c3766 100644 (file)
@@ -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;
@@ -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);
   }
index 2b4e646d559a44b7591c685899854d43561a94f8..1f99979eec42a1357cf25c8e88a70f823a8e7216 100644 (file)
@@ -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. */
@@ -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;
 }