]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common/blkdev: fix block device discard check
authorSage Weil <sage@redhat.com>
Thu, 11 Dec 2014 18:07:48 +0000 (10:07 -0800)
committerSage Weil <sage@redhat.com>
Thu, 11 Dec 2014 18:18:56 +0000 (10:18 -0800)
- 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 <sage@redhat.com>
src/common/blkdev.cc
src/common/blkdev.h
src/test/common/test_blkdev.cc

index bff23cee804fb76479a33c5070607bb2c4bde061..7c838341360ddb7ac75c707107b33f87f041c05b 100644 (file)
@@ -6,6 +6,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <dirent.h>
+#include <stdlib.h>
 #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)
index 2f76d40d53154fbd2cdf45ee1ddcef921a122fe9..3f1277800151a76015e7519588a58fedef2bbd5e 100644 (file)
@@ -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
index 2eb8750d72dbc2f4737daa4548ad8f4201d54599..f3f03d3b6e4bb5f99ff043018b7ec259f396b8c3 100644 (file)
@@ -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);