Whamcloud - gitweb
- missed patches from suse-2.4.21-2 series added
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-inode-reuse-2.4.22.patch
1 Index: linux-2.4.22-ac1/fs/ext3/ialloc.c
2 ===================================================================
3 --- linux-2.4.22-ac1.orig/fs/ext3/ialloc.c      2003-10-22 14:20:03.000000000 +0400
4 +++ linux-2.4.22-ac1/fs/ext3/ialloc.c   2003-10-29 22:32:28.000000000 +0300
5 @@ -242,11 +242,16 @@
6  
7         bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
8  
9 -       BUFFER_TRACE(bh, "get_write_access");
10 -       fatal = ext3_journal_get_write_access(handle, bh);
11 +       BUFFER_TRACE(bh, "get_undo_access");
12 +       fatal = ext3_journal_get_undo_access(handle, bh);
13         if (fatal)
14                 goto error_return;
15  
16 +       /* to prevent inode reusing within single transaction -bzzz */
17 +       BUFFER_TRACE(bh, "clear in b_committed_data");
18 +       J_ASSERT_BH(bh, bh2jh(bh)->b_committed_data != NULL);
19 +       ext3_set_bit(bit, bh2jh(bh)->b_committed_data);
20 +
21         /* Ok, now we can actually update the inode bitmaps.. */
22         if (!ext3_clear_bit (bit, bh->b_data))
23                 ext3_error (sb, "ext3_free_inode",
24 @@ -320,6 +325,43 @@
25         return 0;
26  }
27  
28 +static int ext3_test_allocatable(int nr, struct buffer_head *bh)
29 +{
30 +       if (ext3_test_bit(nr, bh->b_data))
31 +               return 0;
32 +       if (!buffer_jbd(bh) || !bh2jh(bh)->b_committed_data)
33 +               return 1;
34 +#if 0
35 +       if (!ext3_test_bit(nr, bh2jh(bh)->b_committed_data))
36 +               printk("EXT3-fs: inode %d was used\n", nr);
37 +#endif
38 +       return !ext3_test_bit(nr, bh2jh(bh)->b_committed_data);
39 +}
40 +
41 +static int ext3_find_usable_inode(struct super_block *sb,
42 +                                       struct buffer_head *bh)
43 +{
44 +       int here, maxinodes, next;
45 +
46 +       maxinodes = EXT3_INODES_PER_GROUP(sb);
47 +       here = 0;       
48 +
49 +       while (here < maxinodes) {
50 +               next  = ext3_find_next_zero_bit((unsigned long *) bh->b_data, 
51 +                                                maxinodes, here);
52 +               if (next >= maxinodes)
53 +                       return -1;
54 +               if (ext3_test_allocatable(next, bh))
55 +                       return next;
56 +
57 +               J_ASSERT_BH(bh, bh2jh(bh)->b_committed_data);
58 +               here = ext3_find_next_zero_bit
59 +                       ((unsigned long *) bh2jh(bh)->b_committed_data, 
60 +                        maxinodes, next);
61 +       }
62 +       return -1;
63 +}
64 +
65  /*
66   * There are two policies for allocating an inode.  If the new inode is
67   * a directory, then a forward search is made for a block group with both
68 @@ -530,7 +572,7 @@
69         struct super_block * sb;
70         struct buffer_head * bh;
71         struct buffer_head * bh2;
72 -       int group;
73 +       int group, k;
74         ino_t ino;
75         struct inode * inode;
76         int bitmap_nr;
77 @@ -569,7 +611,8 @@
78                 err = ext3_journal_get_write_access(handle, bh);
79                 if (err) goto fail;
80  
81 -               if (ext3_set_bit(ino, bh->b_data)) {
82 +               if (!ext3_test_allocatable(ino, bh) ||
83 +                               ext3_set_bit(ino, bh->b_data)) {
84                         printk(KERN_ERR "goal inode %lu unavailable\n", goal);
85                         /* Oh well, we tried. */
86                         goto repeat;
87 @@ -595,52 +638,63 @@
88                 group = find_group_other(sb, dir);
89    
90         err = -ENOSPC;
91 -       if (!group == -1)
92 +       if (group == -1)
93                 goto out;
94  
95         err = -EIO;
96 -       bitmap_nr = load_inode_bitmap (sb, group);
97 +       bitmap_nr = load_inode_bitmap(sb, group);
98         if (bitmap_nr < 0)
99                 goto fail;
100 -
101         bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
102 -       gdp = ext3_get_group_desc (sb, group, &bh2);
103  
104 -       if ((ino = ext3_find_first_zero_bit ((unsigned long *) bh->b_data,
105 -                                     EXT3_INODES_PER_GROUP(sb))) <
106 -           EXT3_INODES_PER_GROUP(sb)) {
107 -               BUFFER_TRACE(bh, "get_write_access");
108 -               err = ext3_journal_get_write_access(handle, bh);
109 -               if (err) goto fail;
110 -               
111 -               if (ext3_set_bit (ino, bh->b_data)) {
112 -                       ext3_error (sb, "ext3_new_inode",
113 -                                     "bit already set for inode %lu", ino);
114 -                       goto repeat;
115 -               }
116 -               BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
117 -               err = ext3_journal_dirty_metadata(handle, bh);
118 -               if (err) goto fail;
119 -       } else {
120 -               if (le16_to_cpu(gdp->bg_free_inodes_count) != 0) {
121 -                       ext3_error (sb, "ext3_new_inode",
122 -                                   "Free inodes count corrupted in group %d",
123 -                                   group);
124 -                       /* Is it really ENOSPC? */
125 -                       err = -ENOSPC;
126 -                       if (sb->s_flags & MS_RDONLY)
127 -                               goto fail;
128 -
129 -                       BUFFER_TRACE(bh2, "get_write_access");
130 -                       err = ext3_journal_get_write_access(handle, bh2);
131 -                       if (err) goto fail;
132 -                       gdp->bg_free_inodes_count = 0;
133 -                       BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata");
134 -                       err = ext3_journal_dirty_metadata(handle, bh2);
135 -                       if (err) goto fail;
136 +       /* try to allocate in selected group */
137 +       if ((ino = ext3_find_usable_inode(sb, bh)) >= 0)
138 +               goto find_free;
139 +
140 +       /* can't allocate: try to allocate in ANY another groups */
141 +       k = group;
142 +       gdp = NULL;
143 +       err = -EIO;
144 +       for (group = group + 1; group != k; group++) {
145 +               struct ext3_group_desc *tmp;
146 +
147 +               if (group >= sb->u.ext3_sb.s_groups_count)
148 +                       group = 0;
149 +               tmp = ext3_get_group_desc(sb, group, &bh2);
150 +               if (le16_to_cpu(tmp->bg_free_inodes_count) == 0)
151 +                       continue;
152 +
153 +               bitmap_nr = load_inode_bitmap(sb, group);
154 +               if (bitmap_nr < 0)
155 +                       goto fail;
156 +               bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
157 +
158 +               /* try to allocate in selected group */
159 +               if ((ino = ext3_find_usable_inode(sb, bh)) >= 0) {
160 +                       gdp = tmp;
161 +                       break;
162                 }
163 -               goto repeat;
164         }
165 +       err = -ENOSPC;
166 +       if (!gdp)
167 +               goto out;
168 +
169 +find_free:
170 +       BUFFER_TRACE(bh, "get_undo_access");
171 +       err = ext3_journal_get_undo_access(handle, bh);
172 +       if (err)
173 +               goto fail;
174 +
175 +       if (ext3_set_bit(ino, bh->b_data)) {
176 +               ext3_error (sb, "ext3_new_inode",
177 +                               "bit already set for inode %lu",
178 +                               (unsigned long) ino);
179 +               goto fail; 
180 +       }
181 +       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
182 +       err = ext3_journal_dirty_metadata(handle, bh);
183 +       if (err)
184 +               goto fail;
185  
186  have_bit_and_group:
187         ino += group * EXT3_INODES_PER_GROUP(sb) + 1;