|
@@ -624,6 +624,51 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * In no journal mode, if an inode has recently been deleted, we want
|
|
|
+ * to avoid reusing it until we're reasonably sure the inode table
|
|
|
+ * block has been written back to disk. (Yes, these values are
|
|
|
+ * somewhat arbitrary...)
|
|
|
+ */
|
|
|
+#define RECENTCY_MIN 5
|
|
|
+#define RECENTCY_DIRTY 30
|
|
|
+
|
|
|
+static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino)
|
|
|
+{
|
|
|
+ struct ext4_group_desc *gdp;
|
|
|
+ struct ext4_inode *raw_inode;
|
|
|
+ struct buffer_head *bh;
|
|
|
+ unsigned long dtime, now;
|
|
|
+ int inodes_per_block = EXT4_SB(sb)->s_inodes_per_block;
|
|
|
+ int offset, ret = 0, recentcy = RECENTCY_MIN;
|
|
|
+
|
|
|
+ gdp = ext4_get_group_desc(sb, group, NULL);
|
|
|
+ if (unlikely(!gdp))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ bh = sb_getblk(sb, ext4_inode_table(sb, gdp) +
|
|
|
+ (ino / inodes_per_block));
|
|
|
+ if (unlikely(!bh) || !buffer_uptodate(bh))
|
|
|
+ /*
|
|
|
+ * If the block is not in the buffer cache, then it
|
|
|
+ * must have been written out.
|
|
|
+ */
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ offset = (ino % inodes_per_block) * EXT4_INODE_SIZE(sb);
|
|
|
+ raw_inode = (struct ext4_inode *) (bh->b_data + offset);
|
|
|
+ dtime = le32_to_cpu(raw_inode->i_dtime);
|
|
|
+ now = get_seconds();
|
|
|
+ if (buffer_dirty(bh))
|
|
|
+ recentcy += RECENTCY_DIRTY;
|
|
|
+
|
|
|
+ if (dtime && (dtime < now) && (now < dtime + recentcy))
|
|
|
+ ret = 1;
|
|
|
+out:
|
|
|
+ brelse(bh);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* There are two policies for allocating an inode. If the new inode is
|
|
|
* a directory, then a forward search is made for a block group with both
|
|
@@ -741,6 +786,11 @@ repeat_in_this_group:
|
|
|
"inode=%lu", ino + 1);
|
|
|
continue;
|
|
|
}
|
|
|
+ if ((EXT4_SB(sb)->s_journal == NULL) &&
|
|
|
+ recently_deleted(sb, group, ino)) {
|
|
|
+ ino++;
|
|
|
+ goto next_inode;
|
|
|
+ }
|
|
|
if (!handle) {
|
|
|
BUG_ON(nblocks <= 0);
|
|
|
handle = __ext4_journal_start_sb(dir->i_sb, line_no,
|
|
@@ -764,6 +814,7 @@ repeat_in_this_group:
|
|
|
ino++; /* the inode bitmap is zero-based */
|
|
|
if (!ret2)
|
|
|
goto got; /* we grabbed the inode! */
|
|
|
+next_inode:
|
|
|
if (ino < EXT4_INODES_PER_GROUP(sb))
|
|
|
goto repeat_in_this_group;
|
|
|
next_group:
|