summaryrefslogtreecommitdiff
path: root/fs/bcachefs/journal_reclaim.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-03-03 15:15:55 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:17 -0400
commit0ce2dbbe9915af85b2ebafe6dfeca6813ba5e13c (patch)
treee1d09ada09543e231381e2dbc42d54fc11e35236 /fs/bcachefs/journal_reclaim.c
parentfcbf3e509648a94129ae23a6101f5295a3fdced0 (diff)
downloadlwn-0ce2dbbe9915af85b2ebafe6dfeca6813ba5e13c.tar.gz
lwn-0ce2dbbe9915af85b2ebafe6dfeca6813ba5e13c.zip
bcachefs: ja->discard_idx, ja->dirty_idx
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/journal_reclaim.c')
-rw-r--r--fs/bcachefs/journal_reclaim.c63
1 files changed, 39 insertions, 24 deletions
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index 431afeab42b0..3a85fb8b8526 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -14,22 +14,20 @@ unsigned bch2_journal_dev_buckets_available(struct journal *j,
{
struct bch_fs *c = container_of(j, struct bch_fs, journal);
unsigned next = (ja->cur_idx + 1) % ja->nr;
- unsigned available = (ja->last_idx + ja->nr - next) % ja->nr;
+ unsigned available = (ja->discard_idx + ja->nr - next) % ja->nr;
/*
* Allocator startup needs some journal space before we can do journal
* replay:
*/
- if (available &&
- test_bit(BCH_FS_ALLOCATOR_STARTED, &c->flags))
- available--;
+ if (available && test_bit(BCH_FS_ALLOCATOR_STARTED, &c->flags))
+ --available;
/*
* Don't use the last bucket unless writing the new last_seq
* will make another bucket available:
*/
- if (available &&
- journal_last_seq(j) <= ja->bucket_seq[ja->last_idx])
+ if (available && ja->dirty_idx_ondisk == ja->dirty_idx)
--available;
return available;
@@ -55,12 +53,34 @@ void bch2_journal_space_available(struct journal *j)
for_each_member_device_rcu(ca, c, i,
&c->rw_devs[BCH_DATA_JOURNAL]) {
struct journal_device *ja = &ca->journal;
- unsigned buckets_this_device, sectors_this_device;
if (!ja->nr)
continue;
+ while (ja->dirty_idx != ja->cur_idx &&
+ ja->bucket_seq[ja->dirty_idx] < journal_last_seq(j))
+ ja->dirty_idx = (ja->dirty_idx + 1) % ja->nr;
+
+ while (ja->dirty_idx_ondisk != ja->dirty_idx &&
+ ja->bucket_seq[ja->dirty_idx_ondisk] < j->last_seq_ondisk)
+ ja->dirty_idx_ondisk = (ja->dirty_idx_ondisk + 1) % ja->nr;
+
nr_online++;
+ }
+
+ if (nr_online < c->opts.metadata_replicas_required) {
+ ret = -EROFS;
+ sectors_next_entry = 0;
+ goto out;
+ }
+
+ for_each_member_device_rcu(ca, c, i,
+ &c->rw_devs[BCH_DATA_JOURNAL]) {
+ struct journal_device *ja = &ca->journal;
+ unsigned buckets_this_device, sectors_this_device;
+
+ if (!ja->nr)
+ continue;
buckets_this_device = bch2_journal_dev_buckets_available(j, ja);
sectors_this_device = ja->sectors_free;
@@ -100,20 +120,17 @@ void bch2_journal_space_available(struct journal *j)
nr_devs++;
}
- rcu_read_unlock();
- if (nr_online < c->opts.metadata_replicas_required) {
- ret = -EROFS;
- sectors_next_entry = 0;
- } else if (!sectors_next_entry ||
- nr_devs < min_t(unsigned, nr_online,
- c->opts.metadata_replicas)) {
+ if (!sectors_next_entry ||
+ nr_devs < min_t(unsigned, nr_online, c->opts.metadata_replicas)) {
ret = -ENOSPC;
sectors_next_entry = 0;
} else if (!fifo_free(&j->pin)) {
ret = -ENOSPC;
sectors_next_entry = 0;
}
+out:
+ rcu_read_unlock();
j->cur_entry_sectors = sectors_next_entry;
j->cur_entry_error = ret;
@@ -129,25 +146,23 @@ static bool should_discard_bucket(struct journal *j, struct journal_device *ja)
bool ret;
spin_lock(&j->lock);
- ret = ja->nr &&
- ja->last_idx != ja->cur_idx &&
- ja->bucket_seq[ja->last_idx] < j->last_seq_ondisk;
+ ret = ja->discard_idx != ja->dirty_idx_ondisk;
spin_unlock(&j->lock);
return ret;
}
/*
- * Advance ja->last_idx as long as it points to buckets that are no longer
+ * Advance ja->discard_idx as long as it points to buckets that are no longer
* dirty, issuing discards if necessary:
*/
-static void journal_do_discards(struct journal *j)
+static void bch2_journal_do_discards(struct journal *j)
{
struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct bch_dev *ca;
unsigned iter;
- mutex_lock(&j->reclaim_lock);
+ mutex_lock(&j->discard_lock);
for_each_rw_member(ca, c, iter) {
struct journal_device *ja = &ca->journal;
@@ -157,18 +172,18 @@ static void journal_do_discards(struct journal *j)
bdev_max_discard_sectors(ca->disk_sb.bdev))
blkdev_issue_discard(ca->disk_sb.bdev,
bucket_to_sector(ca,
- ja->buckets[ja->last_idx]),
+ ja->buckets[ja->discard_idx]),
ca->mi.bucket_size, GFP_NOIO);
spin_lock(&j->lock);
- ja->last_idx = (ja->last_idx + 1) % ja->nr;
+ ja->discard_idx = (ja->discard_idx + 1) % ja->nr;
bch2_journal_space_available(j);
spin_unlock(&j->lock);
}
}
- mutex_unlock(&j->reclaim_lock);
+ mutex_unlock(&j->discard_lock);
}
/*
@@ -399,7 +414,7 @@ void bch2_journal_reclaim_work(struct work_struct *work)
unsigned iter, bucket_to_flush, min_nr = 0;
u64 seq_to_flush = 0;
- journal_do_discards(j);
+ bch2_journal_do_discards(j);
mutex_lock(&j->reclaim_lock);
spin_lock(&j->lock);