Fix generic/390 failure due to quota release after freeze
Subsystems (3)
Ojaswin Mujoo
reviewerv2 cover Fix generic/390 failure due to quota release after freeze
Changes since v1:
* Patch 1: Move flush_delayed_work() to start of function
* Patch 2: Guard ext4_release_dquot against freeze
Regarding patch 2, as per my understanding of the journalling code, right now ext4_release_dquot() can only be called from the quota_realease_work workqueue and hence ideally should never have a journal open but to future-proof it we make sure the journal is not opened when calling sb_start_inwrite().
** Original Cover **
Recently we noticed generic/390 failing on powerpc systems. This test basically does a freeze-unfreeze loop in parallel with fsstress on the FS to detect any races in the code paths.
We noticed that the test started failing due to kernel WARN_ONs because quota_release_work workqueue started executing while the FS was frozen which led to creating new transactions in ext4_release_quota.
Most of the details are in the bug however I'd just like to add that I'm completely new to quota code so the patch, although fixing the issue, might be not be logically the right thing to do. So reviews and suggestions are welcome.
Also, I can only replicate this race on one of my machines reliably and does not appear on others. I've tested with with fstests -g quota and don't see any new failures.
Ojaswin Mujoo (2):
quota: flush quota_release_work upon quota writeback
ext4: protect ext4_release_dquot against freezing
fs/ext4/super.c | 17 +++++++++++++++++ fs/quota/dquot.c | 2 ++ 2 files changed, 19 insertions(+)
Signature · 1 line
2.43.5
Ojaswin Mujoo
reviewerPATCH v2 1/2 quota: flush quota_release_work upon quota writeback
One of the paths quota writeback is called from is:
freeze_super()
sync_filesystem()
ext4_sync_fs()
dquot_writeback_dquots()Since we currently don't always flush the quota_release_work queue in this path, we can end up with the following race:
1. dquot are added to releasing_dquots list during regular operations.
2. FS Freeze starts, however, this does not flush the quota_release_work queue.
3. Freeze completes.
4. Kernel eventually tries to flush the workqueue while FS is frozen which hits a WARN_ON since transaction gets started during frozen state:
ext4_journal_check_start+0x28/0x110 [ext4] (unreliable) __ext4_journal_start_sb+0x64/0x1c0 [ext4] ext4_release_dquot+0x90/0x1d0 [ext4] quota_release_workfn+0x43c/0x4d0
Which is the following line:
WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
Which ultimately results in generic/390 failing due to dmesg noise. This was detected on powerpc machine 15 cores.
To avoid this, make sure to flush the workqueue during dquot_writeback_dquots() so we dont have any pending workitems after freeze.
--- fs/quota/dquot.c | 2 ++ 1 file changed, 2 insertions(+)
fs/quota/dquot.c +2 -0
@@ -688,6 +688,8 @@ int dquot_writeback_dquots(struct super_block *sb, int type)WARN_ON_ONCE (!rwsem_is_locked (&sb->s_umount)); +flush_delayed_work ("a_release_work); +for (cnt =0 ; cnt <MAXQUOTAS ; cnt++) {if (type !=-1 && cnt != type)continue ;
Signature · 1 line
2.43.5
Jan Kara
reviewerRe: [PATCH v2 1/2] quota: flush quota_release_work upon quota writeback
Quoted 28 lines · Ojaswin Mujoo
One of the paths quota writeback is called from is:
freeze_super()
sync_filesystem()ext4_sync_fs() dquot_writeback_dquots()Since we currently don't always flush the
quota_release_workqueue in this path, we can end up with the following race:1. dquot are added to
releasing_dquotslist during regular operations.
2. FS Freeze starts, however, this does not flush thequota_release_workqueue.
3. Freeze completes.
4. Kernel eventually tries to flush the workqueue while FS is frozen which hits aWARN_ONsince transaction gets started during frozen state:ext4_journal_check_start+0x28/0x110 [ext4] (unreliable) __ext4_journal_start_sb+0x64/0x1c0 [ext4] ext4_release_dquot+0x90/0x1d0 [ext4] quota_release_workfn+0x43c/0x4d0Which is the following line:
WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);Which ultimately results in generic/390 failing due to dmesg noise. This was detected on powerpc machine 15 cores.
Quoted 6 lines
To avoid this, make sure to flush the workqueue during
dquot_writeback_dquots()so we dont have any pending workitems after freeze.Reported-by Disha Goel <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>
Thanks. Since this patch is independent, I've picked it up into my tree (will push it to Linus for rc2).
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Re: [PATCH v2 1/2] quota: flush quota_release_work upon quota writeback
In reply to Ojaswin MujooQuoted 28 lines · Ojaswin Mujoo
One of the paths quota writeback is called from is:
freeze_super()
sync_filesystem()ext4_sync_fs() dquot_writeback_dquots()Since we currently don't always flush the
quota_release_workqueue in this path, we can end up with the following race:1. dquot are added to
releasing_dquotslist during regular operations.
2. FS Freeze starts, however, this does not flush thequota_release_workqueue.
3. Freeze completes.
4. Kernel eventually tries to flush the workqueue while FS is frozen which hits aWARN_ONsince transaction gets started during frozen state:ext4_journal_check_start+0x28/0x110 [ext4] (unreliable) __ext4_journal_start_sb+0x64/0x1c0 [ext4] ext4_release_dquot+0x90/0x1d0 [ext4] quota_release_workfn+0x43c/0x4d0Which is the following line:
WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);Which ultimately results in generic/390 failing due to dmesg noise. This was detected on powerpc machine 15 cores.
Quoted 6 lines
To avoid this, make sure to flush the workqueue during
dquot_writeback_dquots()so we dont have any pending workitems after freeze.Reported-by Disha Goel <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>
Looks good, thanks for the patch!
Quoted 17 lines
--- fs/quota/dquot.c | 2 ++ 1 file changed, 2 insertions(+)fs/quota/dquot.c +2
-0@@ -688,6 +688,8 @@ int dquot_writeback_dquots(struct super_block *sb, int type)WARN_ON_ONCE (!rwsem_is_locked (&sb->s_umount)); +flush_delayed_work ("a_release_work); +for (cnt =0 ; cnt <MAXQUOTAS ; cnt++) {if (type !=-1 && cnt != type)continue ;
Re: [PATCH v2 1/2] quota: flush quota_release_work upon quota writeback
In reply to Ojaswin MujooOn 21/11/24 6:08 pm, Ojaswin Mujoo wrote:
One of the paths quota writeback is called from is:
freeze_super()
sync_filesystem()
ext4_sync_fs()
dquot_writeback_dquots()Since we currently don't always flush the quota_release_work queue in this path, we can end up with the following race:
1. dquot are added to releasing_dquots list during regular operations.
2. FS Freeze starts, however, this does not flush the quota_release_work queue.
3. Freeze completes.
4. Kernel eventually tries to flush the workqueue while FS is frozen which hits a WARN_ON since transaction gets started during frozen state:
ext4_journal_check_start+0x28/0x110 [ext4] (unreliable) __ext4_journal_start_sb+0x64/0x1c0 [ext4] ext4_release_dquot+0x90/0x1d0 [ext4] quota_release_workfn+0x43c/0x4d0
Which is the following line:
WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
Which ultimately results in generic/390 failing due to dmesg noise. This was detected on powerpc machine 15 cores.
To avoid this, make sure to flush the workqueue during dquot_writeback_dquots() so we dont have any pending workitems after freeze.
Thanks for the fix patch Ojaswin.
I have tested the patch on powerpc machine, and it fixes the generic/390 test failure.
--- fs/quota/dquot.c | 2 ++ 1 file changed, 2 insertions(+)
fs/quota/dquot.c +2 -0
@@ -688,6 +688,8 @@ int dquot_writeback_dquots(struct super_block *sb, int type)WARN_ON_ONCE (!rwsem_is_locked (&sb->s_umount)); +flush_delayed_work ("a_release_work); +for (cnt =0 ; cnt <MAXQUOTAS ; cnt++) {if (type !=-1 && cnt != type)continue ;
Ojaswin Mujoo
reviewerPATCH v2 2/2 ext4: protect ext4_release_dquot against freezing
In reply to Ojaswin MujooProtect ext4_release_dquot against freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.
Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355 ext4: fix deadlock with fs freezing and EA inodes
--- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
fs/ext4/super.c +17 -0
@@ -6887,12 +6887,25 @@ static int ext4_release_dquot(struct dquot *dquot) {int ret, err;handle_t *handle; +bool freeze_protected = false; + +/* +* Trying to sb_start_intwrite() in a running transaction +* can result in a deadlock. Further, running transactions +* are already protected from freezing. +*/ +if (!ext4_journal_current_handle ()) { +sb_start_intwrite (dquot->dq_sb); + freeze_protected = true; + } handle =ext4_journal_start (dquot_to_inode (dquot),EXT4_HT_QUOTA ,EXT4_QUOTA_DEL_BLOCKS (dquot->dq_sb));if (IS_ERR (handle)) {/* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release (dquot); +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb);return PTR_ERR (handle); } ret =dquot_release (dquot);
@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot) err =ext4_journal_stop (handle);if (!ret) ret = err; + +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb); +return ret; }
Signature · 1 line
2.43.5
kernel test robot
build botRe: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
kernel test robot noticed the following build errors:
Hi Ojaswin,
kernel test robot noticed the following build errors:
[auto build test ERROR on tytso-ext4/dev]
[also build test ERROR on brauner-vfs/vfs.all jack-fs/for_next linus/master v6.12 next-20241121] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Ojaswin-Mujoo/quota-flush-quota_release_work-upon-quota-writeback/20241121-204331 base: https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git dev patch link: https://lore.kernel.org/r/20241121123855.645335-3-ojaswin%40linux.ibm.com patch subject: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing config: i386-buildonly-randconfig-004-20241122 (https://download.01.org/0day-ci/archive/20241122/[email protected]/config) compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241122/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
In file included from fs/ext4/super.c:27:
In file included from include/linux/blkdev.h:9:
In file included from include/linux/blk_types.h:10:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:8:
In file included from include/linux/cacheflush.h:5:
In file included from arch/x86/include/asm/cacheflush.h:5:
In file included from include/linux/mm.h:2213:
include/linux/vmstat.h:518:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
518 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
| ~~~~~~~~~~~ ^ ~~~
>> fs/ext4/super.c:6912:6: error: use of undeclared identifier 'freeze_protected'; did you mean 'freeze_processes'?
6912 | if (freeze_protected)
| ^~~~~~~~~~~~~~~~
| freeze_processes
include/linux/freezer.h:46:12: note: 'freeze_processes' declared here
46 | extern int freeze_processes(void);
| ^1 warning and 1 error generated.
vim +6912 fs/ext4/super.c
6893
6894 static int ext4_acquire_dquot(struct dquot *dquot)
6895 {
6896 int ret, err;
6897 handle_t *handle;
6898
6899 handle = ext4_journal_start(dquot_to_inode(dquot), EXT4_HT_QUOTA,
6900 EXT4_QUOTA_INIT_BLOCKS(dquot->dq_sb));
6901 if (IS_ERR(handle))
6902 return PTR_ERR(handle);
6903 ret = dquot_acquire(dquot);
6904 if (ret < 0)
6905 ext4_error_err(dquot->dq_sb, -ret,
6906 "Failed to acquire dquot type %d",
6907 dquot->dq_id.type);
6908 err = ext4_journal_stop(handle);
6909 if (!ret)
6910 ret = err;
6911
> 6912 if (freeze_protected)
6913 sb_end_intwrite(dquot->dq_sb);
6914
6915 return ret;
6916 }
6917
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
kernel test robot
build botRe: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
In reply to Ojaswin Mujookernel test robot noticed the following build errors:
Hi Ojaswin,
kernel test robot noticed the following build errors:
[auto build test ERROR on tytso-ext4/dev]
[also build test ERROR on brauner-vfs/vfs.all jack-fs/for_next linus/master v6.12 next-20241121] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Ojaswin-Mujoo/quota-flush-quota_release_work-upon-quota-writeback/20241121-204331 base: https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git dev patch link: https://lore.kernel.org/r/20241121123855.645335-3-ojaswin%40linux.ibm.com patch subject: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing config: arc-randconfig-001-20241122 (https://download.01.org/0day-ci/archive/20241122/[email protected]/config) compiler: arc-elf-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241122/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
fs/ext4/super.c: In function 'ext4_acquire_dquot':
>> fs/ext4/super.c:6912:13: error: 'freeze_protected' undeclared (first use in this function); did you mean 'freeze_processes'?
6912 | if (freeze_protected)
| ^~~~~~~~~~~~~~~~
| freeze_processes fs/ext4/super.c:6912:13: note: each undeclared identifier is reported only once for each function it appears in
vim +6912 fs/ext4/super.c
6893
6894 static int ext4_acquire_dquot(struct dquot *dquot)
6895 {
6896 int ret, err;
6897 handle_t *handle;
6898
6899 handle = ext4_journal_start(dquot_to_inode(dquot), EXT4_HT_QUOTA,
6900 EXT4_QUOTA_INIT_BLOCKS(dquot->dq_sb));
6901 if (IS_ERR(handle))
6902 return PTR_ERR(handle);
6903 ret = dquot_acquire(dquot);
6904 if (ret < 0)
6905 ext4_error_err(dquot->dq_sb, -ret,
6906 "Failed to acquire dquot type %d",
6907 dquot->dq_id.type);
6908 err = ext4_journal_stop(handle);
6909 if (!ret)
6910 ret = err;
6911
> 6912 if (freeze_protected)
6913 sb_end_intwrite(dquot->dq_sb);
6914
6915 return ret;
6916 }
6917
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Re: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
In reply to Ojaswin MujooQuoted 4 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.
Quoted 8 lines
Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodesSuggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>
Looks good to me (the 0-day reports seem to be due to wrong merge). Feel free to add:
Honza
Quoted 48 lines
--- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)fs/ext4/super.c +17
-0@@ -6887,12 +6887,25 @@ static int ext4_release_dquot(struct dquot *dquot) {int ret, err;handle_t *handle; +bool freeze_protected = false; + +/* +* Trying to sb_start_intwrite() in a running transaction +* can result in a deadlock. Further, running transactions +* are already protected from freezing. +*/ +if (!ext4_journal_current_handle ()) { +sb_start_intwrite (dquot->dq_sb); + freeze_protected = true; + } handle =ext4_journal_start (dquot_to_inode (dquot),EXT4_HT_QUOTA ,EXT4_QUOTA_DEL_BLOCKS (dquot->dq_sb));if (IS_ERR (handle)) {/* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release (dquot); +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb);return PTR_ERR (handle); } ret =dquot_release (dquot);@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot) err =ext4_journal_stop (handle);if (!ret) ret = err; + +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb); +return ret; }Signature · 1 line
2.43.5
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Ojaswin Mujoo
reviewerRe: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
Quoted 14 lines · Jan Kara
Quoted 4 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.Quoted 8 lines
Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodesSuggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>
Quoted 6 lines
Looks good to me (the 0-day reports seem to be due to wrong merge). Feel free to add:
Reviewed-by Jan Kara <[email protected]>Honza
Thanks Jan, yes it does seem like an incorrect merge.
Quoted 52 lines
Quoted 49 lines
--- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)fs/ext4/super.c +17
-0@@ -6887,12 +6887,25 @@ static int ext4_release_dquot(struct dquot *dquot) {int ret, err;handle_t *handle; +bool freeze_protected = false; + +/* +* Trying to sb_start_intwrite() in a running transaction +* can result in a deadlock. Further, running transactions +* are already protected from freezing. +*/ +if (!ext4_journal_current_handle ()) { +sb_start_intwrite (dquot->dq_sb); + freeze_protected = true; + } handle =ext4_journal_start (dquot_to_inode (dquot),EXT4_HT_QUOTA ,EXT4_QUOTA_DEL_BLOCKS (dquot->dq_sb));if (IS_ERR (handle)) {/* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release (dquot); +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb);return PTR_ERR (handle); } ret =dquot_release (dquot);@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot) err =ext4_journal_stop (handle);if (!ret) ret = err; + +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb); +return ret; }Signature · 1 line
2.43.5Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Re: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
In reply to Ojaswin Mujoofs/ext4/super.c static int ext4_release_dquot(struct dquot *dquot)
Quoted 47 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodesSuggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>--- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)fs/ext4/super.c +13
-0@@ -6887,12 +6887,25 @@ static int ext4_release_dquot(struct dquot *dquot) {int ret, err;handle_t *handle; +bool freeze_protected = false; + +/* +* Trying to sb_start_intwrite() in a running transaction +* can result in a deadlock. Further, running transactions +* are already protected from freezing. +*/ +if (!ext4_journal_current_handle ()) { +sb_start_intwrite (dquot->dq_sb); + freeze_protected = true; + } handle =ext4_journal_start (dquot_to_inode (dquot),EXT4_HT_QUOTA ,EXT4_QUOTA_DEL_BLOCKS (dquot->dq_sb));if (IS_ERR (handle)) {/* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release (dquot); +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb);return PTR_ERR (handle); } ret =dquot_release (dquot);@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot)
The git am command looks for the following context code from line 6903 to apply the changes. But there are many functions in fs/ext4/super.c that have similar code, such as ext4_write_dquot() and ext4_acquire_dquot().
So when the code before ext4_release_dquot() is added, the first matching context found could be in ext4_write_dquot() or ext4_acquire_dquot().
fs/ext4/super.c static int ext4_release_dquot(struct dquot *dquot) · line 6925
Quoted 10 lines
fs/ext4/super.c +4
-0err =ext4_journal_stop (handle);if (!ret) ret = err; + +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb); +return ret; }
Thus this is actually a bug in git am, which can be avoided by increasing the number of context lines with git format-patch -U8 -1.
Otherwise it looks good. Feel free to add:
Ojaswin Mujoo
reviewerRe: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
Quoted 42 lines · Baokun Li
Quoted 41 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodesSuggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>--- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)fs/ext4/super.c +12
-0@@ -6887,12 +6887,25 @@ static int ext4_release_dquot(struct dquot *dquot) {int ret, err;handle_t *handle; +bool freeze_protected = false; + +/* +* Trying to sb_start_intwrite() in a running transaction +* can result in a deadlock. Further, running transactions +* are already protected from freezing. +*/ +if (!ext4_journal_current_handle ()) { +sb_start_intwrite (dquot->dq_sb); + freeze_protected = true; + } handle =ext4_journal_start (dquot_to_inode (dquot),EXT4_HT_QUOTA ,EXT4_QUOTA_DEL_BLOCKS (dquot->dq_sb));if (IS_ERR (handle)) {/* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release (dquot); +if (freeze_protected)
Quoted 8 lines
fs/ext4/super.c static int ext4_release_dquot(struct dquot *dquot)
Quoted 5 lines
fs/ext4/super.c +1
-0+sb_end_intwrite (dquot->dq_sb);return PTR_ERR (handle); } ret =dquot_release (dquot);@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot)The
git amcommand looks for the following context code from line 6903 to apply the changes. But there are many functions infs/ext4/super.cthat have similar code, such asext4_write_dquot()andext4_acquire_dquot().
Oh that's strange, shouldn't it match the complete line like:
Quoted 1 line
fs/ext4/super.c static int ext4_release_dquot(struct dquot *dquot)
Quoted 1 line
fs/ext4/super.c +0
-0@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot)
That should only have one occurence around line 6903? Or does it try to fuzzy match which ends up matching ext4_write_dquot etc?
Quoted 16 lines
So when the code before
ext4_release_dquot()is added, the first matching context found could be inext4_write_dquot()orext4_acquire_dquot().fs/ext4/super.c static int ext4_release_dquot(struct dquot *dquot) · line 6924
Quoted 9 lines
fs/ext4/super.c +4
-0err =ext4_journal_stop (handle);if (!ret) ret = err; + +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb); +return ret; }Thus this is actually a bug in
git am, which can be avoided by increasing the number of context lines withgit format-patch -U8 -1.
Quoted 3 lines
Otherwise it looks good. Feel free to add:
Reviewed-by Baokun Li <[email protected]>
Thanks Baokun!
Regards,
ojaswin
Quoted 1 line
Re: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
Quoted 51 lines · Ojaswin Mujoo
Quoted 42 lines · Baokun Li
Quoted 41 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodesSuggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>--- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)fs/ext4/super.c +12
-0@@ -6887,12 +6887,25 @@ static int ext4_release_dquot(struct dquot *dquot) {int ret, err;handle_t *handle; +bool freeze_protected = false; + +/* +* Trying to sb_start_intwrite() in a running transaction +* can result in a deadlock. Further, running transactions +* are already protected from freezing. +*/ +if (!ext4_journal_current_handle ()) { +sb_start_intwrite (dquot->dq_sb); + freeze_protected = true; + } handle =ext4_journal_start (dquot_to_inode (dquot),EXT4_HT_QUOTA ,EXT4_QUOTA_DEL_BLOCKS (dquot->dq_sb));if (IS_ERR (handle)) {/* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release (dquot); +if (freeze_protected)Quoted 8 lines
fs/ext4/super.c static int ext4_release_dquot(struct dquot *dquot)
Quoted 5 lines
fs/ext4/super.c +1
-0+sb_end_intwrite (dquot->dq_sb);return PTR_ERR (handle); } ret =dquot_release (dquot);@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot)The
git amcommand looks for the following context code from line 6903 to apply the changes. But there are many functions infs/ext4/super.cthat have similar code, such asext4_write_dquot()andext4_acquire_dquot().
Quoted 1 line
Oh that's strange, shouldn't it match the complete line like:
A rough look at the git am source code looks like it only focuses on line numbers between two ‘@@’.
am_run
run_apply
apply_all_patches
apply_patch
parse_chunk
find_header
parse_fragment_header
check_patch_list
check_patch
apply_data
load_preimage
apply_fragments
apply_one_fragment
find_pos
match_fragment
Quoted 3 lines
Quoted 1 line
fs/ext4/super.c static int ext4_release_dquot(struct dquot *dquot)
Quoted 1 line
fs/ext4/super.c +0
-0@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot)That should only have one occurence around line 6903? Or does it try to fuzzy match which ends up matching
ext4_write_dquotetc?
In find_pos(), start from line 6903, compare the hash value of each line of code line by line in forward direction, if it can't match, then match the hash value of each line of code line by line in reverse direction from line 6903. Fuzzy matching is used if some whitespace characters should be ignored.
Regards,
Baokun
Ojaswin Mujoo
reviewerRe: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
Quoted 71 lines · Baokun Li
Quoted 51 lines · Ojaswin Mujoo
Quoted 42 lines · Baokun Li
Quoted 41 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodesSuggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>--- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)fs/ext4/super.c +12
-0@@ -6887,12 +6887,25 @@ static int ext4_release_dquot(struct dquot *dquot) {int ret, err;handle_t *handle; +bool freeze_protected = false; + +/* +* Trying to sb_start_intwrite() in a running transaction +* can result in a deadlock. Further, running transactions +* are already protected from freezing. +*/ +if (!ext4_journal_current_handle ()) { +sb_start_intwrite (dquot->dq_sb); + freeze_protected = true; + } handle =ext4_journal_start (dquot_to_inode (dquot),EXT4_HT_QUOTA ,EXT4_QUOTA_DEL_BLOCKS (dquot->dq_sb));if (IS_ERR (handle)) {/* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release (dquot); +if (freeze_protected)Quoted 8 lines
fs/ext4/super.c static int ext4_release_dquot(struct dquot *dquot)
Quoted 5 lines
fs/ext4/super.c +1
-0+sb_end_intwrite (dquot->dq_sb);return PTR_ERR (handle); } ret =dquot_release (dquot);@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot)The
git amcommand looks for the following context code from line 6903 to apply the changes. But there are many functions infs/ext4/super.cthat have similar code, such asext4_write_dquot()andext4_acquire_dquot().Quoted 1 line
Oh that's strange, shouldn't it match the complete line like:
A rough look at the
git amsource code looks like it only focuses on line numbers between two ‘@@’.
am_run
run_apply
apply_all_patches
apply_patch
parse_chunk
find_header
parse_fragment_header
check_patch_list
check_patch
apply_data
load_preimage
apply_fragments
apply_one_fragment
find_pos
match_fragment
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
fs/ext4/super.c static int ext4_release_dquot(struct dquot *dquot)
Quoted 1 line
fs/ext4/super.c +0
-0@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot)That should only have one occurence around line 6903? Or does it try to fuzzy match which ends up matching
ext4_write_dquotetc?In
find_pos(), start from line 6903, compare the hash value of each line of code line by line in forward direction, if it can't match, then match the hash value of each line of code line by line in reverse direction from line 6903. Fuzzy matching is used if some whitespace characters should be ignored.
Ahh okay thanks for looking into this Baokun, pretty interesting since I've never looked at git code :)
Regards,
ojaswin
Quoted 5 lines
Regards,
Baokun
Ritesh Harjani (IBM)
reviewerRe: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
In reply to Ojaswin MujooQuoted 4 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.
Quoted 8 lines
Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodesSuggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>
Sorry for being late on this. Ideally, shouldn't it be the responsibility of higher level FS (ext4) to make sure that FS never freezes while there is pending work for releasing dquot structures and that it should also prevent any context where such dquot structures gets added for release/delayed release.
e.g. this is what FS takes care during freeze path i.e.
freeze_super() -> sync_fs -> ext4_sync_fs()-> dquot_writeback_dquots() -> flush_delayed_work() (now fixed)
Now coming to iput() case which Jan mentioned [1] which could still be called after FS have frozen. As I see we have a protection from FS freeze in the ext4_evict_path() right? So ideally we should never see dquot_drop() w/o fs freeze protection. And say, if the FS freezing immediately happened after we scheduled this delayed work (but before the work gets scheduled), then that will be taken care in the freeze_super() chain, where we will flush all the delayed work no? - which is what Patch-1 is fixing.
(There still might be an error handling path in ext4_evict_inode() -> ext4_clear_inode() which we don't freeze protect. I still need to take a closer look at that though).
So.. isn't this patch trying to hide the problem where FS failed to freeze protect some code path?
-ritesh
Quoted 47 lines
--- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)fs/ext4/super.c +17
-0@@ -6887,12 +6887,25 @@ static int ext4_release_dquot(struct dquot *dquot) {int ret, err;handle_t *handle; +bool freeze_protected = false; + +/* +* Trying to sb_start_intwrite() in a running transaction +* can result in a deadlock. Further, running transactions +* are already protected from freezing. +*/ +if (!ext4_journal_current_handle ()) { +sb_start_intwrite (dquot->dq_sb); + freeze_protected = true; + } handle =ext4_journal_start (dquot_to_inode (dquot),EXT4_HT_QUOTA ,EXT4_QUOTA_DEL_BLOCKS (dquot->dq_sb));if (IS_ERR (handle)) {/* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release (dquot); +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb);return PTR_ERR (handle); } ret =dquot_release (dquot);@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot) err =ext4_journal_stop (handle);if (!ret) ret = err; + +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb); +return ret; }Signature · 1 line
2.43.5
Jan Kara
reviewerRe: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
Quoted 21 lines · Ritesh Harjani
Quoted 4 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.Quoted 8 lines
Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodesSuggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>Sorry for being late on this. Ideally, shouldn't it be the responsibility of higher level FS (ext4) to make sure that FS never freezes while there is pending work for releasing dquot structures and that it should also prevent any context where such dquot structures gets added for release/delayed release.
Quoted 6 lines
e.g. this is what FS takes care during freeze path i.e.
freeze_super()->sync_fs-> ext4_sync_fs()->dquot_writeback_dquots()->flush_delayed_work()(now fixed)Now coming to
iput()case which Jan mentioned [1] which could still be called after FS have frozen. As I see we have a protection from FS freeze in theext4_evict_path()right? So ideally we should never see
We don't if we go through:
ext4_evict_inode()
if (inode->i_nlink) {
truncate_inode_pages_final(&inode->i_data);
goto no_delete;
}
no_delete:
ext4_clear_inode(inode)
...
dquot_drop()Quoted 9 lines
dquot_drop()w/o fs freeze protection. And say, if the FS freezing immediately happened after we scheduled this delayed work (but before the work gets scheduled), then that will be taken care in thefreeze_super()chain, where we will flush all the delayed work no? - which is what Patch-1 is fixing.(There still might be an error handling path in
ext4_evict_inode()->ext4_clear_inode()which we don't freeze protect. I still need to take a closer look at that though).
It isn't error handling. It is a standard inode eviction path if the inode isn't being deleted.
Quoted 2 lines
So.. isn't this patch trying to hide the problem where FS failed to freeze protect some code path?
Well, it is kind of self-inflicted damage of ext4_dquot_release() because it starts a transaction even if there will be nothing to do. We could add checks to ext4_dquot_release() to start a transaction only if dquot structure will need to be deleted but that's a layering violation because it would have to make assumptions about how quota format code is going to behave.
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Ojaswin Mujoo
reviewerRe: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
In reply to Ojaswin MujooQuoted 4 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.
Quoted 8 lines
Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodesSuggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>
Hey Ted,
Just a ping, I think you might have missed this patch. Let me know if anything else is needed from my side.
Regards,
ojaswin
Quoted 48 lines
--- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)fs/ext4/super.c +17
-0@@ -6887,12 +6887,25 @@ static int ext4_release_dquot(struct dquot *dquot) {int ret, err;handle_t *handle; +bool freeze_protected = false; + +/* +* Trying to sb_start_intwrite() in a running transaction +* can result in a deadlock. Further, running transactions +* are already protected from freezing. +*/ +if (!ext4_journal_current_handle ()) { +sb_start_intwrite (dquot->dq_sb); + freeze_protected = true; + } handle =ext4_journal_start (dquot_to_inode (dquot),EXT4_HT_QUOTA ,EXT4_QUOTA_DEL_BLOCKS (dquot->dq_sb));if (IS_ERR (handle)) {/* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release (dquot); +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb);return PTR_ERR (handle); } ret =dquot_release (dquot);@@ -6903,6 +6916,10 @@ static int ext4_release_dquot(struct dquot *dquot) err =ext4_journal_stop (handle);if (!ret) ret = err; + +if (freeze_protected) +sb_end_intwrite (dquot->dq_sb); +return ret; }Signature · 1 line
2.43.5
Theodore Ts'o
maintainerRe: [PATCH v2 2/2] ext4: protect ext4_release_dquot against freezing
Quoted 11 lines · Ojaswin Mujoo
Quoted 10 lines · Ojaswin Mujoo
Protect
ext4_release_dquotagainst freezing so that we don't try to start a transaction when FS is frozen, leading to warnings.Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in
46e294efc355ext4: fix deadlock with fs freezing and EA inodes
Quoted 7 lines
Quoted 2 lines
Suggested-by Jan Kara <[email protected]>Signed-off-by Ojaswin Mujoo <[email protected]>Hey Ted,
Just a ping, I think you might have missed this patch. Let me know if anything else is needed from my side.
Yes, I did miss this patch; thanks for the reminder. It looks good and I've added it to my tree.
- Ted
Ojaswin Mujoo
reviewerQuoted 1 line · Ojaswin Mujoo
Changes since v1:
Forgot to link v1:
https://lore.kernel.org/linux-ext4/[email protected]/T/#t
Quoted 40 lines
* Patch 1: Move
flush_delayed_work()to start of function
* Patch 2: Guardext4_release_dquotagainst freezeRegarding patch 2, as per my understanding of the journalling code, right now
ext4_release_dquot()can only be called from thequota_realease_workworkqueue and hence ideally should never have a journal open but to future-proof it we make sure the journal is not opened when callingsb_start_inwrite().** Original Cover **
Recently we noticed generic/390 failing on powerpc systems. This test basically does a freeze-unfreeze loop in parallel with fsstress on the FS to detect any races in the code paths.
We noticed that the test started failing due to kernel
WARN_ONsbecausequota_release_workworkqueue started executing while the FS was frozen which led to creating new transactions inext4_release_quota.Most of the details are in the bug however I'd just like to add that I'm completely new to quota code so the patch, although fixing the issue, might be not be logically the right thing to do. So reviews and suggestions are welcome.
Also, I can only replicate this race on one of my machines reliably and does not appear on others. I've tested with with fstests -g quota and don't see any new failures.
Ojaswin Mujoo (2):
quota: flushquota_release_workupon quota writeback
ext4: protectext4_release_dquotagainst freezingfs/ext4/super.c | 17 +++++++++++++++++ fs/quota/dquot.c | 2 ++ 2 files changed, 19 insertions(+)Signature · 1 line
2.43.5