From: Ilya Dryomov Date: Fri, 13 Dec 2013 15:40:52 +0000 (+0200) Subject: rbd: match against whole disks on unmap X-Git-Tag: v0.75~113^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=462b3898e5016ce49c5c1c4828f68d5011b9e7ce;p=ceph.git 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 --- diff --git a/README b/README index 16e2cde24e46..197a7bfaadea 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 b2c9d839904f..a746461551b1 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 ab2e49dd707a..5fdd8066fefc 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 1aec592c9f89..fcbadc48ddff 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 9481b981fc81..7ee5e6a11207 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 a5806b9b4c69..69f550e48290 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;