summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 623ea830..f7b92cdf 100644
--- a/bcacheadm.c
+++ b/bcacheadm.c
@@ -559,6 +559,7 @@ int bcache_query_devs(NihCommand *command, char *const *args)
set_uuid_str,
clus_uuid);
}
+ free(sb);
}
return 0;
@@ -582,7 +583,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)
@@ -601,6 +603,9 @@ int bcache_status(NihCommand *command, char *const *args)
CACHE_TIER(m));
}
+ if(seq_sb)
+ free(seq_sb);
+
return 0;
}