]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs.c
nix: replace deprecated cargo/rustc aliases with new version
[bcachefs-tools-debian] / libbcachefs.c
index 393d36857e0626ea049fccc2b21850f27ef1595a..092a54a67ef8ffb82b0807560f8e39dedc0017af 100644 (file)
@@ -39,7 +39,7 @@ static void init_layout(struct bch_sb_layout *l,
 
        memset(l, 0, sizeof(*l));
 
-       l->magic                = BCACHE_MAGIC;
+       l->magic                = BCHFS_MAGIC;
        l->layout_type          = 0;
        l->nr_superblocks       = 2;
        l->sb_max_size_bits     = ilog2(sb_size);
@@ -188,7 +188,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs      fs_opt_strs,
 
        sb.sb->version          = le16_to_cpu(opts.version);
        sb.sb->version_min      = le16_to_cpu(opts.version);
-       sb.sb->magic            = BCACHE_MAGIC;
+       sb.sb->magic            = BCHFS_MAGIC;
        sb.sb->user_uuid        = opts.uuid;
        sb.sb->nr_devices       = nr_devs;
 
@@ -241,7 +241,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs      fs_opt_strs,
 
        /* Disk labels*/
        for (i = devs; i < devs + nr_devs; i++) {
-               struct bch_member *m = mi->members + (i - devs);
+               struct bch_member *m;
                int idx;
 
                if (!i->label)
@@ -251,6 +251,13 @@ struct bch_sb *bch2_format(struct bch_opt_strs     fs_opt_strs,
                if (idx < 0)
                        die("error creating disk path: %s", strerror(-idx));
 
+               /*
+                * Recompute mi and m after each sb modification: its location
+                * in memory may have changed due to reallocation.
+                */
+               mi = bch2_sb_get_members(sb.sb);
+               m = mi->members + (i - devs);
+
                SET_BCH_MEMBER_GROUP(m, idx + 1);
        }
 
@@ -346,7 +353,8 @@ struct bch_sb *__bch2_super_read(int fd, u64 sector)
 
        xpread(fd, &sb, sizeof(sb), sector << 9);
 
-       if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic)))
+       if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic)) &&
+           memcmp(&sb.magic, &BCHFS_MAGIC, sizeof(sb.magic)))
                die("not a bcachefs superblock");
 
        size_t bytes = vstruct_bytes(&sb);
@@ -358,503 +366,6 @@ struct bch_sb *__bch2_super_read(int fd, u64 sector)
        return ret;
 }
 
-static unsigned get_dev_has_data(struct bch_sb *sb, unsigned dev)
-{
-       struct bch_sb_field_replicas *replicas;
-       struct bch_replicas_entry *r;
-       unsigned i, data_has = 0;
-
-       replicas = bch2_sb_get_replicas(sb);
-
-       if (replicas)
-               for_each_replicas_entry(replicas, r)
-                       for (i = 0; i < r->nr_devs; i++)
-                               if (r->devs[i] == dev)
-                                       data_has |= 1 << r->data_type;
-
-       return data_has;
-}
-
-static int bch2_sb_get_target(struct bch_sb *sb, char *buf, size_t len, u64 v)
-{
-       struct target t = target_decode(v);
-       int ret;
-
-       switch (t.type) {
-       case TARGET_NULL:
-               return scnprintf(buf, len, "none");
-       case TARGET_DEV: {
-               struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
-               struct bch_member *m = mi->members + t.dev;
-
-               if (bch2_dev_exists(sb, mi, t.dev)) {
-                       char uuid_str[40];
-
-                       uuid_unparse(m->uuid.b, uuid_str);
-
-                       ret = scnprintf(buf, len, "Device %u (%s)", t.dev,
-                               uuid_str);
-               } else {
-                       ret = scnprintf(buf, len, "Bad device %u", t.dev);
-               }
-
-               break;
-       }
-       case TARGET_GROUP: {
-               struct bch_sb_field_disk_groups *gi;
-               gi = bch2_sb_get_disk_groups(sb);
-
-               struct bch_disk_group *g = gi->entries + t.group;
-
-               if (t.group < disk_groups_nr(gi) && !BCH_GROUP_DELETED(g)) {
-                       ret = scnprintf(buf, len, "Label %u (%.*s)", t.group,
-                               BCH_SB_LABEL_SIZE, g->label);
-               } else {
-                       ret = scnprintf(buf, len, "Bad label %u", t.group);
-               }
-               break;
-       }
-       default:
-               BUG();
-       }
-
-       return ret;
-}
-
-/* superblock printing: */
-
-static void bch2_sb_print_layout(struct bch_sb *sb, enum units units)
-{
-       struct bch_sb_layout *l = &sb->layout;
-       unsigned i;
-
-       printf("  type:                         %u\n"
-              "  superblock max size:          %s\n"
-              "  nr superblocks:               %u\n"
-              "  Offsets:                      ",
-              l->layout_type,
-              pr_units(1 << l->sb_max_size_bits, units),
-              l->nr_superblocks);
-
-       for (i = 0; i < l->nr_superblocks; i++) {
-               if (i)
-                       printf(", ");
-               printf("%llu", le64_to_cpu(l->sb_offset[i]));
-       }
-       putchar('\n');
-}
-
-static void bch2_sb_print_journal(struct bch_sb *sb, struct bch_sb_field *f,
-                                 enum units units)
-{
-       struct bch_sb_field_journal *journal = field_to_type(f, journal);
-       unsigned i, nr = bch2_nr_journal_buckets(journal);
-
-       printf("  Buckets:                      ");
-       for (i = 0; i < nr; i++) {
-               if (i)
-                       putchar(' ');
-               printf("%llu", le64_to_cpu(journal->buckets[i]));
-       }
-       putchar('\n');
-}
-
-static void bch2_sb_print_members(struct bch_sb *sb, struct bch_sb_field *f,
-                                 enum units units)
-{
-       struct bch_sb_field_members *mi = field_to_type(f, members);
-       struct bch_sb_field_disk_groups *gi = bch2_sb_get_disk_groups(sb);
-       unsigned i;
-
-       for (i = 0; i < sb->nr_devices; i++) {
-               struct bch_member *m = mi->members + i;
-               time_t last_mount = le64_to_cpu(m->last_mount);
-               char member_uuid_str[40];
-               char data_allowed_str[100];
-               char data_has_str[100];
-               char label [BCH_SB_LABEL_SIZE+10];
-               char time_str[64];
-
-               if (!bch2_member_exists(m))
-                       continue;
-
-               uuid_unparse(m->uuid.b, member_uuid_str);
-
-               if (BCH_MEMBER_GROUP(m)) {
-                       unsigned idx = BCH_MEMBER_GROUP(m) - 1;
-
-                       if (idx < disk_groups_nr(gi)) {
-                               scnprintf(label, sizeof(label), "%.*s (%u)",
-                                       BCH_SB_LABEL_SIZE,
-                                       gi->entries[idx].label, idx);
-                       } else {
-                               strcpy(label, "(bad disk labels section)");
-                       }
-               } else {
-                       strcpy(label, "(none)");
-               }
-
-               bch2_flags_to_text(&PBUF(data_allowed_str),
-                                  bch2_data_types,
-                                  BCH_MEMBER_DATA_ALLOWED(m));
-               if (!data_allowed_str[0])
-                       strcpy(data_allowed_str, "(none)");
-
-               bch2_flags_to_text(&PBUF(data_has_str),
-                                  bch2_data_types,
-                                  get_dev_has_data(sb, i));
-               if (!data_has_str[0])
-                       strcpy(data_has_str, "(none)");
-
-               if (last_mount) {
-                       struct tm *tm = localtime(&last_mount);
-                       size_t err = strftime(time_str, sizeof(time_str), "%c", tm);
-                       if (!err)
-                               strcpy(time_str, "(formatting error)");
-               } else {
-                       strcpy(time_str, "(never)");
-               }
-
-               printf("  Device %u:\n"
-                      "    UUID:                       %s\n"
-                      "    Size:                       %s\n"
-                      "    Bucket size:                %s\n"
-                      "    First bucket:               %u\n"
-                      "    Buckets:                    %llu\n"
-                      "    Last mount:                 %s\n"
-                      "    State:                      %s\n"
-                      "    Group:                      %s\n"
-                      "    Data allowed:               %s\n"
-
-                      "    Has data:                   %s\n"
-
-                      "    Discard:                    %llu\n",
-                      i, member_uuid_str,
-                      pr_units(le16_to_cpu(m->bucket_size) *
-                               le64_to_cpu(m->nbuckets), units),
-                      pr_units(le16_to_cpu(m->bucket_size), units),
-                      le16_to_cpu(m->first_bucket),
-                      le64_to_cpu(m->nbuckets),
-                      time_str,
-
-                      BCH_MEMBER_STATE(m) < BCH_MEMBER_STATE_NR
-                      ? bch2_member_states[BCH_MEMBER_STATE(m)]
-                      : "unknown",
-
-                      label,
-                      data_allowed_str,
-                      data_has_str,
-
-                      BCH_MEMBER_DISCARD(m));
-       }
-}
-
-static void bch2_sb_print_crypt(struct bch_sb *sb, struct bch_sb_field *f,
-                               enum units units)
-{
-       struct bch_sb_field_crypt *crypt = field_to_type(f, crypt);
-
-       printf("  KFD:                  %llu\n"
-              "  scrypt n:             %llu\n"
-              "  scrypt r:             %llu\n"
-              "  scrypt p:             %llu\n",
-              BCH_CRYPT_KDF_TYPE(crypt),
-              BCH_KDF_SCRYPT_N(crypt),
-              BCH_KDF_SCRYPT_R(crypt),
-              BCH_KDF_SCRYPT_P(crypt));
-}
-
-static void bch2_sb_print_replicas_v0(struct bch_sb *sb, struct bch_sb_field *f,
-                                     enum units units)
-{
-       struct bch_sb_field_replicas_v0 *replicas = field_to_type(f, replicas_v0);
-       struct bch_replicas_entry_v0 *e;
-       unsigned i;
-
-       for_each_replicas_entry(replicas, e) {
-               printf_pad(32, "  %s:", bch2_data_types[e->data_type]);
-
-               putchar('[');
-               for (i = 0; i < e->nr_devs; i++) {
-                       if (i)
-                               putchar(' ');
-                       printf("%u", e->devs[i]);
-               }
-               printf("]\n");
-       }
-}
-
-static void bch2_sb_print_replicas(struct bch_sb *sb, struct bch_sb_field *f,
-                                  enum units units)
-{
-       struct bch_sb_field_replicas *replicas = field_to_type(f, replicas);
-       struct bch_replicas_entry *e;
-       unsigned i;
-
-       for_each_replicas_entry(replicas, e) {
-               printf_pad(32, "  %s: %u/%u",
-                          bch2_data_types[e->data_type],
-                          e->nr_required,
-                          e->nr_devs);
-
-               putchar('[');
-               for (i = 0; i < e->nr_devs; i++) {
-                       if (i)
-                               putchar(' ');
-                       printf("%u", e->devs[i]);
-               }
-               printf("]\n");
-       }
-}
-
-static void bch2_sb_print_quota(struct bch_sb *sb, struct bch_sb_field *f,
-                               enum units units)
-{
-}
-
-static void bch2_sb_print_disk_groups(struct bch_sb *sb, struct bch_sb_field *f,
-                                     enum units units)
-{
-}
-
-static void bch2_sb_print_clean(struct bch_sb *sb, struct bch_sb_field *f,
-                               enum units units)
-{
-       struct bch_sb_field_clean *clean = field_to_type(f, clean);
-
-
-       printf("  flags:       %x", le32_to_cpu(clean->flags));
-       printf("  journal seq: %llx", le64_to_cpu(clean->journal_seq));
-}
-
-static void bch2_sb_print_journal_seq_blacklist(struct bch_sb *sb, struct bch_sb_field *f,
-                                               enum units units)
-{
-       struct bch_sb_field_journal_seq_blacklist *bl = field_to_type(f, journal_seq_blacklist);
-       unsigned i, nr = blacklist_nr_entries(bl);
-
-       for (i = 0; i < nr; i++) {
-               struct journal_seq_blacklist_entry *e =
-                       bl->start + i;
-
-               printf("  %llu-%llu\n",
-                      le64_to_cpu(e->start),
-                      le64_to_cpu(e->end));
-       }
-}
-
-typedef void (*sb_field_print_fn)(struct bch_sb *, struct bch_sb_field *, enum units);
-
-struct bch_sb_field_toolops {
-       sb_field_print_fn       print;
-};
-
-static const struct bch_sb_field_toolops bch2_sb_field_ops[] = {
-#define x(f, nr)                                       \
-       [BCH_SB_FIELD_##f] = {                          \
-               .print  = bch2_sb_print_##f,            \
-       },
-       BCH_SB_FIELDS()
-#undef x
-};
-
-static inline void bch2_sb_field_print(struct bch_sb *sb,
-                                      struct bch_sb_field *f,
-                                      enum units units)
-{
-       unsigned type = le32_to_cpu(f->type);
-
-       if (type < BCH_SB_FIELD_NR)
-               bch2_sb_field_ops[type].print(sb, f, units);
-       else
-               printf("(unknown field %u)\n", type);
-}
-
-void bch2_sb_print(struct bch_sb *sb, bool print_layout,
-                  unsigned fields, enum units units)
-{
-       struct bch_sb_field_members *mi;
-       char user_uuid_str[40], internal_uuid_str[40];
-       char features_str[500];
-       char compat_features_str[500];
-       char fields_have_str[200];
-       char label[BCH_SB_LABEL_SIZE + 1];
-       char time_str[64];
-       char foreground_str[64];
-       char background_str[64];
-       char promote_str[64];
-       char metadata_str[64];
-       struct bch_sb_field *f;
-       u64 fields_have = 0;
-       unsigned nr_devices = 0;
-       time_t time_base = le64_to_cpu(sb->time_base_lo) / NSEC_PER_SEC;
-
-       memcpy(label, sb->label, BCH_SB_LABEL_SIZE);
-       label[BCH_SB_LABEL_SIZE] = '\0';
-
-       uuid_unparse(sb->user_uuid.b, user_uuid_str);
-       uuid_unparse(sb->uuid.b, internal_uuid_str);
-
-       if (time_base) {
-               struct tm *tm = localtime(&time_base);
-               size_t err = strftime(time_str, sizeof(time_str), "%c", tm);
-               if (!err)
-                       strcpy(time_str, "(formatting error)");
-       } else {
-               strcpy(time_str, "(not set)");
-       }
-
-       mi = bch2_sb_get_members(sb);
-       if (mi) {
-               struct bch_member *m;
-
-               for (m = mi->members;
-                    m < mi->members + sb->nr_devices;
-                    m++)
-                       nr_devices += bch2_member_exists(m);
-       }
-
-       bch2_sb_get_target(sb, foreground_str, sizeof(foreground_str),
-               BCH_SB_FOREGROUND_TARGET(sb));
-
-       bch2_sb_get_target(sb, background_str, sizeof(background_str),
-               BCH_SB_BACKGROUND_TARGET(sb));
-
-       bch2_sb_get_target(sb, promote_str, sizeof(promote_str),
-               BCH_SB_PROMOTE_TARGET(sb));
-
-       bch2_sb_get_target(sb, metadata_str, sizeof(metadata_str),
-               BCH_SB_METADATA_TARGET(sb));
-
-       bch2_flags_to_text(&PBUF(features_str),
-                          bch2_sb_features,
-                          le64_to_cpu(sb->features[0]));
-
-       bch2_flags_to_text(&PBUF(compat_features_str),
-                          bch2_sb_compat,
-                          le64_to_cpu(sb->compat[0]));
-
-       vstruct_for_each(sb, f)
-               fields_have |= 1 << le32_to_cpu(f->type);
-       bch2_flags_to_text(&PBUF(fields_have_str),
-                          bch2_sb_fields, fields_have);
-
-       printf("External UUID:                  %s\n"
-              "Internal UUID:                  %s\n"
-              "Device index:                   %u\n"
-              "Label:                          %s\n"
-              "Version:                        %u\n"
-              "Oldest version on disk:         %u\n"
-              "Created:                        %s\n"
-              "Squence number:                 %llu\n"
-              "Block_size:                     %s\n"
-              "Btree node size:                %s\n"
-              "Error action:                   %s\n"
-              "Clean:                          %llu\n"
-              "Features:                       %s\n"
-              "Compat features:                %s\n"
-
-              "Metadata replicas:              %llu\n"
-              "Data replicas:                  %llu\n"
-
-              "Metadata checksum type:         %s (%llu)\n"
-              "Data checksum type:             %s (%llu)\n"
-              "Compression type:               %s (%llu)\n"
-
-              "Foreground write target:        %s\n"
-              "Background write target:        %s\n"
-              "Promote target:                 %s\n"
-               "Metadata target:                %s\n"
-
-              "String hash type:               %s (%llu)\n"
-              "32 bit inodes:                  %llu\n"
-              "GC reserve percentage:          %llu%%\n"
-              "Root reserve percentage:        %llu%%\n"
-
-              "Devices:                        %u live, %u total\n"
-              "Sections:                       %s\n"
-              "Superblock size:                %llu\n",
-              user_uuid_str,
-              internal_uuid_str,
-              sb->dev_idx,
-              label,
-              le16_to_cpu(sb->version),
-              le16_to_cpu(sb->version_min),
-              time_str,
-              le64_to_cpu(sb->seq),
-              pr_units(le16_to_cpu(sb->block_size), units),
-              pr_units(BCH_SB_BTREE_NODE_SIZE(sb), units),
-
-              BCH_SB_ERROR_ACTION(sb) < BCH_ON_ERROR_NR
-              ? bch2_error_actions[BCH_SB_ERROR_ACTION(sb)]
-              : "unknown",
-
-              BCH_SB_CLEAN(sb),
-              features_str,
-              compat_features_str,
-
-              BCH_SB_META_REPLICAS_WANT(sb),
-              BCH_SB_DATA_REPLICAS_WANT(sb),
-
-              BCH_SB_META_CSUM_TYPE(sb) < BCH_CSUM_OPT_NR
-              ? bch2_csum_opts[BCH_SB_META_CSUM_TYPE(sb)]
-              : "unknown",
-              BCH_SB_META_CSUM_TYPE(sb),
-
-              BCH_SB_DATA_CSUM_TYPE(sb) < BCH_CSUM_OPT_NR
-              ? bch2_csum_opts[BCH_SB_DATA_CSUM_TYPE(sb)]
-              : "unknown",
-              BCH_SB_DATA_CSUM_TYPE(sb),
-
-              BCH_SB_COMPRESSION_TYPE(sb) < BCH_COMPRESSION_OPT_NR
-              ? bch2_compression_opts[BCH_SB_COMPRESSION_TYPE(sb)]
-              : "unknown",
-              BCH_SB_COMPRESSION_TYPE(sb),
-
-              foreground_str,
-              background_str,
-              promote_str,
-               metadata_str,
-
-              BCH_SB_STR_HASH_TYPE(sb) < BCH_STR_HASH_NR
-              ? bch2_str_hash_types[BCH_SB_STR_HASH_TYPE(sb)]
-              : "unknown",
-              BCH_SB_STR_HASH_TYPE(sb),
-
-              BCH_SB_INODE_32BIT(sb),
-              BCH_SB_GC_RESERVE(sb),
-              BCH_SB_ROOT_RESERVE(sb),
-
-              nr_devices, sb->nr_devices,
-              fields_have_str,
-              vstruct_bytes(sb));
-
-       if (print_layout) {
-               printf("\n"
-                      "Layout:\n");
-               bch2_sb_print_layout(sb, units);
-       }
-
-       vstruct_for_each(sb, f) {
-               unsigned type = le32_to_cpu(f->type);
-               char name[60];
-
-               if (!(fields & (1 << type)))
-                       continue;
-
-               if (type < BCH_SB_FIELD_NR) {
-                       scnprintf(name, sizeof(name), "%s", bch2_sb_fields[type]);
-                       name[0] = toupper(name[0]);
-               } else {
-                       scnprintf(name, sizeof(name), "(unknown field %u)", type);
-               }
-
-               printf("\n%s (size %llu):\n", name, vstruct_bytes(f));
-               if (type < BCH_SB_FIELD_NR)
-                       bch2_sb_field_print(sb, f, units);
-       }
-}
-
 /* ioctl interface: */
 
 /* Global control device: */
@@ -1087,6 +598,7 @@ next:
 struct bch_opts bch2_parse_opts(struct bch_opt_strs strs)
 {
        struct bch_opts opts = bch2_opts_empty();
+       struct printbuf err = PRINTBUF;
        unsigned i;
        int ret;
        u64 v;
@@ -1096,17 +608,16 @@ struct bch_opts bch2_parse_opts(struct bch_opt_strs strs)
                    bch2_opt_table[i].type == BCH_OPT_FN)
                        continue;
 
-               ret = bch2_opt_parse(NULL, "option",
+               ret = bch2_opt_parse(NULL,
                                     &bch2_opt_table[i],
-                                    strs.by_id[i], &v);
+                                    strs.by_id[i], &v, &err);
                if (ret < 0)
-                       die("Invalid %s: %s",
-                           bch2_opt_table[i].attr.name,
-                           strerror(-ret));
+                       die("Invalid option %s", err.buf);
 
                bch2_opt_set_by_id(&opts, i, v);
        }
 
+       printbuf_exit(&err);
        return opts;
 }
 
@@ -1179,7 +690,7 @@ dev_names bchu_fs_get_devices(struct bchfs_handle fs)
        struct dirent *d;
        dev_names devs;
 
-       darray_init(devs);
+       darray_init(&devs);
 
        while ((errno = 0), (d = readdir(dir))) {
                struct dev_name n = { 0, NULL, NULL };
@@ -1203,7 +714,7 @@ dev_names bchu_fs_get_devices(struct bchfs_handle fs)
                n.label = read_file_str(fs.sysfs_fd, label_attr);
                free(label_attr);
 
-               darray_append(devs, n);
+               darray_push(&devs, n);
        }
 
        closedir(dir);