* [PATCH 0/2] ext4: Do not let fstrim block suspend
@ 2023-09-13 15:04 Jan Kara
2023-09-13 15:04 ` [PATCH 1/2] ext4: Move setting of trimmed bit into ext4_try_to_trim_range() Jan Kara
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Jan Kara @ 2023-09-13 15:04 UTC (permalink / raw)
To: Ted Tso; +Cc: linux-ext4, todd.e.brandt, lenb, Jan Kara
Hello,
these two patches fix a long standing issue that long running fstrim request
can block a system suspend as reported by Len Brown in [1]. The solution is
quite simple - just report whatever we have trimmed upto now since discard
is an advisory call anyway. What makes things a bit more complex is handling
of group's TRIMMED bit - we deal with that in patch 1.
Honza
[1] https://bugzilla.kernel.org/show_bug.cgi?id=216322
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] ext4: Move setting of trimmed bit into ext4_try_to_trim_range()
2023-09-13 15:04 [PATCH 0/2] ext4: Do not let fstrim block suspend Jan Kara
@ 2023-09-13 15:04 ` Jan Kara
2023-09-13 15:04 ` [PATCH 2/2] ext4: Do not let fstrim block system suspend Jan Kara
2023-09-14 15:00 ` [PATCH 0/2] ext4: Do not let fstrim block suspend Theodore Ts'o
2 siblings, 0 replies; 4+ messages in thread
From: Jan Kara @ 2023-09-13 15:04 UTC (permalink / raw)
To: Ted Tso; +Cc: linux-ext4, todd.e.brandt, lenb, Jan Kara
Currently we set the group's trimmed bit in ext4_trim_all_free() based
on return value of ext4_try_to_trim_range(). However when we will want
to abort trimming because of suspend attempt, we want to return success
from ext4_try_to_trim_range() but not set the trimmed bit. Instead
implementing awkward propagation of this information, just move setting
of trimmed bit into ext4_try_to_trim_range() when the whole group is
trimmed.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/ext4/mballoc.c | 46 +++++++++++++++++++++++++---------------------
1 file changed, 25 insertions(+), 21 deletions(-)
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index c91db9f57524..09091adfde64 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -6906,6 +6906,16 @@ __acquires(bitlock)
return ret;
}
+static ext4_grpblk_t ext4_last_grp_cluster(struct super_block *sb,
+ ext4_group_t grp)
+{
+ if (grp < ext4_get_groups_count(sb))
+ return EXT4_CLUSTERS_PER_GROUP(sb) - 1;
+ return (ext4_blocks_count(EXT4_SB(sb)->s_es) -
+ ext4_group_first_block_no(sb, grp) - 1) >>
+ EXT4_CLUSTER_BITS(sb);
+}
+
static int ext4_try_to_trim_range(struct super_block *sb,
struct ext4_buddy *e4b, ext4_grpblk_t start,
ext4_grpblk_t max, ext4_grpblk_t minblocks)
@@ -6913,9 +6923,12 @@ __acquires(ext4_group_lock_ptr(sb, e4b->bd_group))
__releases(ext4_group_lock_ptr(sb, e4b->bd_group))
{
ext4_grpblk_t next, count, free_count;
+ bool set_trimmed = false;
void *bitmap;
bitmap = e4b->bd_bitmap;
+ if (start == 0 && max >= ext4_last_grp_cluster(sb, e4b->bd_group))
+ set_trimmed = true;
start = max(e4b->bd_info->bb_first_free, start);
count = 0;
free_count = 0;
@@ -6930,16 +6943,14 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
int ret = ext4_trim_extent(sb, start, next - start, e4b);
if (ret && ret != -EOPNOTSUPP)
- break;
+ return count;
count += next - start;
}
free_count += next - start;
start = next + 1;
- if (fatal_signal_pending(current)) {
- count = -ERESTARTSYS;
- break;
- }
+ if (fatal_signal_pending(current))
+ return -ERESTARTSYS;
if (need_resched()) {
ext4_unlock_group(sb, e4b->bd_group);
@@ -6951,6 +6962,9 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
break;
}
+ if (set_trimmed)
+ EXT4_MB_GRP_SET_TRIMMED(e4b->bd_info);
+
return count;
}
@@ -6961,7 +6975,6 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
* @start: first group block to examine
* @max: last group block to examine
* @minblocks: minimum extent block count
- * @set_trimmed: set the trimmed flag if at least one block is trimmed
*
* ext4_trim_all_free walks through group's block bitmap searching for free
* extents. When the free extent is found, mark it as used in group buddy
@@ -6971,7 +6984,7 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
static ext4_grpblk_t
ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
ext4_grpblk_t start, ext4_grpblk_t max,
- ext4_grpblk_t minblocks, bool set_trimmed)
+ ext4_grpblk_t minblocks)
{
struct ext4_buddy e4b;
int ret;
@@ -6988,13 +7001,10 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
ext4_lock_group(sb, group);
if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) ||
- minblocks < EXT4_SB(sb)->s_last_trim_minblks) {
+ minblocks < EXT4_SB(sb)->s_last_trim_minblks)
ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks);
- if (ret >= 0 && set_trimmed)
- EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
- } else {
+ else
ret = 0;
- }
ext4_unlock_group(sb, group);
ext4_mb_unload_buddy(&e4b);
@@ -7027,7 +7037,6 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
ext4_fsblk_t first_data_blk =
le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
ext4_fsblk_t max_blks = ext4_blocks_count(EXT4_SB(sb)->s_es);
- bool whole_group, eof = false;
int ret = 0;
start = range->start >> sb->s_blocksize_bits;
@@ -7046,10 +7055,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
if (minlen > EXT4_CLUSTERS_PER_GROUP(sb))
goto out;
}
- if (end >= max_blks - 1) {
+ if (end >= max_blks - 1)
end = max_blks - 1;
- eof = true;
- }
if (end <= first_data_blk)
goto out;
if (start < first_data_blk)
@@ -7063,7 +7070,6 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
/* end now represents the last cluster to discard in this group */
end = EXT4_CLUSTERS_PER_GROUP(sb) - 1;
- whole_group = true;
for (group = first_group; group <= last_group; group++) {
grp = ext4_get_group_info(sb, group);
@@ -7082,13 +7088,11 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
* change it for the last group, note that last_cluster is
* already computed earlier by ext4_get_group_no_and_offset()
*/
- if (group == last_group) {
+ if (group == last_group)
end = last_cluster;
- whole_group = eof ? true : end == EXT4_CLUSTERS_PER_GROUP(sb) - 1;
- }
if (grp->bb_free >= minlen) {
cnt = ext4_trim_all_free(sb, group, first_cluster,
- end, minlen, whole_group);
+ end, minlen);
if (cnt < 0) {
ret = cnt;
break;
--
2.35.3
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] ext4: Do not let fstrim block system suspend
2023-09-13 15:04 [PATCH 0/2] ext4: Do not let fstrim block suspend Jan Kara
2023-09-13 15:04 ` [PATCH 1/2] ext4: Move setting of trimmed bit into ext4_try_to_trim_range() Jan Kara
@ 2023-09-13 15:04 ` Jan Kara
2023-09-14 15:00 ` [PATCH 0/2] ext4: Do not let fstrim block suspend Theodore Ts'o
2 siblings, 0 replies; 4+ messages in thread
From: Jan Kara @ 2023-09-13 15:04 UTC (permalink / raw)
To: Ted Tso; +Cc: linux-ext4, todd.e.brandt, lenb, Jan Kara, Dave Chinner
Len Brown has reported that system suspend sometimes fail due to
inability to freeze a task working in ext4_trim_fs() for one minute.
Trimming a large filesystem on a disk that slowly processes discard
requests can indeed take a long time. Since discard is just an advisory
call, it is perfectly fine to interrupt it at any time and the return
number of discarded blocks until that moment. Do that when we detect the
task is being frozen.
Reported-by: Len Brown <lenb@kernel.org>
Suggested-by: Dave Chinner <david@fromorbit.com>
References: https://bugzilla.kernel.org/show_bug.cgi?id=216322
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/ext4/mballoc.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 09091adfde64..1e599305d85f 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/nospec.h>
#include <linux/backing-dev.h>
+#include <linux/freezer.h>
#include <trace/events/ext4.h>
/*
@@ -6916,6 +6917,11 @@ static ext4_grpblk_t ext4_last_grp_cluster(struct super_block *sb,
EXT4_CLUSTER_BITS(sb);
}
+static bool ext4_trim_interrupted(void)
+{
+ return fatal_signal_pending(current) || freezing(current);
+}
+
static int ext4_try_to_trim_range(struct super_block *sb,
struct ext4_buddy *e4b, ext4_grpblk_t start,
ext4_grpblk_t max, ext4_grpblk_t minblocks)
@@ -6949,8 +6955,8 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
free_count += next - start;
start = next + 1;
- if (fatal_signal_pending(current))
- return -ERESTARTSYS;
+ if (ext4_trim_interrupted())
+ return count;
if (need_resched()) {
ext4_unlock_group(sb, e4b->bd_group);
@@ -7072,6 +7078,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
end = EXT4_CLUSTERS_PER_GROUP(sb) - 1;
for (group = first_group; group <= last_group; group++) {
+ if (ext4_trim_interrupted())
+ break;
grp = ext4_get_group_info(sb, group);
if (!grp)
continue;
--
2.35.3
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 0/2] ext4: Do not let fstrim block suspend
2023-09-13 15:04 [PATCH 0/2] ext4: Do not let fstrim block suspend Jan Kara
2023-09-13 15:04 ` [PATCH 1/2] ext4: Move setting of trimmed bit into ext4_try_to_trim_range() Jan Kara
2023-09-13 15:04 ` [PATCH 2/2] ext4: Do not let fstrim block system suspend Jan Kara
@ 2023-09-14 15:00 ` Theodore Ts'o
2 siblings, 0 replies; 4+ messages in thread
From: Theodore Ts'o @ 2023-09-14 15:00 UTC (permalink / raw)
To: Jan Kara; +Cc: Theodore Ts'o, linux-ext4, todd.e.brandt, lenb
On Wed, 13 Sep 2023 17:04:53 +0200, Jan Kara wrote:
> these two patches fix a long standing issue that long running fstrim request
> can block a system suspend as reported by Len Brown in [1]. The solution is
> quite simple - just report whatever we have trimmed upto now since discard
> is an advisory call anyway. What makes things a bit more complex is handling
> of group's TRIMMED bit - we deal with that in patch 1.
>
> Honza
>
> [...]
Applied, thanks!
[1/2] ext4: Move setting of trimmed bit into ext4_try_to_trim_range()
commit: 5e4a9f11b5d7cb70a4e4474f0ba25d5f1fd2a8ed
[2/2] ext4: Do not let fstrim block system suspend
commit: b016ebb300e514bc46151f8fc006caae141a8bde
Best regards,
--
Theodore Ts'o <tytso@mit.edu>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-09-14 15:01 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-13 15:04 [PATCH 0/2] ext4: Do not let fstrim block suspend Jan Kara
2023-09-13 15:04 ` [PATCH 1/2] ext4: Move setting of trimmed bit into ext4_try_to_trim_range() Jan Kara
2023-09-13 15:04 ` [PATCH 2/2] ext4: Do not let fstrim block system suspend Jan Kara
2023-09-14 15:00 ` [PATCH 0/2] ext4: Do not let fstrim block suspend Theodore Ts'o
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).