OPTION(memstore_page_set, OPT_BOOL, true)
OPTION(memstore_page_size, OPT_U64, 64 << 10)
-OPTION(bdev_backend_type, OPT_STR, "kernel")
OPTION(bdev_debug_inflight_ios, OPT_BOOL, false)
OPTION(bdev_inject_crash, OPT_INT, 0) // if N>0, then ~ 1/N IOs will complete before we crash on flush.
OPTION(bdev_aio, OPT_BOOL, true)
OPTION(bdev_aio_poll_ms, OPT_INT, 250) // milliseconds
OPTION(bdev_aio_max_queue_depth, OPT_INT, 32)
-// Define the whitelist of NVMe controllers to initialize.
-// Users can use 'lspci -vvv -d 8086:0953 | grep "Device Serial Number"' to
-// get the serial number of Intel(R) Fultondale NVMe controllers.
-OPTION(bdev_nvme_serial_number, OPT_STR, "")
// if yes, osd will unbind all NVMe devices from kernel driver and bind them
// to the uio_pci_generic driver. The purpose is to prevent the case where
// NVMe driver is loaded while osd is running.
OPTION(bluestore_bluefs_max_ratio, OPT_FLOAT, .90) // max fs free / total free
OPTION(bluestore_bluefs_gift_ratio, OPT_FLOAT, .02) // how much to add at a time
OPTION(bluestore_bluefs_reclaim_ratio, OPT_FLOAT, .20) // how much to reclaim at a time
+// If you want to use spdk driver, you need to specify NVMe serial number here
+// with "spdk:" prefix.
+// Users can use 'lspci -vvv -d 8086:0953 | grep "Device Serial Number"' to
+// get the serial number of Intel(R) Fultondale NVMe controllers.
+// Example:
+// bluestore_block_path = spdk:55cd2e404bd73932
OPTION(bluestore_block_path, OPT_STR, "")
OPTION(bluestore_block_size, OPT_U64, 10 * 1024*1024*1024) // 10gb for testing
OPTION(bluestore_block_db_path, OPT_STR, "")
*
*/
+#include <unistd.h>
+
#include "KernelDevice.h"
#if defined(HAVE_SPDK)
#include "NVMEDevice.h"
dout(20) << __func__ << " " << this << " done" << dendl;
}
-BlockDevice *BlockDevice::create(const string& type, aio_callback_t cb, void *cbpriv)
+BlockDevice *BlockDevice::create(const string& path, aio_callback_t cb, void *cbpriv)
{
+ char buf[2];
+ int r = ::readlink(path.c_str(), buf, 2);
+
+ string type = "kernel";
+ if (r < 0)
+ type = "ust-nvme";
+ dout(1) << __func__ << " path " << path << " type " << type << dendl;
+
if (type == "kernel") {
return new KernelDevice(cb, cbpriv);
}
}
#endif
+ derr << __func__ << " unknown bacend " << type << dendl;
+ assert(0);
return NULL;
}
typedef void (*aio_callback_t)(void *handle, void *aio);
static BlockDevice *create(
- const string& type, aio_callback_t cb, void *cbpriv);
+ const string& path, aio_callback_t cb, void *cbpriv);
+ virtual bool supported_bdev_label() { return true; }
virtual void aio_submit(IOContext *ioc) = 0;
{
dout(10) << __func__ << " bdev " << id << " path " << path << dendl;
assert(id == bdev.size());
- BlockDevice *b = BlockDevice::create(g_conf->bdev_backend_type, NULL, NULL); //aio_cb, this);
+ BlockDevice *b = BlockDevice::create(path, NULL, NULL); //aio_cb, this);
int r = b->open(path);
if (r < 0) {
delete b;
{
bluestore_bdev_label_t label;
assert(bdev == NULL);
- bdev = BlockDevice::create(g_conf->bdev_backend_type, aio_cb, static_cast<void*>(this));
string p = path + "/block";
+ bdev = BlockDevice::create(p, aio_cb, static_cast<void*>(this));
int r = bdev->open(p);
if (r < 0)
goto fail;
- r = _check_or_set_bdev_label(p, bdev->get_size(), "main", create);
- if (r < 0)
- goto fail_close;
+ if (bdev->supported_bdev_label()) {
+ r = _check_or_set_bdev_label(p, bdev->get_size(), "main", create);
+ if (r < 0)
+ goto fail_close;
+ }
return 0;
fail_close:
{
dout(20) << __func__ << " name " << name << " path " << path
<< " size " << size << dendl;
+ int r = 0;
if (path.length()) {
- int r = ::symlinkat(path.c_str(), path_fd, name.c_str());
- if (r < 0) {
- r = -errno;
- derr << __func__ << " failed to create " << name << " symlink to "
- << path << ": " << cpp_strerror(r) << dendl;
- return r;
+ string spdk_prefix = "spdk:";
+ if (!path.compare(0, spdk_prefix.size(), spdk_prefix)) {
+ int fd = ::openat(path_fd, name.c_str(), O_CREAT|O_RDWR, 0644);
+ if (fd < 0) {
+ r = -errno;
+ derr << __func__ << " failed to create " << name << " file: "
+ << cpp_strerror(r) << dendl;
+ return r;
+ }
+ string serial_number = path.substr(spdk_prefix.size());
+ r = ::write(fd, serial_number.c_str(), serial_number.size());
+ assert(r == (int)serial_number.size());
+ dout(1) << __func__ << " created " << name << " file with " << dendl;
+ VOID_TEMP_FAILURE_RETRY(::close(fd));
+ } else {
+ r = ::symlinkat(path.c_str(), path_fd, name.c_str());
+ if (r < 0) {
+ r = -errno;
+ derr << __func__ << " failed to create " << name << " symlink to "
+ << path << ": " << cpp_strerror(r) << dendl;
+ return r;
+ }
}
} else if (size) {
struct stat st;
- int r = ::fstatat(path_fd, name.c_str(), &st, 0);
+ r = ::fstatat(path_fd, name.c_str(), &st, 0);
if (r < 0)
r = -errno;
if (r == -ENOENT) {
<< cpp_strerror(r) << dendl;
return r;
}
- int r = ::ftruncate(fd, size);
+ r = ::ftruncate(fd, size);
assert(r == 0);
dout(1) << __func__ << " created " << name << " file with size "
<< pretty_si_t(size) << "B" << dendl;
int r = 0;
dout(1) << __func__ << " path " << p << dendl;
- r = driver_data.try_get(g_conf->bdev_nvme_serial_number, &ctrlr, &name);
+ string serial_number;
+ int fd = ::open(p.c_str(), O_RDONLY);
+ if (fd < 0) {
+ r = -errno;
+ derr << __func__ << " unable to open " << p << ": " << cpp_strerror(r)
+ << dendl;
+ return r;
+ }
+ char buf[100];
+ r = ::read(fd, buf, sizeof(buf));
+ if (r <= 0) {
+ r = -errno;
+ derr << __func__ << " unable to read " << p << ": " << cpp_strerror(r) << dendl;
+ return r;
+ }
+ serial_number = string(buf, r);
+ r = driver_data.try_get(serial_number, &ctrlr, &name);
if (r < 0) {
- derr << __func__ << " failed to get nvme deivce with sn " << g_conf->bdev_nvme_serial_number << dendl;
+ derr << __func__ << " failed to get nvme deivce with sn " << serial_number << dendl;
return r;
}
NVMEDevice(aio_callback_t cb, void *cbpriv);
+ bool supported_bdev_label() override { return false; }
+
void aio_submit(IOContext *ioc) override;
uint64_t get_size() const override {