mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
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>
This commit is contained in:
@@ -495,6 +495,12 @@ enum fsck_err_opts {
|
||||
OPT_BOOL(), \
|
||||
BCH_SB_REBALANCE_AC_ONLY, false, \
|
||||
NULL, "Enable rebalance while on mains power only\n") \
|
||||
x(auto_snapshot_deletion, u8, \
|
||||
OPT_FS|OPT_MOUNT|OPT_RUNTIME, \
|
||||
OPT_BOOL(), \
|
||||
BCH2_NO_SB_OPT, true, \
|
||||
NULL, "Enable automatic snapshot deletion: disable for debugging, or to\n"\
|
||||
"quiet the system when doing performance testing\n")\
|
||||
x(no_data_io, u8, \
|
||||
OPT_MOUNT, \
|
||||
OPT_BOOL(), \
|
||||
|
||||
@@ -1776,15 +1776,19 @@ 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))
|
||||
return 0;
|
||||
|
||||
struct btree_trans *trans = bch2_trans_get(c);
|
||||
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);
|
||||
|
||||
/*
|
||||
* For every snapshot node: If we have no live children and it's not
|
||||
* pointed to by a subvolume, delete it:
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -273,6 +273,7 @@ static inline int bch2_key_has_snapshot_overwrites(struct btree_trans *trans,
|
||||
return __bch2_key_has_snapshot_overwrites(trans, id, pos);
|
||||
}
|
||||
|
||||
int __bch2_delete_dead_snapshots(struct bch_fs *);
|
||||
int bch2_delete_dead_snapshots(struct bch_fs *);
|
||||
void bch2_delete_dead_snapshots_work(struct work_struct *);
|
||||
void bch2_delete_dead_snapshots_async(struct bch_fs *);
|
||||
|
||||
@@ -42,6 +42,7 @@ struct snapshot_interior_delete {
|
||||
typedef DARRAY(struct snapshot_interior_delete) interior_delete_list;
|
||||
|
||||
struct snapshot_delete {
|
||||
struct mutex lock;
|
||||
struct work_struct work;
|
||||
|
||||
struct mutex progress_lock;
|
||||
|
||||
@@ -149,6 +149,7 @@ write_attribute(trigger_btree_key_cache_shrink);
|
||||
write_attribute(trigger_btree_updates);
|
||||
write_attribute(trigger_freelist_wakeup);
|
||||
write_attribute(trigger_recalc_capacity);
|
||||
write_attribute(trigger_delete_dead_snapshots);
|
||||
read_attribute(gc_gens_pos);
|
||||
|
||||
read_attribute(uuid);
|
||||
@@ -439,6 +440,9 @@ STORE(bch2_fs)
|
||||
up_read(&c->state_lock);
|
||||
}
|
||||
|
||||
if (attr == &sysfs_trigger_delete_dead_snapshots)
|
||||
__bch2_delete_dead_snapshots(c);
|
||||
|
||||
#ifdef CONFIG_BCACHEFS_TESTS
|
||||
if (attr == &sysfs_perf_test) {
|
||||
char *tmp = kstrdup(buf, GFP_KERNEL), *p = tmp;
|
||||
@@ -568,6 +572,7 @@ struct attribute *bch2_fs_internal_files[] = {
|
||||
&sysfs_trigger_btree_updates,
|
||||
&sysfs_trigger_freelist_wakeup,
|
||||
&sysfs_trigger_recalc_capacity,
|
||||
&sysfs_trigger_delete_dead_snapshots,
|
||||
|
||||
&sysfs_gc_gens_pos,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user