From 3999627447c01eebd96c14cc5cf8bba93f89a66b Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Wed, 5 Apr 2023 12:54:13 +1000 Subject: [PATCH] LU-16712 cksum: fix generating T10PI guard tags for partial brw page To get better performance, we allocate a page as the buffer for T10PI guard tags, we fill the buffer going over every page for brw, when the buffer is considered full, we use cfs_crypto_hash_update_page() to update the hash and reuse the buffer. It doesn't work when there's a page in the brw gets clipped, and the checksum sector size is 512. For a page with PAGE_SIZE of 4096, and offset at 1024, we will end up with 6 guard tags, and won't have enough space in the very end of the buffer for a full brw page, which needs 8. Work out the number of guard tags for each page, update the checksum hash and reuse the buffer when needed. Change-Id: Ic591e63b24534f2a42b670669520895cb35a9546 Fixes: b1e7be00cb ("LU-10472 osc: add T10PI support for RPC checksum") Signed-off-by: Li Dongyang Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50540 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Li Xi Reviewed-by: Oleg Drokin --- lustre/osc/osc_request.c | 42 ++++++++++++++++++++++++------------------ lustre/target/tgt_handler.c | 21 +++++++++++---------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index 5ee8a36..1d0c2b0 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -1189,12 +1189,12 @@ static int osc_checksum_bulk_t10pi(const char *obd_name, int nob, struct page *__page; unsigned char *buffer; __be16 *guard_start; - unsigned int bufsize; int guard_number; int used_number = 0; int used; u32 cksum; - int rc = 0; + unsigned int bufsize = sizeof(cksum); + int rc = 0, rc2; int i = 0; LASSERT(pg_count > 0); @@ -1219,14 +1219,22 @@ static int osc_checksum_bulk_t10pi(const char *obd_name, int nob, guard_number, resend, nob, pg_count); while (nob > 0 && pg_count > 0) { + int off = pga[i]->off & ~PAGE_MASK; unsigned int count = pga[i]->count > nob ? nob : pga[i]->count; + int guards_needed = DIV_ROUND_UP(off + count, sector_size) - + (off / sector_size); + + if (guards_needed > guard_number - used_number) { + cfs_crypto_hash_update_page(req, __page, 0, + used_number * sizeof(*guard_start)); + used_number = 0; + } /* corrupt the data before we compute the checksum, to * simulate an OST->client data error */ if (unlikely(i == 0 && opc == OST_READ && OBD_FAIL_CHECK(OBD_FAIL_OSC_CHECKSUM_RECEIVE))) { unsigned char *ptr = kmap(pga[i]->pg); - int off = pga[i]->off & ~PAGE_MASK; memcpy(ptr + off, "bad1", min_t(typeof(nob), 4, nob)); kunmap(pga[i]->pg); @@ -1253,33 +1261,31 @@ static int osc_checksum_bulk_t10pi(const char *obd_name, int nob, break; used_number += used; - if (used_number == guard_number) { - cfs_crypto_hash_update_page(req, __page, 0, - used_number * sizeof(*guard_start)); - used_number = 0; - } - nob -= pga[i]->count; pg_count--; i++; } kunmap(__page); if (rc) - GOTO(out, rc); + GOTO(out_hash, rc); if (used_number != 0) cfs_crypto_hash_update_page(req, __page, 0, used_number * sizeof(*guard_start)); - bufsize = sizeof(cksum); - cfs_crypto_hash_final(req, (unsigned char *)&cksum, &bufsize); - - /* For sending we only compute the wrong checksum instead - * of corrupting the data so it is still correct on a redo */ - if (opc == OST_WRITE && OBD_FAIL_CHECK(OBD_FAIL_OSC_CHECKSUM_SEND)) - cksum++; +out_hash: + rc2 = cfs_crypto_hash_final(req, (unsigned char *)&cksum, &bufsize); + if (!rc) + rc = rc2; + if (rc == 0) { + /* For sending we only compute the wrong checksum instead + * of corrupting the data so it is still correct on a redo */ + if (opc == OST_WRITE && + OBD_FAIL_CHECK(OBD_FAIL_OSC_CHECKSUM_SEND)) + cksum++; - *check_sum = cksum; + *check_sum = cksum; + } out: __free_page(__page); return rc; diff --git a/lustre/target/tgt_handler.c b/lustre/target/tgt_handler.c index c1d08ba..6c0192b 100644 --- a/lustre/target/tgt_handler.c +++ b/lustre/target/tgt_handler.c @@ -2101,13 +2101,21 @@ static int tgt_checksum_niobuf_t10pi(struct lu_target *tgt, CDEBUG(D_PAGE | D_HA, "GRD tags per page = %u\n", guard_number); for (i = 0; i < npages; i++) { bool use_t10_grd; + int off = local_nb[i].lnb_page_offset & ~PAGE_MASK; + int len = local_nb[i].lnb_len; + int guards_needed = DIV_ROUND_UP(off + len, sector_size) - + (off / sector_size); + + if (guards_needed > guard_number - used_number) { + cfs_crypto_hash_update_page(req, __page, 0, + used_number * sizeof(*guard_start)); + used_number = 0; + } /* corrupt the data before we compute the checksum, to * simulate a client->OST data error */ if (i == 0 && opc == OST_WRITE && OBD_FAIL_CHECK(OBD_FAIL_OST_CHECKSUM_RECEIVE)) { - int off = local_nb[i].lnb_page_offset & ~PAGE_MASK; - int len = local_nb[i].lnb_len; struct page *np = tgt_page_to_corrupt; if (np) { @@ -2140,7 +2148,7 @@ static int tgt_checksum_niobuf_t10pi(struct lu_target *tgt, local_nb[i].lnb_len == PAGE_SIZE && local_nb[i].lnb_guard_disk; if (use_t10_grd) { - used = DIV_ROUND_UP(local_nb[i].lnb_len, sector_size); + used = guards_needed; if (used > (guard_number - used_number)) { rc = -E2BIG; CDEBUG(D_PAGE | D_HA, @@ -2223,18 +2231,11 @@ static int tgt_checksum_niobuf_t10pi(struct lu_target *tgt, } used_number += used; - if (used_number == guard_number) { - cfs_crypto_hash_update_page(req, __page, 0, - used_number * sizeof(*guard_start)); - used_number = 0; - } /* corrupt the data after we compute the checksum, to * simulate an OST->client data error */ if (unlikely(i == 0 && opc == OST_READ && OBD_FAIL_CHECK(OBD_FAIL_OST_CHECKSUM_SEND))) { - int off = local_nb[i].lnb_page_offset & ~PAGE_MASK; - int len = local_nb[i].lnb_len; struct page *np = tgt_page_to_corrupt; if (np) { -- 1.8.3.1