]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - bcache.c
Merge branch 'master' of ssh://gits.daterainc.com:2984/project/2013.MAIN/bcache-tools
[bcachefs-tools-debian] / bcache.c
index f6fcb24c1f1e4fa52a7ac343048c00e41f5632ac..2bc32c035a20efb55cebbd4945178d869bd0f235 100644 (file)
--- a/bcache.c
+++ b/bcache.c
@@ -559,16 +559,6 @@ static unsigned min_bucket_size(int num_bucket_sizes, unsigned *bucket_sizes)
        return min;
 }
 
-static unsigned node_size(unsigned bucket_size) {
-
-       if (bucket_size <= 256)
-               return bucket_size;
-       else if (bucket_size <= 512)
-               return bucket_size / 2;
-       else
-               return bucket_size / 4;
-}
-
 void write_cache_sbs(int *fds, struct cache_sb *sb,
                            unsigned block_size, unsigned *bucket_sizes,
                                int num_bucket_sizes)
@@ -596,7 +586,8 @@ void write_cache_sbs(int *fds, struct cache_sb *sb,
                        sb->bucket_size = bucket_sizes[0];
                else
                        sb->bucket_size = bucket_sizes[i];
-               SET_CACHE_BTREE_NODE_SIZE(sb, node_size(min_size));
+               SET_CACHE_BTREE_NODE_SIZE(sb, min_size);
+
 
                sb->uuid = m->uuid;
                sb->nbuckets            = getblocks(fds[i]) / sb->bucket_size;
@@ -755,7 +746,7 @@ static void show_super_common(struct cache_sb *sb, bool force_csum)
                printf(" [match]\n");
        } else {
                printf(" [expected %" PRIX64 "]\n", expected_csum);
-               if (!force_csum) {
+               if (force_csum) {
                        fprintf(stderr, "Corrupt superblock (bad csum)\n");
                        exit(2);
                }
@@ -906,30 +897,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;
@@ -964,41 +964,50 @@ static char *dev_name(const char *ugly_path) {
 
 static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name) {
        int i = 0;
-       DIR *cachedir;
+       DIR *cachedir, *dir;
        struct stat cache_stat;
-       char intbuf[4];
        char entry[MAX_PATH];
-
-       snprintf(entry, MAX_PATH, "%s/%s/cache0", cset_dir, cset_name);
-       snprintf(intbuf, 4, "%d", i);
-
-       while(true) {
-               char buf[MAX_PATH];
-               int len;
-               char *tmp;
-
-               if((cachedir = opendir(entry)) == NULL)
-                       break;
-
-               if(stat(entry, &cache_stat))
-                       break;
-
-               if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) {
-                       buf[len] = '\0';
-                       if(parse_dev_name) {
-                               tmp = dev_name(buf);
-                               printf("/dev%s\n", tmp);
-                               free(tmp);
-                       } else {
-                               printf("\t%s\n", buf);
+       struct dirent *ent;
+       snprintf(entry, MAX_PATH, "%s/%s", cset_dir, cset_name);
+
+       if((dir = opendir(entry)) != NULL) {
+               while((ent = readdir(dir)) != NULL) {
+                       char buf[MAX_PATH];
+                       int len;
+                       char *tmp;
+
+                       /*
+                        * We are looking for all cache# directories
+                        * do a strlen < 9 to skip over other entries
+                        * that also start with "cache"
+                        */
+                       if(strncmp(ent->d_name, "cache", 5) ||
+                                       !(strlen(ent->d_name) < 9))
+                               continue;
+
+                       snprintf(entry, MAX_PATH, "%s/%s/%s",
+                                       cset_dir,
+                                       cset_name,
+                                       ent->d_name);
+
+                       if((cachedir = opendir(entry)) == NULL)
+                               continue;
+
+                       if(stat(entry, &cache_stat))
+                               continue;
+
+                       if((len = readlink(entry, buf, sizeof(buf) - 1)) !=
+                                       -1) {
+                               buf[len] = '\0';
+                               if(parse_dev_name) {
+                                       tmp = dev_name(buf);
+                                       printf("/dev%s\n", tmp);
+                                       free(tmp);
+                               } else {
+                                       printf("\t%s\n", buf);
+                               }
                        }
                }
-
-               /* remove i from end and append i++ */
-               entry[strlen(entry)-strlen(intbuf)] = 0;
-               i++;
-               snprintf(intbuf, 4, "%d", i);
-               strcat(entry, intbuf);
        }
 }
 
@@ -1052,6 +1061,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);