Skip to content

Commit 127d90d

Browse files
author
Kent Overstreet
committed
bcachefs: bch2_write_prep_encoded_data() now returns errcode
Prep work for killing off EIO and replacing them with proper private error codes. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 2fe2083 commit 127d90d

1 file changed

Lines changed: 71 additions & 88 deletions

File tree

fs/bcachefs/io_write.c

Lines changed: 71 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,12 @@ void bch2_write_op_error(struct bch_write_op *op, u64 offset, const char *fmt, .
434434
printbuf_exit(&buf);
435435
}
436436

437+
static void bch2_write_csum_err_msg(struct bch_write_op *op)
438+
{
439+
bch2_write_op_error(op, op->pos.offset,
440+
"error verifying existing checksum while rewriting existing data (memory corruption?)");
441+
}
442+
437443
void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c,
438444
enum bch_data_type type,
439445
const struct bkey_i *k,
@@ -809,18 +815,17 @@ static int bch2_write_rechecksum(struct bch_fs *c,
809815
{
810816
struct bio *bio = &op->wbio.bio;
811817
struct bch_extent_crc_unpacked new_crc;
812-
int ret;
813818

814819
/* bch2_rechecksum_bio() can't encrypt or decrypt data: */
815820

816821
if (bch2_csum_type_is_encryption(op->crc.csum_type) !=
817822
bch2_csum_type_is_encryption(new_csum_type))
818823
new_csum_type = op->crc.csum_type;
819824

820-
ret = bch2_rechecksum_bio(c, bio, op->version, op->crc,
821-
NULL, &new_crc,
822-
op->crc.offset, op->crc.live_size,
823-
new_csum_type);
825+
int ret = bch2_rechecksum_bio(c, bio, op->version, op->crc,
826+
NULL, &new_crc,
827+
op->crc.offset, op->crc.live_size,
828+
new_csum_type);
824829
if (ret)
825830
return ret;
826831

@@ -830,44 +835,12 @@ static int bch2_write_rechecksum(struct bch_fs *c,
830835
return 0;
831836
}
832837

833-
static int bch2_write_decrypt(struct bch_write_op *op)
834-
{
835-
struct bch_fs *c = op->c;
836-
struct nonce nonce = extent_nonce(op->version, op->crc);
837-
struct bch_csum csum;
838-
int ret;
839-
840-
if (!bch2_csum_type_is_encryption(op->crc.csum_type))
841-
return 0;
842-
843-
/*
844-
* If we need to decrypt data in the write path, we'll no longer be able
845-
* to verify the existing checksum (poly1305 mac, in this case) after
846-
* it's decrypted - this is the last point we'll be able to reverify the
847-
* checksum:
848-
*/
849-
csum = bch2_checksum_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
850-
if (bch2_crc_cmp(op->crc.csum, csum) && !c->opts.no_data_io)
851-
return -EIO;
852-
853-
ret = bch2_encrypt_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
854-
op->crc.csum_type = 0;
855-
op->crc.csum = (struct bch_csum) { 0, 0 };
856-
return ret;
857-
}
858-
859-
static enum prep_encoded_ret {
860-
PREP_ENCODED_OK,
861-
PREP_ENCODED_ERR,
862-
PREP_ENCODED_CHECKSUM_ERR,
863-
PREP_ENCODED_DO_WRITE,
864-
} bch2_write_prep_encoded_data(struct bch_write_op *op, struct write_point *wp)
838+
static noinline int bch2_write_prep_encoded_data(struct bch_write_op *op, struct write_point *wp)
865839
{
866840
struct bch_fs *c = op->c;
867841
struct bio *bio = &op->wbio.bio;
868-
869-
if (!(op->flags & BCH_WRITE_data_encoded))
870-
return PREP_ENCODED_OK;
842+
struct nonce nonce = extent_nonce(op->version, op->crc);
843+
int ret = 0;
871844

872845
BUG_ON(bio_sectors(bio) != op->crc.compressed_size);
873846

@@ -878,33 +851,37 @@ static enum prep_encoded_ret {
878851
(op->crc.compression_type == bch2_compression_opt_to_type(op->compression_opt) ||
879852
op->incompressible)) {
880853
if (!crc_is_compressed(op->crc) &&
881-
op->csum_type != op->crc.csum_type &&
882-
bch2_write_rechecksum(c, op, op->csum_type) &&
883-
!c->opts.no_data_io)
884-
return PREP_ENCODED_CHECKSUM_ERR;
854+
op->csum_type != op->crc.csum_type) {
855+
ret = bch2_write_rechecksum(c, op, op->csum_type);
856+
if (ret)
857+
return ret;
858+
}
885859

886-
return PREP_ENCODED_DO_WRITE;
860+
return 1;
887861
}
888862

889863
/*
890864
* If the data is compressed and we couldn't write the entire extent as
891865
* is, we have to decompress it:
892866
*/
893867
if (crc_is_compressed(op->crc)) {
894-
struct bch_csum csum;
895-
896-
if (bch2_write_decrypt(op))
897-
return PREP_ENCODED_CHECKSUM_ERR;
898-
899868
/* Last point we can still verify checksum: */
900-
csum = bch2_checksum_bio(c, op->crc.csum_type,
901-
extent_nonce(op->version, op->crc),
902-
bio);
869+
struct bch_csum csum = bch2_checksum_bio(c, op->crc.csum_type, nonce, bio);
903870
if (bch2_crc_cmp(op->crc.csum, csum) && !c->opts.no_data_io)
904-
return PREP_ENCODED_CHECKSUM_ERR;
871+
goto csum_err;
905872

906-
if (bch2_bio_uncompress_inplace(op, bio))
907-
return PREP_ENCODED_ERR;
873+
if (bch2_csum_type_is_encryption(op->crc.csum_type)) {
874+
ret = bch2_encrypt_bio(c, op->crc.csum_type, nonce, bio);
875+
if (ret)
876+
return ret;
877+
878+
op->crc.csum_type = 0;
879+
op->crc.csum = (struct bch_csum) { 0, 0 };
880+
}
881+
882+
ret = bch2_bio_uncompress_inplace(op, bio);
883+
if (ret)
884+
return ret;
908885
}
909886

910887
/*
@@ -916,22 +893,34 @@ static enum prep_encoded_ret {
916893
* If the data is checksummed and we're only writing a subset,
917894
* rechecksum and adjust bio to point to currently live data:
918895
*/
919-
if ((op->crc.live_size != op->crc.uncompressed_size ||
920-
op->crc.csum_type != op->csum_type) &&
921-
bch2_write_rechecksum(c, op, op->csum_type) &&
922-
!c->opts.no_data_io)
923-
return PREP_ENCODED_CHECKSUM_ERR;
896+
if (op->crc.live_size != op->crc.uncompressed_size ||
897+
op->crc.csum_type != op->csum_type) {
898+
ret = bch2_write_rechecksum(c, op, op->csum_type);
899+
if (ret)
900+
return ret;
901+
}
924902

925903
/*
926904
* If we want to compress the data, it has to be decrypted:
927905
*/
928-
if ((op->compression_opt ||
929-
bch2_csum_type_is_encryption(op->crc.csum_type) !=
930-
bch2_csum_type_is_encryption(op->csum_type)) &&
931-
bch2_write_decrypt(op))
932-
return PREP_ENCODED_CHECKSUM_ERR;
906+
if (bch2_csum_type_is_encryption(op->crc.csum_type) &&
907+
(op->compression_opt || op->crc.csum_type != op->csum_type)) {
908+
struct bch_csum csum = bch2_checksum_bio(c, op->crc.csum_type, nonce, bio);
909+
if (bch2_crc_cmp(op->crc.csum, csum) && !c->opts.no_data_io)
910+
goto csum_err;
911+
912+
ret = bch2_encrypt_bio(c, op->crc.csum_type, nonce, bio);
913+
if (ret)
914+
return ret;
933915

934-
return PREP_ENCODED_OK;
916+
op->crc.csum_type = 0;
917+
op->crc.csum = (struct bch_csum) { 0, 0 };
918+
}
919+
920+
return 0;
921+
csum_err:
922+
bch2_write_csum_err_msg(op);
923+
return -EIO;
935924
}
936925

937926
static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp,
@@ -950,25 +939,21 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp,
950939

951940
ec_buf = bch2_writepoint_ec_buf(c, wp);
952941

953-
switch (bch2_write_prep_encoded_data(op, wp)) {
954-
case PREP_ENCODED_OK:
955-
break;
956-
case PREP_ENCODED_ERR:
957-
ret = -EIO;
958-
goto err;
959-
case PREP_ENCODED_CHECKSUM_ERR:
960-
goto csum_err;
961-
case PREP_ENCODED_DO_WRITE:
962-
/* XXX look for bug here */
963-
if (ec_buf) {
964-
dst = bch2_write_bio_alloc(c, wp, src,
965-
&page_alloc_failed,
966-
ec_buf);
967-
bio_copy_data(dst, src);
968-
bounce = true;
942+
if (unlikely(op->flags & BCH_WRITE_data_encoded)) {
943+
ret = bch2_write_prep_encoded_data(op, wp);
944+
if (ret < 0)
945+
goto err;
946+
if (ret) {
947+
if (ec_buf) {
948+
dst = bch2_write_bio_alloc(c, wp, src,
949+
&page_alloc_failed,
950+
ec_buf);
951+
bio_copy_data(dst, src);
952+
bounce = true;
953+
}
954+
init_append_extent(op, wp, op->version, op->crc);
955+
goto do_write;
969956
}
970-
init_append_extent(op, wp, op->version, op->crc);
971-
goto do_write;
972957
}
973958

974959
if (ec_buf ||
@@ -1141,9 +1126,7 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp,
11411126
*_dst = dst;
11421127
return more;
11431128
csum_err:
1144-
bch2_write_op_error(op, op->pos.offset,
1145-
"error verifying existing checksum while rewriting existing data (memory corruption?)");
1146-
1129+
bch2_write_csum_err_msg(op);
11471130
ret = -EIO;
11481131
err:
11491132
if (to_wbio(dst)->bounce)

0 commit comments

Comments
 (0)