Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / os / bluestore / BlockDevice.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5   *
6  * Copyright (C) 2015 XSky <haomai@xsky.com>
7  *
8  * Author: Haomai Wang <haomaiwang@gmail.com>
9  *
10  * This is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software
13  * Foundation.  See file COPYING.
14  *
15  */
16
17 #include <libgen.h>
18 #include <unistd.h>
19
20 #include "KernelDevice.h"
21 #if defined(HAVE_SPDK)
22 #include "NVMEDevice.h"
23 #endif
24
25 #if defined(HAVE_PMEM)
26 #include "PMEMDevice.h"
27 #include <libpmem.h>
28 #endif
29
30 #include "common/debug.h"
31 #include "common/EventTrace.h"
32 #include "common/errno.h"
33 #include "include/compat.h"
34
35 #define dout_context cct
36 #define dout_subsys ceph_subsys_bdev
37 #undef dout_prefix
38 #define dout_prefix *_dout << "bdev "
39
40 void IOContext::aio_wait()
41 {
42   std::unique_lock<std::mutex> l(lock);
43   // see _aio_thread for waker logic
44   while (num_running.load() > 0) {
45     dout(10) << __func__ << " " << this
46              << " waiting for " << num_running.load() << " aios to complete"
47              << dendl;
48     cond.wait(l);
49   }
50   dout(20) << __func__ << " " << this << " done" << dendl;
51 }
52
53 BlockDevice *BlockDevice::create(CephContext* cct, const string& path,
54                                  aio_callback_t cb, void *cbpriv)
55 {
56   string type = "kernel";
57   char buf[PATH_MAX + 1];
58   int r = ::readlink(path.c_str(), buf, sizeof(buf) - 1);
59   if (r >= 0) {
60     buf[r] = '\0';
61     char *bname = ::basename(buf);
62     if (strncmp(bname, SPDK_PREFIX, sizeof(SPDK_PREFIX)-1) == 0)
63       type = "ust-nvme";
64   }
65
66 #if defined(HAVE_PMEM)
67   if (type == "kernel") {
68     int is_pmem = 0;
69     void *addr = pmem_map_file(path.c_str(), 1024*1024, PMEM_FILE_EXCL, O_RDONLY, NULL, &is_pmem);
70     if (addr != NULL) {
71       if (is_pmem)
72         type = "pmem";
73       pmem_unmap(addr, 1024*1024);
74     }
75   }
76 #endif
77
78   dout(1) << __func__ << " path " << path << " type " << type << dendl;
79
80 #if defined(HAVE_PMEM)
81   if (type == "pmem") {
82     return new PMEMDevice(cct, cb, cbpriv);
83   }
84 #endif
85
86   if (type == "kernel") {
87     return new KernelDevice(cct, cb, cbpriv);
88   }
89 #if defined(HAVE_SPDK)
90   if (type == "ust-nvme") {
91     return new NVMEDevice(cct, cb, cbpriv);
92   }
93 #endif
94
95
96   derr << __func__ << " unknown backend " << type << dendl;
97   ceph_abort();
98   return NULL;
99 }
100
101 void BlockDevice::queue_reap_ioc(IOContext *ioc)
102 {
103   std::lock_guard<std::mutex> l(ioc_reap_lock);
104   if (ioc_reap_count.load() == 0)
105     ++ioc_reap_count;
106   ioc_reap_queue.push_back(ioc);
107 }
108
109 void BlockDevice::reap_ioc()
110 {
111   if (ioc_reap_count.load()) {
112     std::lock_guard<std::mutex> l(ioc_reap_lock);
113     for (auto p : ioc_reap_queue) {
114       dout(20) << __func__ << " reap ioc " << p << dendl;
115       delete p;
116     }
117     ioc_reap_queue.clear();
118     --ioc_reap_count;
119   }
120 }