summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-08-06 07:41:19 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-09-25 05:59:35 -0800
commit0faa1ccc5ff4a29ac3cd0d561d9ceec5cbbe3e61 (patch)
treef1d9387c08b7cbfef1f2334f1e18c60189f88819
parent5a6a7df52aa32889b19d6e64c3ccd8d4ae4b148c (diff)
bcache: transactions
-rw-r--r--drivers/md/bcache/Makefile4
-rw-r--r--drivers/md/bcache/bcache.h7
-rw-r--r--drivers/md/bcache/bkey.h3
-rw-r--r--drivers/md/bcache/btree_types.h1
-rw-r--r--drivers/md/bcache/btree_update.c80
-rw-r--r--drivers/md/bcache/btree_update.h16
-rw-r--r--drivers/md/bcache/journal.c3
-rw-r--r--drivers/md/bcache/super.c13
-rw-r--r--drivers/md/bcache/trans.c220
-rw-r--r--drivers/md/bcache/trans.h25
-rw-r--r--drivers/md/bcache/trans_types.h28
-rw-r--r--include/trace/events/bcache.h27
-rw-r--r--include/uapi/linux/bcache.h25
13 files changed, 400 insertions, 52 deletions
diff --git a/drivers/md/bcache/Makefile b/drivers/md/bcache/Makefile
index baf502a54c0e..2c4a626c2840 100644
--- a/drivers/md/bcache/Makefile
+++ b/drivers/md/bcache/Makefile
@@ -6,5 +6,5 @@ bcache-y := acl.o alloc.o bkey.o bkey_methods.o blockdev.o\
buckets.o chardev.o checksum.o clock.o closure.o compress.o debug.o\
dirent.o error.o extents.o fs.o fs-gc.o fs-io.o inode.o io.o journal.o\
keybuf.o keylist.o migrate.o move.o movinggc.o notify.o opts.o\
- request.o siphash.o six.o stats.o super.o sysfs.o tier.o trace.o util.o\
- writeback.o xattr.o
+ request.o siphash.o six.o stats.o super.o sysfs.o tier.o trace.o\
+ trans.o util.o writeback.o xattr.o
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index aee5451a762d..0dfe49ac8583 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -287,6 +287,7 @@ do { \
#include "move_types.h"
#include "stats_types.h"
#include "super_types.h"
+#include "trans_types.h"
/* 256k, in sectors */
#define BTREE_NODE_SIZE_MAX 512
@@ -765,6 +766,8 @@ struct cache_set {
#endif
u64 unused_inode_hint;
+ struct mutex inode_create_lock;
+ struct bch_trans_inode_create inode_create;
/*
* A btree node on disk could have too many bsets for an iterator to fit
@@ -775,6 +778,10 @@ struct cache_set {
struct bset_sort_state sort;
struct journal journal;
+
+ struct list_head transactions_replay;
+ atomic64_t transactions_cur_id;
+
unsigned btree_flush_delay;
/* CACHING OTHER BLOCK DEVICES */
diff --git a/drivers/md/bcache/bkey.h b/drivers/md/bcache/bkey.h
index 1e68822e13bd..8f6ff6e77161 100644
--- a/drivers/md/bcache/bkey.h
+++ b/drivers/md/bcache/bkey.h
@@ -503,6 +503,9 @@ BKEY_VAL_ACCESSORS(dirent, BCH_DIRENT);
BKEY_VAL_ACCESSORS(xattr, BCH_XATTR);
+BKEY_VAL_ACCESSORS(trans_inode_create_val, BCH_TRANS_INODE_CREATE);
+BKEY_VAL_ACCESSORS(trans_fcollapse_val, BCH_TRANS_FCOLLAPSE);
+
/* byte order helpers */
#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
diff --git a/drivers/md/bcache/btree_types.h b/drivers/md/bcache/btree_types.h
index f294aa2965c9..b6c1dedeff49 100644
--- a/drivers/md/bcache/btree_types.h
+++ b/drivers/md/bcache/btree_types.h
@@ -167,6 +167,7 @@ enum btree_insert_ret {
BTREE_INSERT_BTREE_NODE_FULL,
BTREE_INSERT_JOURNAL_RES_FULL,
BTREE_INSERT_ENOSPC,
+ BTREE_INSERT_ENOMEM, /* only during journal replay */
};
#endif /* _BCACHE_BTREE_TYPES_H */
diff --git a/drivers/md/bcache/btree_update.c b/drivers/md/bcache/btree_update.c
index 5b4a743a1f8f..be54010cffbd 100644
--- a/drivers/md/bcache/btree_update.c
+++ b/drivers/md/bcache/btree_update.c
@@ -13,6 +13,7 @@
#include "journal.h"
#include "keylist.h"
#include "super.h"
+#include "trans.h"
#include <linux/random.h>
#include <linux/sort.h>
@@ -1491,16 +1492,17 @@ btree_insert_key(struct btree_insert *trans,
struct btree_insert_entry *insert,
struct journal_res *res)
{
- struct btree_iter *iter = insert->iter;
- struct btree *b = iter->nodes[0];
- enum btree_insert_ret ret;
-
- ret = !b->keys.ops->is_extents
- ? bch_insert_fixup_key(trans, insert, res)
- : bch_insert_fixup_extent(trans, insert, res);
+ trace_bcache_btree_insert_key(insert->btree_id, insert->k);
- trace_bcache_btree_insert_key(b, insert->k);
- return ret;
+ switch (insert->btree_id) {
+ case BTREE_ID_EXTENTS:
+ return bch_insert_fixup_extent(trans, insert, res);
+ break;
+ case BTREE_ID_TRANSACTIONS:
+ return bch_insert_fixup_transaction_key(trans, insert, res);
+ default:
+ return bch_insert_fixup_key(trans, insert, res);
+ }
}
static bool same_leaf_as_prev(struct btree_insert *trans,
@@ -1517,11 +1519,17 @@ static bool same_leaf_as_prev(struct btree_insert *trans,
#define trans_for_each_entry(trans, i) \
for ((i) = (trans)->entries; (i) < (trans)->entries + (trans)->nr; (i)++)
+#define trans_for_each_btree_entry(trans, i) \
+ for ((i) = (trans)->entries; \
+ (i) < (trans)->entries + (trans)->nr && \
+ (i)->btree_id != BTREE_ID_TRANSACTIONS; \
+ (i)++)
+
static void multi_lock_write(struct btree_insert *trans)
{
struct btree_insert_entry *i;
- trans_for_each_entry(trans, i)
+ trans_for_each_btree_entry(trans, i)
if (!same_leaf_as_prev(trans, i))
btree_node_lock_for_insert(i->iter->nodes[0], i->iter);
}
@@ -1530,17 +1538,19 @@ static void multi_unlock_write(struct btree_insert *trans)
{
struct btree_insert_entry *i;
- trans_for_each_entry(trans, i)
+ trans_for_each_btree_entry(trans, i)
if (!same_leaf_as_prev(trans, i))
btree_node_unlock_write(i->iter->nodes[0], i->iter);
}
-static int btree_trans_entry_cmp(const void *_l, const void *_r)
+static int btree_insert_entry_cmp(const void *_l, const void *_r)
{
const struct btree_insert_entry *l = _l;
const struct btree_insert_entry *r = _r;
- return btree_iter_cmp(l->iter, r->iter);
+ if (l->btree_id != r->btree_id)
+ return l->btree_id < r->btree_id ? -1 : 1;
+ return bkey_cmp(l->k->k.p, r->k->k.p);
}
/* Normal update interface: */
@@ -1568,18 +1578,19 @@ int __bch_btree_insert_at(struct btree_insert *trans, u64 *journal_seq)
closure_init_stack(&cl);
- trans_for_each_entry(trans, i) {
+ sort(trans->entries, trans->nr, sizeof(trans->entries[0]),
+ btree_insert_entry_cmp, NULL);
+
+ trans_for_each_btree_entry(trans, i) {
+ EBUG_ON(i->btree_id != i->iter->btree_id);
EBUG_ON(i->iter->level);
EBUG_ON(bkey_cmp(bkey_start_pos(&i->k->k), i->iter->pos));
}
- sort(trans->entries, trans->nr, sizeof(trans->entries[0]),
- btree_trans_entry_cmp, NULL);
-
if (unlikely(!percpu_ref_tryget(&c->writes)))
return -EROFS;
- trans_for_each_entry(trans, i) {
+ trans_for_each_btree_entry(trans, i) {
i->iter->locks_want = max_t(int, i->iter->locks_want, 1);
if (unlikely(!bch_btree_iter_upgrade(i->iter))) {
ret = -EINTR;
@@ -1602,7 +1613,7 @@ retry:
multi_lock_write(trans);
u64s = 0;
- trans_for_each_entry(trans, i) {
+ trans_for_each_btree_entry(trans, i) {
/* Multiple inserts might go to same leaf: */
if (!same_leaf_as_prev(trans, i))
u64s = 0;
@@ -1641,6 +1652,9 @@ retry:
case BTREE_INSERT_ENOSPC:
ret = -ENOSPC;
break;
+ case BTREE_INSERT_ENOMEM:
+ ret = -ENOMEM;
+ break;
}
if (!trans->did_work && (ret || split))
@@ -1655,7 +1669,7 @@ unlock:
if (ret)
goto err;
- trans_for_each_entry(trans, i)
+ trans_for_each_btree_entry(trans, i)
if (!same_leaf_as_prev(trans, i))
bch_btree_node_write_lazy(i->iter->nodes[0], i->iter);
out:
@@ -1699,7 +1713,7 @@ err:
* reservations:
*/
if (ret == -EINTR && !(trans->flags & BTREE_INSERT_ATOMIC)) {
- trans_for_each_entry(trans, i) {
+ trans_for_each_btree_entry(trans, i) {
ret = bch_btree_iter_traverse(i->iter);
if (ret)
goto out;
@@ -1797,17 +1811,23 @@ int bch_btree_insert(struct cache_set *c, enum btree_id id,
struct btree_iter iter;
int ret, ret2;
- bch_btree_iter_init_intent(&iter, c, id, bkey_start_pos(&k->k));
-
- ret = bch_btree_iter_traverse(&iter);
- if (unlikely(ret))
- goto out;
+ switch (id) {
+ case BTREE_ID_TRANSACTIONS:
+ return bch_btree_insert_at(c, disk_res, hook, journal_seq, flags,
+ BTREE_TRANS_ENTRY(NULL, k));
+ break;
+ default:
+ bch_btree_iter_init_intent(&iter, c, id, bkey_start_pos(&k->k));
- ret = bch_btree_insert_at(c, disk_res, hook, journal_seq, flags,
- BTREE_INSERT_ENTRY(&iter, k));
-out: ret2 = bch_btree_iter_unlock(&iter);
+ ret = bch_btree_iter_traverse(&iter);
+ if (unlikely(ret))
+ goto out;
- return ret ?: ret2;
+ ret = bch_btree_insert_at(c, disk_res, hook, journal_seq, flags,
+ BTREE_INSERT_ENTRY(&iter, k));
+ out: ret2 = bch_btree_iter_unlock(&iter);
+ return ret ?: ret2;
+ }
}
/**
diff --git a/drivers/md/bcache/btree_update.h b/drivers/md/bcache/btree_update.h
index 97725296a2e8..11f9aa93fc1f 100644
--- a/drivers/md/bcache/btree_update.h
+++ b/drivers/md/bcache/btree_update.h
@@ -215,8 +215,13 @@ struct btree_insert {
unsigned short nr;
struct btree_insert_entry {
- struct btree_iter *iter;
+ union {
+ struct btree_iter *iter;
+ struct bch_transaction *trans;
+ };
+
struct bkey_i *k;
+ enum btree_id btree_id:8;
/*
* true if entire key was inserted - can only be false for
* extents
@@ -235,6 +240,15 @@ int __bch_btree_insert_at(struct btree_insert *, u64 *);
((struct btree_insert_entry) { \
.iter = (_iter), \
.k = (_k), \
+ .btree_id = (_iter)->btree_id, \
+ .done = false, \
+ })
+
+#define BTREE_TRANS_ENTRY(_trans, _k) \
+ ((struct btree_insert_entry) { \
+ .trans = (_trans), \
+ .k = (_k), \
+ .btree_id = BTREE_ID_TRANSACTIONS, \
.done = false, \
})
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 1a9f27dcdc0d..a36730337502 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -2134,9 +2134,10 @@ int bch_journal_res_get(struct journal *j, struct journal_res *res,
{
int ret;
- BUG_ON(res->ref);
BUG_ON(u64s_max < u64s_min);
+ memset(res, 0, sizeof(*res));
+
wait_event(j->wait,
(ret = __journal_res_get(j, res, u64s_min,
u64s_max)));
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 7b0b165efe7b..e2d80e42baec 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -30,6 +30,7 @@
#include "stats.h"
#include "super.h"
#include "tier.h"
+#include "trans.h"
#include "writeback.h"
#include <linux/backing-dev.h>
@@ -889,6 +890,7 @@ static void cache_set_free(struct cache_set *c)
cancel_work_sync(&c->bio_submit_work);
cancel_work_sync(&c->read_retry_work);
+ bch_transactions_exit_cache_set(c);
bch_bset_sort_state_free(&c->sort);
bch_btree_cache_free(c);
bch_journal_free(&c->journal);
@@ -1082,6 +1084,7 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb,
bch_open_buckets_init(c);
bch_tiering_init_cache_set(c);
+ bch_transactions_init_cache_set(c);
INIT_LIST_HEAD(&c->list);
INIT_LIST_HEAD(&c->cached_devs);
@@ -1093,6 +1096,8 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb,
mutex_init(&c->btree_reserve_cache_lock);
mutex_init(&c->btree_interior_update_lock);
+ mutex_init(&c->inode_create_lock);
+
mutex_init(&c->bio_bounce_pages_lock);
INIT_WORK(&c->bio_submit_work, bch_bio_submit_work);
spin_lock_init(&c->bio_submit_lock);
@@ -1347,6 +1352,14 @@ static const char *run_cache_set(struct cache_set *c)
bch_verbose(c, "journal replay done");
+ bch_verbose(c, "starting transaction replay:");
+
+ err = "transaction replay failed";
+ if (bch_transactions_replay(c))
+ goto err;
+
+ bch_verbose(c, "transaction replay done");
+
bch_verbose(c, "starting fs gc:");
err = "error gcing inode nlinks";
diff --git a/drivers/md/bcache/trans.c b/drivers/md/bcache/trans.c
new file mode 100644
index 000000000000..3c84be2af6b6
--- /dev/null
+++ b/drivers/md/bcache/trans.c
@@ -0,0 +1,220 @@
+
+#include "bcache.h"
+#include "bkey.h"
+#include "btree_update.h"
+#include "journal.h"
+#include "trans.h"
+
+/* Long running transactions: */
+
+struct bch_transaction_replay {
+ struct list_head list;
+ struct bch_transaction trans;
+};
+
+static void __bch_journal_transaction(struct journal *j,
+ struct bch_transaction *,
+ struct journal_res *);
+
+/* Called when the journal wants us to release our pin so it can reclaim: */
+static void bch_transaction_flush(struct journal *j,
+ struct journal_entry_pin *pin)
+{
+ struct bch_transaction *trans =
+ container_of(pin, struct bch_transaction, journal_pin);
+ struct journal_res res;
+ unsigned u64s = jset_u64s(trans->k.k.u64s);
+ int ret;
+
+ BUG_ON(!bch_transaction_active(trans));
+
+ /*
+ * XXX: this can deadlock because we're holding a journal pin, we need
+ * reservations:
+ */
+ ret = bch_journal_res_get(j, &res, u64s, u64s);
+ if (ret)
+ return;
+
+ __bch_journal_transaction(j, trans, &res);
+ bch_journal_res_put(j, &res, NULL);
+}
+
+static void __bch_journal_transaction(struct journal *j,
+ struct bch_transaction *trans,
+ struct journal_res *res)
+{
+ /*
+ * There's no race between dropping the old pin and adding the new one
+ * because we're holding a journal reservation:
+ */
+ bch_journal_pin_drop(j, &trans->journal_pin);
+ bch_journal_pin_add(j, &trans->journal_pin, bch_transaction_flush);
+ bch_journal_add_keys(j, res, BTREE_ID_TRANSACTIONS, &trans->k);
+}
+
+enum btree_insert_ret
+bch_insert_fixup_transaction_key(struct btree_insert *insert,
+ struct btree_insert_entry *insert_entry,
+ struct journal_res *res)
+{
+ struct cache_set *c = insert->c;
+ struct journal *j = &c->journal;
+ struct bch_transaction *trans;
+
+ if (test_bit(JOURNAL_REPLAY_DONE, &j->flags)) {
+ trans = insert_entry->trans;
+
+ BUG_ON(!bch_transaction_active(trans));
+ BUG_ON(insert_entry->k->k.u64s != trans->k.k.u64s);
+
+ bkey_copy(&trans->k, insert_entry->k);
+ __bch_journal_transaction(j, trans, res);
+ } else {
+ struct bch_transaction_replay *r;
+
+ if (insert_entry->k->k.p.offset >=
+ atomic64_read(&c->transactions_cur_id))
+ atomic64_set(&c->transactions_cur_id,
+ insert_entry->k->k.p.offset);
+
+ /*
+ * In journal replay - add the transaction to the list to be
+ * replayed:
+ */
+ list_for_each_entry(r, &c->transactions_replay, list)
+ if (!bkey_cmp(insert_entry->k->k.p, r->trans.k.k.p)) {
+ BUG_ON(insert_entry->k->k.u64s !=
+ r->trans.k.k.u64s);
+ goto found;
+ }
+
+ r = kzalloc(sizeof(*r) + bkey_val_bytes(&insert_entry->k->k),
+ GFP_KERNEL);
+ if (!r)
+ return BTREE_INSERT_ENOMEM;
+
+ list_add(&r->list, &c->transactions_replay);
+found:
+ trans = &r->trans;
+ bkey_copy(&trans->k, insert_entry->k);
+ bch_journal_pin_drop(j, &trans->journal_pin);
+ bch_journal_pin_add(j, &trans->journal_pin, bch_transaction_flush);
+ }
+
+ insert->did_work = true;
+ return BTREE_INSERT_OK;
+}
+
+int bch_transaction_done(struct cache_set *c, struct bch_transaction *trans)
+{
+ struct journal *j = &c->journal;
+ struct journal_res res;
+ unsigned u64s;
+ int ret;
+
+ BUG_ON(!bch_transaction_active(trans));
+
+ set_bkey_deleted(&trans->k.k);
+
+ u64s = jset_u64s(trans->k.k.u64s);
+
+ /*
+ * XXX: this can deadlock because we're holding a journal pin, we need
+ * reservations:
+ */
+ ret = bch_journal_res_get(j, &res, u64s, u64s);
+ if (ret)
+ return ret;
+
+ bch_journal_pin_drop(j, &trans->journal_pin);
+ bch_journal_add_keys(j, &res, BTREE_ID_TRANSACTIONS, &trans->k);
+ bch_journal_res_put(j, &res, NULL);
+ return 0;
+}
+
+int bch_transaction_start(struct cache_set *c, struct bch_transaction *trans)
+{
+ struct journal *j = &c->journal;
+ struct journal_res res;
+ unsigned u64s = jset_u64s(trans->k.k.u64s);
+ int ret;
+
+ BUG_ON(trans->k.k.u64s <= BKEY_U64s);
+
+ memset(&trans->journal_pin, 0, sizeof(trans->journal_pin));
+ trans->k.k.p = POS(0, atomic64_inc_return(&c->transactions_cur_id));
+
+ ret = bch_journal_res_get(j, &res, u64s, u64s);
+ if (ret)
+ return ret;
+
+ __bch_journal_transaction(j, trans, &res);
+ bch_journal_res_put(j, &res, NULL);
+ return 0;
+}
+
+static int bch_transaction_replay_one(struct cache_set *c,
+ struct bch_transaction *trans)
+{
+ struct journal *j = &c->journal;
+
+ switch (trans->k.k.type) {
+ case KEY_TYPE_DELETED:
+ bch_journal_pin_drop(j, &trans->journal_pin);
+ break;
+ case BCH_TRANS_INODE_CREATE:
+ __journal_pin_add(j, trans->journal_pin.pin_list,
+ &c->inode_create.__journal_pin,
+ bch_transaction_flush);
+ bkey_copy(&c->inode_create.k.k_i, &trans->k);
+
+ bch_journal_pin_drop(j, &trans->journal_pin);
+ break;
+ case BCH_TRANS_FCOLLAPSE:
+ break;
+ default:
+ BUG();
+ };
+
+ return 0;
+}
+
+int bch_transactions_replay(struct cache_set *c)
+{
+ struct bch_transaction_replay *r;
+ int ret = 0;
+
+ while (!list_empty(&c->transactions_replay)) {
+ r = list_first_entry(&c->transactions_replay,
+ struct bch_transaction_replay,
+ list);
+ list_del(&r->list);
+
+ ret = bch_transaction_replay_one(c, &r->trans);
+ if (ret)
+ break;
+
+ kfree(r);
+ }
+
+ return ret;
+}
+
+void bch_transactions_exit_cache_set(struct cache_set *c)
+{
+ struct bch_transaction_replay *r;
+
+ while (!list_empty(&c->transactions_replay)) {
+ r = list_first_entry(&c->transactions_replay,
+ struct bch_transaction_replay,
+ list);
+ list_del(&r->list);
+ kfree(r);
+ }
+}
+
+void bch_transactions_init_cache_set(struct cache_set *c)
+{
+ INIT_LIST_HEAD(&c->transactions_replay);
+}
diff --git a/drivers/md/bcache/trans.h b/drivers/md/bcache/trans.h
new file mode 100644
index 000000000000..7bcaff14eaee
--- /dev/null
+++ b/drivers/md/bcache/trans.h
@@ -0,0 +1,25 @@
+#ifndef _BCACHE_TRANS_H
+#define _BCACHE_TRANS_H
+
+#include "trans_types.h"
+#include "journal.h"
+
+enum btree_insert_ret
+bch_insert_fixup_transaction_key(struct btree_insert *,
+ struct btree_insert_entry *,
+ struct journal_res *);
+
+int bch_transaction_done(struct cache_set *, struct bch_transaction *);
+int bch_transaction_start(struct cache_set *, struct bch_transaction *);
+
+int bch_transactions_replay(struct cache_set *);
+
+void bch_transactions_exit_cache_set(struct cache_set *);
+void bch_transactions_init_cache_set(struct cache_set *);
+
+static inline bool bch_transaction_active(struct bch_transaction *trans)
+{
+ return journal_pin_active(&trans->journal_pin);
+}
+
+#endif /* _BCACHE_TRANS_H */
diff --git a/drivers/md/bcache/trans_types.h b/drivers/md/bcache/trans_types.h
new file mode 100644
index 000000000000..a2b8bfd09231
--- /dev/null
+++ b/drivers/md/bcache/trans_types.h
@@ -0,0 +1,28 @@
+#ifndef _BCACHE_TRANS_TYPES_H
+#define _BCACHE_TRANS_TYPES_H
+
+#include "journal_types.h"
+
+struct bch_transaction {
+ struct journal_entry_pin journal_pin;
+ struct bkey_i k;
+};
+
+#define BCH_TRANS_TYPE(name, nr) \
+struct bch_trans_##name { \
+ union { \
+ struct { \
+ struct bch_transaction t; \
+ struct bch_trans_##name##_val v; \
+ }; \
+ struct { \
+ struct journal_entry_pin __journal_pin; \
+ struct bkey_i_trans_##name##_val k; \
+ }; \
+ }; \
+}
+
+BCH_TRANS_TYPE(inode_create, BCH_TRANS_INODE_CREATE);
+BCH_TRANS_TYPE(fcollapse, BCH_TRANS_FCOLLAPSE);
+
+#endif /* _BCACHE_TRANS_TYPES_H */
diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h
index 00bd60de2ce4..f065c356c54a 100644
--- a/include/trace/events/bcache.h
+++ b/include/trace/events/bcache.h
@@ -614,35 +614,28 @@ DEFINE_EVENT(btree_node_op, bcache_btree_intent_lock_fail,
);
TRACE_EVENT(bcache_btree_insert_key,
- TP_PROTO(struct btree *b, struct bkey_i *k),
- TP_ARGS(b, k),
+ TP_PROTO(enum btree_id btree_id, struct bkey_i *k),
+ TP_ARGS(btree_id, k),
TP_STRUCT__entry(
- __field(u64, b_bucket )
- __field(u64, b_offset )
+ __field(u8, btree )
+ __field(u64, inode )
__field(u64, offset )
- __field(u32, b_inode )
- __field(u32, inode )
+ __field(u32, snapshot )
__field(u32, size )
- __field(u8, level )
- __field(u8, id )
),
TP_fast_assign(
- __entry->b_bucket = PTR_BUCKET_NR_TRACE(b->c, &b->key, 0);
- __entry->level = b->level;
- __entry->id = b->btree_id;
- __entry->b_inode = b->key.k.p.inode;
- __entry->b_offset = b->key.k.p.offset;
+ __entry->btree = btree_id;
__entry->inode = k->k.p.inode;
__entry->offset = k->k.p.offset;
+ __entry->snapshot = k->k.p.snapshot;
__entry->size = k->k.size;
),
- TP_printk("bucket %llu(%u) id %u: %u:%llu %u:%llu len %u",
- __entry->b_bucket, __entry->level, __entry->id,
- __entry->b_inode, __entry->b_offset,
- __entry->inode, __entry->offset, __entry->size)
+ TP_printk("btree %u: %llu:%llu snapshot %u size %u",
+ __entry->btree, __entry->inode, __entry->offset,
+ __entry->snapshot, __entry->size)
);
DECLARE_EVENT_CLASS(btree_split,
diff --git a/include/uapi/linux/bcache.h b/include/uapi/linux/bcache.h
index 999ed8f4c535..caa048f82020 100644
--- a/include/uapi/linux/bcache.h
+++ b/include/uapi/linux/bcache.h
@@ -613,6 +613,27 @@ struct bch_xattr {
} __attribute__((packed));
BKEY_VAL_TYPE(xattr, BCH_XATTR);
+/* Transactions */
+
+enum {
+ BCH_TRANS_INODE_CREATE = 128,
+ BCH_TRANS_FCOLLAPSE = 129,
+};
+
+struct bch_trans_inode_create_val {
+ struct bch_val v;
+ __le64 ino;
+ __le64 gen;
+};
+BKEY_VAL_TYPE(trans_inode_create_val, BCH_TRANS_INODE_CREATE);
+
+struct bch_trans_fcollapse_val {
+ struct bch_val v;
+ struct bpos pos;
+ __le64 shift;
+};
+BKEY_VAL_TYPE(trans_fcollapse_val, BCH_TRANS_FCOLLAPSE);
+
/* Superblock */
/* Version 0: Cache device
@@ -1088,7 +1109,9 @@ LE32_BITMASK(PSET_CSUM_TYPE, struct prio_set, flags, 0, 4);
enum btree_id {
DEFINE_BCH_BTREE_IDS()
- BTREE_ID_NR
+ BTREE_ID_NR,
+/* Pseudo btree: */
+ BTREE_ID_TRANSACTIONS = 255
};
#undef DEF_BTREE_ID