mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
writeback: Fix periodic writeback after fs mount
commit a5faeaf910 upstream.
Code in blkdev.c moves a device inode to default_backing_dev_info when
the last reference to the device is put and moves the device inode back
to its bdi when the first reference is acquired. This includes moving to
wb.b_dirty list if the device inode is dirty. The code however doesn't
setup timer to wake corresponding flusher thread and while wb.b_dirty
list is non-empty __mark_inode_dirty() will not set it up either. Thus
periodic writeback is effectively disabled until a sync(2) call which can
lead to unexpected data loss in case of crash or power failure.
Fix the problem by setting up a timer for periodic writeback in case we
add the first dirty inode to wb.b_dirty list in bdev_inode_switch_bdi().
Reported-by: Bert De Jonghe <Bert.DeJonghe@amplidata.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
This commit is contained in:
@@ -57,17 +57,24 @@ static void bdev_inode_switch_bdi(struct inode *inode,
|
||||
struct backing_dev_info *dst)
|
||||
{
|
||||
struct backing_dev_info *old = inode->i_data.backing_dev_info;
|
||||
bool wakeup_bdi = false;
|
||||
|
||||
if (unlikely(dst == old)) /* deadlock avoidance */
|
||||
return;
|
||||
bdi_lock_two(&old->wb, &dst->wb);
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_data.backing_dev_info = dst;
|
||||
if (inode->i_state & I_DIRTY)
|
||||
if (inode->i_state & I_DIRTY) {
|
||||
if (bdi_cap_writeback_dirty(dst) && !wb_has_dirty_io(&dst->wb))
|
||||
wakeup_bdi = true;
|
||||
list_move(&inode->i_wb_list, &dst->wb.b_dirty);
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
spin_unlock(&old->wb.list_lock);
|
||||
spin_unlock(&dst->wb.list_lock);
|
||||
|
||||
if (wakeup_bdi)
|
||||
bdi_wakeup_thread_delayed(dst);
|
||||
}
|
||||
|
||||
/* Kill _all_ buffers and pagecache , dirty or not.. */
|
||||
|
||||
Reference in New Issue
Block a user