From 462b3898e5016ce49c5c1c4828f68d5011b9e7ce Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Fri, 13 Dec 2013 17:40:52 +0200 Subject: [PATCH] rbd: match against whole disks on unmap Currently the way 'rbd unmap' translates a user-provided block device into an rbd id is it matches the major number of the specified device against /sys/bus/rbd/devices//major for each rbd mapping and declares success on the first match. This works for both entire disks and partitions, because under the current device number allocation scheme, each mapping means a new major number. In preparation for support for single-major device number allocation scheme, which would require matching both major and minor numbers, make sure to always match against entire disk device numbers, by converting the specified device major:minor pair into wholdedisk major:minor pair. To achive that, use the libblkid library, which accomplishes this goal by walking stable sysfs structures. Signed-off-by: Ilya Dryomov --- README | 6 ++++-- ceph.spec.in | 1 + configure.ac | 5 +++++ debian/control | 1 + src/Makefile.am | 4 ++-- src/rbd.cc | 26 ++++++++++++++++++-------- 6 files changed, 31 insertions(+), 12 deletions(-) diff --git a/README b/README index 16e2cde24e469..197a7bfaadead 100644 --- a/README +++ b/README @@ -122,6 +122,7 @@ To build the source code, you must install the following: - libgoogle-perftools-dev - libkeyutils-dev - uuid-dev +- libblkid-dev - libatomic-ops-dev - libboost-program-options-dev - libboost-thread-dev @@ -134,7 +135,7 @@ To build the source code, you must install the following: For example: - $ apt-get install automake autoconf pkg-config gcc g++ make libboost-dev libedit-dev libssl-dev libtool libfcgi libfcgi-dev libfuse-dev linux-kernel-headers libcrypto++-dev libaio-dev libgoogle-perftools-dev libkeyutils-dev uuid-dev libatomic-ops-dev libboost-program-options-dev libboost-thread-dev libexpat1-dev libleveldb-dev libsnappy-dev libcurl4-gnutls-dev python-argparse python-flask + $ apt-get install automake autoconf pkg-config gcc g++ make libboost-dev libedit-dev libssl-dev libtool libfcgi libfcgi-dev libfuse-dev linux-kernel-headers libcrypto++-dev libaio-dev libgoogle-perftools-dev libkeyutils-dev uuid-dev libblkid-dev libatomic-ops-dev libboost-program-options-dev libboost-thread-dev libexpat1-dev libleveldb-dev libsnappy-dev libcurl4-gnutls-dev python-argparse python-flask rpm-based --------- @@ -149,6 +150,7 @@ These are the rpm packages needed to install in an rpm-based OS: python-argparse python-flask libuuid-devel + libblkid-devel keyutils-libs-devel cryptopp-devel nss-devel @@ -166,5 +168,5 @@ These are the rpm packages needed to install in an rpm-based OS: For example: - $ yum install autoconf automake gcc gcc-c++ make libtool python-argparse python-flask libuuid-devel keyutils-libs-devel cryptopp-devel nss-devel fcgi-devel expat-devel libcurl-devel fuse-devel gperftools-devel libedit-devel libatomic_ops-devel snappy-devel leveldb-devel libaio-devel boost-devel + $ yum install autoconf automake gcc gcc-c++ make libtool python-argparse python-flask libuuid-devel libblkid-devel keyutils-libs-devel cryptopp-devel nss-devel fcgi-devel expat-devel libcurl-devel fuse-devel gperftools-devel libedit-devel libatomic_ops-devel snappy-devel leveldb-devel libaio-devel boost-devel diff --git a/ceph.spec.in b/ceph.spec.in index b2c9d839904fb..a746461551b17 100644 --- a/ceph.spec.in +++ b/ceph.spec.in @@ -43,6 +43,7 @@ BuildRequires: libaio-devel BuildRequires: libcurl-devel BuildRequires: libxml2-devel BuildRequires: libuuid-devel +BuildRequires: libblkid-devel >= 2.17 BuildRequires: leveldb-devel > 1.2 BuildRequires: yasm %if 0%{?rhel_version} || 0%{?centos_version} || 0%{?fedora} diff --git a/configure.ac b/configure.ac index ab2e49dd707a3..5fdd8066fefcd 100644 --- a/configure.ac +++ b/configure.ac @@ -128,8 +128,13 @@ AX_C_PRETTY_FUNC # Checks for libraries. ACX_PTHREAD + AC_CHECK_LIB([uuid], [uuid_parse], [true], AC_MSG_FAILURE([libuuid not found])) +if test x"$linux" = x"yes"; then + AC_CHECK_LIB([blkid], [blkid_devno_to_wholedisk], [true], AC_MSG_FAILURE([libblkid not found])) +fi + # # Check for res_nquery in libresolv. There are several variations. On OSX # res_nquery is a macro defined in resolv.h, so the typical AC_CHECK_LIB diff --git a/debian/control b/debian/control index 1aec592c9f891..fcbadc48ddffe 100644 --- a/debian/control +++ b/debian/control @@ -36,6 +36,7 @@ Build-Depends: autoconf, python (>= 2.6.6-3~), python-nose, uuid-dev, + libblkid-dev (>= 2.17), yasm Standards-Version: 3.9.3 diff --git a/src/Makefile.am b/src/Makefile.am index 9481b981fc81e..7ee5e6a11207b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,8 +75,8 @@ ceph_syn_SOURCES += client/SyntheticClient.cc # uses g_conf.. needs cleanup ceph_syn_LDADD = $(LIBCLIENT) $(CEPH_GLOBAL) bin_PROGRAMS += ceph-syn -rbd_SOURCES = rbd.cc -rbd_LDADD = $(LIBRBD) $(LIBRADOS) $(CEPH_GLOBAL) +rbd_SOURCES = rbd.cc +rbd_LDADD = $(LIBRBD) $(LIBRADOS) $(CEPH_GLOBAL) -lblkid if LINUX bin_PROGRAMS += rbd endif #LINUX diff --git a/src/rbd.cc b/src/rbd.cc index a5806b9b4c693..69f550e482901 100644 --- a/src/rbd.cc +++ b/src/rbd.cc @@ -57,6 +57,8 @@ #include #endif +#include + #define MAX_SECRET_LEN 1000 #define MAX_POOL_NAME_SIZE 128 @@ -1859,9 +1861,19 @@ static int do_kernel_showmapped(Formatter *f) return 0; } -static int get_rbd_seq(int major_num, string &seq) +static int get_rbd_seq(dev_t devno, string &seq) { - int r; + // convert devno, which might be a partition major:minor pair, into + // a whole disk major:minor pair + dev_t wholediskno; + int r = blkid_devno_to_wholedisk(devno, NULL, 0, &wholediskno); + if (r) { + cerr << "rbd: could not compute wholediskno: " << r << std::endl; + // ignore the error: devno == wholediskno most of the time, and if + // it turns out it's not we will fail with -ENOENT later anyway + wholediskno = devno; + } + const char *devices_path = "/sys/bus/rbd/devices"; DIR *device_dir = opendir(devices_path); if (!device_dir) { @@ -1904,7 +1916,7 @@ static int get_rbd_seq(int major_num, string &seq) continue; } - if (cur_major == major_num) { + if (cur_major == (int)major(wholediskno)) { seq = string(dent->d_name); closedir(device_dir); return 0; @@ -1918,16 +1930,14 @@ static int get_rbd_seq(int major_num, string &seq) static int do_kernel_rm(const char *dev) { - struct stat dev_stat; - int r = stat(dev, &dev_stat); - if (!S_ISBLK(dev_stat.st_mode)) { + struct stat sbuf; + if (stat(dev, &sbuf) || !S_ISBLK(sbuf.st_mode)) { cerr << "rbd: " << dev << " is not a block device" << std::endl; return -EINVAL; } - int major = major(dev_stat.st_rdev); string seq_num; - r = get_rbd_seq(major, seq_num); + int r = get_rbd_seq(sbuf.st_rdev, seq_num); if (r == -ENOENT) { cerr << "rbd: " << dev << " is not an rbd device" << std::endl; return -EINVAL; -- 2.39.5