ext4: avoid ENOSPC when avoiding to reuse recently deleted inodes
[linux-2.6-microblaze.git] / fs / ext4 / ialloc.c
index f95ee99..9652a0e 100644 (file)
@@ -712,21 +712,34 @@ out:
 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;
 }