aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ialloc.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 8bf5999875ee..666a5ed48bcc 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -625,6 +625,51 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
625} 625}
626 626
627/* 627/*
628 * In no journal mode, if an inode has recently been deleted, we want
629 * to avoid reusing it until we're reasonably sure the inode table
630 * block has been written back to disk. (Yes, these values are
631 * somewhat arbitrary...)
632 */
633#define RECENTCY_MIN 5
634#define RECENTCY_DIRTY 30
635
636static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino)
637{
638 struct ext4_group_desc *gdp;
639 struct ext4_inode *raw_inode;
640 struct buffer_head *bh;
641 unsigned long dtime, now;
642 int inodes_per_block = EXT4_SB(sb)->s_inodes_per_block;
643 int offset, ret = 0, recentcy = RECENTCY_MIN;
644
645 gdp = ext4_get_group_desc(sb, group, NULL);
646 if (unlikely(!gdp))
647 return 0;
648
649 bh = sb_getblk(sb, ext4_inode_table(sb, gdp) +
650 (ino / inodes_per_block));
651 if (unlikely(!bh) || !buffer_uptodate(bh))
652 /*
653 * If the block is not in the buffer cache, then it
654 * must have been written out.
655 */
656 goto out;
657
658 offset = (ino % inodes_per_block) * EXT4_INODE_SIZE(sb);
659 raw_inode = (struct ext4_inode *) (bh->b_data + offset);
660 dtime = le32_to_cpu(raw_inode->i_dtime);
661 now = get_seconds();
662 if (buffer_dirty(bh))
663 recentcy += RECENTCY_DIRTY;
664
665 if (dtime && (dtime < now) && (now < dtime + recentcy))
666 ret = 1;
667out:
668 brelse(bh);
669 return ret;
670}
671
672/*
628 * There are two policies for allocating an inode. If the new inode is 673 * There are two policies for allocating an inode. If the new inode is
629 * a directory, then a forward search is made for a block group with both 674 * a directory, then a forward search is made for a block group with both
630 * free space and a low directory-to-inode ratio; if that fails, then of 675 * free space and a low directory-to-inode ratio; if that fails, then of
@@ -741,6 +786,11 @@ repeat_in_this_group:
741 "inode=%lu", ino + 1); 786 "inode=%lu", ino + 1);
742 continue; 787 continue;
743 } 788 }
789 if ((EXT4_SB(sb)->s_journal == NULL) &&
790 recently_deleted(sb, group, ino)) {
791 ino++;
792 goto next_inode;
793 }
744 if (!handle) { 794 if (!handle) {
745 BUG_ON(nblocks <= 0); 795 BUG_ON(nblocks <= 0);
746 handle = __ext4_journal_start_sb(dir->i_sb, line_no, 796 handle = __ext4_journal_start_sb(dir->i_sb, line_no,
@@ -764,6 +814,7 @@ repeat_in_this_group:
764 ino++; /* the inode bitmap is zero-based */ 814 ino++; /* the inode bitmap is zero-based */
765 if (!ret2) 815 if (!ret2)
766 goto got; /* we grabbed the inode! */ 816 goto got; /* we grabbed the inode! */
817next_inode:
767 if (ino < EXT4_INODES_PER_GROUP(sb)) 818 if (ino < EXT4_INODES_PER_GROUP(sb))
768 goto repeat_in_this_group; 819 goto repeat_in_this_group;
769next_group: 820next_group: