summaryrefslogtreecommitdiff
path: root/libbcachefs/super-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/super-io.c')
-rw-r--r--libbcachefs/super-io.c110
1 files changed, 72 insertions, 38 deletions
diff --git a/libbcachefs/super-io.c b/libbcachefs/super-io.c
index f333b8fa..c7473917 100644
--- a/libbcachefs/super-io.c
+++ b/libbcachefs/super-io.c
@@ -546,6 +546,8 @@ int bch2_read_super(const char *path, struct bch_opts *opts,
__le64 *i;
int ret;
+ pr_verbose_init(*opts, "");
+
memset(sb, 0, sizeof(*sb));
sb->mode = FMODE_READ;
@@ -566,8 +568,10 @@ int bch2_read_super(const char *path, struct bch_opts *opts,
opt_set(*opts, nochanges, true);
}
- if (IS_ERR(sb->bdev))
- return PTR_ERR(sb->bdev);
+ if (IS_ERR(sb->bdev)) {
+ ret = PTR_ERR(sb->bdev);
+ goto out;
+ }
err = "cannot allocate memory";
ret = __bch2_super_realloc(sb, 0);
@@ -638,12 +642,14 @@ got_super:
if (sb->mode & FMODE_WRITE)
bdev_get_queue(sb->bdev)->backing_dev_info->capabilities
|= BDI_CAP_STABLE_WRITES;
-
- return 0;
+ ret = 0;
+out:
+ pr_verbose_init(*opts, "ret %i", ret);
+ return ret;
err:
bch2_free_super(sb);
pr_err("error reading superblock: %s", err);
- return ret;
+ goto out;
}
/* write superblock: */
@@ -744,17 +750,15 @@ void bch2_write_super(struct bch_fs *c)
nr_wrote = dev_mask_nr(&sb_written);
can_mount_with_written =
- bch2_have_enough_devs(c,
- __bch2_replicas_status(c, sb_written),
- BCH_FORCE_IF_DEGRADED);
+ bch2_have_enough_devs(__bch2_replicas_status(c, sb_written),
+ BCH_FORCE_IF_DEGRADED);
for (i = 0; i < ARRAY_SIZE(sb_written.d); i++)
sb_written.d[i] = ~sb_written.d[i];
can_mount_without_written =
- bch2_have_enough_devs(c,
- __bch2_replicas_status(c, sb_written),
- BCH_FORCE_IF_DEGRADED);
+ bch2_have_enough_devs(__bch2_replicas_status(c, sb_written),
+ BCH_FORCE_IF_DEGRADED);
/*
* If we would be able to mount _without_ the devices we successfully
@@ -1052,7 +1056,7 @@ static bool replicas_has_entry(struct bch_replicas_cpu *r,
}
noinline
-static int bch2_check_mark_super_slowpath(struct bch_fs *c,
+static int bch2_mark_replicas_slowpath(struct bch_fs *c,
struct bch_replicas_cpu_entry new_entry,
unsigned max_dev)
{
@@ -1109,9 +1113,9 @@ err:
return ret;
}
-int bch2_check_mark_super(struct bch_fs *c,
- enum bch_data_type data_type,
- struct bch_devs_list devs)
+int bch2_mark_replicas(struct bch_fs *c,
+ enum bch_data_type data_type,
+ struct bch_devs_list devs)
{
struct bch_replicas_cpu_entry search;
struct bch_replicas_cpu *r, *gc_r;
@@ -1121,6 +1125,8 @@ int bch2_check_mark_super(struct bch_fs *c,
if (!devs.nr)
return 0;
+ BUG_ON(devs.nr >= BCH_REPLICAS_MAX);
+
devlist_to_replicas(devs, data_type, &search, &max_dev);
rcu_read_lock();
@@ -1131,7 +1137,23 @@ int bch2_check_mark_super(struct bch_fs *c,
rcu_read_unlock();
return likely(marked) ? 0
- : bch2_check_mark_super_slowpath(c, search, max_dev);
+ : bch2_mark_replicas_slowpath(c, search, max_dev);
+}
+
+int bch2_mark_bkey_replicas(struct bch_fs *c,
+ enum bch_data_type data_type,
+ struct bkey_s_c k)
+{
+ struct bch_devs_list cached = bch2_bkey_cached_devs(k);
+ unsigned i;
+ int ret;
+
+ for (i = 0; i < cached.nr; i++)
+ if ((ret = bch2_mark_replicas(c, BCH_DATA_CACHED,
+ bch2_dev_list_single(cached.devs[i]))))
+ return ret;
+
+ return bch2_mark_replicas(c, data_type, bch2_bkey_dirty_devs(k));
}
int bch2_replicas_gc_end(struct bch_fs *c, int err)
@@ -1417,7 +1439,7 @@ int bch2_sb_replicas_to_text(struct bch_sb_field_replicas *r, char *buf, size_t
/* Query replicas: */
-bool bch2_sb_has_replicas(struct bch_fs *c,
+bool bch2_replicas_marked(struct bch_fs *c,
enum bch_data_type data_type,
struct bch_devs_list devs)
{
@@ -1438,6 +1460,21 @@ bool bch2_sb_has_replicas(struct bch_fs *c,
return ret;
}
+bool bch2_bkey_replicas_marked(struct bch_fs *c,
+ enum bch_data_type data_type,
+ struct bkey_s_c k)
+{
+ struct bch_devs_list cached = bch2_bkey_cached_devs(k);
+ unsigned i;
+
+ for (i = 0; i < cached.nr; i++)
+ if (!bch2_replicas_marked(c, BCH_DATA_CACHED,
+ bch2_dev_list_single(cached.devs[i])))
+ return false;
+
+ return bch2_replicas_marked(c, data_type, bch2_bkey_dirty_devs(k));
+}
+
struct replicas_status __bch2_replicas_status(struct bch_fs *c,
struct bch_devs_mask online_devs)
{
@@ -1495,29 +1532,26 @@ struct replicas_status bch2_replicas_status(struct bch_fs *c)
return __bch2_replicas_status(c, bch2_online_devs(c));
}
-bool bch2_have_enough_devs(struct bch_fs *c,
- struct replicas_status s,
- unsigned flags)
+static bool have_enough_devs(struct replicas_status s,
+ enum bch_data_type type,
+ bool force_if_degraded,
+ bool force_if_lost)
{
- if ((s.replicas[BCH_DATA_JOURNAL].nr_offline ||
- s.replicas[BCH_DATA_BTREE].nr_offline) &&
- !(flags & BCH_FORCE_IF_METADATA_DEGRADED))
- return false;
-
- if ((!s.replicas[BCH_DATA_JOURNAL].nr_online ||
- !s.replicas[BCH_DATA_BTREE].nr_online) &&
- !(flags & BCH_FORCE_IF_METADATA_LOST))
- return false;
-
- if (s.replicas[BCH_DATA_USER].nr_offline &&
- !(flags & BCH_FORCE_IF_DATA_DEGRADED))
- return false;
-
- if (!s.replicas[BCH_DATA_USER].nr_online &&
- !(flags & BCH_FORCE_IF_DATA_LOST))
- return false;
+ return (!s.replicas[type].nr_offline || force_if_degraded) &&
+ (s.replicas[type].nr_online || force_if_lost);
+}
- return true;
+bool bch2_have_enough_devs(struct replicas_status s, unsigned flags)
+{
+ return (have_enough_devs(s, BCH_DATA_JOURNAL,
+ flags & BCH_FORCE_IF_METADATA_DEGRADED,
+ flags & BCH_FORCE_IF_METADATA_LOST) &&
+ have_enough_devs(s, BCH_DATA_BTREE,
+ flags & BCH_FORCE_IF_METADATA_DEGRADED,
+ flags & BCH_FORCE_IF_METADATA_LOST) &&
+ have_enough_devs(s, BCH_DATA_USER,
+ flags & BCH_FORCE_IF_DATA_DEGRADED,
+ flags & BCH_FORCE_IF_DATA_LOST));
}
unsigned bch2_replicas_online(struct bch_fs *c, bool meta)