* with the run gone they are claimable again, so have the next commit
* rescan the group and credit them back.
*/
- if (READ_ONCE(bg->stripe_unusable_ready))
+ if (READ_ONCE(bg->stripe_unusable_ready)) {
set_bit(BLOCK_GROUP_FLAG_STRIPE_UNUSABLE_DIRTY, &bg->runtime_flags);
+ atomic64_inc(&bg->fs_info->stripe_run_stats.strand_rescan_marks);
+ }
wake_up_var(&bg->open_stripe_runs);
}
(btrfs_stripe_allow_rmw(fs_info) &
(BTRFS_STRIPE_RMW_NODATACOW |
BTRFS_STRIPE_RMW_PREALLOC));
+ if (class == BTRFS_STRIPE_RUN_NOCOW)
+ atomic64_inc(&fs_info->stripe_run_stats.nocow_run_opened);
new_run->owner = ino;
new_run->start = start;
new_run->end = start + len;
len = run->start - run_start;
}
spin_unlock_irqrestore(&bg->stripe_run_lock, flags);
- if (len < bg->full_stripe_len)
+ if (len < bg->full_stripe_len) {
+ atomic64_inc(&bg->fs_info->stripe_run_stats.claim_refused_live_run);
return false;
+ }
*run_len = len;
return true;
}
}
}
spin_unlock_irqrestore(&bg->stripe_run_lock, flags);
+ if (stranded)
+ atomic64_add(stranded, &bg->fs_info->stripe_run_stats.strand_scan_bytes);
return stranded;
}
atomic64_t meta_rmw_free;
atomic64_t congestion_short;
} stripe_park_stats;
+ /*
+ * Stripe run lifecycle observability: lifetime counters exposed
+ * through sysfs stripe_run_stats, so a test can show it exercised
+ * the nocow private-run and stranded-stripe paths at all.
+ */
+ struct {
+ /* private NOCOW runs opened (they outlive commits) */
+ atomic64_t nocow_run_opened;
+ /* claim candidates refused for overlapping a live run */
+ atomic64_t claim_refused_live_run;
+ /* bytes of whole stripes the scans found stranded behind live runs */
+ atomic64_t strand_scan_bytes;
+ /* rescans requested by a freed run to credit its stripes back */
+ atomic64_t strand_rescan_marks;
+ } stripe_run_stats;
/* BTRFS_STRIPE_RMW_* masks; see btrfs_stripe_allow_rmw(). */
u32 stripe_rmw_opt;
u32 stripe_rmw_prop;
}
BTRFS_ATTR(, stripe_park_stats, btrfs_stripe_park_stats_show);
+static ssize_t btrfs_stripe_run_stats_show(struct kobject *kobj,
+ struct kobj_attribute *a, char *buf)
+{
+ struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+
+ return sysfs_emit(buf,
+ "nocow_run_opened %lld\n"
+ "claim_refused_live_run %lld\n"
+ "strand_scan_bytes %lld\n"
+ "strand_rescan_marks %lld\n",
+ atomic64_read(&fs_info->stripe_run_stats.nocow_run_opened),
+ atomic64_read(&fs_info->stripe_run_stats.claim_refused_live_run),
+ atomic64_read(&fs_info->stripe_run_stats.strand_scan_bytes),
+ atomic64_read(&fs_info->stripe_run_stats.strand_rescan_marks));
+}
+BTRFS_ATTR(, stripe_run_stats, btrfs_stripe_run_stats_show);
+
/*
* Park deadlines, ms. Writable so the constants can be swept against a
* workload rather than rebuilt per data point; 0 disables parking for that
BTRFS_ATTR_PTR(, bg_reclaim_threshold),
BTRFS_ATTR_PTR(, commit_stats),
BTRFS_ATTR_PTR(, stripe_park_stats),
+ BTRFS_ATTR_PTR(, stripe_run_stats),
BTRFS_ATTR_PTR(, stripe_park_timeout_ms),
BTRFS_ATTR_PTR(, stripe_park_sync_timeout_ms),
BTRFS_ATTR_PTR(, stripe_park_congestion),