summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/alloc_background.c15
-rw-r--r--fs/bcachefs/bcachefs.h3
-rw-r--r--fs/bcachefs/fs.c3
-rw-r--r--fs/bcachefs/sysfs.c9
4 files changed, 28 insertions, 2 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c
index 4dfcf3e6fffd..54e0cc373bb1 100644
--- a/fs/bcachefs/alloc_background.c
+++ b/fs/bcachefs/alloc_background.c
@@ -1806,6 +1806,19 @@ struct discard_buckets_state {
u64 discarded;
};
+/*
+ * This is needed because discard is both a filesystem option and a device
+ * option, and mount options are supposed to apply to that mount and not be
+ * persisted, i.e. if it's set as a mount option we can't propagate it to the
+ * device.
+ */
+static inline bool discard_opt_enabled(struct bch_fs *c, struct bch_dev *ca)
+{
+ return test_bit(BCH_FS_discard_mount_opt_set, &c->flags)
+ ? c->opts.discard
+ : ca->mi.discard;
+}
+
static int bch2_discard_one_bucket(struct btree_trans *trans,
struct bch_dev *ca,
struct btree_iter *need_discard_iter,
@@ -1869,7 +1882,7 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
s->discarded++;
*discard_pos_done = iter.pos;
- if (ca->mi.discard && !c->opts.nochanges) {
+ if (discard_opt_enabled(c, ca) && !c->opts.nochanges) {
/*
* This works without any other locks because this is the only
* thread that removes items from the need_discard tree
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h
index 0ea593e813f4..f52311017aee 100644
--- a/fs/bcachefs/bcachefs.h
+++ b/fs/bcachefs/bcachefs.h
@@ -627,7 +627,8 @@ struct bch_dev {
x(topology_error) \
x(errors_fixed) \
x(errors_not_fixed) \
- x(no_invalid_checks)
+ x(no_invalid_checks) \
+ x(discard_mount_opt_set) \
enum bch_fs_flags {
#define x(n) BCH_FS_##n,
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 17ac9c55fb96..4453dd2f888e 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -2172,6 +2172,9 @@ static int bch2_fs_get_tree(struct fs_context *fc)
if (ret)
goto err;
+ if (opt_defined(opts, discard))
+ set_bit(BCH_FS_discard_mount_opt_set, &c->flags);
+
/* Some options can't be parsed until after the fs is started: */
opts = bch2_opts_empty();
ret = bch2_parse_mount_opts(c, &opts, NULL, opts_parse->parse_later.buf);
diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c
index e8a795578186..251ba8224c1f 100644
--- a/fs/bcachefs/sysfs.c
+++ b/fs/bcachefs/sysfs.c
@@ -664,6 +664,15 @@ static ssize_t sysfs_opt_store(struct bch_fs *c,
c->copygc_thread)
wake_up_process(c->copygc_thread);
+ if (id == Opt_discard && !ca) {
+ mutex_lock(&c->sb_lock);
+ for_each_member_device(c, ca)
+ opt->set_member(bch2_members_v2_get_mut(ca->disk_sb.sb, ca->dev_idx), v);
+
+ bch2_write_super(c);
+ mutex_unlock(&c->sb_lock);
+ }
+
ret = size;
err:
up_write(&c->state_lock);