spin_unlock_irqrestore(&bg->stripe_run_lock, flags);
}
+/* DEBUG: every open run overlapping [logical, logical + len), any class. */
+void btrfs_stripe_dump_runs_at(struct btrfs_fs_info *fs_info, u64 logical,
+ u64 len)
+{
+ struct btrfs_block_group *bg = btrfs_lookup_block_group(fs_info, logical);
+ struct btrfs_open_stripe_run *run;
+ unsigned long flags;
+ int n = 0;
+
+ if (!bg) {
+ btrfs_warn(fs_info, " no block group for %llu", logical);
+ return;
+ }
+ btrfs_warn(fs_info,
+" bg %llu len %llu ro %d armed %d claimable %llu trapped %llu fsl %llu",
+ bg->start, bg->length, bg->ro,
+ READ_ONCE(bg->stripe_unusable_ready),
+ (u64)bg->stripe_claimable, (u64)bg->stripe_unusable,
+ (u64)bg->full_stripe_len);
+ spin_lock_irqsave(&bg->stripe_run_lock, flags);
+ list_for_each_entry(run, &bg->open_stripe_runs, list) {
+ if (run->end <= logical || run->start >= logical + len)
+ continue;
+ n++;
+ btrfs_warn(fs_info,
+" run %llu..%llu frontier %llu open %d inflight %llu transid %llu class %d open_seq %llu",
+ run->start, run->end, run->offset, run->open,
+ run->inflight_bytes, run->transid, run->class,
+ run->open_seq);
+ }
+ spin_unlock_irqrestore(&bg->stripe_run_lock, flags);
+ if (!n)
+ btrfs_warn(fs_info, " no open run covers %llu", logical);
+ btrfs_put_block_group(bg);
+}
+
static bool bg_has_undrained_meta_runs(struct btrfs_block_group *bg,
u64 transid)
{
int btrfs_stripe_alloc_check_support(struct btrfs_fs_info *fs_info);
int btrfs_enable_stripe_alloc(struct btrfs_fs_info *fs_info);
void btrfs_disable_stripe_alloc(struct btrfs_fs_info *fs_info);
+void btrfs_stripe_dump_runs_at(struct btrfs_fs_info *fs_info, u64 logical,
+ u64 len);
void btrfs_retire_open_stripes(struct btrfs_fs_info *fs_info,
struct btrfs_transaction *trans);
void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg);
*/
index_rbio_pages(rbio);
+ bool dumped = false;
+
/* The generation this write is putting into the stripe. */
for (u32 i = 0; i < nsectors; i += sectors_per_tree) {
u64 gen;
"read-modify-write of stripe %llu rewrites parity over committed tree block %llu at generation %llu (refs %llu, extent generation %llu) while writing generation %llu: write hole",
rbio->bioc->full_stripe_logical, logical,
gen, refs, egen, write_gen);
+ /* DEBUG: who wrote here, and which run handed it out */
+ if (!dumped) {
+ dumped = true;
+ for (u32 j = 0; j < nsectors; j += sectors_per_tree) {
+ struct btrfs_header *h;
+ void *ka;
+
+ if (!rbio->bio_sectors[j].has_paddr)
+ continue;
+ ka = kmap_local_sector(&rbio->bio_sectors[j]);
+ h = ka;
+ btrfs_warn(fs_info,
+" covered block %llu owner %llu generation %llu level %u (sector %u)",
+ btrfs_stack_header_bytenr(h),
+ btrfs_stack_header_owner(h),
+ btrfs_stack_header_generation(h),
+ (unsigned int)h->level, j);
+ kunmap_local(ka);
+ }
+ btrfs_stripe_dump_runs_at(fs_info,
+ rbio->bioc->full_stripe_logical,
+ (u64)rbio->nr_data * BTRFS_STRIPE_LEN);
+ }
}
}
}