struct bch_sb_field_disk_groups *groups =
field_to_type(f, disk_groups);
struct bch_disk_group *g, *sorted = NULL;
- struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
unsigned nr_groups = disk_groups_nr(groups);
unsigned i, len;
int ret = 0;
for (i = 0; i < sb->nr_devices; i++) {
- struct bch_member *m = mi->members + i;
+ struct bch_member m = bch2_sb_member_get(sb, i);
unsigned group_id;
- if (!BCH_MEMBER_GROUP(m))
+ if (!BCH_MEMBER_GROUP(&m))
continue;
- group_id = BCH_MEMBER_GROUP(m) - 1;
+ group_id = BCH_MEMBER_GROUP(&m) - 1;
if (group_id >= nr_groups) {
prt_printf(err, "disk %u has invalid label %u (have %u)",
int bch2_sb_disk_groups_to_cpu(struct bch_fs *c)
{
- struct bch_sb_field_members *mi;
struct bch_sb_field_disk_groups *groups;
struct bch_disk_groups_cpu *cpu_g, *old_g;
unsigned i, g, nr_groups;
lockdep_assert_held(&c->sb_lock);
- mi = bch2_sb_get_members(c->disk_sb.sb);
groups = bch2_sb_get_disk_groups(c->disk_sb.sb);
nr_groups = disk_groups_nr(groups);
}
for (i = 0; i < c->disk_sb.sb->nr_devices; i++) {
- struct bch_member *m = mi->members + i;
+ struct bch_member m = bch2_sb_member_get(c->disk_sb.sb, i);
struct bch_disk_group_cpu *dst;
- if (!bch2_member_exists(m))
+ if (!bch2_member_exists(&m))
continue;
- g = BCH_MEMBER_GROUP(m);
+ g = BCH_MEMBER_GROUP(&m);
while (g) {
dst = &cpu_g->entries[g - 1];
__set_bit(i, dst->devs.d);
rcu_read_unlock();
} else {
- struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
- struct bch_member *m = mi->members + t.dev;
+ struct bch_member m = bch2_sb_member_get(sb, t.dev);
- if (bch2_dev_exists(sb, mi, t.dev)) {
+ if (bch2_dev_exists(sb, t.dev)) {
prt_printf(out, "Device ");
- pr_uuid(out, m->uuid.b);
+ pr_uuid(out, m.uuid.b);
prt_printf(out, " (%u)", t.dev);
} else {
prt_printf(out, "Bad device %u", t.dev);
struct printbuf *err)
{
struct bch_sb_field_journal *journal = field_to_type(f, journal);
- struct bch_member *m = bch2_sb_get_members(sb)->members + sb->dev_idx;
+ struct bch_member m = bch2_sb_member_get(sb, sb->dev_idx);
int ret = -BCH_ERR_invalid_sb_journal;
unsigned nr;
unsigned i;
goto err;
}
- if (b[0] < le16_to_cpu(m->first_bucket)) {
+ if (b[0] < le16_to_cpu(m.first_bucket)) {
prt_printf(err, "journal bucket %llu before first bucket %u",
- b[0], le16_to_cpu(m->first_bucket));
+ b[0], le16_to_cpu(m.first_bucket));
goto err;
}
- if (b[nr - 1] >= le64_to_cpu(m->nbuckets)) {
+ if (b[nr - 1] >= le64_to_cpu(m.nbuckets)) {
prt_printf(err, "journal bucket %llu past end of device (nbuckets %llu)",
- b[nr - 1], le64_to_cpu(m->nbuckets));
+ b[nr - 1], le64_to_cpu(m.nbuckets));
goto err;
}
struct printbuf *err)
{
struct bch_sb_field_journal_v2 *journal = field_to_type(f, journal_v2);
- struct bch_member *m = bch2_sb_get_members(sb)->members + sb->dev_idx;
+ struct bch_member m = bch2_sb_member_get(sb, sb->dev_idx);
int ret = -BCH_ERR_invalid_sb_journal;
unsigned nr;
unsigned i;
goto err;
}
- if (b[0].start < le16_to_cpu(m->first_bucket)) {
+ if (b[0].start < le16_to_cpu(m.first_bucket)) {
prt_printf(err, "journal bucket %llu before first bucket %u",
- b[0].start, le16_to_cpu(m->first_bucket));
+ b[0].start, le16_to_cpu(m.first_bucket));
goto err;
}
- if (b[nr - 1].end > le64_to_cpu(m->nbuckets)) {
+ if (b[nr - 1].end > le64_to_cpu(m.nbuckets)) {
prt_printf(err, "journal bucket %llu past end of device (nbuckets %llu)",
- b[nr - 1].end - 1, le64_to_cpu(m->nbuckets));
+ b[nr - 1].end - 1, le64_to_cpu(m.nbuckets));
goto err;
}
struct bch_sb *sb,
struct printbuf *err)
{
- struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
unsigned i, j;
sort_cmp_size(cpu_r->entries,
}
for (j = 0; j < e->nr_devs; j++)
- if (!bch2_dev_exists(sb, mi, e->devs[j])) {
+ if (!bch2_dev_exists(sb, e->devs[j])) {
prt_printf(err, "invalid device %u in entry ", e->devs[j]);
bch2_replicas_entry_to_text(err, e);
return -BCH_ERR_invalid_sb_replicas;
#include "super-io.h"
/* Code for bch_sb_field_members: */
+static struct bch_member *members_v1_get_mut(struct bch_sb_field_members *mi, int i)
+{
+ return mi->members + i;
+}
+
+static struct bch_member members_v1_get(struct bch_sb_field_members *mi, int i)
+{
+ struct bch_member ret, *p = members_v1_get_mut(mi, i);
+ memset(&ret, 0, sizeof(ret));
+ memcpy(&ret, p, min_t(size_t, sizeof(struct bch_member), sizeof(ret))); return ret;
+}
+
+struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i)
+{
+ struct bch_sb_field_members *mi1 = bch2_sb_get_members(sb);
+ return members_v1_get(mi1, i);
+}
static int bch2_sb_members_validate(struct bch_sb *sb,
struct bch_sb_field *f,
#ifndef _BCACHEFS_SB_MEMBERS_H
#define _BCACHEFS_SB_MEMBERS_H
+struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i);
+
static inline bool bch2_dev_is_online(struct bch_dev *ca)
{
return !percpu_ref_is_zero(&ca->io_ref);
static void bch2_sb_update(struct bch_fs *c)
{
struct bch_sb *src = c->disk_sb.sb;
- struct bch_sb_field_members *mi = bch2_sb_get_members(src);
struct bch_dev *ca;
unsigned i;
c->sb.features = le64_to_cpu(src->features[0]);
c->sb.compat = le64_to_cpu(src->compat[0]);
- for_each_member_device(ca, c, i)
- ca->mi = bch2_mi_to_cpu(mi->members + i);
+ for_each_member_device(ca, c, i) {
+ struct bch_member m = bch2_sb_member_get(src, i);
+ ca->mi = bch2_mi_to_cpu(&m);
+ }
}
static int __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src)
void bch2_sb_to_text(struct printbuf *out, struct bch_sb *sb,
bool print_layout, unsigned fields)
{
- struct bch_sb_field_members *mi;
struct bch_sb_field *f;
u64 fields_have = 0;
unsigned nr_devices = 0;
if (!out->nr_tabstops)
printbuf_tabstop_push(out, 44);
- 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);
- }
+ for (int i = 0; i < sb->nr_devices; i++)
+ nr_devices += bch2_dev_exists(sb, i);
prt_printf(out, "External UUID:");
prt_tab(out);
#include "eytzinger.h"
#include "super_types.h"
#include "super.h"
+#include "sb-members.h"
#include <asm/byteorder.h>
}
static inline bool bch2_dev_exists(struct bch_sb *sb,
- struct bch_sb_field_members *mi,
unsigned dev)
{
- return dev < sb->nr_devices &&
- bch2_member_exists(&mi->members[dev]);
+ if (dev < sb->nr_devices) {
+ struct bch_member m = bch2_sb_member_get(sb, dev);
+ return bch2_member_exists(&m);
+ }
+ return false;
}
static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
#include "recovery.h"
#include "replicas.h"
#include "sb-clean.h"
+#include "sb-members.h"
#include "snapshot.h"
#include "subvolume.h"
#include "super.h"
static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
{
- struct bch_sb_field_members *mi;
struct bch_fs *c;
struct printbuf name = PRINTBUF;
unsigned i, iter_size;
if (ret)
goto err;
- mi = bch2_sb_get_members(c->disk_sb.sb);
for (i = 0; i < c->sb.nr_devices; i++)
- if (bch2_dev_exists(c->disk_sb.sb, mi, i) &&
+ if (bch2_dev_exists(c->disk_sb.sb, i) &&
bch2_dev_alloc(c, i)) {
ret = -EEXIST;
goto err;
static int bch2_dev_may_add(struct bch_sb *sb, struct bch_fs *c)
{
- struct bch_sb_field_members *sb_mi;
-
- sb_mi = bch2_sb_get_members(sb);
- if (!sb_mi)
- return -BCH_ERR_member_info_missing;
+ struct bch_member m = bch2_sb_member_get(sb, sb->dev_idx);
if (le16_to_cpu(sb->block_size) != block_sectors(c))
return -BCH_ERR_mismatched_block_size;
- if (le16_to_cpu(sb_mi->members[sb->dev_idx].bucket_size) <
+ if (le16_to_cpu(m.bucket_size) <
BCH_SB_BTREE_NODE_SIZE(c->disk_sb.sb))
return -BCH_ERR_bucket_size_too_small;
{
struct bch_sb *newest =
le64_to_cpu(fs->seq) > le64_to_cpu(sb->seq) ? fs : sb;
- struct bch_sb_field_members *mi = bch2_sb_get_members(newest);
if (!uuid_equal(&fs->uuid, &sb->uuid))
return -BCH_ERR_device_not_a_member_of_filesystem;
- if (!bch2_dev_exists(newest, mi, sb->dev_idx))
+ if (!bch2_dev_exists(newest, sb->dev_idx))
return -BCH_ERR_device_has_been_removed;
if (fs->block_size != sb->block_size)
static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx)
{
- struct bch_member *member =
- bch2_sb_get_members(c->disk_sb.sb)->members + dev_idx;
+ struct bch_member member = bch2_sb_member_get(c->disk_sb.sb, dev_idx);
struct bch_dev *ca = NULL;
int ret = 0;
if (bch2_fs_init_fault("dev_alloc"))
goto err;
- ca = __bch2_dev_alloc(c, member);
+ ca = __bch2_dev_alloc(c, &member);
if (!ca)
goto err;
static bool bch2_fs_may_start(struct bch_fs *c)
{
- struct bch_sb_field_members *mi;
struct bch_dev *ca;
unsigned i, flags = 0;
if (!c->opts.degraded &&
!c->opts.very_degraded) {
mutex_lock(&c->sb_lock);
- mi = bch2_sb_get_members(c->disk_sb.sb);
for (i = 0; i < c->disk_sb.sb->nr_devices; i++) {
- if (!bch2_dev_exists(c->disk_sb.sb, mi, i))
+ if (!bch2_dev_exists(c->disk_sb.sb, i))
continue;
ca = bch_dev_locked(c, i);
goto err;
}
- dev_mi = bch2_sb_get_members(sb.sb)->members[sb.sb->dev_idx];
+ dev_mi = bch2_sb_member_get(sb.sb, sb.sb->dev_idx);
if (BCH_MEMBER_GROUP(&dev_mi)) {
bch2_disk_path_to_text(&label, sb.sb, BCH_MEMBER_GROUP(&dev_mi) - 1);
if (dynamic_fault("bcachefs:add:no_slot"))
goto no_slot;
- mi = bch2_sb_get_members(c->disk_sb.sb);
for (dev_idx = 0; dev_idx < BCH_SB_MEMBERS_MAX; dev_idx++)
- if (!bch2_dev_exists(c->disk_sb.sb, mi, dev_idx))
+ if (!bch2_dev_exists(c->disk_sb.sb, dev_idx))
goto have_slot;
no_slot:
ret = -BCH_ERR_ENOSPC_sb_members;
{
struct bch_sb_handle *sb = NULL;
struct bch_fs *c = NULL;
- struct bch_sb_field_members *mi;
unsigned i, best_sb = 0;
struct printbuf errbuf = PRINTBUF;
int ret = 0;
le64_to_cpu(sb[best_sb].sb->seq))
best_sb = i;
- mi = bch2_sb_get_members(sb[best_sb].sb);
-
i = 0;
while (i < nr_devices) {
if (i != best_sb &&
- !bch2_dev_exists(sb[best_sb].sb, mi, sb[i].sb->dev_idx)) {
+ !bch2_dev_exists(sb[best_sb].sb, sb[i].sb->dev_idx)) {
pr_info("%pg has been removed, skipping", sb[i].bdev);
bch2_free_super(&sb[i]);
array_remove_item(sb, nr_devices, i);