summaryrefslogtreecommitdiff
path: root/fs/bcachefs/fs-io-buffered.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/fs-io-buffered.c')
-rw-r--r--fs/bcachefs/fs-io-buffered.c68
1 files changed, 50 insertions, 18 deletions
diff --git a/fs/bcachefs/fs-io-buffered.c b/fs/bcachefs/fs-io-buffered.c
index 45175a478b92..fe684adca370 100644
--- a/fs/bcachefs/fs-io-buffered.c
+++ b/fs/bcachefs/fs-io-buffered.c
@@ -284,12 +284,12 @@ void bch2_readahead(struct readahead_control *ractl)
{
struct bch_inode_info *inode = to_bch_ei(ractl->mapping->host);
struct bch_fs *c = inode->v.i_sb->s_fs_info;
- struct bch_io_opts opts;
struct folio *folio;
struct readpages_iter readpages_iter;
struct blk_plug plug;
- bch2_inode_opts_get(&opts, c, &inode->ei_inode);
+ struct bch_inode_opts opts;
+ bch2_inode_opts_get_inode(c, &inode->ei_inode, &opts);
int ret = readpages_iter_init(&readpages_iter, ractl);
if (ret)
@@ -350,7 +350,7 @@ int bch2_read_single_folio(struct folio *folio, struct address_space *mapping)
struct bch_inode_info *inode = to_bch_ei(mapping->host);
struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_read_bio *rbio;
- struct bch_io_opts opts;
+ struct bch_inode_opts opts;
struct blk_plug plug;
int ret;
DECLARE_COMPLETION_ONSTACK(done);
@@ -361,7 +361,7 @@ int bch2_read_single_folio(struct folio *folio, struct address_space *mapping)
if (!bch2_folio_create(folio, GFP_KERNEL))
return -ENOMEM;
- bch2_inode_opts_get(&opts, c, &inode->ei_inode);
+ bch2_inode_opts_get_inode(c, &inode->ei_inode, &opts);
rbio = rbio_init(bio_alloc_bioset(NULL, 1, REQ_OP_READ, GFP_KERNEL, &c->bio_read),
c,
@@ -407,7 +407,7 @@ struct bch_writepage_io {
struct bch_writepage_state {
struct bch_writepage_io *io;
- struct bch_io_opts opts;
+ struct bch_inode_opts opts;
struct bch_folio_sector *tmp;
unsigned tmp_sectors;
struct blk_plug plug;
@@ -532,6 +532,39 @@ static void bch2_writepage_io_alloc(struct bch_fs *c,
op->wbio.bio.bi_opf = wbc_to_write_flags(wbc);
}
+static bool can_write_now(struct bch_fs *c, unsigned replicas_want, struct closure *cl)
+{
+ unsigned reserved = OPEN_BUCKETS_COUNT -
+ (OPEN_BUCKETS_COUNT - bch2_open_buckets_reserved(BCH_WATERMARK_normal)) / 2;
+
+ if (unlikely(c->open_buckets_nr_free <= reserved)) {
+ closure_wait(&c->open_buckets_wait, cl);
+ return false;
+ }
+
+ if (BCH_WATERMARK_normal < c->journal.watermark && !bch2_journal_error(&c->journal)) {
+ closure_wait(&c->journal.async_wait, cl);
+ return false;
+ }
+
+ return true;
+}
+
+static void throttle_writes(struct bch_fs *c, unsigned replicas_want, struct closure *cl)
+{
+ u64 start = 0;
+ while (!can_write_now(c, replicas_want, cl)) {
+ if (!start)
+ start = local_clock();
+ closure_sync(cl);
+ }
+
+ BUG_ON(closure_nr_remaining(cl) > 1);
+
+ if (start)
+ bch2_time_stats_update(&c->times[BCH_TIME_blocked_writeback_throttle], start);
+}
+
static int __bch2_writepage(struct folio *folio,
struct writeback_control *wbc,
void *data)
@@ -667,26 +700,25 @@ do_io:
return 0;
}
-static int bch2_write_cache_pages(struct address_space *mapping,
- struct writeback_control *wbc, void *data)
-{
- struct folio *folio = NULL;
- int error;
-
- while ((folio = writeback_iter(mapping, wbc, folio, &error)))
- error = __bch2_writepage(folio, wbc, data);
- return error;
-}
-
int bch2_writepages(struct address_space *mapping, struct writeback_control *wbc)
{
struct bch_fs *c = mapping->host->i_sb->s_fs_info;
struct bch_writepage_state *w = kzalloc(sizeof(*w), GFP_NOFS|__GFP_NOFAIL);
- bch2_inode_opts_get(&w->opts, c, &to_bch_ei(mapping->host)->ei_inode);
+ bch2_inode_opts_get_inode(c, &to_bch_ei(mapping->host)->ei_inode, &w->opts);
blk_start_plug(&w->plug);
- int ret = bch2_write_cache_pages(mapping, wbc, w);
+
+ struct closure cl;
+ closure_init_stack(&cl);
+
+ struct folio *folio = NULL;
+ int ret = 0;
+
+ while (throttle_writes(c, w->opts.data_replicas, &cl),
+ (folio = writeback_iter(mapping, wbc, folio, &ret)))
+ ret = __bch2_writepage(folio, wbc, w);
+
if (w->io)
bch2_writepage_do_io(w);
blk_finish_plug(&w->plug);