diff options
Diffstat (limited to 'libbcache/error.c')
-rw-r--r-- | libbcache/error.c | 140 |
1 files changed, 0 insertions, 140 deletions
diff --git a/libbcache/error.c b/libbcache/error.c deleted file mode 100644 index ba46d2d1..00000000 --- a/libbcache/error.c +++ /dev/null @@ -1,140 +0,0 @@ -#include "bcache.h" -#include "error.h" -#include "io.h" -#include "notify.h" -#include "super.h" - -void bch_inconsistent_error(struct bch_fs *c) -{ - set_bit(BCH_FS_ERROR, &c->flags); - - switch (c->opts.errors) { - case BCH_ON_ERROR_CONTINUE: - break; - case BCH_ON_ERROR_RO: - if (!test_bit(BCH_FS_INITIAL_GC_DONE, &c->flags)) { - /* XXX do something better here? */ - bch_fs_stop_async(c); - return; - } - - if (bch_fs_emergency_read_only(c)) - bch_err(c, "emergency read only"); - break; - case BCH_ON_ERROR_PANIC: - panic(bch_fmt(c, "panic after error")); - break; - } -} - -void bch_fatal_error(struct bch_fs *c) -{ - if (bch_fs_emergency_read_only(c)) - bch_err(c, "emergency read only"); -} - -/* Nonfatal IO errors, IO error/latency accounting: */ - -/* Just does IO error accounting: */ -void bch_account_io_completion(struct bch_dev *ca) -{ - /* - * The halflife of an error is: - * log2(1/2)/log2(127/128) * refresh ~= 88 * refresh - */ - - if (ca->fs->error_decay) { - unsigned count = atomic_inc_return(&ca->io_count); - - while (count > ca->fs->error_decay) { - unsigned errors; - unsigned old = count; - unsigned new = count - ca->fs->error_decay; - - /* - * First we subtract refresh from count; each time we - * succesfully do so, we rescale the errors once: - */ - - count = atomic_cmpxchg(&ca->io_count, old, new); - - if (count == old) { - count = new; - - errors = atomic_read(&ca->io_errors); - do { - old = errors; - new = ((uint64_t) errors * 127) / 128; - errors = atomic_cmpxchg(&ca->io_errors, - old, new); - } while (old != errors); - } - } - } -} - -/* IO error accounting and latency accounting: */ -void bch_account_io_completion_time(struct bch_dev *ca, - unsigned submit_time_us, int op) -{ - struct bch_fs *c; - unsigned threshold; - - if (!ca) - return; - - c = ca->fs; - threshold = op_is_write(op) - ? c->congested_write_threshold_us - : c->congested_read_threshold_us; - - if (threshold && submit_time_us) { - unsigned t = local_clock_us(); - - int us = t - submit_time_us; - int congested = atomic_read(&c->congested); - - if (us > (int) threshold) { - int ms = us / 1024; - c->congested_last_us = t; - - ms = min(ms, CONGESTED_MAX + congested); - atomic_sub(ms, &c->congested); - } else if (congested < 0) - atomic_inc(&c->congested); - } - - bch_account_io_completion(ca); -} - -void bch_nonfatal_io_error_work(struct work_struct *work) -{ - struct bch_dev *ca = container_of(work, struct bch_dev, io_error_work); - struct bch_fs *c = ca->fs; - unsigned errors = atomic_read(&ca->io_errors); - bool dev; - - if (errors < c->error_limit) { - bch_notify_dev_error(ca, false); - } else { - bch_notify_dev_error(ca, true); - - mutex_lock(&c->state_lock); - dev = bch_dev_state_allowed(c, ca, BCH_MEMBER_STATE_RO, - BCH_FORCE_IF_DEGRADED); - if (dev - ? __bch_dev_set_state(c, ca, BCH_MEMBER_STATE_RO, - BCH_FORCE_IF_DEGRADED) - : bch_fs_emergency_read_only(c)) - bch_err(ca, - "too many IO errors, setting %s RO", - dev ? "device" : "filesystem"); - mutex_unlock(&c->state_lock); - } -} - -void bch_nonfatal_io_error(struct bch_dev *ca) -{ - atomic_add(1 << IO_ERROR_SHIFT, &ca->io_errors); - queue_work(system_long_wq, &ca->io_error_work); -} |