diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-12-20 00:08:29 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-12-23 23:40:46 -0500 |
commit | be12f5651d3f5c1d1f256ccb2a8731adbbd0d1d8 (patch) | |
tree | 4b34aadcc04725852869bb088d646ed124200231 | |
parent | d78d34661415d81357c229a8628ed1fc8a2c5ba4 (diff) |
bcachefs: Initial support for zones
- On zoned devices, bucket size must match zone size
- Factor out bch2_bucket_discard(), which now also issues a zone reset
on zoned devices.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/Kconfig | 1 | ||||
-rw-r--r-- | fs/bcachefs/Makefile | 3 | ||||
-rw-r--r-- | fs/bcachefs/alloc_background.c | 6 | ||||
-rw-r--r-- | fs/bcachefs/bcachefs.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/journal_reclaim.c | 9 | ||||
-rw-r--r-- | fs/bcachefs/super-io.c | 1 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 19 | ||||
-rw-r--r-- | fs/bcachefs/zone.c | 55 | ||||
-rw-r--r-- | fs/bcachefs/zone.h | 17 |
9 files changed, 98 insertions, 14 deletions
diff --git a/fs/bcachefs/Kconfig b/fs/bcachefs/Kconfig index 5cdfef3b551a..368132e927d6 100644 --- a/fs/bcachefs/Kconfig +++ b/fs/bcachefs/Kconfig @@ -24,6 +24,7 @@ config BCACHEFS_FS select XXHASH select SRCU select SYMBOLIC_ERRNAME + select BLK_DEV_ZONED help The bcachefs filesystem - a modern, copy on write filesystem, with support for multiple devices, compression, checksumming, etc. diff --git a/fs/bcachefs/Makefile b/fs/bcachefs/Makefile index ed550a40463e..f0a0a1f9ed11 100644 --- a/fs/bcachefs/Makefile +++ b/fs/bcachefs/Makefile @@ -85,6 +85,7 @@ bcachefs-y := \ two_state_shared_lock.o \ util.o \ varint.o \ - xattr.o + xattr.o \ + zone.o obj-$(CONFIG_MEAN_AND_VARIANCE_UNIT_TEST) += mean_and_variance_test.o diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c index 1a127b0a08b3..9d3666b94b0c 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -20,6 +20,7 @@ #include "recovery.h" #include "trace.h" #include "varint.h" +#include "zone.h" #include <linux/kthread.h> #include <linux/math64.h> @@ -1631,10 +1632,7 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, * thread that removes items from the need_discard tree */ bch2_trans_unlock(trans); - blkdev_issue_discard(ca->disk_sb.bdev, - k.k->p.offset * ca->mi.bucket_size, - ca->mi.bucket_size, - GFP_KERNEL); + bch2_bucket_discard(ca, k.k->p.offset); *discard_pos_done = iter.pos; ret = bch2_trans_relock_notrace(trans); diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index bf8d69fbfdb3..afa86dd7ff1a 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -553,6 +553,7 @@ struct bch_dev { struct bch_sb_handle disk_sb; struct bch_sb *sb_read_scratch; int sb_write_error; + bool zoned; dev_t dev; atomic_t flush_seq; diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c index 820d25e19e5f..330490d50ced 100644 --- a/fs/bcachefs/journal_reclaim.c +++ b/fs/bcachefs/journal_reclaim.c @@ -13,6 +13,7 @@ #include "replicas.h" #include "sb-members.h" #include "trace.h" +#include "zone.h" #include <linux/kthread.h> #include <linux/sched/mm.h> @@ -266,13 +267,7 @@ void bch2_journal_do_discards(struct journal *j) struct journal_device *ja = &ca->journal; while (should_discard_bucket(j, ja)) { - if (!c->opts.nochanges && - ca->mi.discard && - bdev_max_discard_sectors(ca->disk_sb.bdev)) - blkdev_issue_discard(ca->disk_sb.bdev, - bucket_to_sector(ca, - ja->buckets[ja->discard_idx]), - ca->mi.bucket_size, GFP_NOFS); + bch2_bucket_discard(ca, ja->buckets[ja->discard_idx]); spin_lock(&j->lock); ja->discard_idx = (ja->discard_idx + 1) % ja->nr; diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 134f2c2faf86..270863663595 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -19,6 +19,7 @@ #include "super.h" #include "trace.h" #include "vstructs.h" +#include "zone.h" #include <linux/backing-dev.h> #include <linux/sort.h> diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 0f189c9d56b5..f27b93d0f56b 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -57,6 +57,7 @@ #include "super-io.h" #include "sysfs.h" #include "trace.h" +#include "zone.h" #include <linux/backing-dev.h> #include <linux/blkdev.h> @@ -1313,7 +1314,9 @@ err: static int __bch2_dev_attach_bdev(struct bch_dev *ca, struct bch_sb_handle *sb) { - unsigned ret; + int ret; + + BUG_ON(!percpu_ref_is_zero(&ca->io_ref)); if (bch2_dev_is_online(ca)) { bch_err(ca, "already have device online in slot %u", @@ -1327,7 +1330,19 @@ static int __bch2_dev_attach_bdev(struct bch_dev *ca, struct bch_sb_handle *sb) return -BCH_ERR_device_size_too_small; } - BUG_ON(!percpu_ref_is_zero(&ca->io_ref)); + ca->zoned = bdev_nr_zones(sb->bdev) != 0; + if (ca->zoned) { + struct blk_zone zone; + + ret = bch2_zone_report(sb->bdev, 0, &zone); + if (ret) + return ret; + + if (zone.len != ca->mi.bucket_size) { + bch_err(ca, "zone size doesn't match bucket size"); + return -EINVAL; + } + } ret = bch2_dev_journal_init(ca, sb->sb); if (ret) diff --git a/fs/bcachefs/zone.c b/fs/bcachefs/zone.c new file mode 100644 index 000000000000..b6ad8c9daaea --- /dev/null +++ b/fs/bcachefs/zone.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "bcachefs.h" +#include "buckets.h" +#include "zone.h" + +#include <linux/blkdev.h> + +static int zone_report_cb(struct blk_zone *src, unsigned int idx, void *data) +{ + struct blk_zone *dst = data; + + *dst = *src; + return 0; +} + +int bch2_zone_report(struct block_device *bdev, sector_t sector, struct blk_zone *zone) +{ + int ret = blkdev_report_zones(bdev, sector, 1, zone_report_cb, zone); + + if (ret) + pr_err("error getting zone %u: %i", 0, ret); + return ret; +} + +void bch2_bucket_discard(struct bch_dev *ca, u64 b) +{ + struct bch_fs *c = ca->fs; + + if (c->opts.nochanges) + return; + + if (ca->mi.discard && + bdev_max_discard_sectors(ca->disk_sb.bdev)) + blkdev_issue_discard(ca->disk_sb.bdev, + bucket_to_sector(ca, b), + ca->mi.bucket_size, GFP_NOFS); + + if (ca->zoned) + blkdev_zone_mgmt(ca->disk_sb.bdev, REQ_OP_ZONE_RESET, + bucket_to_sector(ca, b), + ca->mi.bucket_size, GFP_NOFS); +} + +void bch2_bucket_finish(struct bch_dev *ca, u64 b) +{ + struct bch_fs *c = ca->fs; + + if (c->opts.nochanges || !ca->zoned) + return; + + blkdev_zone_mgmt(ca->disk_sb.bdev, REQ_OP_ZONE_FINISH, + bucket_to_sector(ca, b), + ca->mi.bucket_size, GFP_KERNEL); +} diff --git a/fs/bcachefs/zone.h b/fs/bcachefs/zone.h new file mode 100644 index 000000000000..aa3653bdb59b --- /dev/null +++ b/fs/bcachefs/zone.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _BCACHEFS_ZONE_H +#define _BCACHEFS_ZONE_H + +static inline bool blk_zone_writeable(struct blk_zone zone) +{ + return (zone.cond == BLK_ZONE_COND_EMPTY || + zone.cond == BLK_ZONE_COND_IMP_OPEN || + zone.cond == BLK_ZONE_COND_EXP_OPEN || + zone.cond == BLK_ZONE_COND_CLOSED); +} + +int bch2_zone_report(struct block_device *, sector_t, struct blk_zone *); +void bch2_bucket_discard(struct bch_dev *, u64); +void bch2_bucket_finish(struct bch_dev *, u64); + +#endif /* _BCACHEFS_ZONE_H */ |