* [PATCH v4 0/3] btrfs: fix sleep from invalid context bug in update_qgroup_limit_item()
@ 2022-11-15 17:17 ChenXiaoSong
2022-11-15 17:17 ` [PATCH v4 1/3] btrfs: add might_sleep() to some places " ChenXiaoSong
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: ChenXiaoSong @ 2022-11-15 17:17 UTC (permalink / raw)
To: clm, josef, dsterba
Cc: linux-btrfs, linux-kernel, chenxiaosong2, zhangxiaoxu5, yanaijie,
quwenruo.btrfs, wqu
At least 3 places might sleep in update_qgroup_limit_item(), as shown below:
update_qgroup_limit_item
btrfs_alloc_path
/* allocate memory non-atomically, might sleep */
kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS)
btrfs_search_slot
setup_nodes_for_search
reada_for_balance
btrfs_readahead_node_child
btrfs_readahead_tree_block
btrfs_find_create_tree_block
alloc_extent_buffer
kmem_cache_zalloc
/* allocate memory non-atomically, might sleep */
kmem_cache_alloc(GFP_NOFS|__GFP_NOFAIL|__GFP_ZERO)
read_extent_buffer_pages
submit_extent_page
/* disk IO, might sleep */
submit_one_bio
Fix this by delaying the limit item updates until unlock the spin lock.
By the way, add might_sleep() to some places.
ChenXiaoSong (3):
btrfs: add might_sleep() to some places in update_qgroup_limit_item()
btrfs: qgroup: introduce btrfs_update_quoto_limit() helper
btrfs: qgroup: fix sleep from invalid context bug in
update_qgroup_limit_item()
fs/btrfs/ctree.c | 2 ++
fs/btrfs/qgroup.c | 45 ++++++++++++++++++++++++++-------------------
2 files changed, 28 insertions(+), 19 deletions(-)
--
2.31.1
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v4 1/3] btrfs: add might_sleep() to some places in update_qgroup_limit_item() 2022-11-15 17:17 [PATCH v4 0/3] btrfs: fix sleep from invalid context bug in update_qgroup_limit_item() ChenXiaoSong @ 2022-11-15 17:17 ` ChenXiaoSong 2022-11-15 17:41 ` David Sterba 2022-11-15 22:48 ` Qu Wenruo 2022-11-15 17:17 ` [PATCH v4 2/3] btrfs: qgroup: introduce btrfs_update_quoto_limit() helper ChenXiaoSong 2022-11-15 17:17 ` [PATCH v4 3/3] btrfs: qgroup: fix sleep from invalid context bug in update_qgroup_limit_item() ChenXiaoSong 2 siblings, 2 replies; 13+ messages in thread From: ChenXiaoSong @ 2022-11-15 17:17 UTC (permalink / raw) To: clm, josef, dsterba Cc: linux-btrfs, linux-kernel, chenxiaosong2, zhangxiaoxu5, yanaijie, quwenruo.btrfs, wqu As the potential sleeping under spin lock is hard to spot, we should add might_sleep() to some places. Signed-off-by: ChenXiaoSong <chenxiaosong2@huawei.com> --- fs/btrfs/ctree.c | 2 ++ fs/btrfs/qgroup.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index a9543f01184c..809053e9cfde 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1934,6 +1934,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, int min_write_lock_level; int prev_cmp; + might_sleep(); + lowest_level = p->lowest_level; WARN_ON(lowest_level && ins_len > 0); WARN_ON(p->nodes[0] != NULL); diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 9334c3157c22..d0480b9c6c86 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -779,6 +779,8 @@ static int update_qgroup_limit_item(struct btrfs_trans_handle *trans, int ret; int slot; + might_sleep(); + key.objectid = 0; key.type = BTRFS_QGROUP_LIMIT_KEY; key.offset = qgroup->qgroupid; -- 2.31.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/3] btrfs: add might_sleep() to some places in update_qgroup_limit_item() 2022-11-15 17:17 ` [PATCH v4 1/3] btrfs: add might_sleep() to some places " ChenXiaoSong @ 2022-11-15 17:41 ` David Sterba 2022-11-15 22:48 ` Qu Wenruo 1 sibling, 0 replies; 13+ messages in thread From: David Sterba @ 2022-11-15 17:41 UTC (permalink / raw) To: ChenXiaoSong Cc: clm, josef, dsterba, linux-btrfs, linux-kernel, zhangxiaoxu5, yanaijie, quwenruo.btrfs, wqu On Wed, Nov 16, 2022 at 01:17:07AM +0800, ChenXiaoSong wrote: > As the potential sleeping under spin lock is hard to spot, we should add > might_sleep() to some places. > > Signed-off-by: ChenXiaoSong <chenxiaosong2@huawei.com> > --- > fs/btrfs/ctree.c | 2 ++ > fs/btrfs/qgroup.c | 2 ++ > 2 files changed, 4 insertions(+) > > diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c > index a9543f01184c..809053e9cfde 100644 > --- a/fs/btrfs/ctree.c > +++ b/fs/btrfs/ctree.c > @@ -1934,6 +1934,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, > int min_write_lock_level; > int prev_cmp; > > + might_sleep(); This needs some explanation in the changelog, the reason was mentioned in some past patch iteration that it's due to potential IO fi the blocks are not cached. > + > lowest_level = p->lowest_level; > WARN_ON(lowest_level && ins_len > 0); > WARN_ON(p->nodes[0] != NULL); > diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c > index 9334c3157c22..d0480b9c6c86 100644 > --- a/fs/btrfs/qgroup.c > +++ b/fs/btrfs/qgroup.c > @@ -779,6 +779,8 @@ static int update_qgroup_limit_item(struct btrfs_trans_handle *trans, > int ret; > int slot; > > + might_sleep(); This one is redundant, no? There's call to btrfs_search_slot a few lines below. > + > key.objectid = 0; > key.type = BTRFS_QGROUP_LIMIT_KEY; > key.offset = qgroup->qgroupid; > -- > 2.31.1 > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/3] btrfs: add might_sleep() to some places in update_qgroup_limit_item() 2022-11-15 17:17 ` [PATCH v4 1/3] btrfs: add might_sleep() to some places " ChenXiaoSong 2022-11-15 17:41 ` David Sterba @ 2022-11-15 22:48 ` Qu Wenruo 2022-11-16 8:09 ` ChenXiaoSong 1 sibling, 1 reply; 13+ messages in thread From: Qu Wenruo @ 2022-11-15 22:48 UTC (permalink / raw) To: ChenXiaoSong, clm, josef, dsterba Cc: linux-btrfs, linux-kernel, zhangxiaoxu5, yanaijie, wqu On 2022/11/16 01:17, ChenXiaoSong wrote: > As the potential sleeping under spin lock is hard to spot, we should add > might_sleep() to some places. > > Signed-off-by: ChenXiaoSong <chenxiaosong2@huawei.com> Looks good. We may want to add more in other locations, but this is really a good start. Reviewed-by: Qu Wenruo <wqu@suse.com> Thanks, Qu > --- > fs/btrfs/ctree.c | 2 ++ > fs/btrfs/qgroup.c | 2 ++ > 2 files changed, 4 insertions(+) > > diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c > index a9543f01184c..809053e9cfde 100644 > --- a/fs/btrfs/ctree.c > +++ b/fs/btrfs/ctree.c > @@ -1934,6 +1934,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, > int min_write_lock_level; > int prev_cmp; > > + might_sleep(); > + > lowest_level = p->lowest_level; > WARN_ON(lowest_level && ins_len > 0); > WARN_ON(p->nodes[0] != NULL); > diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c > index 9334c3157c22..d0480b9c6c86 100644 > --- a/fs/btrfs/qgroup.c > +++ b/fs/btrfs/qgroup.c > @@ -779,6 +779,8 @@ static int update_qgroup_limit_item(struct btrfs_trans_handle *trans, > int ret; > int slot; > > + might_sleep(); > + > key.objectid = 0; > key.type = BTRFS_QGROUP_LIMIT_KEY; > key.offset = qgroup->qgroupid; ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/3] btrfs: add might_sleep() to some places in update_qgroup_limit_item() 2022-11-15 22:48 ` Qu Wenruo @ 2022-11-16 8:09 ` ChenXiaoSong 2022-11-16 8:43 ` Qu Wenruo 0 siblings, 1 reply; 13+ messages in thread From: ChenXiaoSong @ 2022-11-16 8:09 UTC (permalink / raw) To: Qu Wenruo, clm, josef, dsterba Cc: linux-btrfs, linux-kernel, zhangxiaoxu5, yanaijie, wqu 在 2022/11/16 6:48, Qu Wenruo 写道: > Looks good. > > We may want to add more in other locations, but this is really a good > start. > > Reviewed-by: Qu Wenruo <wqu@suse.com> > > Thanks, > Qu If I just add might_sleep() in btrfs_alloc_path() and btrfs_search_slot(), is it reasonable? Or just add might_sleep() to one place in update_qgroup_limit_item() ? ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/3] btrfs: add might_sleep() to some places in update_qgroup_limit_item() 2022-11-16 8:09 ` ChenXiaoSong @ 2022-11-16 8:43 ` Qu Wenruo 2022-11-16 12:24 ` David Sterba 0 siblings, 1 reply; 13+ messages in thread From: Qu Wenruo @ 2022-11-16 8:43 UTC (permalink / raw) To: ChenXiaoSong, clm, josef, dsterba Cc: linux-btrfs, linux-kernel, zhangxiaoxu5, yanaijie, wqu On 2022/11/16 16:09, ChenXiaoSong wrote: > 在 2022/11/16 6:48, Qu Wenruo 写道: >> Looks good. >> >> We may want to add more in other locations, but this is really a good >> start. >> >> Reviewed-by: Qu Wenruo <wqu@suse.com> >> >> Thanks, >> Qu > > If I just add might_sleep() in btrfs_alloc_path() and > btrfs_search_slot(), is it reasonable? Adding it to btrfs_search_slot() is definitely correct. But why for btrfs_alloc_path()? Wouldn't kmem_cache_zalloc() itself already do the might_sleep_if() somewhere? I just looked the call chain, and indeed it is doing the check already: btrfs_alloc_path() |- kmem_cache_zalloc() |- kmem_cache_alloc() |- __kmem_cache_alloc_lru() |- slab_alloc() |- slab_alloc_node() |- slab_pre_alloc_hook() |- might_alloc() |- might_sleep_if() Thanks, Qu > > Or just add might_sleep() to one place in update_qgroup_limit_item() ? ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/3] btrfs: add might_sleep() to some places in update_qgroup_limit_item() 2022-11-16 8:43 ` Qu Wenruo @ 2022-11-16 12:24 ` David Sterba 2022-11-16 12:26 ` Qu Wenruo 0 siblings, 1 reply; 13+ messages in thread From: David Sterba @ 2022-11-16 12:24 UTC (permalink / raw) To: Qu Wenruo Cc: ChenXiaoSong, clm, josef, dsterba, linux-btrfs, linux-kernel, zhangxiaoxu5, yanaijie, wqu On Wed, Nov 16, 2022 at 04:43:50PM +0800, Qu Wenruo wrote: > > > On 2022/11/16 16:09, ChenXiaoSong wrote: > > 在 2022/11/16 6:48, Qu Wenruo 写道: > >> Looks good. > >> > >> We may want to add more in other locations, but this is really a good > >> start. > >> > >> Reviewed-by: Qu Wenruo <wqu@suse.com> > >> > >> Thanks, > >> Qu > > > > If I just add might_sleep() in btrfs_alloc_path() and > > btrfs_search_slot(), is it reasonable? > > Adding it to btrfs_search_slot() is definitely correct. > > But why for btrfs_alloc_path()? Wouldn't kmem_cache_zalloc() itself > already do the might_sleep_if() somewhere? > > I just looked the call chain, and indeed it is doing the check already: > > btrfs_alloc_path() > |- kmem_cache_zalloc() > |- kmem_cache_alloc() > |- __kmem_cache_alloc_lru() > |- slab_alloc() > |- slab_alloc_node() > |- slab_pre_alloc_hook() > |- might_alloc() > |- might_sleep_if() The call chaing is unconditional so the check will always happen but the condition itself in might_sleep_if does not recognize GFP_NOFS: 34 static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags) 35 { 36 return !!(gfp_flags & __GFP_DIRECT_RECLAIM); 37 } #define GFP_NOFS (__GFP_RECLAIM | __GFP_IO) And I think the qgroup limit was exactly a spin lock over btrfs_path_alloc so it did not help. An might_sleep() inside btrfs_path_alloc() is a very minimal but reliable check we could add, the paths are used in many places so it would increase the coverage. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/3] btrfs: add might_sleep() to some places in update_qgroup_limit_item() 2022-11-16 12:24 ` David Sterba @ 2022-11-16 12:26 ` Qu Wenruo 0 siblings, 0 replies; 13+ messages in thread From: Qu Wenruo @ 2022-11-16 12:26 UTC (permalink / raw) To: dsterba Cc: ChenXiaoSong, clm, josef, dsterba, linux-btrfs, linux-kernel, zhangxiaoxu5, yanaijie, wqu On 2022/11/16 20:24, David Sterba wrote: > On Wed, Nov 16, 2022 at 04:43:50PM +0800, Qu Wenruo wrote: >> >> >> On 2022/11/16 16:09, ChenXiaoSong wrote: >>> 在 2022/11/16 6:48, Qu Wenruo 写道: >>>> Looks good. >>>> >>>> We may want to add more in other locations, but this is really a good >>>> start. >>>> >>>> Reviewed-by: Qu Wenruo <wqu@suse.com> >>>> >>>> Thanks, >>>> Qu >>> >>> If I just add might_sleep() in btrfs_alloc_path() and >>> btrfs_search_slot(), is it reasonable? >> >> Adding it to btrfs_search_slot() is definitely correct. >> >> But why for btrfs_alloc_path()? Wouldn't kmem_cache_zalloc() itself >> already do the might_sleep_if() somewhere? >> >> I just looked the call chain, and indeed it is doing the check already: >> >> btrfs_alloc_path() >> |- kmem_cache_zalloc() >> |- kmem_cache_alloc() >> |- __kmem_cache_alloc_lru() >> |- slab_alloc() >> |- slab_alloc_node() >> |- slab_pre_alloc_hook() >> |- might_alloc() >> |- might_sleep_if() > > The call chaing is unconditional so the check will always happen but the > condition itself in might_sleep_if does not recognize GFP_NOFS: > > 34 static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags) > 35 { > 36 return !!(gfp_flags & __GFP_DIRECT_RECLAIM); > 37 } > > #define GFP_NOFS (__GFP_RECLAIM | __GFP_IO) > > And I think the qgroup limit was exactly a spin lock over btrfs_path_alloc so > it did not help. An might_sleep() inside btrfs_path_alloc() is a very minimal > but reliable check we could add, the paths are used in many places so it would > increase the coverage. OK, then it makes sense now for btrfs_alloc_path(). But I still believe this looks like a bug in gfpflags_allow_blocking()... Thanks, Qu ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 2/3] btrfs: qgroup: introduce btrfs_update_quoto_limit() helper 2022-11-15 17:17 [PATCH v4 0/3] btrfs: fix sleep from invalid context bug in update_qgroup_limit_item() ChenXiaoSong 2022-11-15 17:17 ` [PATCH v4 1/3] btrfs: add might_sleep() to some places " ChenXiaoSong @ 2022-11-15 17:17 ` ChenXiaoSong 2022-11-15 17:33 ` David Sterba 2022-11-15 17:17 ` [PATCH v4 3/3] btrfs: qgroup: fix sleep from invalid context bug in update_qgroup_limit_item() ChenXiaoSong 2 siblings, 1 reply; 13+ messages in thread From: ChenXiaoSong @ 2022-11-15 17:17 UTC (permalink / raw) To: clm, josef, dsterba Cc: linux-btrfs, linux-kernel, chenxiaosong2, zhangxiaoxu5, yanaijie, quwenruo.btrfs, wqu No functional changed. Just simplify the code. Signed-off-by: ChenXiaoSong <chenxiaosong2@huawei.com> --- fs/btrfs/qgroup.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index d0480b9c6c86..ca609a70d067 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1677,6 +1677,19 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid) return ret; } +static int btrfs_update_quoto_limit(struct btrfs_trans_handle *trans, + struct btrfs_qgroup *qgroup, + struct btrfs_fs_info *fs_info) +{ + int ret = update_qgroup_limit_item(trans, qgroup); + if (ret) { + qgroup_mark_inconsistent(fs_info); + btrfs_info(fs_info, "unable to update quota limit for %llu", + qgroup->qgroupid); + } + return ret; +} + int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid, struct btrfs_qgroup_limit *limit) { @@ -1742,13 +1755,7 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid, spin_unlock(&fs_info->qgroup_lock); - ret = update_qgroup_limit_item(trans, qgroup); - if (ret) { - qgroup_mark_inconsistent(fs_info); - btrfs_info(fs_info, "unable to update quota limit for %llu", - qgroupid); - } - + ret = btrfs_update_quoto_limit(trans, qgroup, fs_info); out: mutex_unlock(&fs_info->qgroup_ioctl_lock); return ret; @@ -2824,9 +2831,7 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans) ret = update_qgroup_info_item(trans, qgroup); if (ret) qgroup_mark_inconsistent(fs_info); - ret = update_qgroup_limit_item(trans, qgroup); - if (ret) - qgroup_mark_inconsistent(fs_info); + ret = btrfs_update_quoto_limit(trans, qgroup, fs_info); spin_lock(&fs_info->qgroup_lock); } if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) @@ -2953,14 +2958,9 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, dstgroup->rsv_rfer = inherit->lim.rsv_rfer; dstgroup->rsv_excl = inherit->lim.rsv_excl; - ret = update_qgroup_limit_item(trans, dstgroup); - if (ret) { - qgroup_mark_inconsistent(fs_info); - btrfs_info(fs_info, - "unable to update quota limit for %llu", - dstgroup->qgroupid); + ret = btrfs_update_quoto_limit(trans, dstgroup, fs_info); + if (ret) goto unlock; - } } if (srcid) { -- 2.31.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/3] btrfs: qgroup: introduce btrfs_update_quoto_limit() helper 2022-11-15 17:17 ` [PATCH v4 2/3] btrfs: qgroup: introduce btrfs_update_quoto_limit() helper ChenXiaoSong @ 2022-11-15 17:33 ` David Sterba 0 siblings, 0 replies; 13+ messages in thread From: David Sterba @ 2022-11-15 17:33 UTC (permalink / raw) To: ChenXiaoSong Cc: clm, josef, dsterba, linux-btrfs, linux-kernel, zhangxiaoxu5, yanaijie, quwenruo.btrfs, wqu On Wed, Nov 16, 2022 at 01:17:08AM +0800, ChenXiaoSong wrote: > No functional changed. Just simplify the code. Please write some description of the change, like "factor out quota limit update that also marks qgroup as inconsistent if it fals". > Signed-off-by: ChenXiaoSong <chenxiaosong2@huawei.com> > --- > fs/btrfs/qgroup.c | 34 +++++++++++++++++----------------- > 1 file changed, 17 insertions(+), 17 deletions(-) > > diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c > index d0480b9c6c86..ca609a70d067 100644 > --- a/fs/btrfs/qgroup.c > +++ b/fs/btrfs/qgroup.c > @@ -1677,6 +1677,19 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid) > return ret; > } > > +static int btrfs_update_quoto_limit(struct btrfs_trans_handle *trans, Typo 'quoto' and it should rather be qgroup as the limit is related to a qgroup, quota is usually in connection with the whole subsystem. > + struct btrfs_qgroup *qgroup, > + struct btrfs_fs_info *fs_info) > +{ > + int ret = update_qgroup_limit_item(trans, qgroup); > + if (ret) { > + qgroup_mark_inconsistent(fs_info); > + btrfs_info(fs_info, "unable to update quota limit for %llu", > + qgroup->qgroupid); > + } > + return ret; > +} > + > int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid, > struct btrfs_qgroup_limit *limit) > { > @@ -1742,13 +1755,7 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid, > > spin_unlock(&fs_info->qgroup_lock); > > - ret = update_qgroup_limit_item(trans, qgroup); > - if (ret) { > - qgroup_mark_inconsistent(fs_info); > - btrfs_info(fs_info, "unable to update quota limit for %llu", > - qgroupid); > - } > - > + ret = btrfs_update_quoto_limit(trans, qgroup, fs_info); > out: > mutex_unlock(&fs_info->qgroup_ioctl_lock); > return ret; > @@ -2824,9 +2831,7 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans) > ret = update_qgroup_info_item(trans, qgroup); > if (ret) > qgroup_mark_inconsistent(fs_info); > - ret = update_qgroup_limit_item(trans, qgroup); > - if (ret) > - qgroup_mark_inconsistent(fs_info); > + ret = btrfs_update_quoto_limit(trans, qgroup, fs_info); > spin_lock(&fs_info->qgroup_lock); > } > if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) > @@ -2953,14 +2958,9 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, > dstgroup->rsv_rfer = inherit->lim.rsv_rfer; > dstgroup->rsv_excl = inherit->lim.rsv_excl; > > - ret = update_qgroup_limit_item(trans, dstgroup); > - if (ret) { > - qgroup_mark_inconsistent(fs_info); > - btrfs_info(fs_info, > - "unable to update quota limit for %llu", > - dstgroup->qgroupid); > + ret = btrfs_update_quoto_limit(trans, dstgroup, fs_info); > + if (ret) > goto unlock; > - } > } > > if (srcid) { > -- > 2.31.1 > ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 3/3] btrfs: qgroup: fix sleep from invalid context bug in update_qgroup_limit_item() 2022-11-15 17:17 [PATCH v4 0/3] btrfs: fix sleep from invalid context bug in update_qgroup_limit_item() ChenXiaoSong 2022-11-15 17:17 ` [PATCH v4 1/3] btrfs: add might_sleep() to some places " ChenXiaoSong 2022-11-15 17:17 ` [PATCH v4 2/3] btrfs: qgroup: introduce btrfs_update_quoto_limit() helper ChenXiaoSong @ 2022-11-15 17:17 ` ChenXiaoSong 2022-11-15 16:22 ` ChenXiaoSong 2022-11-15 22:50 ` Qu Wenruo 2 siblings, 2 replies; 13+ messages in thread From: ChenXiaoSong @ 2022-11-15 17:17 UTC (permalink / raw) To: clm, josef, dsterba Cc: linux-btrfs, linux-kernel, chenxiaosong2, zhangxiaoxu5, yanaijie, quwenruo.btrfs, wqu Syzkaller reported BUG as follows: BUG: sleeping function called from invalid context at include/linux/sched/mm.h:274 Call Trace: <TASK> dump_stack_lvl+0xcd/0x134 __might_resched.cold+0x222/0x26b kmem_cache_alloc+0x2e7/0x3c0 update_qgroup_limit_item+0xe1/0x390 btrfs_qgroup_inherit+0x147b/0x1ee0 create_subvol+0x4eb/0x1710 btrfs_mksubvol+0xfe5/0x13f0 __btrfs_ioctl_snap_create+0x2b0/0x430 btrfs_ioctl_snap_create_v2+0x25a/0x520 btrfs_ioctl+0x2a1c/0x5ce0 __x64_sys_ioctl+0x193/0x200 do_syscall_64+0x35/0x80 Fix this by delaying the limit item updates until unlock the spin lock. Signed-off-by: ChenXiaoSong <chenxiaosong2@huawei.com> --- fs/btrfs/qgroup.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index ca609a70d067..f84507ca3b99 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -2867,6 +2867,8 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, bool need_rescan = false; u32 level_size = 0; u64 nums; + bool update_limit = false; + int err; /* * There are only two callers of this function. @@ -2957,10 +2959,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, dstgroup->max_excl = inherit->lim.max_excl; dstgroup->rsv_rfer = inherit->lim.rsv_rfer; dstgroup->rsv_excl = inherit->lim.rsv_excl; - - ret = btrfs_update_quoto_limit(trans, dstgroup, fs_info); - if (ret) - goto unlock; + update_limit = true; } if (srcid) { @@ -2987,6 +2986,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, dstgroup->max_excl = srcgroup->max_excl; dstgroup->rsv_rfer = srcgroup->rsv_rfer; dstgroup->rsv_excl = srcgroup->rsv_excl; + update_limit = false; qgroup_dirty(fs_info, dstgroup); qgroup_dirty(fs_info, srcgroup); @@ -3055,6 +3055,11 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, unlock: spin_unlock(&fs_info->qgroup_lock); + if (update_limit) { + err = btrfs_update_quoto_limit(trans, dstgroup, fs_info); + if (err) + ret = err; + } if (!ret) ret = btrfs_sysfs_add_one_qgroup(fs_info, dstgroup); out: -- 2.31.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v4 3/3] btrfs: qgroup: fix sleep from invalid context bug in update_qgroup_limit_item() 2022-11-15 17:17 ` [PATCH v4 3/3] btrfs: qgroup: fix sleep from invalid context bug in update_qgroup_limit_item() ChenXiaoSong @ 2022-11-15 16:22 ` ChenXiaoSong 2022-11-15 22:50 ` Qu Wenruo 1 sibling, 0 replies; 13+ messages in thread From: ChenXiaoSong @ 2022-11-15 16:22 UTC (permalink / raw) To: clm, josef, dsterba Cc: linux-btrfs, linux-kernel, zhangxiaoxu5, yanaijie, quwenruo.btrfs, wqu 在 2022/11/16 1:17, ChenXiaoSong 写道: > @@ -2987,6 +2986,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, > dstgroup->max_excl = srcgroup->max_excl; > dstgroup->rsv_rfer = srcgroup->rsv_rfer; > dstgroup->rsv_excl = srcgroup->rsv_excl; > + update_limit = false; > > qgroup_dirty(fs_info, dstgroup); > qgroup_dirty(fs_info, srcgroup); No need to call update_qgroup_limit_item() when condition "if (srcid)" is true according to Qu Wenruo's suggestions, btrfs_run_qgroups() will update the quota tree to reflect the result after calling qgroup_dirty(). ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 3/3] btrfs: qgroup: fix sleep from invalid context bug in update_qgroup_limit_item() 2022-11-15 17:17 ` [PATCH v4 3/3] btrfs: qgroup: fix sleep from invalid context bug in update_qgroup_limit_item() ChenXiaoSong 2022-11-15 16:22 ` ChenXiaoSong @ 2022-11-15 22:50 ` Qu Wenruo 1 sibling, 0 replies; 13+ messages in thread From: Qu Wenruo @ 2022-11-15 22:50 UTC (permalink / raw) To: ChenXiaoSong, clm, josef, dsterba Cc: linux-btrfs, linux-kernel, zhangxiaoxu5, yanaijie, wqu On 2022/11/16 01:17, ChenXiaoSong wrote: > Syzkaller reported BUG as follows: > > BUG: sleeping function called from invalid context at > include/linux/sched/mm.h:274 > Call Trace: > <TASK> > dump_stack_lvl+0xcd/0x134 > __might_resched.cold+0x222/0x26b > kmem_cache_alloc+0x2e7/0x3c0 > update_qgroup_limit_item+0xe1/0x390 > btrfs_qgroup_inherit+0x147b/0x1ee0 > create_subvol+0x4eb/0x1710 > btrfs_mksubvol+0xfe5/0x13f0 > __btrfs_ioctl_snap_create+0x2b0/0x430 > btrfs_ioctl_snap_create_v2+0x25a/0x520 > btrfs_ioctl+0x2a1c/0x5ce0 > __x64_sys_ioctl+0x193/0x200 > do_syscall_64+0x35/0x80 > > Fix this by delaying the limit item updates until unlock the spin lock. > > Signed-off-by: ChenXiaoSong <chenxiaosong2@huawei.com> > --- > fs/btrfs/qgroup.c | 13 +++++++++---- > 1 file changed, 9 insertions(+), 4 deletions(-) > > diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c > index ca609a70d067..f84507ca3b99 100644 > --- a/fs/btrfs/qgroup.c > +++ b/fs/btrfs/qgroup.c > @@ -2867,6 +2867,8 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, > bool need_rescan = false; > u32 level_size = 0; > u64 nums; > + bool update_limit = false; > + int err; > > /* > * There are only two callers of this function. > @@ -2957,10 +2959,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, > dstgroup->max_excl = inherit->lim.max_excl; > dstgroup->rsv_rfer = inherit->lim.rsv_rfer; > dstgroup->rsv_excl = inherit->lim.rsv_excl; > - > - ret = btrfs_update_quoto_limit(trans, dstgroup, fs_info); > - if (ret) > - goto unlock; > + update_limit = true; Nope, just call qgroup_dirty() for @dstgroup. Thanks, Qu > } > > if (srcid) { > @@ -2987,6 +2986,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, > dstgroup->max_excl = srcgroup->max_excl; > dstgroup->rsv_rfer = srcgroup->rsv_rfer; > dstgroup->rsv_excl = srcgroup->rsv_excl; > + update_limit = false; > > qgroup_dirty(fs_info, dstgroup); > qgroup_dirty(fs_info, srcgroup); > @@ -3055,6 +3055,11 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid, > > unlock: > spin_unlock(&fs_info->qgroup_lock); > + if (update_limit) { > + err = btrfs_update_quoto_limit(trans, dstgroup, fs_info); > + if (err) > + ret = err; > + } > if (!ret) > ret = btrfs_sysfs_add_one_qgroup(fs_info, dstgroup); > out: ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2022-11-16 12:29 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-11-15 17:17 [PATCH v4 0/3] btrfs: fix sleep from invalid context bug in update_qgroup_limit_item() ChenXiaoSong 2022-11-15 17:17 ` [PATCH v4 1/3] btrfs: add might_sleep() to some places " ChenXiaoSong 2022-11-15 17:41 ` David Sterba 2022-11-15 22:48 ` Qu Wenruo 2022-11-16 8:09 ` ChenXiaoSong 2022-11-16 8:43 ` Qu Wenruo 2022-11-16 12:24 ` David Sterba 2022-11-16 12:26 ` Qu Wenruo 2022-11-15 17:17 ` [PATCH v4 2/3] btrfs: qgroup: introduce btrfs_update_quoto_limit() helper ChenXiaoSong 2022-11-15 17:33 ` David Sterba 2022-11-15 17:17 ` [PATCH v4 3/3] btrfs: qgroup: fix sleep from invalid context bug in update_qgroup_limit_item() ChenXiaoSong 2022-11-15 16:22 ` ChenXiaoSong 2022-11-15 22:50 ` Qu Wenruo
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox