Whamcloud - gitweb
LU-14895 brw: log T10 GRD tags during checksum calcs 55/44655/4
authorAndreas Dilger <adilger@whamcloud.com>
Wed, 4 Aug 2021 08:08:12 +0000 (02:08 -0600)
committerOleg Drokin <green@whamcloud.com>
Wed, 22 Sep 2021 04:43:46 +0000 (04:43 +0000)
Log the T10 guard tags during checksum calculation on the client and
target to help identify where checksum errors are being introduced.
The added debugging is only active on RPC resend, so will not add
overhead during the normal IO path.

Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Change-Id: Ia4f14f2f2296da096acf629c74558386e7ce7057
Reviewed-on: https://review.whamcloud.com/44655
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/osc/osc_request.c
lustre/target/tgt_handler.c

index b9c2e05..b80f8f4 100644 (file)
@@ -1178,7 +1178,7 @@ static int osc_checksum_bulk_t10pi(const char *obd_name, int nob,
                                   size_t pg_count, struct brw_page **pga,
                                   int opc, obd_dif_csum_fn *fn,
                                   int sector_size,
-                                  u32 *check_sum)
+                                  u32 *check_sum, bool resend)
 {
        struct ahash_request *req;
        /* Used Adler as the default checksum type on top of DIF tags */
@@ -1211,6 +1211,10 @@ static int osc_checksum_bulk_t10pi(const char *obd_name, int nob,
        buffer = kmap(__page);
        guard_start = (__u16 *)buffer;
        guard_number = PAGE_SIZE / sizeof(*guard_start);
+       CDEBUG(D_PAGE | (resend ? D_HA : 0),
+              "GRD tags per page=%u, resend=%u, bytes=%u, pages=%zu\n",
+              guard_number, resend, nob, pg_count);
+
        while (nob > 0 && pg_count > 0) {
                unsigned int count = pga[i]->count > nob ? nob : pga[i]->count;
 
@@ -1236,6 +1240,12 @@ static int osc_checksum_bulk_t10pi(const char *obd_name, int nob,
                                                  guard_number - used_number,
                                                  &used, sector_size,
                                                  fn);
+               if (unlikely(resend))
+                       CDEBUG(D_PAGE | D_HA,
+                              "pga[%u]: used %u off %llu+%u gen checksum: %*phN\n",
+                              i, used, pga[i]->off & ~PAGE_MASK, count,
+                              (int)(used * sizeof(*guard_start)),
+                              guard_start + used_number);
                if (rc)
                        break;
 
@@ -1274,7 +1284,7 @@ out:
 #else /* !CONFIG_CRC_T10DIF */
 #define obd_dif_ip_fn NULL
 #define obd_dif_crc_fn NULL
-#define osc_checksum_bulk_t10pi(name, nob, pgc, pga, opc, fn, ssize, csum \
+#define osc_checksum_bulk_t10pi(name, nob, pgc, pga, opc, fn, ssize, csum, re) \
        -EOPNOTSUPP
 #endif /* CONFIG_CRC_T10DIF */
 
@@ -1336,7 +1346,7 @@ static int osc_checksum_bulk_rw(const char *obd_name,
                                enum cksum_types cksum_type,
                                int nob, size_t pg_count,
                                struct brw_page **pga, int opc,
-                               u32 *check_sum)
+                               u32 *check_sum, bool resend)
 {
        obd_dif_csum_fn *fn = NULL;
        int sector_size = 0;
@@ -1347,7 +1357,8 @@ static int osc_checksum_bulk_rw(const char *obd_name,
 
        if (fn)
                rc = osc_checksum_bulk_t10pi(obd_name, nob, pg_count, pga,
-                                            opc, fn, sector_size, check_sum);
+                                            opc, fn, sector_size, check_sum,
+                                            resend);
        else
                rc = osc_checksum_bulk(nob, pg_count, pga, opc, cksum_type,
                                       check_sum);
@@ -1710,17 +1721,18 @@ no_bulk:
                        rc = osc_checksum_bulk_rw(obd_name, cksum_type,
                                                  requested_nob, page_count,
                                                  pga, OST_WRITE,
-                                                 &body->oa.o_cksum);
+                                                 &body->oa.o_cksum, resend);
                        if (rc < 0) {
-                               CDEBUG(D_PAGE, "failed to checksum, rc = %d\n",
+                               CDEBUG(D_PAGE, "failed to checksum: rc = %d\n",
                                       rc);
                                GOTO(out, rc);
                        }
-                        CDEBUG(D_PAGE, "checksum at write origin: %x\n",
-                               body->oa.o_cksum);
+                       CDEBUG(D_PAGE | (resend ? D_HA : 0),
+                              "checksum at write origin: %x (%x)\n",
+                              body->oa.o_cksum, cksum_type);
 
-                        /* save this in 'oa', too, for later checking */
-                        oa->o_valid |= OBD_MD_FLCKSUM | OBD_MD_FLFLAGS;
+                       /* save this in 'oa', too, for later checking */
+                       oa->o_valid |= OBD_MD_FLCKSUM | OBD_MD_FLFLAGS;
                        oa->o_flags |= obd_cksum_type_pack(obd_name,
                                                           cksum_type);
                 } else {
@@ -1793,6 +1805,7 @@ static void dump_all_bulk_pages(struct obdo *oa, __u32 page_count,
                 pga[0]->off,
                 pga[page_count-1]->off + pga[page_count-1]->count - 1,
                 client_cksum, server_cksum);
+       CWARN("dumping checksum data to %s\n", dbgcksum_file_name);
        filp = filp_open(dbgcksum_file_name,
                         O_CREAT | O_EXCL | O_WRONLY | O_LARGEFILE, 0600);
        if (IS_ERR(filp)) {
@@ -1819,8 +1832,6 @@ static void dump_all_bulk_pages(struct obdo *oa, __u32 page_count,
                        }
                        len -= rc;
                        buf += rc;
-                       CDEBUG(D_INFO, "%s: wrote %d bytes\n",
-                              dbgcksum_file_name, rc);
                }
                kunmap(pga[i]->pg);
        }
@@ -1829,6 +1840,8 @@ static void dump_all_bulk_pages(struct obdo *oa, __u32 page_count,
        if (rc)
                CERROR("%s: sync returns %d\n", dbgcksum_file_name, rc);
        filp_close(filp, NULL);
+
+       libcfs_debug_dumplog();
 }
 
 static int
@@ -1881,7 +1894,7 @@ check_write_checksum(struct obdo *oa, const struct lnet_process_id *peer,
                rc = osc_checksum_bulk_t10pi(obd_name, aa->aa_requested_nob,
                                             aa->aa_page_count, aa->aa_ppga,
                                             OST_WRITE, fn, sector_size,
-                                            &new_cksum);
+                                            &new_cksum, true);
        else
                rc = osc_checksum_bulk(aa->aa_requested_nob, aa->aa_page_count,
                                       aa->aa_ppga, OST_WRITE, cksum_type,
@@ -2043,22 +2056,23 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
                }
        }
 
-        if (rc < aa->aa_requested_nob)
-                handle_short_read(rc, aa->aa_page_count, aa->aa_ppga);
+       if (rc < aa->aa_requested_nob)
+               handle_short_read(rc, aa->aa_page_count, aa->aa_ppga);
 
-        if (body->oa.o_valid & OBD_MD_FLCKSUM) {
-                static int cksum_counter;
-               u32        server_cksum = body->oa.o_cksum;
-               char      *via = "";
-               char      *router = "";
+       if (body->oa.o_valid & OBD_MD_FLCKSUM) {
+               static int cksum_counter;
+               u32 server_cksum = body->oa.o_cksum;
+               int nob = rc;
+               char *via = "";
+               char *router = "";
                enum cksum_types cksum_type;
                u32 o_flags = body->oa.o_valid & OBD_MD_FLFLAGS ?
                        body->oa.o_flags : 0;
 
                cksum_type = obd_cksum_type_unpack(o_flags);
-               rc = osc_checksum_bulk_rw(obd_name, cksum_type, rc,
+               rc = osc_checksum_bulk_rw(obd_name, cksum_type, nob,
                                          aa->aa_page_count, aa->aa_ppga,
-                                         OST_READ, &client_cksum);
+                                         OST_READ, &client_cksum, false);
                if (rc < 0)
                        GOTO(out, rc);
 
@@ -2070,8 +2084,12 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
 
                if (server_cksum != client_cksum) {
                        struct ost_body *clbody;
+                       __u32 client_cksum2;
                        u32 page_count = aa->aa_page_count;
 
+                       osc_checksum_bulk_rw(obd_name, cksum_type, nob,
+                                            page_count, aa->aa_ppga,
+                                            OST_READ, &client_cksum2, true);
                        clbody = req_capsule_client_get(&req->rq_pill,
                                                        &RMF_OST_BODY);
                        if (cli->cl_checksum_dump)
@@ -2081,7 +2099,7 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
 
                        LCONSOLE_ERROR_MSG(0x133, "%s: BAD READ CHECKSUM: from "
                                           "%s%s%s inode "DFID" object "DOSTID
-                                          " extent [%llu-%llu], client %x, "
+                                          " extent [%llu-%llu], client %x/%x, "
                                           "server %x, cksum_type %x\n",
                                           obd_name,
                                           libcfs_nid2str(peer->nid),
@@ -2096,8 +2114,8 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
                                           aa->aa_ppga[0]->off,
                                           aa->aa_ppga[page_count-1]->off +
                                           aa->aa_ppga[page_count-1]->count - 1,
-                                          client_cksum, server_cksum,
-                                          cksum_type);
+                                          client_cksum, client_cksum2,
+                                          server_cksum, cksum_type);
                        cksum_counter = 0;
                        aa->aa_oa->o_cksum = client_cksum;
                        rc = -EAGAIN;
@@ -2336,7 +2354,7 @@ static int brw_interpret(const struct lu_env *env,
                               req->rq_import->imp_obd->obd_name,
                               POSTID(&aa->aa_oa->o_oi), rc);
                } else if (rc == -EINPROGRESS ||
-                   client_should_resend(aa->aa_resends, aa->aa_cli)) {
+                          client_should_resend(aa->aa_resends, aa->aa_cli)) {
                        rc = osc_brw_redo_request(req, aa, rc);
                } else {
                        CERROR("%s: too many resent retries for object: "
index c4ef17a..882591e 100644 (file)
@@ -1896,6 +1896,7 @@ static void dump_all_bulk_pages(struct obdo *oa, int count,
                 local_nb[0].lnb_file_offset,
                 local_nb[count-1].lnb_file_offset +
                 local_nb[count-1].lnb_len - 1, client_cksum, server_cksum);
+       CWARN("dumping checksum data to %s\n", dbgcksum_file_name);
        filp = filp_open(dbgcksum_file_name,
                         O_CREAT | O_EXCL | O_WRONLY | O_LARGEFILE, 0600);
        if (IS_ERR(filp)) {
@@ -1922,8 +1923,6 @@ static void dump_all_bulk_pages(struct obdo *oa, int count,
                        }
                        len -= rc;
                        buf += rc;
-                       CDEBUG(D_INFO, "%s: wrote %d bytes\n",
-                              dbgcksum_file_name, rc);
                }
                kunmap(local_nb[i].lnb_page);
        }
@@ -1932,6 +1931,8 @@ static void dump_all_bulk_pages(struct obdo *oa, int count,
        if (rc)
                CERROR("%s: sync returns %d\n", dbgcksum_file_name, rc);
        filp_close(filp, NULL);
+
+       libcfs_debug_dumplog();
 }
 
 static int check_read_checksum(struct niobuf_local *local_nb, int npages,
@@ -2009,11 +2010,10 @@ static int tgt_pages2shortio(struct niobuf_local *local, int npages,
 }
 
 static int tgt_checksum_niobuf_t10pi(struct lu_target *tgt,
-                                    struct niobuf_local *local_nb,
-                                    int npages, int opc,
-                                    obd_dif_csum_fn *fn,
-                                    int sector_size,
-                                    u32 *check_sum)
+                                    struct niobuf_local *local_nb, int npages,
+                                    int opc, obd_dif_csum_fn *fn,
+                                    int sector_size, u32 *check_sum,
+                                    bool resend)
 {
        enum cksum_types t10_cksum_type = tgt->lut_dt_conf.ddp_t10_cksum_type;
        unsigned char cfs_alg = cksum_obd2cfs(OBD_CKSUM_T10_TOP);
@@ -2044,7 +2044,11 @@ static int tgt_checksum_niobuf_t10pi(struct lu_target *tgt,
        buffer = kmap(__page);
        guard_start = (__u16 *)buffer;
        guard_number = PAGE_SIZE / sizeof(*guard_start);
+       if (unlikely(resend))
+               CDEBUG(D_PAGE | D_HA, "GRD tags per page = %u\n", guard_number);
        for (i = 0; i < npages; i++) {
+               bool use_t10_grd;
+
                /* corrupt the data before we compute the checksum, to
                 * simulate a client->OST data error */
                if (i == 0 && opc == OST_WRITE &&
@@ -2078,9 +2082,10 @@ static int tgt_checksum_niobuf_t10pi(struct lu_target *tgt,
                 * The left guard number should be able to hold checksums of a
                 * whole page
                 */
-               if (t10_cksum_type && opc == OST_READ &&
-                   local_nb[i].lnb_len == PAGE_SIZE &&
-                   local_nb[i].lnb_guard_disk) {
+               use_t10_grd = t10_cksum_type && opc == OST_READ &&
+                             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);
                        if (used > (guard_number - used_number)) {
                                rc = -E2BIG;
@@ -2088,14 +2093,52 @@ static int tgt_checksum_niobuf_t10pi(struct lu_target *tgt,
                        }
                        memcpy(guard_start + used_number,
                               local_nb[i].lnb_guards,
-                              used * sizeof(*local_nb[i].lnb_guards));
-               } else {
+                              used * sizeof(*guard_start));
+                       if (unlikely(resend))
+                               CDEBUG(D_PAGE | D_HA,
+                                      "lnb[%u]: used %u off %u+%u lnb checksum: %*phN\n",
+                                      i, used,
+                                      local_nb[i].lnb_page_offset,
+                                      local_nb[i].lnb_len,
+                                      (int)(used * sizeof(*guard_start)),
+                                      guard_start + used_number);
+               }
+               if (!use_t10_grd || unlikely(resend)) {
+                       __u16 guard_tmp[MAX_GUARD_NUMBER];
+                       __u16 *guards = guard_start + used_number;
+                       int used_tmp = -1, *usedp = &used;
+
+                       if (unlikely(use_t10_grd)) {
+                               guards = guard_tmp;
+                               usedp = &used_tmp;
+                       }
                        rc = obd_page_dif_generate_buffer(obd_name,
                                local_nb[i].lnb_page,
                                local_nb[i].lnb_page_offset & ~PAGE_MASK,
-                               local_nb[i].lnb_len, guard_start + used_number,
-                               guard_number - used_number, &used, sector_size,
+                               local_nb[i].lnb_len, guards,
+                               guard_number - used_number, usedp, sector_size,
                                fn);
+                       if (unlikely(resend)) {
+                               bool bad = use_t10_grd &&
+                                       memcmp(guard_tmp,
+                                              local_nb[i].lnb_guards,
+                                              used_tmp * sizeof(*guard_tmp));
+
+                               if (bad)
+                                       CERROR("lnb[%u]: used %u/%u off %u+%u tmp checksum: %*phN\n",
+                                              i, used, used_tmp,
+                                              local_nb[i].lnb_page_offset,
+                                              local_nb[i].lnb_len,
+                                              (int)(used_tmp * sizeof(*guard_start)),
+                                              guard_tmp);
+                               CDEBUG_LIMIT(D_PAGE | D_HA | (bad ? D_ERROR : 0),
+                                      "lnb[%u]: used %u/%u off %u+%u gen checksum: %*phN\n",
+                                      i, used, used_tmp,
+                                      local_nb[i].lnb_page_offset,
+                                      local_nb[i].lnb_len,
+                                      (int)(used * sizeof(*guard_start)),
+                                      guard_start + used_number);
+                       }
                        if (rc)
                                break;
                }
@@ -2176,7 +2219,8 @@ out:
 static int tgt_checksum_niobuf_rw(struct lu_target *tgt,
                                  enum cksum_types cksum_type,
                                  struct niobuf_local *local_nb,
-                                 int npages, int opc, u32 *check_sum)
+                                 int npages, int opc, u32 *check_sum,
+                                 bool resend)
 {
        obd_dif_csum_fn *fn = NULL;
        int sector_size = 0;
@@ -2188,10 +2232,11 @@ static int tgt_checksum_niobuf_rw(struct lu_target *tgt,
        if (fn)
                rc = tgt_checksum_niobuf_t10pi(tgt, local_nb, npages,
                                               opc, fn, sector_size,
-                                              check_sum);
+                                              check_sum, resend);
        else
                rc = tgt_checksum_niobuf(tgt, local_nb, npages, opc,
                                         cksum_type, check_sum);
+
        RETURN(rc);
 }
 
@@ -2347,6 +2392,8 @@ int tgt_brw_read(struct tgt_session_info *tsi)
                u32 flag = body->oa.o_valid & OBD_MD_FLFLAGS ?
                           body->oa.o_flags : 0;
                enum cksum_types cksum_type = obd_cksum_type_unpack(flag);
+               bool resend = (body->oa.o_valid & OBD_MD_FLFLAGS) &&
+                       (body->oa.o_flags & OBD_FL_RECOV_RESEND);
 
                repbody->oa.o_flags = obd_cksum_type_pack(obd_name,
                                                          cksum_type);
@@ -2354,17 +2401,17 @@ int tgt_brw_read(struct tgt_session_info *tsi)
 
                rc = tgt_checksum_niobuf_rw(tsi->tsi_tgt, cksum_type,
                                            local_nb, npages_read, OST_READ,
-                                           &repbody->oa.o_cksum);
+                                           &repbody->oa.o_cksum, resend);
                if (rc < 0)
                        GOTO(out_commitrw, rc);
-               CDEBUG(D_PAGE, "checksum at read origin: %x\n",
-                      repbody->oa.o_cksum);
+               CDEBUG(D_PAGE | (resend ? D_HA : 0),
+                      "checksum at read origin: %x (%x)\n",
+                      repbody->oa.o_cksum, cksum_type);
 
                /* if a resend it could be for a cksum error, so check Server
                 * cksum with returned Client cksum (this should even cover
                 * zero-cksum case) */
-               if ((body->oa.o_valid & OBD_MD_FLFLAGS) &&
-                   (body->oa.o_flags & OBD_FL_RECOV_RESEND))
+               if (resend)
                        check_read_checksum(local_nb, npages_read, exp,
                                            &body->oa, &req->rq_peer,
                                            body->oa.o_cksum,
@@ -2724,7 +2771,7 @@ skip_transfer:
 
                rc = tgt_checksum_niobuf_rw(tsi->tsi_tgt, cksum_type,
                                            local_nb, npages, OST_WRITE,
-                                           &repbody->oa.o_cksum);
+                                           &repbody->oa.o_cksum, false);
                if (rc < 0)
                        GOTO(out_commitrw, rc);