xref: /linux/fs/bcachefs/journal_seq_blacklist.c (revision 424eb881300467a21a108d04c9dd08a6f8c007dc)
11c6fdbd8SKent Overstreet // SPDX-License-Identifier: GPL-2.0
21c6fdbd8SKent Overstreet 
31c6fdbd8SKent Overstreet #include "bcachefs.h"
41c6fdbd8SKent Overstreet #include "btree_update.h"
51c6fdbd8SKent Overstreet #include "btree_update_interior.h"
61c6fdbd8SKent Overstreet #include "error.h"
71c6fdbd8SKent Overstreet #include "journal.h"
81c6fdbd8SKent Overstreet #include "journal_io.h"
91c6fdbd8SKent Overstreet #include "journal_reclaim.h"
101c6fdbd8SKent Overstreet #include "journal_seq_blacklist.h"
111c6fdbd8SKent Overstreet 
121c6fdbd8SKent Overstreet /*
131c6fdbd8SKent Overstreet  * journal_seq_blacklist machinery:
141c6fdbd8SKent Overstreet  *
151c6fdbd8SKent Overstreet  * To guarantee order of btree updates after a crash, we need to detect when a
161c6fdbd8SKent Overstreet  * btree node entry (bset) is newer than the newest journal entry that was
171c6fdbd8SKent Overstreet  * successfully written, and ignore it - effectively ignoring any btree updates
181c6fdbd8SKent Overstreet  * that didn't make it into the journal.
191c6fdbd8SKent Overstreet  *
201c6fdbd8SKent Overstreet  * If we didn't do this, we might have two btree nodes, a and b, both with
211c6fdbd8SKent Overstreet  * updates that weren't written to the journal yet: if b was updated after a,
221c6fdbd8SKent Overstreet  * but b was flushed and not a - oops; on recovery we'll find that the updates
231c6fdbd8SKent Overstreet  * to b happened, but not the updates to a that happened before it.
241c6fdbd8SKent Overstreet  *
251c6fdbd8SKent Overstreet  * Ignoring bsets that are newer than the newest journal entry is always safe,
261c6fdbd8SKent Overstreet  * because everything they contain will also have been journalled - and must
271c6fdbd8SKent Overstreet  * still be present in the journal on disk until a journal entry has been
281c6fdbd8SKent Overstreet  * written _after_ that bset was written.
291c6fdbd8SKent Overstreet  *
301c6fdbd8SKent Overstreet  * To accomplish this, bsets record the newest journal sequence number they
311c6fdbd8SKent Overstreet  * contain updates for; then, on startup, the btree code queries the journal
321c6fdbd8SKent Overstreet  * code to ask "Is this sequence number newer than the newest journal entry? If
331c6fdbd8SKent Overstreet  * so, ignore it."
341c6fdbd8SKent Overstreet  *
351c6fdbd8SKent Overstreet  * When this happens, we must blacklist that journal sequence number: the
361c6fdbd8SKent Overstreet  * journal must not write any entries with that sequence number, and it must
371c6fdbd8SKent Overstreet  * record that it was blacklisted so that a) on recovery we don't think we have
381c6fdbd8SKent Overstreet  * missing journal entries and b) so that the btree code continues to ignore
391c6fdbd8SKent Overstreet  * that bset, until that btree node is rewritten.
401c6fdbd8SKent Overstreet  *
411c6fdbd8SKent Overstreet  * Blacklisted journal sequence numbers are themselves recorded as entries in
421c6fdbd8SKent Overstreet  * the journal.
431c6fdbd8SKent Overstreet  */
441c6fdbd8SKent Overstreet 
451c6fdbd8SKent Overstreet /*
461c6fdbd8SKent Overstreet  * Called when journal needs to evict a blacklist entry to reclaim space: find
471c6fdbd8SKent Overstreet  * any btree nodes that refer to the blacklist journal sequence numbers, and
481c6fdbd8SKent Overstreet  * rewrite them:
491c6fdbd8SKent Overstreet  */
501c6fdbd8SKent Overstreet static void journal_seq_blacklist_flush(struct journal *j,
511c6fdbd8SKent Overstreet 					struct journal_entry_pin *pin, u64 seq)
521c6fdbd8SKent Overstreet {
531c6fdbd8SKent Overstreet 	struct bch_fs *c =
541c6fdbd8SKent Overstreet 		container_of(j, struct bch_fs, journal);
551c6fdbd8SKent Overstreet 	struct journal_seq_blacklist *bl =
561c6fdbd8SKent Overstreet 		container_of(pin, struct journal_seq_blacklist, pin);
571c6fdbd8SKent Overstreet 	struct blacklisted_node n;
581c6fdbd8SKent Overstreet 	struct closure cl;
591c6fdbd8SKent Overstreet 	unsigned i;
601c6fdbd8SKent Overstreet 	int ret;
611c6fdbd8SKent Overstreet 
621c6fdbd8SKent Overstreet 	closure_init_stack(&cl);
631c6fdbd8SKent Overstreet 
641c6fdbd8SKent Overstreet 	for (i = 0;; i++) {
65*424eb881SKent Overstreet 		struct btree_trans trans;
66*424eb881SKent Overstreet 		struct btree_iter *iter;
671c6fdbd8SKent Overstreet 		struct btree *b;
681c6fdbd8SKent Overstreet 
69*424eb881SKent Overstreet 		bch2_trans_init(&trans, c);
70*424eb881SKent Overstreet 
711c6fdbd8SKent Overstreet 		mutex_lock(&j->blacklist_lock);
721c6fdbd8SKent Overstreet 		if (i >= bl->nr_entries) {
731c6fdbd8SKent Overstreet 			mutex_unlock(&j->blacklist_lock);
741c6fdbd8SKent Overstreet 			break;
751c6fdbd8SKent Overstreet 		}
761c6fdbd8SKent Overstreet 		n = bl->entries[i];
771c6fdbd8SKent Overstreet 		mutex_unlock(&j->blacklist_lock);
781c6fdbd8SKent Overstreet 
79*424eb881SKent Overstreet 		iter = bch2_trans_get_node_iter(&trans, n.btree_id, n.pos,
80*424eb881SKent Overstreet 						0, 0, 0);
811c6fdbd8SKent Overstreet 
82*424eb881SKent Overstreet 		b = bch2_btree_iter_peek_node(iter);
831c6fdbd8SKent Overstreet 
841c6fdbd8SKent Overstreet 		/* The node might have already been rewritten: */
851c6fdbd8SKent Overstreet 
861c6fdbd8SKent Overstreet 		if (b->data->keys.seq == n.seq) {
87*424eb881SKent Overstreet 			ret = bch2_btree_node_rewrite(c, iter, n.seq, 0);
881c6fdbd8SKent Overstreet 			if (ret) {
89*424eb881SKent Overstreet 				bch2_trans_exit(&trans);
901c6fdbd8SKent Overstreet 				bch2_fs_fatal_error(c,
911c6fdbd8SKent Overstreet 					"error %i rewriting btree node with blacklisted journal seq",
921c6fdbd8SKent Overstreet 					ret);
931c6fdbd8SKent Overstreet 				bch2_journal_halt(j);
941c6fdbd8SKent Overstreet 				return;
951c6fdbd8SKent Overstreet 			}
961c6fdbd8SKent Overstreet 		}
971c6fdbd8SKent Overstreet 
98*424eb881SKent Overstreet 		bch2_trans_exit(&trans);
991c6fdbd8SKent Overstreet 	}
1001c6fdbd8SKent Overstreet 
1011c6fdbd8SKent Overstreet 	for (i = 0;; i++) {
1021c6fdbd8SKent Overstreet 		struct btree_update *as;
1031c6fdbd8SKent Overstreet 		struct pending_btree_node_free *d;
1041c6fdbd8SKent Overstreet 
1051c6fdbd8SKent Overstreet 		mutex_lock(&j->blacklist_lock);
1061c6fdbd8SKent Overstreet 		if (i >= bl->nr_entries) {
1071c6fdbd8SKent Overstreet 			mutex_unlock(&j->blacklist_lock);
1081c6fdbd8SKent Overstreet 			break;
1091c6fdbd8SKent Overstreet 		}
1101c6fdbd8SKent Overstreet 		n = bl->entries[i];
1111c6fdbd8SKent Overstreet 		mutex_unlock(&j->blacklist_lock);
1121c6fdbd8SKent Overstreet redo_wait:
1131c6fdbd8SKent Overstreet 		mutex_lock(&c->btree_interior_update_lock);
1141c6fdbd8SKent Overstreet 
1151c6fdbd8SKent Overstreet 		/*
1161c6fdbd8SKent Overstreet 		 * Is the node on the list of pending interior node updates -
1171c6fdbd8SKent Overstreet 		 * being freed? If so, wait for that to finish:
1181c6fdbd8SKent Overstreet 		 */
1191c6fdbd8SKent Overstreet 		for_each_pending_btree_node_free(c, as, d)
1201c6fdbd8SKent Overstreet 			if (n.seq	== d->seq &&
1211c6fdbd8SKent Overstreet 			    n.btree_id	== d->btree_id &&
1221c6fdbd8SKent Overstreet 			    !d->level &&
1231c6fdbd8SKent Overstreet 			    !bkey_cmp(n.pos, d->key.k.p)) {
1241c6fdbd8SKent Overstreet 				closure_wait(&as->wait, &cl);
1251c6fdbd8SKent Overstreet 				mutex_unlock(&c->btree_interior_update_lock);
1261c6fdbd8SKent Overstreet 				closure_sync(&cl);
1271c6fdbd8SKent Overstreet 				goto redo_wait;
1281c6fdbd8SKent Overstreet 			}
1291c6fdbd8SKent Overstreet 
1301c6fdbd8SKent Overstreet 		mutex_unlock(&c->btree_interior_update_lock);
1311c6fdbd8SKent Overstreet 	}
1321c6fdbd8SKent Overstreet 
1331c6fdbd8SKent Overstreet 	mutex_lock(&j->blacklist_lock);
1341c6fdbd8SKent Overstreet 
1351c6fdbd8SKent Overstreet 	bch2_journal_pin_drop(j, &bl->pin);
1361c6fdbd8SKent Overstreet 	list_del(&bl->list);
1371c6fdbd8SKent Overstreet 	kfree(bl->entries);
1381c6fdbd8SKent Overstreet 	kfree(bl);
1391c6fdbd8SKent Overstreet 
1401c6fdbd8SKent Overstreet 	mutex_unlock(&j->blacklist_lock);
1411c6fdbd8SKent Overstreet }
1421c6fdbd8SKent Overstreet 
1431c6fdbd8SKent Overstreet /*
1441c6fdbd8SKent Overstreet  * Determine if a particular sequence number is blacklisted - if so, return
1451c6fdbd8SKent Overstreet  * blacklist entry:
1461c6fdbd8SKent Overstreet  */
1471c6fdbd8SKent Overstreet struct journal_seq_blacklist *
1481c6fdbd8SKent Overstreet bch2_journal_seq_blacklist_find(struct journal *j, u64 seq)
1491c6fdbd8SKent Overstreet {
1501c6fdbd8SKent Overstreet 	struct journal_seq_blacklist *bl;
1511c6fdbd8SKent Overstreet 
1521c6fdbd8SKent Overstreet 	lockdep_assert_held(&j->blacklist_lock);
1531c6fdbd8SKent Overstreet 
1541c6fdbd8SKent Overstreet 	list_for_each_entry(bl, &j->seq_blacklist, list)
1551c6fdbd8SKent Overstreet 		if (seq >= bl->start && seq <= bl->end)
1561c6fdbd8SKent Overstreet 			return bl;
1571c6fdbd8SKent Overstreet 
1581c6fdbd8SKent Overstreet 	return NULL;
1591c6fdbd8SKent Overstreet }
1601c6fdbd8SKent Overstreet 
1611c6fdbd8SKent Overstreet /*
1621c6fdbd8SKent Overstreet  * Allocate a new, in memory blacklist entry:
1631c6fdbd8SKent Overstreet  */
1641c6fdbd8SKent Overstreet static struct journal_seq_blacklist *
1651c6fdbd8SKent Overstreet bch2_journal_seq_blacklisted_new(struct journal *j, u64 start, u64 end)
1661c6fdbd8SKent Overstreet {
1671c6fdbd8SKent Overstreet 	struct journal_seq_blacklist *bl;
1681c6fdbd8SKent Overstreet 
1691c6fdbd8SKent Overstreet 	lockdep_assert_held(&j->blacklist_lock);
1701c6fdbd8SKent Overstreet 
1711c6fdbd8SKent Overstreet 	/*
1721c6fdbd8SKent Overstreet 	 * When we start the journal, bch2_journal_start() will skip over @seq:
1731c6fdbd8SKent Overstreet 	 */
1741c6fdbd8SKent Overstreet 
1751c6fdbd8SKent Overstreet 	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
1761c6fdbd8SKent Overstreet 	if (!bl)
1771c6fdbd8SKent Overstreet 		return NULL;
1781c6fdbd8SKent Overstreet 
1791c6fdbd8SKent Overstreet 	bl->start	= start;
1801c6fdbd8SKent Overstreet 	bl->end		= end;
1811c6fdbd8SKent Overstreet 
1821c6fdbd8SKent Overstreet 	list_add_tail(&bl->list, &j->seq_blacklist);
1831c6fdbd8SKent Overstreet 	return bl;
1841c6fdbd8SKent Overstreet }
1851c6fdbd8SKent Overstreet 
1861c6fdbd8SKent Overstreet /*
1871c6fdbd8SKent Overstreet  * Returns true if @seq is newer than the most recent journal entry that got
1881c6fdbd8SKent Overstreet  * written, and data corresponding to @seq should be ignored - also marks @seq
1891c6fdbd8SKent Overstreet  * as blacklisted so that on future restarts the corresponding data will still
1901c6fdbd8SKent Overstreet  * be ignored:
1911c6fdbd8SKent Overstreet  */
1921c6fdbd8SKent Overstreet int bch2_journal_seq_should_ignore(struct bch_fs *c, u64 seq, struct btree *b)
1931c6fdbd8SKent Overstreet {
1941c6fdbd8SKent Overstreet 	struct journal *j = &c->journal;
1951c6fdbd8SKent Overstreet 	struct journal_seq_blacklist *bl = NULL;
1961c6fdbd8SKent Overstreet 	struct blacklisted_node *n;
1971c6fdbd8SKent Overstreet 	u64 journal_seq;
1981c6fdbd8SKent Overstreet 	int ret = 0;
1991c6fdbd8SKent Overstreet 
2001c6fdbd8SKent Overstreet 	if (!seq)
2011c6fdbd8SKent Overstreet 		return 0;
2021c6fdbd8SKent Overstreet 
2031c6fdbd8SKent Overstreet 	spin_lock(&j->lock);
2041c6fdbd8SKent Overstreet 	journal_seq = journal_cur_seq(j);
2051c6fdbd8SKent Overstreet 	spin_unlock(&j->lock);
2061c6fdbd8SKent Overstreet 
2071c6fdbd8SKent Overstreet 	/* Interier updates aren't journalled: */
2081c6fdbd8SKent Overstreet 	BUG_ON(b->level);
2091c6fdbd8SKent Overstreet 	BUG_ON(seq > journal_seq && test_bit(BCH_FS_INITIAL_GC_DONE, &c->flags));
2101c6fdbd8SKent Overstreet 
2111c6fdbd8SKent Overstreet 	/*
2121c6fdbd8SKent Overstreet 	 * Decrease this back to j->seq + 2 when we next rev the on disk format:
2131c6fdbd8SKent Overstreet 	 * increasing it temporarily to work around bug in old kernels
2141c6fdbd8SKent Overstreet 	 */
2151c6fdbd8SKent Overstreet 	fsck_err_on(seq > journal_seq + 4, c,
2161c6fdbd8SKent Overstreet 		    "bset journal seq too far in the future: %llu > %llu",
2171c6fdbd8SKent Overstreet 		    seq, journal_seq);
2181c6fdbd8SKent Overstreet 
2191c6fdbd8SKent Overstreet 	if (seq <= journal_seq &&
2201c6fdbd8SKent Overstreet 	    list_empty_careful(&j->seq_blacklist))
2211c6fdbd8SKent Overstreet 		return 0;
2221c6fdbd8SKent Overstreet 
2231c6fdbd8SKent Overstreet 	mutex_lock(&j->blacklist_lock);
2241c6fdbd8SKent Overstreet 
2251c6fdbd8SKent Overstreet 	if (seq <= journal_seq) {
2261c6fdbd8SKent Overstreet 		bl = bch2_journal_seq_blacklist_find(j, seq);
2271c6fdbd8SKent Overstreet 		if (!bl)
2281c6fdbd8SKent Overstreet 			goto out;
2291c6fdbd8SKent Overstreet 	} else {
2301c6fdbd8SKent Overstreet 		bch_verbose(c, "btree node %u:%llu:%llu has future journal sequence number %llu, blacklisting",
2311c6fdbd8SKent Overstreet 			    b->btree_id, b->key.k.p.inode, b->key.k.p.offset, seq);
2321c6fdbd8SKent Overstreet 
2331c6fdbd8SKent Overstreet 		if (!j->new_blacklist) {
2341c6fdbd8SKent Overstreet 			j->new_blacklist = bch2_journal_seq_blacklisted_new(j,
2351c6fdbd8SKent Overstreet 						journal_seq + 1,
2361c6fdbd8SKent Overstreet 						journal_seq + 1);
2371c6fdbd8SKent Overstreet 			if (!j->new_blacklist) {
2381c6fdbd8SKent Overstreet 				ret = -ENOMEM;
2391c6fdbd8SKent Overstreet 				goto out;
2401c6fdbd8SKent Overstreet 			}
2411c6fdbd8SKent Overstreet 		}
2421c6fdbd8SKent Overstreet 		bl = j->new_blacklist;
2431c6fdbd8SKent Overstreet 		bl->end = max(bl->end, seq);
2441c6fdbd8SKent Overstreet 	}
2451c6fdbd8SKent Overstreet 
2461c6fdbd8SKent Overstreet 	for (n = bl->entries; n < bl->entries + bl->nr_entries; n++)
2471c6fdbd8SKent Overstreet 		if (b->data->keys.seq	== n->seq &&
2481c6fdbd8SKent Overstreet 		    b->btree_id		== n->btree_id &&
2491c6fdbd8SKent Overstreet 		    !bkey_cmp(b->key.k.p, n->pos))
2501c6fdbd8SKent Overstreet 			goto found_entry;
2511c6fdbd8SKent Overstreet 
2521c6fdbd8SKent Overstreet 	if (!bl->nr_entries ||
2531c6fdbd8SKent Overstreet 	    is_power_of_2(bl->nr_entries)) {
2541c6fdbd8SKent Overstreet 		n = krealloc(bl->entries,
2551c6fdbd8SKent Overstreet 			     max_t(size_t, bl->nr_entries * 2, 8) * sizeof(*n),
2561c6fdbd8SKent Overstreet 			     GFP_KERNEL);
2571c6fdbd8SKent Overstreet 		if (!n) {
2581c6fdbd8SKent Overstreet 			ret = -ENOMEM;
2591c6fdbd8SKent Overstreet 			goto out;
2601c6fdbd8SKent Overstreet 		}
2611c6fdbd8SKent Overstreet 		bl->entries = n;
2621c6fdbd8SKent Overstreet 	}
2631c6fdbd8SKent Overstreet 
2641c6fdbd8SKent Overstreet 	bl->entries[bl->nr_entries++] = (struct blacklisted_node) {
2651c6fdbd8SKent Overstreet 		.seq		= b->data->keys.seq,
2661c6fdbd8SKent Overstreet 		.btree_id	= b->btree_id,
2671c6fdbd8SKent Overstreet 		.pos		= b->key.k.p,
2681c6fdbd8SKent Overstreet 	};
2691c6fdbd8SKent Overstreet found_entry:
2701c6fdbd8SKent Overstreet 	ret = 1;
2711c6fdbd8SKent Overstreet out:
2721c6fdbd8SKent Overstreet fsck_err:
2731c6fdbd8SKent Overstreet 	mutex_unlock(&j->blacklist_lock);
2741c6fdbd8SKent Overstreet 	return ret;
2751c6fdbd8SKent Overstreet }
2761c6fdbd8SKent Overstreet 
2771c6fdbd8SKent Overstreet static int __bch2_journal_seq_blacklist_read(struct journal *j,
2781c6fdbd8SKent Overstreet 					     struct journal_replay *i,
2791c6fdbd8SKent Overstreet 					     u64 start, u64 end)
2801c6fdbd8SKent Overstreet {
2811c6fdbd8SKent Overstreet 	struct bch_fs *c = container_of(j, struct bch_fs, journal);
2821c6fdbd8SKent Overstreet 	struct journal_seq_blacklist *bl;
2831c6fdbd8SKent Overstreet 
2841c6fdbd8SKent Overstreet 	bch_verbose(c, "blacklisting existing journal seq %llu-%llu",
2851c6fdbd8SKent Overstreet 		    start, end);
2861c6fdbd8SKent Overstreet 
2871c6fdbd8SKent Overstreet 	bl = bch2_journal_seq_blacklisted_new(j, start, end);
2881c6fdbd8SKent Overstreet 	if (!bl)
2891c6fdbd8SKent Overstreet 		return -ENOMEM;
2901c6fdbd8SKent Overstreet 
2911c6fdbd8SKent Overstreet 	bch2_journal_pin_add(j, le64_to_cpu(i->j.seq), &bl->pin,
2921c6fdbd8SKent Overstreet 			     journal_seq_blacklist_flush);
2931c6fdbd8SKent Overstreet 	return 0;
2941c6fdbd8SKent Overstreet }
2951c6fdbd8SKent Overstreet 
2961c6fdbd8SKent Overstreet /*
2971c6fdbd8SKent Overstreet  * After reading the journal, find existing journal seq blacklist entries and
2981c6fdbd8SKent Overstreet  * read them into memory:
2991c6fdbd8SKent Overstreet  */
3001c6fdbd8SKent Overstreet int bch2_journal_seq_blacklist_read(struct journal *j,
3011c6fdbd8SKent Overstreet 				    struct journal_replay *i)
3021c6fdbd8SKent Overstreet {
3031c6fdbd8SKent Overstreet 	struct jset_entry *entry;
3041c6fdbd8SKent Overstreet 	int ret = 0;
3051c6fdbd8SKent Overstreet 
3061c6fdbd8SKent Overstreet 	vstruct_for_each(&i->j, entry) {
3071c6fdbd8SKent Overstreet 		switch (entry->type) {
3081c6fdbd8SKent Overstreet 		case BCH_JSET_ENTRY_blacklist: {
3091c6fdbd8SKent Overstreet 			struct jset_entry_blacklist *bl_entry =
3101c6fdbd8SKent Overstreet 				container_of(entry, struct jset_entry_blacklist, entry);
3111c6fdbd8SKent Overstreet 
3121c6fdbd8SKent Overstreet 			ret = __bch2_journal_seq_blacklist_read(j, i,
3131c6fdbd8SKent Overstreet 					le64_to_cpu(bl_entry->seq),
3141c6fdbd8SKent Overstreet 					le64_to_cpu(bl_entry->seq));
3151c6fdbd8SKent Overstreet 			break;
3161c6fdbd8SKent Overstreet 		}
3171c6fdbd8SKent Overstreet 		case BCH_JSET_ENTRY_blacklist_v2: {
3181c6fdbd8SKent Overstreet 			struct jset_entry_blacklist_v2 *bl_entry =
3191c6fdbd8SKent Overstreet 				container_of(entry, struct jset_entry_blacklist_v2, entry);
3201c6fdbd8SKent Overstreet 
3211c6fdbd8SKent Overstreet 			ret = __bch2_journal_seq_blacklist_read(j, i,
3221c6fdbd8SKent Overstreet 					le64_to_cpu(bl_entry->start),
3231c6fdbd8SKent Overstreet 					le64_to_cpu(bl_entry->end));
3241c6fdbd8SKent Overstreet 			break;
3251c6fdbd8SKent Overstreet 		}
3261c6fdbd8SKent Overstreet 		}
3271c6fdbd8SKent Overstreet 
3281c6fdbd8SKent Overstreet 		if (ret)
3291c6fdbd8SKent Overstreet 			break;
3301c6fdbd8SKent Overstreet 	}
3311c6fdbd8SKent Overstreet 
3321c6fdbd8SKent Overstreet 	return ret;
3331c6fdbd8SKent Overstreet }
3341c6fdbd8SKent Overstreet 
3351c6fdbd8SKent Overstreet /*
3361c6fdbd8SKent Overstreet  * After reading the journal and walking the btree, we might have new journal
3371c6fdbd8SKent Overstreet  * sequence numbers to blacklist - add entries to the next journal entry to be
3381c6fdbd8SKent Overstreet  * written:
3391c6fdbd8SKent Overstreet  */
3401c6fdbd8SKent Overstreet void bch2_journal_seq_blacklist_write(struct journal *j)
3411c6fdbd8SKent Overstreet {
3421c6fdbd8SKent Overstreet 	struct journal_seq_blacklist *bl = j->new_blacklist;
3431c6fdbd8SKent Overstreet 	struct jset_entry_blacklist_v2 *bl_entry;
3441c6fdbd8SKent Overstreet 	struct jset_entry *entry;
3451c6fdbd8SKent Overstreet 
3461c6fdbd8SKent Overstreet 	if (!bl)
3471c6fdbd8SKent Overstreet 		return;
3481c6fdbd8SKent Overstreet 
3491c6fdbd8SKent Overstreet 	entry = bch2_journal_add_entry_noreservation(journal_cur_buf(j),
3501c6fdbd8SKent Overstreet 			(sizeof(*bl_entry) - sizeof(*entry)) / sizeof(u64));
3511c6fdbd8SKent Overstreet 
3521c6fdbd8SKent Overstreet 	bl_entry = container_of(entry, struct jset_entry_blacklist_v2, entry);
3531c6fdbd8SKent Overstreet 	bl_entry->entry.type	= BCH_JSET_ENTRY_blacklist_v2;
3541c6fdbd8SKent Overstreet 	bl_entry->start		= cpu_to_le64(bl->start);
3551c6fdbd8SKent Overstreet 	bl_entry->end		= cpu_to_le64(bl->end);
3561c6fdbd8SKent Overstreet 
3571c6fdbd8SKent Overstreet 	bch2_journal_pin_add(j,
3581c6fdbd8SKent Overstreet 			     journal_cur_seq(j),
3591c6fdbd8SKent Overstreet 			     &bl->pin,
3601c6fdbd8SKent Overstreet 			     journal_seq_blacklist_flush);
3611c6fdbd8SKent Overstreet 
3621c6fdbd8SKent Overstreet 	j->new_blacklist = NULL;
3631c6fdbd8SKent Overstreet }
364