]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/super.c
Update bcachefs sources to 9a555a741e80 bcachefs: omit alignment attribute on big...
[bcachefs-tools-debian] / libbcachefs / super.c
index 0f189c9d56b5dfe1bc49a5b10bafe8e1f51861de..a7f9de220d903f45899c9c515ad0bee26ffd2b60 100644 (file)
@@ -23,7 +23,6 @@
 #include "checksum.h"
 #include "clock.h"
 #include "compress.h"
-#include "counters.h"
 #include "debug.h"
 #include "disk_groups.h"
 #include "ec.h"
@@ -49,6 +48,7 @@
 #include "recovery.h"
 #include "replicas.h"
 #include "sb-clean.h"
+#include "sb-counters.h"
 #include "sb-errors.h"
 #include "sb-members.h"
 #include "snapshot.h"
@@ -67,6 +67,7 @@
 #include <linux/percpu.h>
 #include <linux/random.h>
 #include <linux/sysfs.h>
+#include <linux/thread_with_file.h>
 #include <crypto/hash.h>
 
 MODULE_LICENSE("GPL");
@@ -86,28 +87,36 @@ const char * const bch2_fs_flag_strs[] = {
        NULL
 };
 
-void __bch2_print(struct bch_fs *c, const char *fmt, ...)
+void bch2_print_opts(struct bch_opts *opts, const char *fmt, ...)
 {
-       struct log_output *output = c->output;
+       struct stdio_redirect *stdio = (void *)(unsigned long)opts->stdio;
+
        va_list args;
+       va_start(args, fmt);
+       if (likely(!stdio)) {
+               vprintk(fmt, args);
+       } else {
+               if (fmt[0] == KERN_SOH[0])
+                       fmt += 2;
 
-       if (c->output_filter && c->output_filter != current)
-               output = NULL;
+               stdio_redirect_vprintf(stdio, true, fmt, args);
+       }
+       va_end(args);
+}
+
+void __bch2_print(struct bch_fs *c, const char *fmt, ...)
+{
+       struct stdio_redirect *stdio = bch2_fs_stdio_redirect(c);
 
+       va_list args;
        va_start(args, fmt);
-       if (likely(!output)) {
+       if (likely(!stdio)) {
                vprintk(fmt, args);
        } else {
-               unsigned long flags;
-
                if (fmt[0] == KERN_SOH[0])
                        fmt += 2;
 
-               spin_lock_irqsave(&output->lock, flags);
-               prt_vprintf(&output->buf, fmt, args);
-               spin_unlock_irqrestore(&output->lock, flags);
-
-               wake_up(&output->wait);
+               stdio_redirect_vprintf(stdio, true, fmt, args);
        }
        va_end(args);
 }
@@ -523,7 +532,7 @@ static void __bch2_fs_free(struct bch_fs *c)
        unsigned i;
 
        for (i = 0; i < BCH_TIME_STAT_NR; i++)
-               bch2_time_stats_exit(&c->times[i]);
+               time_stats_exit(&c->times[i]);
 
        bch2_free_pending_node_rewrites(c);
        bch2_fs_sb_errors_exit(c);
@@ -579,7 +588,7 @@ static void __bch2_fs_free(struct bch_fs *c)
                destroy_workqueue(c->btree_update_wq);
 
        bch2_free_super(&c->disk_sb);
-       kvpfree(c, sizeof(*c));
+       kvfree(c);
        module_put(THIS_MODULE);
 }
 
@@ -718,13 +727,13 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
        unsigned i, iter_size;
        int ret = 0;
 
-       c = kvpmalloc(sizeof(struct bch_fs), GFP_KERNEL|__GFP_ZERO);
+       c = kvmalloc(sizeof(struct bch_fs), GFP_KERNEL|__GFP_ZERO);
        if (!c) {
                c = ERR_PTR(-BCH_ERR_ENOMEM_fs_alloc);
                goto out;
        }
 
-       c->output = (void *)(unsigned long) opts.log_output;
+       c->stdio = (void *)(unsigned long) opts.stdio;
 
        __module_get(THIS_MODULE);
 
@@ -756,7 +765,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
        c->journal_keys.initial_ref_held = true;
 
        for (i = 0; i < BCH_TIME_STAT_NR; i++)
-               bch2_time_stats_init(&c->times[i]);
+               time_stats_init(&c->times[i]);
 
        bch2_fs_copygc_init(c);
        bch2_fs_btree_key_cache_init_early(&c->btree_key_cache);
@@ -865,13 +874,13 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
        c->inode_shard_bits = ilog2(roundup_pow_of_two(num_possible_cpus()));
 
        if (!(c->btree_update_wq = alloc_workqueue("bcachefs",
-                               WQ_FREEZABLE|WQ_UNBOUND|WQ_MEM_RECLAIM, 512)) ||
+                               WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_UNBOUND, 512)) ||
            !(c->btree_io_complete_wq = alloc_workqueue("bcachefs_btree_io",
-                               WQ_FREEZABLE|WQ_MEM_RECLAIM, 1)) ||
+                               WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 1)) ||
            !(c->copygc_wq = alloc_workqueue("bcachefs_copygc",
-                               WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE, 1)) ||
+                               WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE, 1)) ||
            !(c->io_complete_wq = alloc_workqueue("bcachefs_io",
-                               WQ_FREEZABLE|WQ_HIGHPRI|WQ_MEM_RECLAIM, 1)) ||
+                               WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 512)) ||
            !(c->write_ref_wq = alloc_workqueue("bcachefs_write_ref",
                                WQ_FREEZABLE, 0)) ||
 #ifndef BCH_WRITE_REF_DEBUG
@@ -885,8 +894,8 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
                        BIOSET_NEED_BVECS) ||
            !(c->pcpu = alloc_percpu(struct bch_fs_pcpu)) ||
            !(c->online_reserved = alloc_percpu(u64)) ||
-           mempool_init_kvpmalloc_pool(&c->btree_bounce_pool, 1,
-                                       btree_bytes(c)) ||
+           mempool_init_kvmalloc_pool(&c->btree_bounce_pool, 1,
+                                      c->opts.btree_node_size) ||
            mempool_init_kmalloc_pool(&c->large_bkey_pool, 1, 2048) ||
            !(c->unused_inode_hints = kcalloc(1U << c->inode_shard_bits,
                                              sizeof(u64), GFP_KERNEL))) {
@@ -1040,12 +1049,13 @@ int bch2_fs_start(struct bch_fs *c)
        }
 
        ret = 0;
-out:
+err:
+       if (ret)
+               bch_err_msg(c, ret, "starting filesystem");
+       else
+               bch_verbose(c, "done starting filesystem");
        up_write(&c->state_lock);
        return ret;
-err:
-       bch_err_msg(c, ret, "starting filesystem");
-       goto out;
 }
 
 static int bch2_dev_may_add(struct bch_sb *sb, struct bch_fs *c)
@@ -1085,17 +1095,22 @@ static int bch2_dev_in_fs(struct bch_sb_handle *fs,
            fs->sb->write_time != sb->sb->write_time) {
                struct printbuf buf = PRINTBUF;
 
-               prt_printf(&buf, "Split brain detected between %pg and %pg:",
-                          sb->bdev, fs->bdev);
+               prt_str(&buf, "Split brain detected between ");
+               prt_bdevname(&buf, sb->bdev);
+               prt_str(&buf, " and ");
+               prt_bdevname(&buf, fs->bdev);
+               prt_char(&buf, ':');
                prt_newline(&buf);
                prt_printf(&buf, "seq=%llu but write_time different, got", le64_to_cpu(sb->sb->seq));
                prt_newline(&buf);
 
-               prt_printf(&buf, "%pg ", fs->bdev);
+               prt_bdevname(&buf, fs->bdev);
+               prt_char(&buf, ' ');
                bch2_prt_datetime(&buf, le64_to_cpu(fs->sb->write_time));;
                prt_newline(&buf);
 
-               prt_printf(&buf, "%pg ", sb->bdev);
+               prt_bdevname(&buf, sb->bdev);
+               prt_char(&buf, ' ');
                bch2_prt_datetime(&buf, le64_to_cpu(sb->sb->write_time));;
                prt_newline(&buf);
 
@@ -1111,13 +1126,26 @@ static int bch2_dev_in_fs(struct bch_sb_handle *fs,
        u64 seq_from_member     = le64_to_cpu(sb->sb->seq);
 
        if (seq_from_fs && seq_from_fs < seq_from_member) {
-               pr_err("Split brain detected between %pg and %pg:\n"
-                      "%pg believes seq of %pg to be %llu, but %pg has %llu\n"
-                      "Not using %pg",
-                      sb->bdev, fs->bdev,
-                      fs->bdev, sb->bdev, seq_from_fs,
-                      sb->bdev, seq_from_member,
-                      sb->bdev);
+               struct printbuf buf = PRINTBUF;
+
+               prt_str(&buf, "Split brain detected between ");
+               prt_bdevname(&buf, sb->bdev);
+               prt_str(&buf, " and ");
+               prt_bdevname(&buf, fs->bdev);
+               prt_char(&buf, ':');
+               prt_newline(&buf);
+
+               prt_bdevname(&buf, fs->bdev);
+               prt_str(&buf, " believes seq of ");
+               prt_bdevname(&buf, sb->bdev);
+               prt_printf(&buf, " to be %llu, but ", seq_from_fs);
+               prt_bdevname(&buf, sb->bdev);
+               prt_printf(&buf, " has %llu\n", seq_from_member);
+               prt_str(&buf, "Not using ");
+               prt_bdevname(&buf, sb->bdev);
+
+               pr_err("%s", buf.buf);
+               printbuf_exit(&buf);
                return -BCH_ERR_device_splitbrain;
        }
 
@@ -1152,8 +1180,8 @@ static void bch2_dev_free(struct bch_dev *ca)
        bch2_dev_buckets_free(ca);
        free_page((unsigned long) ca->sb_read_scratch);
 
-       bch2_time_stats_exit(&ca->io_latency[WRITE]);
-       bch2_time_stats_exit(&ca->io_latency[READ]);
+       time_stats_quantiles_exit(&ca->io_latency[WRITE]);
+       time_stats_quantiles_exit(&ca->io_latency[READ]);
 
        percpu_ref_exit(&ca->io_ref);
        percpu_ref_exit(&ca->ref);
@@ -1244,8 +1272,8 @@ static struct bch_dev *__bch2_dev_alloc(struct bch_fs *c,
 
        INIT_WORK(&ca->io_error_work, bch2_io_error_work);
 
-       bch2_time_stats_init(&ca->io_latency[READ]);
-       bch2_time_stats_init(&ca->io_latency[WRITE]);
+       time_stats_quantiles_init(&ca->io_latency[READ]);
+       time_stats_quantiles_init(&ca->io_latency[WRITE]);
 
        ca->mi = bch2_mi_to_cpu(member);
 
@@ -1366,9 +1394,14 @@ static int bch2_dev_attach_bdev(struct bch_fs *c, struct bch_sb_handle *sb)
 
        bch2_dev_sysfs_online(c, ca);
 
+       struct printbuf name = PRINTBUF;
+       prt_bdevname(&name, ca->disk_sb.bdev);
+
        if (c->sb.nr_devices == 1)
-               snprintf(c->name, sizeof(c->name), "%pg", ca->disk_sb.bdev);
-       snprintf(ca->name, sizeof(ca->name), "%pg", ca->disk_sb.bdev);
+               strscpy(c->name, name.buf, sizeof(c->name));
+       strscpy(ca->name, name.buf, sizeof(ca->name));
+
+       printbuf_exit(&name);
 
        rebalance_wakeup(c);
        return 0;
@@ -1407,10 +1440,10 @@ bool bch2_dev_state_allowed(struct bch_fs *c, struct bch_dev *ca,
 
                required = max(!(flags & BCH_FORCE_IF_METADATA_DEGRADED)
                               ? c->opts.metadata_replicas
-                              : c->opts.metadata_replicas_required,
+                              : metadata_replicas_required(c),
                               !(flags & BCH_FORCE_IF_DATA_DEGRADED)
                               ? c->opts.data_replicas
-                              : c->opts.data_replicas_required);
+                              : data_replicas_required(c));
 
                return nr_rw >= required;
        case BCH_MEMBER_STATE_failed:
@@ -1576,27 +1609,27 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
        __bch2_dev_read_only(c, ca);
 
        ret = bch2_dev_data_drop(c, ca->dev_idx, flags);
-       bch_err_msg(ca, ret, "dropping data");
+       bch_err_msg(ca, ret, "bch2_dev_data_drop()");
        if (ret)
                goto err;
 
        ret = bch2_dev_remove_alloc(c, ca);
-       bch_err_msg(ca, ret, "deleting alloc info");
+       bch_err_msg(ca, ret, "bch2_dev_remove_alloc()");
        if (ret)
                goto err;
 
        ret = bch2_journal_flush_device_pins(&c->journal, ca->dev_idx);
-       bch_err_msg(ca, ret, "flushing journal");
+       bch_err_msg(ca, ret, "bch2_journal_flush_device_pins()");
        if (ret)
                goto err;
 
        ret = bch2_journal_flush(&c->journal);
-       bch_err(ca, "journal error");
+       bch_err_msg(ca, ret, "bch2_journal_flush()");
        if (ret)
                goto err;
 
        ret = bch2_replicas_gc2(c);
-       bch_err_msg(ca, ret, "in replicas_gc2()");
+       bch_err_msg(ca, ret, "bch2_replicas_gc2()");
        if (ret)
                goto err;
 
@@ -1604,7 +1637,7 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
        if (data) {
                struct printbuf data_has = PRINTBUF;
 
-               prt_bitflags(&data_has, bch2_data_types, data);
+               prt_bitflags(&data_has, __bch2_data_types, data);
                bch_err(ca, "Remove failed, still has data (%s)", data_has.buf);
                printbuf_exit(&data_has);
                ret = -EBUSY;