summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-09-03 17:32:42 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:11 -0400
commit8f54337dc6825f323f7761c182d98efdd180ce70 (patch)
tree6a095523f764170174ecd382bb4cfcfd6c2ef850
parentfbf14104dabe91e6c3b5544f9289eebc94a52c93 (diff)
downloadlwn-8f54337dc6825f323f7761c182d98efdd180ce70.tar.gz
lwn-8f54337dc6825f323f7761c182d98efdd180ce70.zip
bcachefs: Fix initialization of bch_write_op.nonce
If an extent ends up with a replica that is encrypted an a replica that isn't encrypted (due the user changing options), and then copygc/rebalance moves one of the replicas by reading from the unencrypted replica, we had a bug where we wouldn't correctly initialize op->nonce - for each crc field in an extent, crc.offset + crc.nonce must be equal. This patch fixes that by moving op.nonce initialization to bch2_migrate_write_init. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/move.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c
index c804af8b81de..3c2e566beb2d 100644
--- a/fs/bcachefs/move.c
+++ b/fs/bcachefs/move.c
@@ -220,11 +220,6 @@ void bch2_migrate_read_done(struct migrate_write *m, struct bch_read_bio *rbio)
m->op.crc = rbio->pick.crc;
m->op.wbio.bio.bi_iter.bi_size = m->op.crc.compressed_size << 9;
- if (bch2_csum_type_is_encryption(m->op.crc.csum_type)) {
- m->op.nonce = m->op.crc.nonce + m->op.crc.offset;
- m->op.csum_type = m->op.crc.csum_type;
- }
-
if (m->data_cmd == DATA_REWRITE)
bch2_dev_list_drop_dev(&m->op.devs_have, m->data_opts.rewrite_dev);
}
@@ -239,6 +234,7 @@ int bch2_migrate_write_init(struct bch_fs *c, struct migrate_write *m,
{
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
const union bch_extent_entry *entry;
+ struct bch_extent_crc_unpacked crc;
struct extent_ptr_decoded p;
int ret;
@@ -259,6 +255,18 @@ int bch2_migrate_write_init(struct bch_fs *c, struct migrate_write *m,
m->op.target = data_opts.target,
m->op.write_point = wp;
+ /*
+ * op->csum_type is normally initialized from the fs/file's current
+ * options - but if an extent is encrypted, we require that it stays
+ * encrypted:
+ */
+ bkey_for_each_crc(k.k, ptrs, crc, entry)
+ if (bch2_csum_type_is_encryption(crc.csum_type)) {
+ m->op.nonce = crc.nonce + crc.offset;
+ m->op.csum_type = crc.csum_type;
+ break;
+ }
+
if (m->data_opts.btree_insert_flags & BTREE_INSERT_USE_RESERVE) {
m->op.alloc_reserve = RESERVE_MOVINGGC;
m->op.flags |= BCH_WRITE_ALLOC_NOWAIT;