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: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
374153c2a9
commit
4efe71a646
@ -864,8 +864,11 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id,
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
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;
|
||||
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
|
||||
@ -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->parent_keys, as->inline_keys);
|
||||
|
||||
if (!(flags & BTREE_INSERT_JOURNAL_RESERVED))
|
||||
ret = bch2_journal_preres_get(&c->journal, &as->journal_preres,
|
||||
BTREE_UPDATE_JOURNAL_RES,
|
||||
JOURNAL_RES_GET_NONBLOCK);
|
||||
ret = bch2_journal_preres_get(&c->journal, &as->journal_preres,
|
||||
BTREE_UPDATE_JOURNAL_RES,
|
||||
journal_flags|JOURNAL_RES_GET_NONBLOCK);
|
||||
if (ret == -EAGAIN) {
|
||||
if (flags & BTREE_INSERT_NOUNLOCK)
|
||||
return ERR_PTR(-EINTR);
|
||||
@ -899,7 +901,8 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id,
|
||||
bch2_trans_unlock(trans);
|
||||
|
||||
ret = bch2_journal_preres_get(&c->journal, &as->journal_preres,
|
||||
BTREE_UPDATE_JOURNAL_RES, 0);
|
||||
BTREE_UPDATE_JOURNAL_RES,
|
||||
journal_flags);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
@ -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,
|
||||
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)
|
||||
bch2_journal_reclaim_work(&j->reclaim_work.work);
|
||||
@ -439,13 +440,14 @@ static bool journal_preres_available(struct journal *j,
|
||||
|
||||
int __bch2_journal_preres_get(struct journal *j,
|
||||
struct journal_preres *res,
|
||||
unsigned new_u64s)
|
||||
unsigned new_u64s,
|
||||
unsigned flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
closure_wait_event(&j->preres_wait,
|
||||
(ret = bch2_journal_error(j)) ||
|
||||
journal_preres_available(j, res, new_u64s));
|
||||
journal_preres_available(j, res, new_u64s, flags));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -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_CHECK (1 << 1)
|
||||
#define JOURNAL_RES_GET_RESERVED (1 << 2)
|
||||
#define JOURNAL_RES_GET_RECLAIM (1 << 3)
|
||||
|
||||
static inline int journal_res_get_fast(struct journal *j,
|
||||
struct journal_res *res,
|
||||
@ -408,11 +409,12 @@ static inline void bch2_journal_preres_put(struct journal *j,
|
||||
}
|
||||
|
||||
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,
|
||||
struct journal_preres *res,
|
||||
unsigned new_u64s)
|
||||
unsigned new_u64s,
|
||||
unsigned flags)
|
||||
{
|
||||
int d = new_u64s - res->u64s;
|
||||
union journal_preres_state old, new;
|
||||
@ -423,7 +425,15 @@ static inline int bch2_journal_preres_get_fast(struct journal *j,
|
||||
|
||||
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;
|
||||
} while ((v = atomic64_cmpxchg(&j->prereserved.counter,
|
||||
old.v, new.v)) != old.v);
|
||||
@ -440,13 +450,13 @@ static inline int bch2_journal_preres_get(struct journal *j,
|
||||
if (new_u64s <= res->u64s)
|
||||
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;
|
||||
|
||||
if (flags & JOURNAL_RES_GET_NONBLOCK)
|
||||
return -EAGAIN;
|
||||
|
||||
return __bch2_journal_preres_get(j, res, new_u64s);
|
||||
return __bch2_journal_preres_get(j, res, new_u64s, flags);
|
||||
}
|
||||
|
||||
/* journal_entry_res: */
|
||||
|
Loading…
Reference in New Issue
Block a user