V209: a storage profile's copies are counted per kind of bucket, local and cloud.
A profile used to say "N copies of each file" and let placement pick any N buckets. It now says how many copies go to local buckets and how many to cloud buckets, so a profile can keep two copies on the server's own disks and one in the cloud, which survives the server:
copies_local(0..5) — copies onlocalbuckets;copies_cloud(0..5) — copies on cloud buckets (S3, B2, R2, Tigris).
copies_originals stays and is now the total: the CHECK below keeps it
equal to copies_local + copies_cloud, so everything that reads the old
column (min_copies_on_write is bounded by it, an older core on the same
database) still sees how many copies a file has. copies_variants is not
used any more; the application keeps it equal to the total.
Backfill
Existing profiles are split the way their buckets are, local first: the cloud
share is as many of the profile's copies as the local buckets cannot take, up
to the cloud buckets it has (active, enabled); the rest is local. A profile
with no bucket yet keeps all its copies local. The total never changes, and
revision is not touched, so no file is placed again by this migration.
The backfill runs only when the columns are added, so a re-run never overwrites a split an admin chose.
Locks
ALTER TABLE on the (tiny) profiles table, one UPDATE of its rows.
Summary
Functions
Rolls V209 back: the columns go, the total (copies_originals) stays.