Commit 4efe71a6 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Always give out journal pre-res if we already have one

This is better than skipping the journal pre-reservation if we already
have one - we should still acount for the journal reservation we're
going to have to get.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 374153c2
...@@ -864,8 +864,11 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id, ...@@ -864,8 +864,11 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id,
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct btree_update *as; struct btree_update *as;
int ret, disk_res_flags = (flags & BTREE_INSERT_NOFAIL) int disk_res_flags = (flags & BTREE_INSERT_NOFAIL)
? BCH_DISK_RESERVATION_NOFAIL : 0; ? BCH_DISK_RESERVATION_NOFAIL : 0;
int journal_flags = (flags & BTREE_INSERT_JOURNAL_RESERVED)
? JOURNAL_RES_GET_RECLAIM : 0;
int ret = 0;
/* /*
* This check isn't necessary for correctness - it's just to potentially * This check isn't necessary for correctness - it's just to potentially
...@@ -888,10 +891,9 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id, ...@@ -888,10 +891,9 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id,
bch2_keylist_init(&as->new_keys, as->_new_keys); bch2_keylist_init(&as->new_keys, as->_new_keys);
bch2_keylist_init(&as->parent_keys, as->inline_keys); bch2_keylist_init(&as->parent_keys, as->inline_keys);
if (!(flags & BTREE_INSERT_JOURNAL_RESERVED)) ret = bch2_journal_preres_get(&c->journal, &as->journal_preres,
ret = bch2_journal_preres_get(&c->journal, &as->journal_preres, BTREE_UPDATE_JOURNAL_RES,
BTREE_UPDATE_JOURNAL_RES, journal_flags|JOURNAL_RES_GET_NONBLOCK);
JOURNAL_RES_GET_NONBLOCK);
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
if (flags & BTREE_INSERT_NOUNLOCK) if (flags & BTREE_INSERT_NOUNLOCK)
return ERR_PTR(-EINTR); return ERR_PTR(-EINTR);
...@@ -899,7 +901,8 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id, ...@@ -899,7 +901,8 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id,
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
ret = bch2_journal_preres_get(&c->journal, &as->journal_preres, ret = bch2_journal_preres_get(&c->journal, &as->journal_preres,
BTREE_UPDATE_JOURNAL_RES, 0); BTREE_UPDATE_JOURNAL_RES,
journal_flags);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
......
...@@ -427,9 +427,10 @@ int bch2_journal_res_get_slowpath(struct journal *j, struct journal_res *res, ...@@ -427,9 +427,10 @@ int bch2_journal_res_get_slowpath(struct journal *j, struct journal_res *res,
static bool journal_preres_available(struct journal *j, static bool journal_preres_available(struct journal *j,
struct journal_preres *res, struct journal_preres *res,
unsigned new_u64s) unsigned new_u64s,
unsigned flags)
{ {
bool ret = bch2_journal_preres_get_fast(j, res, new_u64s); bool ret = bch2_journal_preres_get_fast(j, res, new_u64s, flags);
if (!ret) if (!ret)
bch2_journal_reclaim_work(&j->reclaim_work.work); bch2_journal_reclaim_work(&j->reclaim_work.work);
...@@ -439,13 +440,14 @@ static bool journal_preres_available(struct journal *j, ...@@ -439,13 +440,14 @@ static bool journal_preres_available(struct journal *j,
int __bch2_journal_preres_get(struct journal *j, int __bch2_journal_preres_get(struct journal *j,
struct journal_preres *res, struct journal_preres *res,
unsigned new_u64s) unsigned new_u64s,
unsigned flags)
{ {
int ret; int ret;
closure_wait_event(&j->preres_wait, closure_wait_event(&j->preres_wait,
(ret = bch2_journal_error(j)) || (ret = bch2_journal_error(j)) ||
journal_preres_available(j, res, new_u64s)); journal_preres_available(j, res, new_u64s, flags));
return ret; return ret;
} }
......
...@@ -301,6 +301,7 @@ int bch2_journal_res_get_slowpath(struct journal *, struct journal_res *, ...@@ -301,6 +301,7 @@ int bch2_journal_res_get_slowpath(struct journal *, struct journal_res *,
#define JOURNAL_RES_GET_NONBLOCK (1 << 0) #define JOURNAL_RES_GET_NONBLOCK (1 << 0)
#define JOURNAL_RES_GET_CHECK (1 << 1) #define JOURNAL_RES_GET_CHECK (1 << 1)
#define JOURNAL_RES_GET_RESERVED (1 << 2) #define JOURNAL_RES_GET_RESERVED (1 << 2)
#define JOURNAL_RES_GET_RECLAIM (1 << 3)
static inline int journal_res_get_fast(struct journal *j, static inline int journal_res_get_fast(struct journal *j,
struct journal_res *res, struct journal_res *res,
...@@ -408,11 +409,12 @@ static inline void bch2_journal_preres_put(struct journal *j, ...@@ -408,11 +409,12 @@ static inline void bch2_journal_preres_put(struct journal *j,
} }
int __bch2_journal_preres_get(struct journal *, int __bch2_journal_preres_get(struct journal *,
struct journal_preres *, unsigned); struct journal_preres *, unsigned, unsigned);
static inline int bch2_journal_preres_get_fast(struct journal *j, static inline int bch2_journal_preres_get_fast(struct journal *j,
struct journal_preres *res, struct journal_preres *res,
unsigned new_u64s) unsigned new_u64s,
unsigned flags)
{ {
int d = new_u64s - res->u64s; int d = new_u64s - res->u64s;
union journal_preres_state old, new; union journal_preres_state old, new;
...@@ -423,7 +425,15 @@ static inline int bch2_journal_preres_get_fast(struct journal *j, ...@@ -423,7 +425,15 @@ static inline int bch2_journal_preres_get_fast(struct journal *j,
new.reserved += d; new.reserved += d;
if (new.reserved > new.remaining) /*
* If we're being called from the journal reclaim path, we have
* to unconditionally give out the pre-reservation, there's
* nothing else sensible we can do - otherwise we'd recurse back
* into the reclaim path and deadlock:
*/
if (!(flags & JOURNAL_RES_GET_RECLAIM) &&
new.reserved > new.remaining)
return 0; return 0;
} while ((v = atomic64_cmpxchg(&j->prereserved.counter, } while ((v = atomic64_cmpxchg(&j->prereserved.counter,
old.v, new.v)) != old.v); old.v, new.v)) != old.v);
...@@ -440,13 +450,13 @@ static inline int bch2_journal_preres_get(struct journal *j, ...@@ -440,13 +450,13 @@ static inline int bch2_journal_preres_get(struct journal *j,
if (new_u64s <= res->u64s) if (new_u64s <= res->u64s)
return 0; return 0;
if (bch2_journal_preres_get_fast(j, res, new_u64s)) if (bch2_journal_preres_get_fast(j, res, new_u64s, flags))
return 0; return 0;
if (flags & JOURNAL_RES_GET_NONBLOCK) if (flags & JOURNAL_RES_GET_NONBLOCK)
return -EAGAIN; return -EAGAIN;
return __bch2_journal_preres_get(j, res, new_u64s); return __bch2_journal_preres_get(j, res, new_u64s, flags);
} }
/* journal_entry_res: */ /* journal_entry_res: */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment