1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2015 XSky <haomai@xsky.com>
8 * Author: Haomai Wang <haomaiwang@gmail.com>
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.
20 #include "BlockDevice.h"
22 #if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
23 #include "kernel/KernelDevice.h"
26 #if defined(HAVE_SPDK)
27 #include "spdk/NVMEDevice.h"
30 #if defined(HAVE_BLUESTORE_PMEM)
31 #include "pmem/PMEMDevice.h"
34 #if defined(HAVE_LIBZBD)
35 #include "zoned/HMSMRDevice.h"
38 #include "common/debug.h"
39 #include "common/EventTrace.h"
40 #include "common/errno.h"
41 #include "include/compat.h"
43 #define dout_context cct
44 #define dout_subsys ceph_subsys_bdev
46 #define dout_prefix *_dout << "bdev "
51 blk_access_mode_t
buffermode(bool buffered
)
53 return buffered
? blk_access_mode_t::BUFFERED
: blk_access_mode_t::DIRECT
;
56 std::ostream
& operator<<(std::ostream
& os
, const blk_access_mode_t buffered
)
58 os
<< (buffered
== blk_access_mode_t::BUFFERED
? "(buffered)" : "(direct)");
64 void IOContext::aio_wait()
66 std::unique_lock
l(lock
);
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"
74 dout(20) << __func__
<< " " << this << " done" << dendl
;
77 uint64_t IOContext::get_num_ios() const
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.
85 #if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
86 ios
+= pending_aios
.size();
94 void IOContext::release_running_aios()
96 ceph_assert(!num_running
);
97 #if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
98 // release aio contexts (including pinned buffers).
103 BlockDevice::block_device_t
104 BlockDevice::detect_device_type(const std::string
& path
)
106 #if defined(HAVE_SPDK)
107 if (NVMEDevice::support(path
)) {
108 return block_device_t::spdk
;
111 #if defined(HAVE_BLUESTORE_PMEM)
112 if (PMEMDevice::support(path
)) {
113 return block_device_t::pmem
;
116 #if (defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)) && defined(HAVE_LIBZBD)
117 if (HMSMRDevice::support(path
)) {
118 return block_device_t::hm_smr
;
121 #if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
122 return block_device_t::aio
;
124 return block_device_t::unknown
;
128 BlockDevice::block_device_t
129 BlockDevice::device_type_from_name(const std::string
& blk_dev_name
)
131 #if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
132 if (blk_dev_name
== "aio") {
133 return block_device_t::aio
;
136 #if defined(HAVE_SPDK)
137 if (blk_dev_name
== "spdk") {
138 return block_device_t::spdk
;
141 #if defined(HAVE_BLUESTORE_PMEM)
142 if (blk_dev_name
== "pmem") {
143 return block_device_t::pmem
;
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
;
151 return block_device_t::unknown
;
154 BlockDevice
* 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
)
159 switch (device_type
) {
160 #if defined(HAVE_LIBAIO) || defined(HAVE_POSIXAIO)
161 case block_device_t::aio
:
162 return new KernelDevice(cct
, cb
, cbpriv
, d_cb
, d_cbpriv
);
164 #if defined(HAVE_SPDK)
165 case block_device_t::spdk
:
166 return new NVMEDevice(cct
, cb
, cbpriv
);
168 #if defined(HAVE_BLUESTORE_PMEM)
169 case block_device_t::pmem
:
170 return new PMEMDevice(cct
, cb
, cbpriv
);
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
);
177 ceph_abort_msg("unsupported device");
182 BlockDevice
*BlockDevice::create(
183 CephContext
* cct
, const string
& path
, aio_callback_t cb
,
184 void *cbpriv
, aio_callback_t d_cb
, void *d_cbpriv
)
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
);
191 device_type
= device_type_from_name(blk_dev_name
);
193 return create_with_type(device_type
, cct
, path
, cb
, cbpriv
, d_cb
, d_cbpriv
);
196 bool BlockDevice::is_valid_io(uint64_t off
, uint64_t len
) const {
197 bool ret
= (off
% block_size
== 0 &&
198 len
% block_size
== 0 &&
204 derr
<< __func__
<< " " << std::hex
206 << " block_size " << block_size
208 << std::dec
<< dendl
;