diff options
Diffstat (limited to 'src/extblkdev/vdo')
-rw-r--r-- | src/extblkdev/vdo/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/extblkdev/vdo/ExtBlkDevPluginVdo.cc | 59 | ||||
-rw-r--r-- | src/extblkdev/vdo/ExtBlkDevPluginVdo.h | 34 | ||||
-rw-r--r-- | src/extblkdev/vdo/ExtBlkDevVdo.cc | 156 | ||||
-rw-r--r-- | src/extblkdev/vdo/ExtBlkDevVdo.h | 52 |
5 files changed, 310 insertions, 0 deletions
diff --git a/src/extblkdev/vdo/CMakeLists.txt b/src/extblkdev/vdo/CMakeLists.txt new file mode 100644 index 000000000..60d4f293d --- /dev/null +++ b/src/extblkdev/vdo/CMakeLists.txt @@ -0,0 +1,9 @@ +# vdo plugin + +set(vdo_srcs + ExtBlkDevPluginVdo.cc + ExtBlkDevVdo.cc +) + +add_library(ceph_ebd_vdo SHARED ${vdo_srcs}) +install(TARGETS ceph_ebd_vdo DESTINATION ${extblkdev_plugin_dir}) diff --git a/src/extblkdev/vdo/ExtBlkDevPluginVdo.cc b/src/extblkdev/vdo/ExtBlkDevPluginVdo.cc new file mode 100644 index 000000000..dbe156182 --- /dev/null +++ b/src/extblkdev/vdo/ExtBlkDevPluginVdo.cc @@ -0,0 +1,59 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * (C) Copyright IBM Corporation 2022 + * Author: Martin Ohmacht <mohmacht@us.ibm.com> + * + * Based on the file src/erasure-code/clay/ErasureCodePluginClay.cc + * Copyright (C) 2018 Indian Institute of Science <office.ece@iisc.ac.in> + * + * Author: Myna Vajha <mynaramana@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include "ceph_ver.h" +#include "ExtBlkDevPluginVdo.h" +#include "common/ceph_context.h" + + +// This plugin does not require any capabilities to be set +int ExtBlkDevPluginVdo::get_required_cap_set(cap_t caps) +{ + return 0; +} + + +int ExtBlkDevPluginVdo::factory(const std::string& logdevname, + ceph::ExtBlkDevInterfaceRef& ext_blk_dev) +{ + auto vdo = new ExtBlkDevVdo(cct); + int r = vdo->init(logdevname); + if (r != 0) { + delete vdo; + return r; + } + ext_blk_dev.reset(vdo); + return 0; +}; + +const char *__ceph_plugin_version() { return CEPH_GIT_NICE_VER; } + +int __ceph_plugin_init(CephContext *cct, + const std::string& type, + const std::string& name) +{ + auto plg = new ExtBlkDevPluginVdo(cct); + if(plg == 0) return -ENOMEM; + int rc = cct->get_plugin_registry()->add(type, name, plg); + if(rc != 0){ + delete plg; + } + return rc; +} diff --git a/src/extblkdev/vdo/ExtBlkDevPluginVdo.h b/src/extblkdev/vdo/ExtBlkDevPluginVdo.h new file mode 100644 index 000000000..784f642ec --- /dev/null +++ b/src/extblkdev/vdo/ExtBlkDevPluginVdo.h @@ -0,0 +1,34 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * (C) Copyright IBM Corporation 2022 + * Author: Martin Ohmacht <mohmacht@us.ibm.com> + * + * Based on the file src/erasure-code/clay/ErasureCodePluginClay.h + * Copyright (C) 2018 Indian Institute of Science <office.ece@iisc.ac.in> + * + * Author: Myna Vajha <mynaramana@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#ifndef CEPH_EXT_BLK_DEV_PLUGIN_VDO_H +#define CEPH_EXT_BLK_DEV_PLUGIN_VDO_H + +#include "ExtBlkDevVdo.h" + +class ExtBlkDevPluginVdo : public ceph::ExtBlkDevPlugin { +public: + explicit ExtBlkDevPluginVdo(CephContext *cct) : ExtBlkDevPlugin(cct) {} + int get_required_cap_set(cap_t caps) override; + int factory(const std::string& logdevname, + ceph::ExtBlkDevInterfaceRef& ext_blk_dev) override; +}; + +#endif diff --git a/src/extblkdev/vdo/ExtBlkDevVdo.cc b/src/extblkdev/vdo/ExtBlkDevVdo.cc new file mode 100644 index 000000000..c40cd1a1a --- /dev/null +++ b/src/extblkdev/vdo/ExtBlkDevVdo.cc @@ -0,0 +1,156 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * (C) Copyright IBM Corporation 2022 + * Author: Martin Ohmacht <mohmacht@us.ibm.com> + * + * Based on the file ceph/src/common/blkdev.cc + * Copyright (c) 2015 Hewlett-Packard Development Company, L.P. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + + +#include "ExtBlkDevVdo.h" +#include "common/blkdev.h" +#include "include/stringify.h" +#include <errno.h> +#include "common/debug.h" + +#define dout_subsys ceph_subsys_bdev +#define dout_context cct +#undef dout_prefix +#define dout_prefix *_dout << "vdo(" << this << ") " + + +int ExtBlkDevVdo::_get_vdo_stats_handle(const std::string& devname) +{ + int rc = -ENOENT; + dout(10) << __func__ << " VDO init checking device: " << devname << dendl; + + // we need to go from the raw devname (e.g., dm-4) to the VDO volume name. + // currently the best way seems to be to look at /dev/mapper/* ... + std::string expect = std::string("../") + devname; // expected symlink target + DIR *dir = ::opendir("/dev/mapper"); + if (!dir) { + return -errno; + } + struct dirent *de = nullptr; + while ((de = ::readdir(dir))) { + if (de->d_name[0] == '.') + continue; + char fn[4096], target[4096]; + snprintf(fn, sizeof(fn), "/dev/mapper/%s", de->d_name); + int r = readlink(fn, target, sizeof(target)); + if (r < 0 || r >= (int)sizeof(target)) + continue; + target[r] = 0; + if (expect == target) { + snprintf(fn, sizeof(fn), "/sys/kvdo/%s/statistics", de->d_name); + int vdo_fd = ::open(fn, O_RDONLY|O_CLOEXEC); + if (vdo_fd >= 0) { + name = de->d_name; + vdo_dir_fd = vdo_fd; + rc = 0; + break; + } + } + } + closedir(dir); + return rc; +} + +int ExtBlkDevVdo::get_vdo_stats_handle() +{ + std::set<std::string> devs = { logdevname }; + while (!devs.empty()) { + std::string dev = *devs.begin(); + devs.erase(devs.begin()); + int rc = _get_vdo_stats_handle(dev); + if (rc == 0) { + // yay, it's vdo + return rc; + } + // ok, see if there are constituent devices + if (dev.find("dm-") == 0) { + get_dm_parents(dev, &devs); + } + } + return -ENOENT; +} + +int64_t ExtBlkDevVdo::get_vdo_stat(const char *property) +{ + int64_t ret = 0; + int fd = ::openat(vdo_dir_fd, property, O_RDONLY|O_CLOEXEC); + if (fd < 0) { + return 0; + } + char buf[1024]; + int r = ::read(fd, buf, sizeof(buf) - 1); + if (r > 0) { + buf[r] = 0; + ret = atoll(buf); + } + VOID_TEMP_FAILURE_RETRY(::close(fd)); + return ret; +} + + +int ExtBlkDevVdo::init(const std::string& alogdevname) +{ + logdevname = alogdevname; + // get directory handle for VDO metadata + return get_vdo_stats_handle(); +} + + +int ExtBlkDevVdo::get_state(ceph::ExtBlkDevState& state) +{ + int64_t block_size = get_vdo_stat("block_size"); + int64_t physical_blocks = get_vdo_stat("physical_blocks"); + int64_t overhead_blocks_used = get_vdo_stat("overhead_blocks_used"); + int64_t data_blocks_used = get_vdo_stat("data_blocks_used"); + int64_t logical_blocks = get_vdo_stat("logical_blocks"); + int64_t logical_blocks_used = get_vdo_stat("logical_blocks_used"); + if (!block_size + || !physical_blocks + || !overhead_blocks_used + || !data_blocks_used + || !logical_blocks) { + dout(1) << __func__ << " VDO sysfs provided zero value for at least one statistic: " << dendl; + dout(1) << __func__ << " VDO block_size: " << block_size << dendl; + dout(1) << __func__ << " VDO physical_blocks: " << physical_blocks << dendl; + dout(1) << __func__ << " VDO overhead_blocks_used: " << overhead_blocks_used << dendl; + dout(1) << __func__ << " VDO data_blocks_used: " << data_blocks_used << dendl; + dout(1) << __func__ << " VDO logical_blocks: " << logical_blocks << dendl; + return -1; + } + int64_t avail_blocks = + physical_blocks - overhead_blocks_used - data_blocks_used; + int64_t logical_avail_blocks = + logical_blocks - logical_blocks_used; + state.set_logical_total(block_size * logical_blocks); + state.set_logical_avail(block_size * logical_avail_blocks); + state.set_physical_total(block_size * physical_blocks); + state.set_physical_avail(block_size * avail_blocks); + return 0; +} + +int ExtBlkDevVdo::collect_metadata(const std::string& prefix, std::map<std::string,std::string> *pm) +{ + ceph::ExtBlkDevState state; + int rc = get_state(state); + if(rc != 0){ + return rc; + } + (*pm)[prefix + "vdo"] = "true"; + (*pm)[prefix + "vdo_physical_size"] = stringify(state.get_physical_total()); + return 0; +} diff --git a/src/extblkdev/vdo/ExtBlkDevVdo.h b/src/extblkdev/vdo/ExtBlkDevVdo.h new file mode 100644 index 000000000..09865a27e --- /dev/null +++ b/src/extblkdev/vdo/ExtBlkDevVdo.h @@ -0,0 +1,52 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * (C) Copyright IBM Corporation 2022 + * Author: Martin Ohmacht <mohmacht@us.ibm.com> + * + * Based on the file ceph/src/common/blkdev.cc + * Copyright (c) 2015 Hewlett-Packard Development Company, L.P. + * + * And also based on the file src/erasure-code/clay/ErasureCodeClay.h + * Copyright (C) 2018 Indian Institute of Science <office.ece@iisc.ac.in> + * + * Author: Myna Vajha <mynaramana@gmail.com> + * + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_EXT_BLK_DEV_VDO_H +#define CEPH_EXT_BLK_DEV_VDO_H + +#include "extblkdev/ExtBlkDevInterface.h" +#include "include/compat.h" + +class ExtBlkDevVdo final : public ceph::ExtBlkDevInterface +{ + int vdo_dir_fd = -1; ///< fd for vdo sysfs directory + std::string name; // name of the underlying vdo device + std::string logdevname; // name of the top level logical device + CephContext *cct; +public: + explicit ExtBlkDevVdo(CephContext *cct) : cct(cct) {} + ~ExtBlkDevVdo(){ + if(vdo_dir_fd >= 0) + VOID_TEMP_FAILURE_RETRY(::close(vdo_dir_fd)); + } + int _get_vdo_stats_handle(const std::string& devname); + int get_vdo_stats_handle(); + int64_t get_vdo_stat(const char *property); + virtual int init(const std::string& logdevname); + virtual const std::string& get_devname() const {return name;} + virtual int get_state(ceph::ExtBlkDevState& state); + virtual int collect_metadata(const std::string& prefix, std::map<std::string,std::string> *pm); +}; + +#endif |