struct bch_io_failures failed = { .nr = 0 };
char buf[200];
struct printbuf out;
+ bool saw_error = false;
bool can_retry;
goto start;
!bch2_btree_node_read_done(c, ca, b, can_retry))
break;
+ saw_error = true;
+
if (!can_retry) {
set_btree_node_read_error(b);
break;
bch2_time_stats_update(&c->times[BCH_TIME_btree_node_read],
rb->start_time);
bio_put(&rb->bio);
+
+ if (saw_error && !btree_node_read_error(b))
+ bch2_btree_node_rewrite_async(c, b);
+
clear_btree_node_read_in_flight(b);
wake_up_bit(&b->flags, BTREE_NODE_read_in_flight);
}
int bch2_btree_node_rewrite(struct bch_fs *c, struct btree_iter *,
__le64, unsigned);
+void bch2_btree_node_rewrite_async(struct bch_fs *, struct btree *);
int bch2_btree_node_update_key(struct bch_fs *, struct btree_iter *,
struct btree *, struct bkey_i *);
return ret;
}
+struct async_btree_rewrite {
+ struct bch_fs *c;
+ struct work_struct work;
+ enum btree_id btree_id;
+ unsigned level;
+ struct bpos pos;
+ __le64 seq;
+};
+
+void async_btree_node_rewrite_work(struct work_struct *work)
+{
+ struct async_btree_rewrite *a =
+ container_of(work, struct async_btree_rewrite, work);
+ struct bch_fs *c = a->c;
+ struct btree_trans trans;
+ struct btree_iter *iter;
+
+ bch2_trans_init(&trans, c, 0, 0);
+ iter = bch2_trans_get_node_iter(&trans, a->btree_id, a->pos,
+ BTREE_MAX_DEPTH, a->level, 0);
+ bch2_btree_node_rewrite(c, iter, a->seq, 0);
+ bch2_trans_iter_put(&trans, iter);
+ bch2_trans_exit(&trans);
+ percpu_ref_put(&c->writes);
+ kfree(a);
+}
+
+void bch2_btree_node_rewrite_async(struct bch_fs *c, struct btree *b)
+{
+ struct async_btree_rewrite *a;
+
+ if (!percpu_ref_tryget(&c->writes))
+ return;
+
+ a = kmalloc(sizeof(*a), GFP_NOFS);
+ if (!a) {
+ percpu_ref_put(&c->writes);
+ return;
+ }
+
+ a->c = c;
+ a->btree_id = b->c.btree_id;
+ a->level = b->c.level;
+ a->pos = b->key.k.p;
+ a->seq = b->data->keys.seq;
+
+ INIT_WORK(&a->work, async_btree_node_rewrite_work);
+ queue_work(system_long_wq, &a->work);
+}
+
static void __bch2_btree_node_update_key(struct bch_fs *c,
struct btree_update *as,
struct btree_iter *iter,