diff options
-rw-r--r-- | fs/ext4/ialloc.c | 51 |
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 | |||
636 | static 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; | ||
667 | out: | ||
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! */ |
817 | next_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; |
769 | next_group: | 820 | next_group: |