bcache: fix race between setting bdev state to none and new write request direct to backing
There is a race condition in detaching as below: A. detaching B. Write request (1) writing back (2) write back done, set bdev state to clean. (3) cached_dev_put() and schedule_work(&dc->detach); (4) write data [0 - 4K] directly into backing and ack to user. (5) power-failure... When we restart this bcache device, this bdev is clean but not detached, and read [0 - 4K], we will get unexpected old data from cache device. To fix this problem, set the bdev state to none when we writeback done in detaching, and then if power-failure happened as above, the data in cache will not be used in next bcache device starting, it's detached, we will read the correct data from backing derectly. Signed-off-by: Dongsheng Yang <dongsheng.yang@easystack.cn> Signed-off-by: Coly Li <colyli@suse.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
733c15bd3a
commit
df4ad53242
@ -1114,9 +1114,6 @@ static void cancel_writeback_rate_update_dwork(struct cached_dev *dc)
|
||||
static void cached_dev_detach_finish(struct work_struct *w)
|
||||
{
|
||||
struct cached_dev *dc = container_of(w, struct cached_dev, detach);
|
||||
struct closure cl;
|
||||
|
||||
closure_init_stack(&cl);
|
||||
|
||||
BUG_ON(!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags));
|
||||
BUG_ON(refcount_read(&dc->count));
|
||||
@ -1130,12 +1127,6 @@ static void cached_dev_detach_finish(struct work_struct *w)
|
||||
dc->writeback_thread = NULL;
|
||||
}
|
||||
|
||||
memset(&dc->sb.set_uuid, 0, 16);
|
||||
SET_BDEV_STATE(&dc->sb, BDEV_STATE_NONE);
|
||||
|
||||
bch_write_bdev_super(dc, &cl);
|
||||
closure_sync(&cl);
|
||||
|
||||
mutex_lock(&bch_register_lock);
|
||||
|
||||
calc_cached_dev_sectors(dc->disk.c);
|
||||
|
@ -705,6 +705,15 @@ static int bch_writeback_thread(void *arg)
|
||||
* bch_cached_dev_detach().
|
||||
*/
|
||||
if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) {
|
||||
struct closure cl;
|
||||
|
||||
closure_init_stack(&cl);
|
||||
memset(&dc->sb.set_uuid, 0, 16);
|
||||
SET_BDEV_STATE(&dc->sb, BDEV_STATE_NONE);
|
||||
|
||||
bch_write_bdev_super(dc, &cl);
|
||||
closure_sync(&cl);
|
||||
|
||||
up_write(&dc->writeback_lock);
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user