From: Sage Weil Date: Thu, 11 Dec 2014 18:07:48 +0000 (-0800) Subject: common/blkdev: fix block device discard check X-Git-Tag: v0.90~2^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=2246dca05fe32a9cda4b071ff1228d6c0173684e;p=ceph.git common/blkdev: fix block device discard check - fix base name calculation (do not assume sda) - reverse sense of check (it was returning false when true before?) - add a generic helper to get other properties, too Fixes: #10296 Signed-off-by: Sage Weil --- diff --git a/src/common/blkdev.cc b/src/common/blkdev.cc index bff23cee804f..7c838341360d 100644 --- a/src/common/blkdev.cc +++ b/src/common/blkdev.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include "include/int_types.h" #ifdef __linux__ @@ -94,40 +95,52 @@ int get_block_device_base(const char *dev, char *out, size_t out_len) return r; } -bool block_device_support_discard(const char *devname) +/** + * get a block device property + * + * return the value (we assume it is positive) + * return negative error on error + */ +int64_t get_block_device_int_property(const char *devname, const char *property) { - bool can_trim = false; - char *p = strstr((char *)devname, "sd"); - char name[32]; + char basename[PATH_MAX], filename[PATH_MAX]; + int64_t r; - strncpy(name, p, sizeof(name) - 1); - name[sizeof(name) - 1] = '\0'; + r = get_block_device_base(devname, basename, sizeof(basename)); + if (r < 0) + return r; - for (unsigned int i = 0; i < strlen(name); i++) { - if(isdigit(name[i])) { - name[i] = 0; - break; - } - } - - char filename[100] = {0}; - sprintf(filename, "/sys/block/%s/queue/discard_granularity", name); + snprintf(filename, sizeof(filename), + "/sys/block/%s/queue/discard_granularity", basename); FILE *fp = fopen(filename, "r"); if (fp == NULL) { - can_trim = false; + return -errno; + } + + char buff[256] = {0}; + if (fgets(buff, sizeof(buff) - 1, fp)) { + // strip newline etc + for (char *p = buff; *p; ++p) { + if (!isdigit(*p)) { + *p = 0; + break; + } + } + char *endptr = 0; + r = strtoll(buff, &endptr, 10); + if (endptr != buff + strlen(buff)) + r = -EINVAL; } else { - char buff[256] = {0}; - if (fgets(buff, sizeof(buff) - 1, fp)) { - if (strcmp(buff, "0")) - can_trim = false; - else - can_trim = true; - } else - can_trim = false; - fclose(fp); + r = 0; } - return can_trim; + fclose(fp); + return r; +} + +bool block_device_support_discard(const char *devname) +{ + return get_block_device_int_property(devname, "discard_granularity") > 0; } int block_device_discard(int fd, int64_t offset, int64_t len) diff --git a/src/common/blkdev.h b/src/common/blkdev.h index 2f76d40d5315..3f1277800151 100644 --- a/src/common/blkdev.h +++ b/src/common/blkdev.h @@ -3,6 +3,7 @@ extern int get_block_device_base(const char *dev, char *out, size_t out_len); extern int get_block_device_size(int fd, int64_t *psize); +extern int64_t get_block_device_int_property(const char *devname, const char *property); extern bool block_device_support_discard(const char *devname); extern int block_device_discard(int fd, int64_t offset, int64_t len); #endif diff --git a/src/test/common/test_blkdev.cc b/src/test/common/test_blkdev.cc index 2eb8750d72db..f3f03d3b6e4b 100644 --- a/src/test/common/test_blkdev.cc +++ b/src/test/common/test_blkdev.cc @@ -37,6 +37,9 @@ TEST(blkdev, get_block_device_base) { ASSERT_EQ(0, get_block_device_base(base, buf3, sizeof(buf3))); printf(" got '%s' expected '%s'\n", buf3, de->d_name); ASSERT_EQ(0, strcmp(de->d_name, buf3)); + printf(" discard granularity = %lld .. supported = %d\n", + get_block_device_int_property(base, "discard_granularity"), + (int)block_device_support_discard(base)); char subdirfn[PATH_MAX]; sprintf(subdirfn, "/sys/block/%s", de->d_name); @@ -62,6 +65,9 @@ TEST(blkdev, get_block_device_base) { ASSERT_EQ(0, get_block_device_base(part, buf3, sizeof(buf3))); printf(" got '%s' expected '%s'\n", buf3, de->d_name); ASSERT_EQ(0, strcmp(buf3, de->d_name)); + printf(" discard granularity = %lld .. supported = %d\n", + get_block_device_int_property(part, "discard_granularity"), + (int)block_device_support_discard(part)); } closedir(subdir);