]> git.proxmox.com Git - ceph.git/blame - ceph/src/blk/BlockDevice.cc
import ceph quincy 17.2.1
[ceph.git] / ceph / src / blk / BlockDevice.cc
CommitLineData
7c673cae
FG
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
11fdf7f2
TL
20#include "BlockDevice.h"
21
22#if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
f67539c2 23#include "kernel/KernelDevice.h"
11fdf7f2
TL
24#endif
25
7c673cae 26#if defined(HAVE_SPDK)
f67539c2 27#include "spdk/NVMEDevice.h"
7c673cae
FG
28#endif
29
9f95a23c 30#if defined(HAVE_BLUESTORE_PMEM)
f67539c2
TL
31#include "pmem/PMEMDevice.h"
32#endif
33
34#if defined(HAVE_LIBZBD)
35#include "zoned/HMSMRDevice.h"
31f18b77
FG
36#endif
37
7c673cae
FG
38#include "common/debug.h"
39#include "common/EventTrace.h"
31f18b77
FG
40#include "common/errno.h"
41#include "include/compat.h"
7c673cae
FG
42
43#define dout_context cct
44#define dout_subsys ceph_subsys_bdev
45#undef dout_prefix
46#define dout_prefix *_dout << "bdev "
47
f67539c2
TL
48using std::string;
49
20effc67
TL
50
51blk_access_mode_t buffermode(bool buffered)
52{
53 return buffered ? blk_access_mode_t::BUFFERED : blk_access_mode_t::DIRECT;
54}
55
56std::ostream& operator<<(std::ostream& os, const blk_access_mode_t buffered)
57{
58 os << (buffered == blk_access_mode_t::BUFFERED ? "(buffered)" : "(direct)");
59 return os;
60}
61
62
63
7c673cae
FG
64void IOContext::aio_wait()
65{
11fdf7f2 66 std::unique_lock l(lock);
7c673cae
FG
67 // see _aio_thread for waker logic
68 while (num_running.load() > 0) {
69 dout(10) << __func__ << " " << this
70 << " waiting for " << num_running.load() << " aios to complete"
71 << dendl;
72 cond.wait(l);
73 }
74 dout(20) << __func__ << " " << this << " done" << dendl;
75}
76
11fdf7f2
TL
77uint64_t IOContext::get_num_ios() const
78{
79 // this is about the simplest model for transaction cost you can
80 // imagine. there is some fixed overhead cost by saying there is a
81 // minimum of one "io". and then we have some cost per "io" that is
82 // a configurable (with different hdd and ssd defaults), and add
83 // that to the bytes value.
84 uint64_t ios = 0;
85#if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
f6b5b4d7 86 ios += pending_aios.size();
11fdf7f2
TL
87#endif
88#ifdef HAVE_SPDK
89 ios += total_nseg;
90#endif
91 return ios;
92}
93
94void IOContext::release_running_aios()
95{
96 ceph_assert(!num_running);
97#if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
98 // release aio contexts (including pinned buffers).
99 running_aios.clear();
100#endif
101}
102
f67539c2
TL
103BlockDevice::block_device_t
104BlockDevice::detect_device_type(const std::string& path)
7c673cae 105{
f67539c2
TL
106#if defined(HAVE_SPDK)
107 if (NVMEDevice::support(path)) {
108 return block_device_t::spdk;
7c673cae 109 }
f67539c2 110#endif
9f95a23c 111#if defined(HAVE_BLUESTORE_PMEM)
f67539c2
TL
112 if (PMEMDevice::support(path)) {
113 return block_device_t::pmem;
114 }
115#endif
116#if (defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)) && defined(HAVE_LIBZBD)
117 if (HMSMRDevice::support(path)) {
118 return block_device_t::hm_smr;
31f18b77
FG
119 }
120#endif
20effc67 121#if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
f67539c2 122 return block_device_t::aio;
20effc67
TL
123#else
124 return block_device_t::unknown;
125#endif
f67539c2 126}
7c673cae 127
f67539c2
TL
128BlockDevice::block_device_t
129BlockDevice::device_type_from_name(const std::string& blk_dev_name)
130{
131#if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
132 if (blk_dev_name == "aio") {
133 return block_device_t::aio;
134 }
135#endif
136#if defined(HAVE_SPDK)
137 if (blk_dev_name == "spdk") {
138 return block_device_t::spdk;
139 }
140#endif
9f95a23c 141#if defined(HAVE_BLUESTORE_PMEM)
f67539c2
TL
142 if (blk_dev_name == "pmem") {
143 return block_device_t::pmem;
31f18b77
FG
144 }
145#endif
f67539c2
TL
146#if (defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)) && defined(HAVE_LIBZBD)
147 if (blk_dev_name == "hm_smr") {
148 return block_device_t::hm_smr;
149 }
150#endif
151 return block_device_t::unknown;
152}
153
154BlockDevice* BlockDevice::create_with_type(block_device_t device_type,
155 CephContext* cct, const std::string& path, aio_callback_t cb,
156 void *cbpriv, aio_callback_t d_cb, void *d_cbpriv)
157{
158
159 switch (device_type) {
11fdf7f2 160#if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
f67539c2 161 case block_device_t::aio:
11fdf7f2 162 return new KernelDevice(cct, cb, cbpriv, d_cb, d_cbpriv);
11fdf7f2 163#endif
7c673cae 164#if defined(HAVE_SPDK)
f67539c2 165 case block_device_t::spdk:
7c673cae 166 return new NVMEDevice(cct, cb, cbpriv);
7c673cae 167#endif
f67539c2
TL
168#if defined(HAVE_BLUESTORE_PMEM)
169 case block_device_t::pmem:
170 return new PMEMDevice(cct, cb, cbpriv);
171#endif
172#if (defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)) && defined(HAVE_LIBZBD)
173 case block_device_t::hm_smr:
174 return new HMSMRDevice(cct, cb, cbpriv, d_cb, d_cbpriv);
9f95a23c 175#endif
f67539c2
TL
176 default:
177 ceph_abort_msg("unsupported device");
178 return nullptr;
179 }
180}
31f18b77 181
f67539c2
TL
182BlockDevice *BlockDevice::create(
183 CephContext* cct, const string& path, aio_callback_t cb,
184 void *cbpriv, aio_callback_t d_cb, void *d_cbpriv)
185{
186 const string blk_dev_name = cct->_conf.get_val<string>("bdev_type");
187 block_device_t device_type = block_device_t::unknown;
188 if (blk_dev_name.empty()) {
189 device_type = detect_device_type(path);
190 } else {
191 device_type = device_type_from_name(blk_dev_name);
192 }
193 return create_with_type(device_type, cct, path, cb, cbpriv, d_cb, d_cbpriv);
7c673cae
FG
194}
195
f67539c2
TL
196bool BlockDevice::is_valid_io(uint64_t off, uint64_t len) const {
197 bool ret = (off % block_size == 0 &&
198 len % block_size == 0 &&
199 len > 0 &&
200 off < size &&
201 off + len <= size);
202
203 if (!ret) {
204 derr << __func__ << " " << std::hex
205 << off << "~" << len
206 << " block_size " << block_size
207 << " size " << size
208 << std::dec << dendl;
209 }
210 return ret;
211}