summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2017-03-31 05:12:36 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2017-03-31 05:12:36 -0800
commit4921d02142fec87999cba32e991bb62c2a80184d (patch)
tree7d5b59a8ae6fc3116da28903f14d835a86511799
parentc0ad33c126300a51721a4f0ec8c0d757647e9cbe (diff)
Update bcachefs sources
-rw-r--r--.bcachefs_revision2
-rw-r--r--libbcachefs/btree_gc.c73
-rw-r--r--libbcachefs/btree_gc.h2
-rw-r--r--libbcachefs/buckets.c53
-rw-r--r--libbcachefs/buckets.h16
-rw-r--r--libbcachefs/extents.c6
-rw-r--r--libbcachefs/fs-gc.c16
-rw-r--r--libbcachefs/io.c2
-rw-r--r--libbcachefs/journal.c12
-rw-r--r--libbcachefs/journal.h2
-rw-r--r--libbcachefs/super.c7
11 files changed, 125 insertions, 66 deletions
diff --git a/.bcachefs_revision b/.bcachefs_revision
index 398cb4ac..f0ec32ef 100644
--- a/.bcachefs_revision
+++ b/.bcachefs_revision
@@ -1 +1 @@
-217509029551f8b40024d7fcd6e311be1fb6410c
+d37e2bb6dca5e4decf6b5918737c719fa6f17cc6
diff --git a/libbcachefs/btree_gc.c b/libbcachefs/btree_gc.c
index 0883b9b4..3620c29e 100644
--- a/libbcachefs/btree_gc.c
+++ b/libbcachefs/btree_gc.c
@@ -98,7 +98,7 @@ u8 bch2_btree_key_recalc_oldest_gen(struct bch_fs *c, struct bkey_s_c k)
struct bch_dev *ca = c->devs[ptr->dev];
size_t b = PTR_BUCKET_NR(ca, ptr);
- if (__gen_after(ca->oldest_gens[b], ptr->gen))
+ if (gen_after(ca->oldest_gens[b], ptr->gen))
ca->oldest_gens[b] = ptr->gen;
max_stale = max(max_stale, ptr_stale(ca, ptr));
@@ -126,14 +126,40 @@ static u8 bch2_btree_mark_key(struct bch_fs *c, enum bkey_type type,
}
}
-u8 bch2_btree_mark_key_initial(struct bch_fs *c, enum bkey_type type,
- struct bkey_s_c k)
+int bch2_btree_mark_key_initial(struct bch_fs *c, enum bkey_type type,
+ struct bkey_s_c k)
{
+ int ret;
+
+ switch (k.k->type) {
+ case BCH_EXTENT:
+ case BCH_EXTENT_CACHED: {
+ struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
+ const struct bch_extent_ptr *ptr;
+
+ extent_for_each_ptr(e, ptr) {
+ struct bch_dev *ca = c->devs[ptr->dev];
+ struct bucket *g = PTR_BUCKET(ca, ptr);
+
+ unfixable_fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c,
+ "%s ptr gen in the future: %u > %u",
+ type == BKEY_TYPE_BTREE
+ ? "btree" : "data",
+ ptr->gen, g->mark.gen);
+
+ }
+ break;
+ }
+ }
+
atomic64_set(&c->key_version,
max_t(u64, k.k->version.lo,
atomic64_read(&c->key_version)));
- return bch2_btree_mark_key(c, type, k);
+ bch2_btree_mark_key(c, type, k);
+ return 0;
+fsck_err:
+ return ret;
}
static bool btree_gc_mark_node(struct bch_fs *c, struct btree *b)
@@ -890,16 +916,22 @@ int bch2_gc_thread_start(struct bch_fs *c)
/* Initial GC computes bucket marks during startup */
-static void bch2_initial_gc_btree(struct bch_fs *c, enum btree_id id)
+static int bch2_initial_gc_btree(struct bch_fs *c, enum btree_id id)
{
struct btree_iter iter;
struct btree *b;
struct range_checks r;
+ int ret = 0;
btree_node_range_checks_init(&r, 0);
if (!c->btree_roots[id].b)
- return;
+ return 0;
+
+ ret = bch2_btree_mark_key_initial(c, BKEY_TYPE_BTREE,
+ bkey_i_to_s_c(&c->btree_roots[id].b->key));
+ if (ret)
+ return ret;
/*
* We have to hit every btree node before starting journal replay, in
@@ -915,28 +947,37 @@ static void bch2_initial_gc_btree(struct bch_fs *c, enum btree_id id)
for_each_btree_node_key_unpack(b, k, &node_iter,
btree_node_is_extents(b),
- &unpacked)
- bch2_btree_mark_key_initial(c, btree_node_type(b), k);
+ &unpacked) {
+ ret = bch2_btree_mark_key_initial(c,
+ btree_node_type(b), k);
+ if (ret)
+ goto err;
+ }
}
bch2_btree_iter_cond_resched(&iter);
}
-
+err:
bch2_btree_iter_unlock(&iter);
-
- bch2_btree_mark_key(c, BKEY_TYPE_BTREE,
- bkey_i_to_s_c(&c->btree_roots[id].b->key));
+ return ret;
}
int bch2_initial_gc(struct bch_fs *c, struct list_head *journal)
{
enum btree_id id;
+ int ret;
- for (id = 0; id < BTREE_ID_NR; id++)
- bch2_initial_gc_btree(c, id);
+ for (id = 0; id < BTREE_ID_NR; id++) {
+ ret = bch2_initial_gc_btree(c, id);
+ if (ret)
+ return ret;
+ }
- if (journal)
- bch2_journal_mark(c, journal);
+ if (journal) {
+ ret = bch2_journal_mark(c, journal);
+ if (ret)
+ return ret;
+ }
bch2_mark_metadata(c);
diff --git a/libbcachefs/btree_gc.h b/libbcachefs/btree_gc.h
index 07210d33..1d461518 100644
--- a/libbcachefs/btree_gc.h
+++ b/libbcachefs/btree_gc.h
@@ -11,7 +11,7 @@ void bch2_gc_thread_stop(struct bch_fs *);
int bch2_gc_thread_start(struct bch_fs *);
int bch2_initial_gc(struct bch_fs *, struct list_head *);
u8 bch2_btree_key_recalc_oldest_gen(struct bch_fs *, struct bkey_s_c);
-u8 bch2_btree_mark_key_initial(struct bch_fs *, enum bkey_type,
+int bch2_btree_mark_key_initial(struct bch_fs *, enum bkey_type,
struct bkey_s_c);
void bch2_mark_dev_metadata(struct bch_fs *, struct bch_dev *);
diff --git a/libbcachefs/buckets.c b/libbcachefs/buckets.c
index 396251d5..f9d41ffc 100644
--- a/libbcachefs/buckets.c
+++ b/libbcachefs/buckets.c
@@ -353,38 +353,45 @@ void bch2_mark_alloc_bucket(struct bch_dev *ca, struct bucket *g,
}));
}
+#define saturated_add(ca, dst, src, max) \
+do { \
+ BUG_ON((int) (dst) + (src) < 0); \
+ if ((dst) == (max)) \
+ ; \
+ else if ((dst) + (src) <= (max)) \
+ dst += (src); \
+ else { \
+ dst = (max); \
+ trace_sectors_saturated(ca); \
+ } \
+} while (0)
+
void bch2_mark_metadata_bucket(struct bch_dev *ca, struct bucket *g,
- enum bucket_data_type type,
- bool may_make_unavailable)
+ enum bucket_data_type type,
+ bool may_make_unavailable)
{
struct bucket_mark old, new;
BUG_ON(!type);
old = bucket_data_cmpxchg(ca, g, new, ({
+ saturated_add(ca, new.dirty_sectors, ca->mi.bucket_size,
+ GC_MAX_SECTORS_USED);
new.data_type = type;
new.had_metadata = 1;
}));
- BUG_ON(old.cached_sectors);
- BUG_ON(old.dirty_sectors);
+ if (old.data_type != type &&
+ (old.data_type ||
+ old.cached_sectors ||
+ old.dirty_sectors))
+ bch_err(ca->fs, "bucket %zu has multiple types of data (%u, %u)",
+ g - ca->buckets, old.data_type, new.data_type);
+
BUG_ON(!may_make_unavailable &&
bucket_became_unavailable(ca->fs, old, new));
}
-#define saturated_add(ca, dst, src, max) \
-do { \
- BUG_ON((int) (dst) + (src) < 0); \
- if ((dst) == (max)) \
- ; \
- else if ((dst) + (src) <= (max)) \
- dst += (src); \
- else { \
- dst = (max); \
- trace_sectors_saturated(ca); \
- } \
-} while (0)
-
#if 0
/* Reverting this until the copygc + compression issue is fixed: */
@@ -431,6 +438,8 @@ static void bch2_mark_pointer(struct bch_fs *c,
unsigned saturated;
struct bch_dev *ca = c->devs[ptr->dev];
struct bucket *g = ca->buckets + PTR_BUCKET_NR(ca, ptr);
+ unsigned data_type = type == S_META
+ ? BUCKET_BTREE : BUCKET_DATA;
unsigned old_sectors, new_sectors;
int disk_sectors, compressed_sectors;
@@ -494,13 +503,19 @@ static void bch2_mark_pointer(struct bch_fs *c,
new.journal_seq = journal_seq;
}
} else {
- new.data_type = type == S_META
- ? BUCKET_BTREE : BUCKET_DATA;
+ new.data_type = data_type;
}
new.had_metadata |= is_meta_bucket(new);
}));
+ if (old.data_type != data_type &&
+ (old.data_type ||
+ old.cached_sectors ||
+ old.dirty_sectors))
+ bch_err(ca->fs, "bucket %zu has multiple types of data (%u, %u)",
+ g - ca->buckets, old.data_type, new.data_type);
+
BUG_ON(!may_make_unavailable &&
bucket_became_unavailable(c, old, new));
diff --git a/libbcachefs/buckets.h b/libbcachefs/buckets.h
index 9c77304f..5303cdc7 100644
--- a/libbcachefs/buckets.h
+++ b/libbcachefs/buckets.h
@@ -73,20 +73,16 @@ static inline struct bucket *PTR_BUCKET(const struct bch_dev *ca,
return ca->buckets + PTR_BUCKET_NR(ca, ptr);
}
-static inline u8 __gen_after(u8 a, u8 b)
+static inline int gen_cmp(u8 a, u8 b)
{
- u8 r = a - b;
-
- return r > 128U ? 0 : r;
+ return (s8) (a - b);
}
-static inline u8 gen_after(u8 a, u8 b)
+static inline int gen_after(u8 a, u8 b)
{
- u8 r = a - b;
-
- BUG_ON(r > 128U);
+ int r = gen_cmp(a, b);
- return r;
+ return r > 0 ? r : 0;
}
/**
@@ -239,7 +235,7 @@ void bch2_invalidate_bucket(struct bch_dev *, struct bucket *);
void bch2_mark_free_bucket(struct bch_dev *, struct bucket *);
void bch2_mark_alloc_bucket(struct bch_dev *, struct bucket *, bool);
void bch2_mark_metadata_bucket(struct bch_dev *, struct bucket *,
- enum bucket_data_type, bool);
+ enum bucket_data_type, bool);
void __bch2_gc_mark_key(struct bch_fs *, struct bkey_s_c, s64, bool,
struct bch_fs_usage *);
diff --git a/libbcachefs/extents.c b/libbcachefs/extents.c
index 26f9352a..c80da362 100644
--- a/libbcachefs/extents.c
+++ b/libbcachefs/extents.c
@@ -602,12 +602,6 @@ bch2_btree_pick_ptr(struct bch_fs *c, const struct btree *b)
PTR_BUCKET_NR(ca, ptr)))
break;
- if (bch2_dev_inconsistent_on(ptr_stale(ca, ptr), ca,
- "stale btree node pointer at btree %u level %u/%u bucket %zu",
- b->btree_id, b->level, root ? root->level : -1,
- PTR_BUCKET_NR(ca, ptr)))
- continue;
-
if (ca->mi.state == BCH_MEMBER_STATE_FAILED)
continue;
diff --git a/libbcachefs/fs-gc.c b/libbcachefs/fs-gc.c
index 1a03b7ea..03370c0e 100644
--- a/libbcachefs/fs-gc.c
+++ b/libbcachefs/fs-gc.c
@@ -134,18 +134,22 @@ static int check_extents(struct bch_fs *c)
"extent type %u for missing inode %llu",
k.k->type, k.k->p.inode);
- unfixable_fsck_err_on(w.first_this_inode && w.have_inode &&
+ unfixable_fsck_err_on(w.have_inode &&
+ !S_ISREG(w.inode.i_mode) && !S_ISLNK(w.inode.i_mode), c,
+ "extent type %u for non regular file, inode %llu mode %o",
+ k.k->type, k.k->p.inode, w.inode.i_mode);
+
+ unfixable_fsck_err_on(w.first_this_inode &&
+ w.have_inode &&
+ !(w.inode.i_flags & BCH_INODE_I_SECTORS_DIRTY) &&
w.inode.i_sectors !=
(i_sectors = bch2_count_inode_sectors(c, w.cur_inum)),
c, "i_sectors wrong: got %llu, should be %llu",
w.inode.i_sectors, i_sectors);
unfixable_fsck_err_on(w.have_inode &&
- !S_ISREG(w.inode.i_mode) && !S_ISLNK(w.inode.i_mode), c,
- "extent type %u for non regular file, inode %llu mode %o",
- k.k->type, k.k->p.inode, w.inode.i_mode);
-
- unfixable_fsck_err_on(k.k->type != BCH_RESERVATION &&
+ !(w.inode.i_flags & BCH_INODE_I_SIZE_DIRTY) &&
+ k.k->type != BCH_RESERVATION &&
k.k->p.offset > round_up(w.inode.i_size, PAGE_SIZE) >> 9, c,
"extent type %u offset %llu past end of inode %llu, i_size %llu",
k.k->type, k.k->p.offset, k.k->p.inode, w.inode.i_size);
diff --git a/libbcachefs/io.c b/libbcachefs/io.c
index 212a5a65..da06845c 100644
--- a/libbcachefs/io.c
+++ b/libbcachefs/io.c
@@ -475,7 +475,7 @@ static int bch2_write_extent(struct bch_write_op *op,
nonce = extent_nonce(op->version,
crc_nonce,
src_len >> 9,
- compression_type),
+ fragment_compression_type),
bch2_encrypt_bio(c, csum_type, nonce, bio);
diff --git a/libbcachefs/journal.c b/libbcachefs/journal.c
index 60c5c9b0..76a3b465 100644
--- a/libbcachefs/journal.c
+++ b/libbcachefs/journal.c
@@ -1077,20 +1077,26 @@ fsck_err:
return ret;
}
-void bch2_journal_mark(struct bch_fs *c, struct list_head *list)
+int bch2_journal_mark(struct bch_fs *c, struct list_head *list)
{
struct bkey_i *k, *n;
struct jset_entry *j;
struct journal_replay *r;
+ int ret;
list_for_each_entry(r, list, list)
for_each_jset_key(k, n, j, &r->j) {
enum bkey_type type = bkey_type(j->level, j->btree_id);
struct bkey_s_c k_s_c = bkey_i_to_s_c(k);
- if (btree_type_has_ptrs(type))
- bch2_btree_mark_key_initial(c, type, k_s_c);
+ if (btree_type_has_ptrs(type)) {
+ ret = bch2_btree_mark_key_initial(c, type, k_s_c);
+ if (ret)
+ return ret;
+ }
}
+
+ return 0;
}
static bool journal_entry_is_open(struct journal *j)
diff --git a/libbcachefs/journal.h b/libbcachefs/journal.h
index f5fc465a..3825f0dc 100644
--- a/libbcachefs/journal.h
+++ b/libbcachefs/journal.h
@@ -336,7 +336,7 @@ static inline bool journal_flushes_device(struct bch_dev *ca)
}
void bch2_journal_start(struct bch_fs *);
-void bch2_journal_mark(struct bch_fs *, struct list_head *);
+int bch2_journal_mark(struct bch_fs *, struct list_head *);
void bch2_journal_entries_free(struct list_head *);
int bch2_journal_read(struct bch_fs *, struct list_head *);
int bch2_journal_replay(struct bch_fs *, struct list_head *);
diff --git a/libbcachefs/super.c b/libbcachefs/super.c
index 1977bdc4..366fa672 100644
--- a/libbcachefs/super.c
+++ b/libbcachefs/super.c
@@ -727,7 +727,8 @@ static const char *__bch2_fs_start(struct bch_fs *c)
bch_verbose(c, "starting mark and sweep:");
err = "error in recovery";
- if (bch2_initial_gc(c, &journal))
+ ret = bch2_initial_gc(c, &journal);
+ if (ret)
goto err;
if (c->opts.noreplay)
@@ -777,7 +778,9 @@ static const char *__bch2_fs_start(struct bch_fs *c)
bch_notice(c, "initializing new filesystem");
- bch2_initial_gc(c, NULL);
+ ret = bch2_initial_gc(c, &journal);
+ if (ret)
+ goto err;
err = "unable to allocate journal buckets";
for_each_rw_member(ca, c, i)