{
        bio_list_merge(&dest->bio_list, &victim->bio_list);
        dest->bio_list_bytes += victim->bio_list_bytes;
+       /* Also inherit the bitmaps from @victim. */
+       bitmap_or(&dest->dbitmap, &victim->dbitmap, &dest->dbitmap,
+                 dest->stripe_nsectors);
        dest->generic_bio_cnt += victim->generic_bio_cnt;
        bio_list_init(&victim->bio_list);
 }
 
        if (rbio->generic_bio_cnt)
                btrfs_bio_counter_sub(rbio->bioc->fs_info, rbio->generic_bio_cnt);
+       /*
+        * Clear the data bitmap, as the rbio may be cached for later usage.
+        * do this before before unlock_stripe() so there will be no new bio
+        * for this bio.
+        */
+       bitmap_clear(&rbio->dbitmap, 0, rbio->stripe_nsectors);
 
        /*
         * At this moment, rbio->bio_list is empty, however since rbio does not
        else
                BUG();
 
+       /* We should have at least one data sector. */
+       ASSERT(bitmap_weight(&rbio->dbitmap, rbio->stripe_nsectors));
+
        /* at this point we either have a full stripe,
         * or we've read the full stripe from the drive.
         * recalculate the parity and write the new results.
                for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
                        struct sector_ptr *sector;
 
+                       /* This vertical stripe has no data, skip it. */
+                       if (!test_bit(sectornr, &rbio->dbitmap))
+                               continue;
+
                        if (stripe < rbio->nr_data) {
                                sector = sector_in_rbio(rbio, stripe, sectornr, 1);
                                if (!sector)
                for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
                        struct sector_ptr *sector;
 
+                       /* This vertical stripe has no data, skip it. */
+                       if (!test_bit(sectornr, &rbio->dbitmap))
+                               continue;
+
                        if (stripe < rbio->nr_data) {
                                sector = sector_in_rbio(rbio, stripe, sectornr, 1);
                                if (!sector)
        run_plug(plug);
 }
 
+/* Add the original bio into rbio->bio_list, and update rbio::dbitmap. */
+static void rbio_add_bio(struct btrfs_raid_bio *rbio, struct bio *orig_bio)
+{
+       const struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
+       const u64 orig_logical = orig_bio->bi_iter.bi_sector << SECTOR_SHIFT;
+       const u64 full_stripe_start = rbio->bioc->raid_map[0];
+       const u32 orig_len = orig_bio->bi_iter.bi_size;
+       const u32 sectorsize = fs_info->sectorsize;
+       u64 cur_logical;
+
+       ASSERT(orig_logical >= full_stripe_start &&
+              orig_logical + orig_len <= full_stripe_start +
+              rbio->nr_data * rbio->stripe_len);
+
+       bio_list_add(&rbio->bio_list, orig_bio);
+       rbio->bio_list_bytes += orig_bio->bi_iter.bi_size;
+
+       /* Update the dbitmap. */
+       for (cur_logical = orig_logical; cur_logical < orig_logical + orig_len;
+            cur_logical += sectorsize) {
+               int bit = ((u32)(cur_logical - full_stripe_start) >>
+                          fs_info->sectorsize_bits) % rbio->stripe_nsectors;
+
+               set_bit(bit, &rbio->dbitmap);
+       }
+}
+
 /*
  * our main entry point for writes from the rest of the FS.
  */
                btrfs_put_bioc(bioc);
                return PTR_ERR(rbio);
        }
-       bio_list_add(&rbio->bio_list, bio);
-       rbio->bio_list_bytes = bio->bi_iter.bi_size;
        rbio->operation = BTRFS_RBIO_WRITE;
+       rbio_add_bio(rbio, bio);
 
        btrfs_bio_counter_inc_noblocked(fs_info);
        rbio->generic_bio_cnt = 1;
        }
 
        rbio->operation = BTRFS_RBIO_READ_REBUILD;
-       bio_list_add(&rbio->bio_list, bio);
-       rbio->bio_list_bytes = bio->bi_iter.bi_size;
+       rbio_add_bio(rbio, bio);
 
        rbio->faila = find_logical_bio_stripe(rbio, bio);
        if (rbio->faila == -1) {