summaryrefslogtreecommitdiff
path: root/libbcache/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcache/super.c')
-rw-r--r--libbcache/super.c94
1 files changed, 88 insertions, 6 deletions
diff --git a/libbcache/super.c b/libbcache/super.c
index bb4a7dc3..1e272af2 100644
--- a/libbcache/super.c
+++ b/libbcache/super.c
@@ -1069,7 +1069,7 @@ static void bch_dev_io_ref_release(struct percpu_ref *ref)
complete(&ca->offline_complete);
}
-static void bch_dev_offline(struct bch_dev *ca)
+static void __bch_dev_offline(struct bch_dev *ca)
{
struct bch_fs *c = ca->fs;
@@ -1244,7 +1244,7 @@ err:
return -ENOMEM;
}
-static int bch_dev_online(struct bch_fs *c, struct bcache_superblock *sb)
+static int __bch_dev_online(struct bch_fs *c, struct bcache_superblock *sb)
{
struct bch_dev *ca;
int ret;
@@ -1534,7 +1534,7 @@ static int __bch_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
bch_journal_meta(&c->journal);
- bch_dev_offline(ca);
+ __bch_dev_offline(ca);
bch_dev_stop(ca);
bch_dev_free(ca);
@@ -1644,7 +1644,7 @@ have_slot:
goto err_unlock;
}
- if (bch_dev_online(c, &sb)) {
+ if (__bch_dev_online(c, &sb)) {
err = "bch_dev_online() error";
ret = -ENOMEM;
goto err_unlock;
@@ -1677,6 +1677,88 @@ err:
return ret ?: -EINVAL;
}
+int bch_dev_online(struct bch_fs *c, const char *path)
+{
+ struct bcache_superblock sb = { 0 };
+ const char *err;
+
+ mutex_lock(&c->state_lock);
+
+ err = bch_read_super(&sb, bch_opts_empty(), path);
+ if (err)
+ goto err;
+
+ err = bch_dev_in_fs(c->disk_sb, sb.sb);
+ if (err)
+ goto err;
+
+ mutex_lock(&c->sb_lock);
+ if (__bch_dev_online(c, &sb)) {
+ mutex_unlock(&c->sb_lock);
+ goto err;
+ }
+ mutex_unlock(&c->sb_lock);
+
+ mutex_unlock(&c->state_lock);
+ return 0;
+err:
+ mutex_unlock(&c->state_lock);
+ bch_free_super(&sb);
+ bch_err(c, "error bringing %s online: %s", path, err);
+ return -EINVAL;
+}
+
+int bch_dev_offline(struct bch_fs *c, struct bch_dev *ca, int flags)
+{
+ mutex_lock(&c->state_lock);
+
+ if (!bch_dev_state_allowed(c, ca, BCH_MEMBER_STATE_FAILED, flags)) {
+ bch_err(ca, "Cannot offline required disk");
+ mutex_unlock(&c->state_lock);
+ return -EINVAL;
+ }
+
+ __bch_dev_read_only(c, ca);
+ __bch_dev_offline(ca);
+
+ mutex_unlock(&c->state_lock);
+ return 0;
+}
+
+int bch_dev_migrate(struct bch_fs *c, struct bch_dev *ca)
+{
+ int ret;
+
+ mutex_lock(&c->state_lock);
+
+ if (ca->mi.state == BCH_MEMBER_STATE_RW) {
+ bch_err(ca, "Cannot migrate data off RW device");
+ mutex_unlock(&c->state_lock);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&c->state_lock);
+
+ ret = bch_move_data_off_device(ca);
+ if (ret) {
+ bch_err(ca, "Error migrating data: %i", ret);
+ return ret;
+ }
+
+ ret = bch_move_metadata_off_device(ca);
+ if (ret) {
+ bch_err(ca, "Error migrating metadata: %i", ret);
+ return ret;
+ }
+
+ if (ca->mi.has_data || ca->mi.has_metadata) {
+ bch_err(ca, "Migrate error: data still present");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/* Filesystem open: */
const char *bch_fs_open(char * const *devices, unsigned nr_devices,
@@ -1731,7 +1813,7 @@ const char *bch_fs_open(char * const *devices, unsigned nr_devices,
err = "bch_dev_online() error";
mutex_lock(&c->sb_lock);
for (i = 0; i < nr_devices; i++)
- if (bch_dev_online(c, &sb[i])) {
+ if (__bch_dev_online(c, &sb[i])) {
mutex_unlock(&c->sb_lock);
goto err;
}
@@ -1803,7 +1885,7 @@ static const char *__bch_fs_open_incremental(struct bcache_superblock *sb,
err = "bch_dev_online() error";
mutex_lock(&c->sb_lock);
- if (bch_dev_online(c, sb)) {
+ if (__bch_dev_online(c, sb)) {
mutex_unlock(&c->sb_lock);
goto err;
}