Message ID | 20240904071004.2067695-1-joseph.qi@linux.alibaba.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v2,1/2] ocfs2: cancel dqi_sync_work before freeing oinfo | expand |
On 9/4/24 15:10, Joseph Qi wrote: > ocfs2_global_read_info() will initialize and schedule dqi_sync_work at > the end, if error occurs after successfully reading global quota, it > will trigger the following warning with CONFIG_DEBUG_OBJECTS_* enabled: > > ODEBUG: free active (active state 0) object: 00000000d8b0ce28 object type: timer_list hint: qsync_work_fn+0x0/0x16c > > This blames there is an active delayed work when freeing oinfo in error > handling, so cancel dqi_sync_work first. BTW, return status instead of > -1 when .read_file_info fails. > > Link: https://syzkaller.appspot.com/bug?extid=f7af59df5d6b25f0febd > Reported-by: syzbot+f7af59df5d6b25f0febd@syzkaller.appspotmail.com > Tested-by: syzbot+f7af59df5d6b25f0febd@syzkaller.appspotmail.com > Fixes: 171bf93ce11f ("ocfs2: Periodic quota syncing") > Cc: stable@vger.kernel.org > Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com> looks good to me. Reviewed-by: Heming Zhao <heming.zhao@suse.com> > --- > fs/ocfs2/quota_local.c | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c > index 8ce462c64c51..73d3367c533b 100644 > --- a/fs/ocfs2/quota_local.c > +++ b/fs/ocfs2/quota_local.c > @@ -692,7 +692,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) > int status; > struct buffer_head *bh = NULL; > struct ocfs2_quota_recovery *rec; > - int locked = 0; > + int locked = 0, global_read = 0; > > info->dqi_max_spc_limit = 0x7fffffffffffffffLL; > info->dqi_max_ino_limit = 0x7fffffffffffffffLL; > @@ -700,6 +700,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) > if (!oinfo) { > mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota" > " info."); > + status = -ENOMEM; > goto out_err; > } > info->dqi_priv = oinfo; > @@ -712,6 +713,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) > status = ocfs2_global_read_info(sb, type); > if (status < 0) > goto out_err; > + global_read = 1; > > status = ocfs2_inode_lock(lqinode, &oinfo->dqi_lqi_bh, 1); > if (status < 0) { > @@ -782,10 +784,12 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) > if (locked) > ocfs2_inode_unlock(lqinode, 1); > ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk); > + if (global_read) > + cancel_delayed_work_sync(&oinfo->dqi_sync_work); > kfree(oinfo); > } > brelse(bh); > - return -1; > + return status; > } > > /* Write local info to quota file */
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 8ce462c64c51..73d3367c533b 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -692,7 +692,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) int status; struct buffer_head *bh = NULL; struct ocfs2_quota_recovery *rec; - int locked = 0; + int locked = 0, global_read = 0; info->dqi_max_spc_limit = 0x7fffffffffffffffLL; info->dqi_max_ino_limit = 0x7fffffffffffffffLL; @@ -700,6 +700,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) if (!oinfo) { mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota" " info."); + status = -ENOMEM; goto out_err; } info->dqi_priv = oinfo; @@ -712,6 +713,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) status = ocfs2_global_read_info(sb, type); if (status < 0) goto out_err; + global_read = 1; status = ocfs2_inode_lock(lqinode, &oinfo->dqi_lqi_bh, 1); if (status < 0) { @@ -782,10 +784,12 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) if (locked) ocfs2_inode_unlock(lqinode, 1); ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk); + if (global_read) + cancel_delayed_work_sync(&oinfo->dqi_sync_work); kfree(oinfo); } brelse(bh); - return -1; + return status; } /* Write local info to quota file */