1 Index: linux-2.6.7/fs/ext3/ialloc.c
2 ===================================================================
3 --- linux-2.6.7.orig/fs/ext3/ialloc.c 2004-10-05 21:15:58.000000000 +0400
4 +++ linux-2.6.7/fs/ext3/ialloc.c 2004-10-06 17:14:39.776562240 +0400
9 - BUFFER_TRACE(bitmap_bh, "get_write_access");
10 - fatal = ext3_journal_get_write_access(handle, bitmap_bh);
11 + BUFFER_TRACE(bitmap_bh, "get_undo_access");
12 + fatal = ext3_journal_get_undo_access(handle, bitmap_bh, NULL);
16 + /* to prevent inode reusing within single transaction -bzzz */
17 + BUFFER_TRACE(bitmap_bh, "clear in b_committed_data");
18 + J_ASSERT_BH(bitmap_bh, bh2jh(bitmap_bh)->b_committed_data != NULL);
19 + ext3_set_bit(bit, bh2jh(bitmap_bh)->b_committed_data);
21 /* Ok, now we can actually update the inode bitmaps.. */
22 if (!ext3_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
23 bit, bitmap_bh->b_data))
28 + * this is just to check was block freed in current transaction -bzzz
30 +static int ext3_test_allocatable(int nr, struct buffer_head *bh)
32 + if (!buffer_jbd(bh) || !bh2jh(bh)->b_committed_data)
34 + return !ext3_test_bit(nr, bh2jh(bh)->b_committed_data);
38 * There are two policies for allocating an inode. If the new inode is
39 * a directory, then a forward search is made for a block group with both
40 * free space and a low directory-to-inode ratio; if that fails, then of
42 struct super_block *sb;
43 struct buffer_head *bitmap_bh = NULL;
44 struct buffer_head *bh2;
47 unsigned long ino = 0;
49 struct ext3_group_desc * gdp = NULL;
54 - BUFFER_TRACE(bh, "get_write_access");
55 - err = ext3_journal_get_write_access(handle, bitmap_bh);
56 + BUFFER_TRACE(bh, "get_undo_access");
57 + err = ext3_journal_get_undo_access(handle, bitmap_bh, &credits);
60 - if (ext3_set_bit_atomic(sb_bgl_lock(sbi, group),
61 - ino, bitmap_bh->b_data)) {
62 + if (!ext3_test_allocatable(ino, bitmap_bh) ||
63 + ext3_set_bit_atomic(sb_bgl_lock(sbi, group),
64 + ino, bitmap_bh->b_data)) {
65 printk(KERN_ERR "goal inode %lu unavailable\n", goal);
66 /* Oh well, we tried. */
67 goto continue_allocation;
69 + if (!ext3_test_allocatable(ino, bitmap_bh)) {
70 + /* in theory it's possible another that thread has
71 + * allocated and freed block between test_allocatable()
72 + * and set_bit_atomic(). so, we we have to check
74 + journal_release_buffer(handle, bitmap_bh, credits);
75 + goto continue_allocation;
78 BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
79 err = ext3_journal_dirty_metadata(handle, bitmap_bh);
83 BUFFER_TRACE(bitmap_bh, "get_write_access");
84 - err = ext3_journal_get_write_access_credits(handle,
85 + err = ext3_journal_get_undo_access(handle,
90 - if (!ext3_set_bit_atomic(sb_bgl_lock(sbi, group),
91 - ino, bitmap_bh->b_data)) {
93 - BUFFER_TRACE(bitmap_bh,
94 - "call ext3_journal_dirty_metadata");
95 - err = ext3_journal_dirty_metadata(handle,
100 + if (ext3_test_allocatable(ino, bitmap_bh) &&
101 + !ext3_set_bit_atomic(sb_bgl_lock(sbi, group),
102 + ino, bitmap_bh->b_data)) {
103 + /* in theory it's possible another that
104 + * thread has allocated and freed block
105 + * between ext3_test_allocatable() and
106 + * set_bit_atomic(). so, we we have to
107 + * check this -bzzz */
108 + if (ext3_test_allocatable(ino, bitmap_bh)) {
110 + BUFFER_TRACE(bitmap_bh,
111 + "call ext3_journal_dirty_metadata");
112 + err = ext3_journal_dirty_metadata(handle,
120 journal_release_buffer(handle, bitmap_bh, credits);