diff options
| author | Kent Overstreet <kent.overstreet@linux.dev> | 2025-05-07 14:26:18 -0400 |
|---|---|---|
| committer | Kent Overstreet <kent.overstreet@linux.dev> | 2025-05-21 20:14:49 -0400 |
| commit | 8c69e2b52ea81b102ace48debd114467199ca77a (patch) | |
| tree | 05cd41ba6d2009dfa8ba2fbae8b4a3aaa79ba33c /fs/bcachefs/snapshot.c | |
| parent | bcachefs: bcachefs_metadata_version_fast_device_removal (diff) | |
| download | linux-8c69e2b52ea81b102ace48debd114467199ca77a.tar.gz linux-8c69e2b52ea81b102ace48debd114467199ca77a.zip | |
bcachefs: Knob for manual snapshot deletion
Add 'opts.snapshot_deletion_enabled', enabled by default.
This may be turned off so that the new sysfs knob,
'internal/trigger_delete_dead_snapshots', may be used instead - this
will allow snapshot deletion to be profiled more easily.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/snapshot.c')
| -rw-r--r-- | fs/bcachefs/snapshot.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c index 9ec3275c7b0a..c3dc450cbcec 100644 --- a/fs/bcachefs/snapshot.c +++ b/fs/bcachefs/snapshot.c @@ -1776,14 +1776,18 @@ static void bch2_snapshot_delete_nodes_to_text(struct printbuf *out, struct snap prt_newline(out); } -int bch2_delete_dead_snapshots(struct bch_fs *c) +int __bch2_delete_dead_snapshots(struct bch_fs *c) { - if (!test_and_clear_bit(BCH_FS_need_delete_dead_snapshots, &c->flags)) + struct snapshot_delete *d = &c->snapshot_delete; + int ret = 0; + + if (!mutex_trylock(&d->lock)) return 0; + if (!test_and_clear_bit(BCH_FS_need_delete_dead_snapshots, &c->flags)) + goto out_unlock; + struct btree_trans *trans = bch2_trans_get(c); - struct snapshot_delete *d = &c->snapshot_delete; - int ret = 0; /* * For every snapshot node: If we have no live children and it's not @@ -1857,11 +1861,21 @@ err: d->running = false; mutex_unlock(&d->progress_lock); bch2_trans_put(trans); +out_unlock: + mutex_unlock(&d->lock); if (!bch2_err_matches(ret, EROFS)) bch_err_fn(c, ret); return ret; } +int bch2_delete_dead_snapshots(struct bch_fs *c) +{ + if (!c->opts.auto_snapshot_deletion) + return 0; + + return __bch2_delete_dead_snapshots(c); +} + void bch2_delete_dead_snapshots_work(struct work_struct *work) { struct bch_fs *c = container_of(work, struct bch_fs, snapshot_delete.work); @@ -1874,6 +1888,9 @@ void bch2_delete_dead_snapshots_work(struct work_struct *work) void bch2_delete_dead_snapshots_async(struct bch_fs *c) { + if (!c->opts.auto_snapshot_deletion) + return; + if (!enumerated_ref_tryget(&c->writes, BCH_WRITE_REF_delete_dead_snapshots)) return; @@ -1977,6 +1994,7 @@ void bch2_fs_snapshots_exit(struct bch_fs *c) void bch2_fs_snapshots_init_early(struct bch_fs *c) { INIT_WORK(&c->snapshot_delete.work, bch2_delete_dead_snapshots_work); + mutex_init(&c->snapshot_delete.lock); mutex_init(&c->snapshot_delete.progress_lock); mutex_init(&c->snapshots_unlinked_lock); } |
