]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bcachefs: Filesystem discard option now propagates to devices
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 13 Mar 2025 04:54:10 +0000 (00:54 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 24 Mar 2025 13:50:35 +0000 (09:50 -0400)
the discard option is special, because it's both a filesystem and a
device option.

When set at the filesytsem level, it's supposed to propagate to (if set
persistently via sysfs) or override (if non persistently as a mount
option) the devices - that now works correctly.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_background.c
fs/bcachefs/bcachefs.h
fs/bcachefs/fs.c
fs/bcachefs/sysfs.c

index 4dfcf3e6fffda85303d5b4c3cb4cfb58ebb51e2d..54e0cc373bb1bd3ec08c2e8ccf813c0bd7e0b5e5 100644 (file)
@@ -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
index 0ea593e813f43d46398e35c97bf51eef5d77645d..f52311017aeefd2e2019beec9884e676a38b0f02 100644 (file)
@@ -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,
index 17ac9c55fb96e5f0ae342ae430d885b66f47a3c8..4453dd2f888efbe823997642572a6ddf766060fc 100644 (file)
@@ -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);
index e8a795578186b2c3f987a964ef6388cb6e432ab0..251ba8224c1f064f348c726f62eb17c6a96f4f3f 100644 (file)
@@ -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);