From e31acf6567138266357fc26c56cc5e36d3ba65fd Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Thu, 28 Sep 2017 14:13:15 -0600 Subject: [PATCH] blkdev: FreeBSD support Signed-off-by: Alan Somers --- CMakeLists.txt | 4 ++ src/common/blkdev.cc | 92 +++++++++++++++++++++++++------- src/os/bluestore/KernelDevice.cc | 20 +++++-- src/test/CMakeLists.txt | 4 +- src/test/common/CMakeLists.txt | 10 ++-- 5 files changed, 101 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1708ad173c3..94d0f474dee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,6 +215,10 @@ if(LINUX) set(HAVE_UDEV ${UDEV_FOUND}) find_package(blkid REQUIRED) set(HAVE_BLKID ${BLKID_FOUND}) +elseif(FREEBSD) + set(HAVE_UDEV OFF) + set(HAVE_LIBAIO OFF) + set(HAVE_BLKID OFF) else() set(HAVE_UDEV OFF) message(STATUS "Not using udev") diff --git a/src/common/blkdev.cc b/src/common/blkdev.cc index f9e9b222015..6ff18634bed 100644 --- a/src/common/blkdev.cc +++ b/src/common/blkdev.cc @@ -7,11 +7,18 @@ * * 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 + * License version 2.1, as published by the Free Software * Foundation. See file COPYING. - * + * */ +#ifdef __FreeBSD__ +#include +#include +#include +#include +#endif + #include #include #include @@ -63,14 +70,6 @@ int get_device_by_path(const char *path, char* partition, char* device, #endif -static const char *blkdev_props2strings[] = { - [BLKDEV_PROP_DEV] = "dev", - [BLKDEV_PROP_DISCARD_GRANULARITY] = "queue/discard_granularity", - [BLKDEV_PROP_MODEL] = "device/model", - [BLKDEV_PROP_ROTATIONAL] = "queue/rotational", - [BLKDEV_PROP_SERIAL] = "device/serial", - [BLKDEV_PROP_VENDOR] = "device/vendor", -}; BlkDev::BlkDev(int f) : fd(f) @@ -80,10 +79,6 @@ BlkDev::BlkDev(const std::string& devname) : devname(devname) {} -const char *BlkDev::sysfsdir() const { - return "/sys"; -} - int BlkDev::get_devid(dev_t *id) const { struct stat st; @@ -584,7 +579,6 @@ bool get_vdo_utilization(int fd, uint64_t *total, uint64_t *avail) } #elif defined(__FreeBSD__) -#include const char *BlkDev::sysfsdir() const { assert(false); // Should never be called on FreeBSD @@ -613,6 +607,19 @@ int BlkDev::get_size(int64_t *psize) const bool BlkDev::support_discard() const { +#ifdef FREEBSD_WITH_TRIM + // there is no point to claim support of discard, but + // unable to do so. + struct diocgattr_arg arg; + + strlcpy(arg.name, "GEOM::candelete", sizeof(arg.name)); + arg.len = sizeof(arg.value.i); + if (ioctl(fd, DIOCGATTR, &arg) == 0) { + return (arg.value.i != 0); + } else { + return false; + } +#endif return false; } @@ -642,17 +649,64 @@ bool BlkDev::is_nvme() const bool BlkDev::is_rotational() const { - return false; +#if __FreeBSD_version >= 1200049 + struct diocgattr_arg arg; + + strlcpy(arg.name, "GEOM::rotation_rate", sizeof(arg.name)); + arg.len = sizeof(arg.value.u16); + + int ioctl_ret = ioctl(fd, DIOCGATTR, &arg); + bool ret; + if (ioctl_ret < 0 || arg.value.u16 == DISK_RR_UNKNOWN) + // DISK_RR_UNKNOWN usually indicates an old drive, which is usually spinny + ret = true; + else if (arg.value.u16 == DISK_RR_NON_ROTATING) + ret = false; + else if (arg.value.u16 >= DISK_RR_MIN && arg.value.u16 <= DISK_RR_MAX) + ret = true; + else + ret = true; // Invalid value. Probably spinny? + + return ret; +#else + return true; // When in doubt, it's probably spinny +#endif } int BlkDev::model(char *model, size_t max) const { - return false; + struct diocgattr_arg arg; + + strlcpy(arg.name, "GEOM::descr", sizeof(arg.name)); + arg.len = sizeof(arg.value.str); + if (ioctl(fd, DIOCGATTR, &arg) < 0) { + return -errno; + } + + // The GEOM description is of the form "vendor product" for SCSI disks + // and "ATA device_model" for ATA disks. Some vendors choose to put the + // vendor name in device_model, and some don't. Strip the first bit. + char *p = arg.value.str; + if (p == NULL || *p == '\0') { + *model = '\0'; + } else { + (void) strsep(&p, " "); + snprintf(model, max, "%s", p); + } + + return 0; } -int BlkDev::serial(char *serial, size_t max) const +int BlkDev::serial(char *serial, size_t max) { - return -EOPNOTSUPP; + char ident[DISK_IDENT_SIZE]; + + if (ioctl(fd, DIOCGIDENT, ident) < 0) + return -errno; + + snprintf(serial, max, "%s", ident); + + return 0; } void get_dm_parents(const std::string& dev, std::set *ls) diff --git a/src/os/bluestore/KernelDevice.cc b/src/os/bluestore/KernelDevice.cc index bb9956bf9c8..52388fd1081 100644 --- a/src/os/bluestore/KernelDevice.cc +++ b/src/os/bluestore/KernelDevice.cc @@ -233,11 +233,25 @@ int KernelDevice::collect_metadata(const string& prefix, map *pm) if (r < 0) return -errno; if (S_ISBLK(st.st_mode)) { - char buffer[1024] = {0}; - BlkDev blkdev(fd_buffered); - (*pm)[prefix + "access_mode"] = "blk"; + char buffer[1024] = {0}; + BlkDev blkdev{fd_buffered}; + if (r = blkdev.partition(buffer, sizeof(buffer)); r) { + (*pm)[prefix + "partition_path"] = "unknown"; + } else { + (*pm)[prefix + "partition_path"] = buffer; + } + buffer[0] = '\0'; + if (r = blkdev.partition(buffer, sizeof(buffer)); r) { + (*pm)[prefix + "dev_node"] = "unknown"; + } else { + (*pm)[prefix + "dev_node"] = buffer; + } + if (!r) { + return 0; + } + buffer[0] = '\0'; blkdev.model(buffer, sizeof(buffer)); (*pm)[prefix + "model"] = buffer; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 49ae77e2ac5..43243785864 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -447,7 +447,7 @@ if(${WITH_CEPHFS}) cephfs) endif(${WITH_CEPHFS}) -if(HAVE_BLKID) +if(HAVE_BLKID OR FREEBSD) add_executable(ceph_test_get_blkdev_props test_get_blkdev_props.cc ) @@ -458,7 +458,7 @@ if(HAVE_BLKID) ${BLKID_LIBRARIES} ${CMAKE_DL_LIBS} ) -endif(HAVE_BLKID) +endif(HAVE_BLKID OR FREEBSD) # ceph_test_admin_socket_output diff --git a/src/test/common/CMakeLists.txt b/src/test/common/CMakeLists.txt index 5692c3de000..21a54aeb677 100644 --- a/src/test/common/CMakeLists.txt +++ b/src/test/common/CMakeLists.txt @@ -12,13 +12,13 @@ target_link_libraries(get_command_descriptions ${CMAKE_DL_LIBS} ) -if(HAVE_BLKID) +# Though FreeBSD has blkdev support, the unittests' mocks only work in Linux +if(HAVE_BLKID AND LINUX) # unittest_blkdev add_executable(unittest_blkdev - test_blkdev.cc - ) - add_ceph_unittest(unittest_blkdev) - target_link_libraries(unittest_blkdev ceph-common ${BLKID_LIBRARIES}) + test_blkdev.cc) + add_ceph_unittest(unittest_blkdev ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_blkdev) + target_link_libraries(unittest_blkdev global ${BLKID_LIBRARIES}) endif() # unittest_lockdep -- 2.39.5