Skip to content

Commit 0942b85

Browse files
author
Kent Overstreet
committed
bcachefs: BCH_RECOVERY_PASS_NO_RATELIMIT
Add a superblock flag to temporarily disable ratelimiting for a recovery pass. This will be used to make check_key_has_snapshot safer: we don't want to delete a key for a missing snapshot unless we know that the snapshots and subvolumes btrees are consistent, i.e. check_snapshots and check_subvols have run recently. Changing those btrees - creating/deleting a subvolume or snapshot - will set the "disable ratelimit" flag, i.e. ensuring that those passes run if check_key_has_snapshot discovers an error. We're only disabling ratelimiting in the snapshot/subvol delete paths, we're not so concerned about the create paths. Signed-off-by: Kent Overstreet <[email protected]>
1 parent a2ffab0 commit 0942b85

File tree

5 files changed

+53
-13
lines changed

5 files changed

+53
-13
lines changed

fs/bcachefs/recovery_passes.c

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,20 @@ static void bch2_sb_recovery_passes_to_text(struct printbuf *out,
103103
prt_tab(out);
104104

105105
bch2_pr_time_units(out, le32_to_cpu(i->last_runtime) * NSEC_PER_SEC);
106+
107+
if (BCH_RECOVERY_PASS_NO_RATELIMIT(i))
108+
prt_str(out, " (no ratelimit)");
109+
106110
prt_newline(out);
107111
}
108112
}
109113

110-
static void bch2_sb_recovery_pass_complete(struct bch_fs *c,
111-
enum bch_recovery_pass pass,
112-
s64 start_time)
114+
static struct recovery_pass_entry *bch2_sb_recovery_pass_entry(struct bch_fs *c,
115+
enum bch_recovery_pass pass)
113116
{
114117
enum bch_recovery_pass_stable stable = bch2_recovery_pass_to_stable(pass);
115-
s64 end_time = ktime_get_real_seconds();
116118

117-
mutex_lock(&c->sb_lock);
118-
struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
119-
__clear_bit_le64(stable, ext->recovery_passes_required);
119+
lockdep_assert_held(&c->sb_lock);
120120

121121
struct bch_sb_field_recovery_passes *r =
122122
bch2_sb_field_get(c->disk_sb.sb, recovery_passes);
@@ -127,15 +127,43 @@ static void bch2_sb_recovery_pass_complete(struct bch_fs *c,
127127
r = bch2_sb_field_resize(&c->disk_sb, recovery_passes, u64s);
128128
if (!r) {
129129
bch_err(c, "error creating recovery_passes sb section");
130-
goto out;
130+
return NULL;
131131
}
132132
}
133133

134-
r->start[stable].last_run = cpu_to_le64(end_time);
135-
r->start[stable].last_runtime = cpu_to_le32(max(0, end_time - start_time));
136-
out:
134+
return r->start + stable;
135+
}
136+
137+
static void bch2_sb_recovery_pass_complete(struct bch_fs *c,
138+
enum bch_recovery_pass pass,
139+
s64 start_time)
140+
{
141+
guard(mutex)(&c->sb_lock);
142+
struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
143+
__clear_bit_le64(bch2_recovery_pass_to_stable(pass),
144+
ext->recovery_passes_required);
145+
146+
struct recovery_pass_entry *e = bch2_sb_recovery_pass_entry(c, pass);
147+
if (e) {
148+
s64 end_time = ktime_get_real_seconds();
149+
e->last_run = cpu_to_le64(end_time);
150+
e->last_runtime = cpu_to_le32(max(0, end_time - start_time));
151+
SET_BCH_RECOVERY_PASS_NO_RATELIMIT(e, false);
152+
}
153+
137154
bch2_write_super(c);
138-
mutex_unlock(&c->sb_lock);
155+
}
156+
157+
void bch2_recovery_pass_set_no_ratelimit(struct bch_fs *c,
158+
enum bch_recovery_pass pass)
159+
{
160+
guard(mutex)(&c->sb_lock);
161+
162+
struct recovery_pass_entry *e = bch2_sb_recovery_pass_entry(c, pass);
163+
if (e && !BCH_RECOVERY_PASS_NO_RATELIMIT(e)) {
164+
SET_BCH_RECOVERY_PASS_NO_RATELIMIT(e, false);
165+
bch2_write_super(c);
166+
}
139167
}
140168

141169
static bool bch2_recovery_pass_want_ratelimit(struct bch_fs *c, enum bch_recovery_pass pass)
@@ -157,6 +185,9 @@ static bool bch2_recovery_pass_want_ratelimit(struct bch_fs *c, enum bch_recover
157185
*/
158186
ret = (u64) le32_to_cpu(i->last_runtime) * 100 >
159187
ktime_get_real_seconds() - le64_to_cpu(i->last_run);
188+
189+
if (BCH_RECOVERY_PASS_NO_RATELIMIT(i))
190+
ret = false;
160191
}
161192

162193
return ret;

fs/bcachefs/recovery_passes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ u64 bch2_recovery_passes_from_stable(u64 v);
1010

1111
u64 bch2_fsck_recovery_passes(void);
1212

13+
void bch2_recovery_pass_set_no_ratelimit(struct bch_fs *, enum bch_recovery_pass);
14+
1315
enum bch_run_recovery_pass_flags {
1416
RUN_RECOVERY_PASS_nopersistent = BIT(0),
1517
RUN_RECOVERY_PASS_ratelimit = BIT(1),

fs/bcachefs/recovery_passes_format.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ struct recovery_pass_entry {
8787
__le32 flags;
8888
};
8989

90+
LE32_BITMASK(BCH_RECOVERY_PASS_NO_RATELIMIT, struct recovery_pass_entry, flags, 0, 1)
91+
9092
struct bch_sb_field_recovery_passes {
9193
struct bch_sb_field field;
9294
struct recovery_pass_entry start[];

fs/bcachefs/snapshot.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,6 +1878,8 @@ int __bch2_delete_dead_snapshots(struct bch_fs *c)
18781878
d->running = false;
18791879
mutex_unlock(&d->progress_lock);
18801880
bch2_trans_put(trans);
1881+
1882+
bch2_recovery_pass_set_no_ratelimit(c, BCH_RECOVERY_PASS_check_snapshots);
18811883
out_unlock:
18821884
mutex_unlock(&d->lock);
18831885
if (!bch2_err_matches(ret, EROFS))

fs/bcachefs/subvolume.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,9 +482,12 @@ static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
482482

483483
static int bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
484484
{
485-
return bch2_subvolumes_reparent(trans, subvolid) ?:
485+
int ret = bch2_subvolumes_reparent(trans, subvolid) ?:
486486
commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
487487
__bch2_subvolume_delete(trans, subvolid));
488+
489+
bch2_recovery_pass_set_no_ratelimit(trans->c, BCH_RECOVERY_PASS_check_subvols);
490+
return ret;
488491
}
489492

490493
static void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work)

0 commit comments

Comments
 (0)