summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Malevich <jam@daterainc.com>2014-12-18 19:19:21 -0800
committerRaghu Krishnamurthy <rk@daterainc.com>2014-12-31 15:17:12 -0800
commit474f0889f0a19416d87fcf1a6b3e5cc9e49731c8 (patch)
treebbd62a7d4d6208d61f29059865ea567335d88139
parent45d1cb0527b082c26747236ef9d391964cd1bf0f (diff)
bcacheadm: fix status and query-devs
Previously we were reading old superblocks stuck in the cache. Pass in O_DIRECT when opening the device. This requires that the dest buffer be memaligned. If we are unable to read the entire superblock then increase the buffer and try again. Also since we now have to alloc the sb, make sure it is freed everywhere in bcacheadm. Fixes DAT-1609 DAT-1626 Change-Id: I04b5337b992a8569809835b5826a2656df753214 Signed-off-by: Jacob Malevich <jam@daterainc.com>
-rw-r--r--bcache.c39
-rw-r--r--bcacheadm.c7
2 files changed, 31 insertions, 15 deletions
diff --git a/bcache.c b/bcache.c
index fb3931ed..a69a46fb 100644
--- a/bcache.c
+++ b/bcache.c
@@ -906,30 +906,39 @@ void sysfs_attr_list() {
struct cache_sb *query_dev(char *dev, bool force_csum,
bool print_sb, bool uuid_only, char *dev_uuid)
{
- struct cache_sb sb_stack, *sb = &sb_stack;
- size_t bytes = sizeof(*sb);
+ size_t bytes = 4096;
+ struct cache_sb *sb = aligned_alloc(bytes, bytes);
- int fd = open(dev, O_RDONLY);
+ int fd = open(dev, O_RDONLY|O_DIRECT);
if (fd < 0) {
printf("Can't open dev %s: %s\n", dev, strerror(errno));
return NULL;
}
- if (pread(fd, sb, bytes, SB_START) != bytes) {
- fprintf(stderr, "Couldn't read\n");
- return NULL;
- }
-
- if (sb->keys) {
- bytes = sizeof(*sb) + sb->keys * sizeof(uint64_t);
- sb = malloc(bytes);
-
- if (pread(fd, sb, bytes, SB_START) != bytes) {
- fprintf(stderr, "Couldn't read\n");
+ while (true) {
+ int ret = pread(fd, sb, bytes, SB_START);
+ if (ret < 0) {
+ fprintf(stderr, "Couldn't read superblock: %s\n",
+ strerror(errno));
+ close(fd);
+ free(sb);
return NULL;
+ } else if (bytes > sizeof(sb) + sb->keys * sizeof(u64)) {
+ /* We read the whole superblock */
+ break;
}
+
+ /*
+ * otherwise double the size of our dest
+ * and read again
+ */
+ free(sb);
+ bytes *= 2;
+ sb = aligned_alloc(4096, bytes);
}
+ close(fd);
+
if(uuid_only) {
show_uuid_only(sb, dev_uuid);
return sb;
@@ -1061,6 +1070,8 @@ char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uu
sb = query_dev(devname, false, false, true, dev_uuid);
if(!sb)
return err;
+ else
+ free(sb);
if(!strcmp(stats_dev_uuid, dev_uuid)) {
strcat(subdir, intbuf);
diff --git a/bcacheadm.c b/bcacheadm.c
index ea9fc751..9cbf3462 100644
--- a/bcacheadm.c
+++ b/bcacheadm.c
@@ -562,6 +562,7 @@ int bcache_query_devs(NihCommand *command, char *const *args)
set_uuid_str,
clus_uuid);
}
+ free(sb);
}
return 0;
@@ -585,7 +586,8 @@ int bcache_status(NihCommand *command, char *const *args)
seq = sb->seq;
seq_sb = sb;
nr_in_set = sb->nr_in_set;
- }
+ } else
+ free(sb);
}
if(!seq_sb)
@@ -604,6 +606,9 @@ int bcache_status(NihCommand *command, char *const *args)
CACHE_TIER(m));
}
+ if(seq_sb)
+ free(seq_sb);
+
return 0;
}