mirror of https://gitee.com/openkylin/linux.git
bcache: fix fifo index swapping condition in journal_pin_cmp()
Fifo structure journal.pin is implemented by a cycle buffer, if the back index reaches highest location of the cycle buffer, it will be swapped to 0. Once the swapping happens, it means a smaller fifo index might be associated to a newer journal entry. So the btree node with oldest journal entry won't be selected in bch_btree_leaf_dirty() to reference the dirty B+tree leaf node. This problem may cause bcache journal won't protect unflushed oldest B+tree dirty leaf node in power failure, and this B+tree leaf node is possible to beinconsistent after reboot from power failure. This patch fixes the fifo index comparing logic in journal_pin_cmp(), to avoid potential corrupted B+tree leaf node when the back index of journal pin is swapped. Signed-off-by: Coly Li <colyli@suse.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
e2a7b9f4a1
commit
c0e0954e90
|
@ -528,6 +528,32 @@ static void btree_node_write_work(struct work_struct *w)
|
||||||
mutex_unlock(&b->write_lock);
|
mutex_unlock(&b->write_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return true if journal pin 'l' is newer than 'r' */
|
||||||
|
static bool journal_pin_cmp(struct cache_set *c,
|
||||||
|
atomic_t *l,
|
||||||
|
atomic_t *r)
|
||||||
|
{
|
||||||
|
int l_idx, r_idx, f_idx, b_idx;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
l_idx = fifo_idx(&(c)->journal.pin, (l));
|
||||||
|
r_idx = fifo_idx(&(c)->journal.pin, (r));
|
||||||
|
f_idx = (c)->journal.pin.front;
|
||||||
|
b_idx = (c)->journal.pin.back;
|
||||||
|
|
||||||
|
if (l_idx > r_idx)
|
||||||
|
ret = true;
|
||||||
|
/* in case fifo back pointer is swapped */
|
||||||
|
if (b_idx < f_idx) {
|
||||||
|
if (l_idx <= b_idx && r_idx >= f_idx)
|
||||||
|
ret = true;
|
||||||
|
else if (l_idx >= f_idx && r_idx <= b_idx)
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void bch_btree_leaf_dirty(struct btree *b, atomic_t *journal_ref)
|
static void bch_btree_leaf_dirty(struct btree *b, atomic_t *journal_ref)
|
||||||
{
|
{
|
||||||
struct bset *i = btree_bset_last(b);
|
struct bset *i = btree_bset_last(b);
|
||||||
|
|
|
@ -157,10 +157,6 @@ struct journal_device {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BTREE_FLUSH_NR 8
|
#define BTREE_FLUSH_NR 8
|
||||||
|
|
||||||
#define journal_pin_cmp(c, l, r) \
|
|
||||||
(fifo_idx(&(c)->journal.pin, (l)) > fifo_idx(&(c)->journal.pin, (r)))
|
|
||||||
|
|
||||||
#define JOURNAL_PIN 20000
|
#define JOURNAL_PIN 20000
|
||||||
|
|
||||||
#define journal_full(j) \
|
#define journal_full(j) \
|
||||||
|
|
Loading…
Reference in New Issue