| From 6ff33d99fc5c96797103b48b7b0902c296f09c05 Mon Sep 17 00:00:00 2001 |
| From: Dmitry Monakhov <dmtrmonakhov@yandex-team.ru> |
| Date: Thu, 31 Oct 2019 10:39:19 +0000 |
| Subject: quota: fix livelock in dquot_writeback_dquots |
| |
| From: Dmitry Monakhov <dmtrmonakhov@yandex-team.ru> |
| |
| commit 6ff33d99fc5c96797103b48b7b0902c296f09c05 upstream. |
| |
| Write only quotas which are dirty at entry. |
| |
| XFSTEST: https://github.com/dmonakhov/xfstests/commit/b10ad23566a5bf75832a6f500e1236084083cddc |
| |
| Link: https://lore.kernel.org/r/20191031103920.3919-1-dmonakhov@openvz.org |
| CC: stable@vger.kernel.org |
| Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> |
| Signed-off-by: Dmitry Monakhov <dmtrmonakhov@yandex-team.ru> |
| Signed-off-by: Jan Kara <jack@suse.cz> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/quota/dquot.c | 9 +++++---- |
| 1 file changed, 5 insertions(+), 4 deletions(-) |
| |
| --- a/fs/quota/dquot.c |
| +++ b/fs/quota/dquot.c |
| @@ -604,7 +604,7 @@ EXPORT_SYMBOL(dquot_scan_active); |
| /* Write all dquot structures to quota files */ |
| int dquot_writeback_dquots(struct super_block *sb, int type) |
| { |
| - struct list_head *dirty; |
| + struct list_head dirty; |
| struct dquot *dquot; |
| struct quota_info *dqopt = sb_dqopt(sb); |
| int cnt; |
| @@ -617,9 +617,10 @@ int dquot_writeback_dquots(struct super_ |
| if (!sb_has_quota_active(sb, cnt)) |
| continue; |
| spin_lock(&dq_list_lock); |
| - dirty = &dqopt->info[cnt].dqi_dirty_list; |
| - while (!list_empty(dirty)) { |
| - dquot = list_first_entry(dirty, struct dquot, |
| + /* Move list away to avoid livelock. */ |
| + list_replace_init(&dqopt->info[cnt].dqi_dirty_list, &dirty); |
| + while (!list_empty(&dirty)) { |
| + dquot = list_first_entry(&dirty, struct dquot, |
| dq_dirty); |
| /* Dirty and inactive can be only bad dquot... */ |
| if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { |