unsigned int init_nr_io_errors;
        unsigned int init_nr_csum_errors;
        unsigned int init_nr_meta_errors;
+       unsigned int init_nr_meta_gen_errors;
 
        /*
         * The following error bitmaps are all for the current status.
         * Every time we submit a new read, these bitmaps may be updated.
         *
-        * error_bitmap = io_error_bitmap | csum_error_bitmap | meta_error_bitmap;
+        * error_bitmap = io_error_bitmap | csum_error_bitmap |
+        *                meta_error_bitmap | meta_generation_bitmap;
         *
         * IO and csum errors can happen for both metadata and data.
         */
        unsigned long io_error_bitmap;
        unsigned long csum_error_bitmap;
        unsigned long meta_error_bitmap;
+       unsigned long meta_gen_error_bitmap;
 
        /* For writeback (repair or replace) error reporting. */
        unsigned long write_error_bitmap;
        }
        if (stripe->sectors[sector_nr].generation !=
            btrfs_stack_header_generation(header)) {
-               bitmap_set(&stripe->meta_error_bitmap, sector_nr, sectors_per_tree);
+               bitmap_set(&stripe->meta_gen_error_bitmap, sector_nr, sectors_per_tree);
                bitmap_set(&stripe->error_bitmap, sector_nr, sectors_per_tree);
                btrfs_warn_rl(fs_info,
                "tree block %llu mirror %u has bad generation, has %llu want %llu",
        bitmap_clear(&stripe->error_bitmap, sector_nr, sectors_per_tree);
        bitmap_clear(&stripe->csum_error_bitmap, sector_nr, sectors_per_tree);
        bitmap_clear(&stripe->meta_error_bitmap, sector_nr, sectors_per_tree);
+       bitmap_clear(&stripe->meta_gen_error_bitmap, sector_nr, sectors_per_tree);
 }
 
 static void scrub_verify_one_sector(struct scrub_stripe *stripe, int sector_nr)
                        if (__ratelimit(&rs) && dev)
                                scrub_print_common_warning("header error", dev, false,
                                                     stripe->logical, physical);
+               if (test_bit(sector_nr, &stripe->meta_gen_error_bitmap))
+                       if (__ratelimit(&rs) && dev)
+                               scrub_print_common_warning("generation error", dev, false,
+                                                    stripe->logical, physical);
        }
 
+       /* Update the device stats. */
+       for (int i = 0; i < stripe->init_nr_io_errors; i++)
+               btrfs_dev_stat_inc_and_print(stripe->dev, BTRFS_DEV_STAT_READ_ERRS);
+       for (int i = 0; i < stripe->init_nr_csum_errors; i++)
+               btrfs_dev_stat_inc_and_print(stripe->dev, BTRFS_DEV_STAT_CORRUPTION_ERRS);
+       /* Generation mismatch error is based on each metadata, not each block. */
+       for (int i = 0; i < stripe->init_nr_meta_gen_errors;
+            i += (fs_info->nodesize >> fs_info->sectorsize_bits))
+               btrfs_dev_stat_inc_and_print(stripe->dev, BTRFS_DEV_STAT_GENERATION_ERRS);
+
        spin_lock(&sctx->stat_lock);
        sctx->stat.data_extents_scrubbed += stripe->nr_data_extents;
        sctx->stat.tree_extents_scrubbed += stripe->nr_meta_extents;
        sctx->stat.no_csum += nr_nodatacsum_sectors;
        sctx->stat.read_errors += stripe->init_nr_io_errors;
        sctx->stat.csum_errors += stripe->init_nr_csum_errors;
-       sctx->stat.verify_errors += stripe->init_nr_meta_errors;
+       sctx->stat.verify_errors += stripe->init_nr_meta_errors +
+                                   stripe->init_nr_meta_gen_errors;
        sctx->stat.uncorrectable_errors +=
                bitmap_weight(&stripe->error_bitmap, stripe->nr_sectors);
        sctx->stat.corrected_errors += nr_repaired_sectors;
                                                    stripe->nr_sectors);
        stripe->init_nr_meta_errors = bitmap_weight(&stripe->meta_error_bitmap,
                                                    stripe->nr_sectors);
+       stripe->init_nr_meta_gen_errors = bitmap_weight(&stripe->meta_gen_error_bitmap,
+                                                       stripe->nr_sectors);
 
        if (bitmap_empty(&stripe->init_error_bitmap, stripe->nr_sectors))
                goto out;
                bitmap_set(&stripe->write_error_bitmap, sector_nr,
                           bio_size >> fs_info->sectorsize_bits);
                spin_unlock_irqrestore(&stripe->write_error_lock, flags);
+               for (int i = 0; i < (bio_size >> fs_info->sectorsize_bits); i++)
+                       btrfs_dev_stat_inc_and_print(stripe->dev,
+                                                    BTRFS_DEV_STAT_WRITE_ERRS);
        }
        bio_put(&bbio->bio);
 
        stripe->init_nr_io_errors = 0;
        stripe->init_nr_csum_errors = 0;
        stripe->init_nr_meta_errors = 0;
+       stripe->init_nr_meta_gen_errors = 0;
        stripe->error_bitmap = 0;
        stripe->io_error_bitmap = 0;
        stripe->csum_error_bitmap = 0;
        stripe->meta_error_bitmap = 0;
+       stripe->meta_gen_error_bitmap = 0;
 }
 
 /*