@@ -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+
437443void 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
937926static 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 ;
11431128csum_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 ;
11481131err :
11491132 if (to_wbio (dst )-> bounce )
0 commit comments