Skip to content

Commit

Permalink
ext4: avoid ENOSPC when avoiding to reuse recently deleted inodes
Browse files Browse the repository at this point in the history
When ext4 is running on a filesystem without a journal, it tries not to
reuse recently deleted inodes to provide better chances for filesystem
recovery in case of crash. However this logic forbids reuse of freed
inodes for up to 5 minutes and especially for filesystems with smaller
number of inodes can lead to ENOSPC errors returned when allocating new
inodes.

Fix the problem by allowing to reuse recently deleted inode if there's
no other inode free in the scanned range.

Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20200318121317.31941-1-jack@suse.cz
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
  • Loading branch information
jankara authored and tytso committed Mar 26, 2020
1 parent 5e47868 commit d05466b
Showing 1 changed file with 18 additions and 5 deletions.
23 changes: 18 additions & 5 deletions fs/ext4/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -712,21 +712,34 @@ static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino)
static int find_inode_bit(struct super_block *sb, ext4_group_t group,
struct buffer_head *bitmap, unsigned long *ino)
{
bool check_recently_deleted = EXT4_SB(sb)->s_journal == NULL;
unsigned long recently_deleted_ino = EXT4_INODES_PER_GROUP(sb);

next:
*ino = ext4_find_next_zero_bit((unsigned long *)
bitmap->b_data,
EXT4_INODES_PER_GROUP(sb), *ino);
if (*ino >= EXT4_INODES_PER_GROUP(sb))
return 0;
goto not_found;

if ((EXT4_SB(sb)->s_journal == NULL) &&
recently_deleted(sb, group, *ino)) {
if (check_recently_deleted && recently_deleted(sb, group, *ino)) {
recently_deleted_ino = *ino;
*ino = *ino + 1;
if (*ino < EXT4_INODES_PER_GROUP(sb))
goto next;
return 0;
goto not_found;
}

return 1;
not_found:
if (recently_deleted_ino >= EXT4_INODES_PER_GROUP(sb))
return 0;
/*
* Not reusing recently deleted inodes is mostly a preference. We don't
* want to report ENOSPC or skew allocation patterns because of that.
* So return even recently deleted inode if we could find better in the
* given range.
*/
*ino = recently_deleted_ino;
return 1;
}

Expand Down

0 comments on commit d05466b

Please sign in to comment.