Whamcloud - gitweb
- ext3 batching allocation against suse2 series
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-mballoc-2.4.24.patch
1 Index: linux-2.4.24/fs/ext3/balloc.c
2 ===================================================================
3 --- linux-2.4.24.orig/fs/ext3/balloc.c  2004-01-10 17:04:42.000000000 +0300
4 +++ linux-2.4.24/fs/ext3/balloc.c       2004-02-05 20:35:11.000000000 +0300
5 @@ -11,6 +11,7 @@
6   *        David S. Miller (davem@caip.rutgers.edu), 1995
7   */
8  
9 +#include <linux/module.h>
10  #include <linux/config.h>
11  #include <linux/sched.h>
12  #include <linux/fs.h>
13 @@ -1007,3 +1008,298 @@
14                         bitmap_count);
15  }
16  #endif
17 +
18 +#define MBDEBUG_
19 +#ifdef MBDEBUG
20 +#define mbdebug(fmt,a...)      printk(fmt, ##a)
21 +#else
22 +#define mbdebug(fmt,a...)
23 +#endif
24 +
25 +/*
26 + * in alloc_status we track allocation: the best found extent, how many
27 + * extents we've skipped, etc
28 + */
29 +struct alloc_status {
30 +       struct inode *inode;
31 +       struct super_block *sb;
32 +       int goal;               /* goal for allocation */
33 +       int target_len;         /* goal for len */
34 +       int start, len;         /* the best found extent */
35 +       int num;                /* number of extent: to limit searching */
36 +};
37 +
38 +/*
39 + * ext3_test_extent() compares requested extent with existing in as.
40 + * if requested extent is better than that, then replace old one.
41 + * then it tries to understand is new extent suitable or not
42 + * return 1 if caller can complete searching
43 + */
44 +inline int ext3_test_extent(struct alloc_status *as, int group,
45 +                               int start, int len)
46 +{
47 +       struct ext3_super_block * es = EXT3_SB(as->sb)->s_es;
48 +       unsigned long tmp;
49 +
50 +       J_ASSERT(as->target_len >= len);
51 +
52 +       mbdebug("found extent %d:%d\n", start, len);
53 +       tmp = start + group * EXT3_BLOCKS_PER_GROUP(as->sb)
54 +                       + le32_to_cpu(es->s_first_data_block);
55 +
56 +       /* account requests in order to limit searching */
57 +       as->num++;
58 +
59 +       if (as->num == 20)
60 +               return 1;
61 +
62 +       /* if hit goal, then searching may complete right now */
63 +       if (tmp == as->goal) {
64 +nice:
65 +               as->start = tmp;
66 +               as->len = len;
67 +               return 1;
68 +       }
69 +
70 +       /* if found extent has lenght we need, return it right now */
71 +       if (as->target_len == len)
72 +               goto nice;
73 +
74 +       /* first, check is found extent better than we have in as */
75 +       if (as->len > len) {
76 +better:
77 +               as->start = tmp;
78 +               as->len = len;
79 +               return 0;
80 +       }
81 +
82 +       /* FIXME: more checks! */
83 +       as->start = tmp;
84 +       as->len = len;
85 +
86 +       /* 1) closeness to goal */
87 +       
88 +       /* 2) extent lenght */
89 +       /* 3) number of tested extent (we check all found extents) */
90 +       /* */
91 +       return 0;
92 +}
93 +
94 +/*
95 + * this routine tries to find upto *len free contig. blocks
96 + * return number of found block (+ lenght of extent in *len)
97 + * or -1 if no free blocks at all
98 + */
99 +int ext3_find_free_extent(struct buffer_head *bh, int goal, int *len, int max)
100 +{
101 +       int i, l = 0;
102 +
103 +repeat:
104 +       if (goal >= max)
105 +               return -1;
106 +       /* find first free block */
107 +       i = ext3_find_next_zero_bit(bh->b_data, max, goal);
108 +       if (i >= max) {
109 +               /* no free block */
110 +               return -1;
111 +       }
112 +       /* check upto len block for ability to be allocated */
113 +       while (l < *len && i + l < max) {
114 +               if (!ext3_test_allocatable(i + l, bh))
115 +                       break;
116 +               l++;
117 +       }
118 +       if (l == 0) {
119 +               goal = i + 1;
120 +               goto repeat;
121 +       }
122 +       *len = l;
123 +       return i;
124 +}
125 +
126 +/*
127 + * this routine loops over group, finds free extents and tests them
128 + * for some criterias
129 + * it may return negative value if group can't be loaded, 0 - if
130 + * no good extent can be found, 1 - if good extent found
131 + */
132 +int ext3_find_extent_in_group(struct alloc_status *as, int group,
133 +                               unsigned long goal, int len)
134 +{
135 +       int k, i, l, bitmap_nr, found = 0;
136 +       struct super_block *sb = as->sb;
137 +       int max = EXT3_BLOCKS_PER_GROUP(sb);
138 +       struct buffer_head *bh, *bmbh;
139 +       struct ext3_group_desc *gdp;
140 +
141 +       mbdebug("look for %d blocks in group %d starting from %lu\n",
142 +                       len, group, goal);
143 +
144 +       gdp = ext3_get_group_desc(as->sb, group, &bh);
145 +       if (!gdp)
146 +               return -EIO;
147 +
148 +       if (le16_to_cpu(gdp->bg_free_blocks_count) == 0)
149 +               return 0;
150 +
151 +       bitmap_nr = load_block_bitmap(as->sb, group);
152 +       if (bitmap_nr < 0)
153 +               return -EIO;
154 +
155 +       bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
156 +
157 +       i = goal;
158 +       /* scan from goal to the end */
159 +repeat:
160 +       while (i < max) {
161 +               l = len;
162 +               k = ext3_find_free_extent(bmbh, i, &l, max);
163 +               i = k + l;
164 +               if (k < 0)
165 +                       break;
166 +               if (ext3_test_extent(as, group, k, l)) {
167 +                       found = 1;
168 +                       goto out;
169 +               }
170 +       }
171 +
172 +       if (goal) {
173 +               /* scan from 0 upto goal */
174 +               mbdebug("repeat from %lu in %d\n", goal, group);
175 +               max = goal - 1;
176 +               goal = i = 0;
177 +               goto repeat;
178 +       }
179 +out:
180 +       return found; 
181 +}
182 +
183 +#define check_in_committed(bh,j)       \
184 +       J_ASSERT_BH((bh), !ext3_test_bit((j), bh2jh((bh))->b_committed_data))
185 +
186 +int ext3_new_blocks(handle_t *handle, struct inode *inode, int *num,
187 +                       unsigned long goal, int *errp)
188 +{
189 +       struct super_block *sb = inode->i_sb;
190 +       int first_group, group, bitmap_nr;
191 +       struct buffer_head *bh, *bmbh;
192 +       struct ext3_super_block *es;
193 +       struct ext3_group_desc *gdp;
194 +       struct alloc_status as;
195 +       int err, bit, i;
196 +
197 +       int scaned = 0;
198 +
199 +       J_ASSERT(num && *num > 0);
200 +
201 +       if (DQUOT_ALLOC_BLOCK(inode, *num)) {
202 +               *errp = -EDQUOT;
203 +               return 0;
204 +       }
205 +
206 +       es = EXT3_SB(inode->i_sb)->s_es;
207 +
208 +       *errp = 0;
209 +       as.target_len = *num;
210 +       as.sb = sb;
211 +       as.inode = inode;
212 +       as.goal = goal;
213 +       as.start = -1;
214 +       as.len = 0;
215 +       as.num = 0;
216 +
217 +       lock_super(sb);
218 +       first_group = (goal - le32_to_cpu(es->s_first_data_block)) /
219 +                       EXT3_BLOCKS_PER_GROUP(sb);
220 +       goal = (goal - le32_to_cpu(es->s_first_data_block)) %
221 +                       EXT3_BLOCKS_PER_GROUP(sb);
222 +       group = first_group;
223 +       do {
224 +               scaned++;
225 +               err = ext3_find_extent_in_group(&as, group, goal, *num);
226 +               if (err < 0) 
227 +                       goto error_out;
228 +               else if (err)
229 +                       break;
230 +
231 +               /* reset goal for next groups */
232 +               goal = 0;
233 +
234 +               /* try next group */
235 +               if (++group == EXT3_SB(sb)->s_groups_count)
236 +                       group = 0;
237 +       } while (group != first_group);
238 +
239 +       if (as.len == 0) {
240 +               err = -ENOSPC;
241 +               goto error_out;
242 +       }
243 +
244 +       /* in the end we've found something, allocate it */
245 +       mbdebug("best extent: %u:%u\n", as.start, as.len);
246 +
247 +       group = (as.start - le32_to_cpu(es->s_first_data_block)) /
248 +               EXT3_BLOCKS_PER_GROUP(sb);
249 +       bit = (as.start - le32_to_cpu(es->s_first_data_block)) %
250 +               EXT3_BLOCKS_PER_GROUP(sb);
251 +       gdp = ext3_get_group_desc(sb, group, &bh);
252 +       if (!gdp) {
253 +               err = -EIO;
254 +               goto error_out; 
255 +       }
256 +
257 +       /* mark block(s) used in bitmap ... */
258 +       bitmap_nr = load_block_bitmap(sb, group);
259 +       if (bitmap_nr < 0) {
260 +               err = -EIO;
261 +               goto error_out;
262 +       }
263 +       bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
264 +       err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
265 +       if (err)
266 +               goto error_out;
267 +       err = ext3_journal_get_write_access(handle, bmbh);
268 +       if (err)
269 +               goto error_out;
270 +       err = ext3_journal_get_write_access(handle, bh);
271 +       if (err)
272 +               goto error_out;
273 +       for (i = 0; i < as.len; i++) {
274 +               J_ASSERT(!ext3_test_bit(bit + i, bmbh->b_data));
275 +               if (buffer_jbd(bmbh) && bh2jh(bmbh)->b_committed_data)
276 +                       check_in_committed(bmbh, bit + i);
277 +               set_bit(bit + i, bmbh->b_data);
278 +       }
279 +       err = ext3_journal_dirty_metadata(handle, bmbh);
280 +       if (err)
281 +               goto error_out;
282 +
283 +       /* ... and correct group descriptor */
284 +       gdp->bg_free_blocks_count =
285 +               cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - as.len);
286 +       es->s_free_blocks_count =
287 +               cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - as.len);
288 +       err = ext3_journal_dirty_metadata(handle, bmbh);
289 +       if (err)
290 +               goto error_out;
291 +       err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
292 +       if (err)
293 +               goto error_out;
294 +       sb->s_dirt = 1;
295 +
296 +       if (*num != as.len)
297 +               DQUOT_FREE_BLOCK(inode, *num - as.len);
298 +       *num = as.len;
299 +
300 +out:
301 +       unlock_super(sb);
302 +       return as.start;
303 +
304 +error_out:
305 +       as.start = 0;
306 +       *errp = err;
307 +       goto out;
308 +}
309 +
310 +EXPORT_SYMBOL(ext3_new_blocks);
311 +
312 Index: linux-2.4.24/fs/ext3/file.c
313 ===================================================================
314 --- linux-2.4.24.orig/fs/ext3/file.c    2004-01-31 02:06:18.000000000 +0300
315 +++ linux-2.4.24/fs/ext3/file.c 2004-02-05 20:57:07.000000000 +0300
316 @@ -69,6 +69,18 @@
317         int err;
318         struct inode *inode = file->f_dentry->d_inode;
319  
320 +#if 0
321 +       /* allocate all the space to be written */
322 +       if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
323 +               int blocksize = inode->i_sb->s_blocksize;
324 +               unsigned long start, end;
325 +
326 +               start = (unsigned long) *ppos / blocksize;
327 +               end = ((unsigned long) *ppos + count + blocksize - 1)
328 +                               / blocksize;
329 +               ext3_ext_allocate_nblocks(inode, start, end - start);
330 +       }
331 +#endif
332         ret = generic_file_write(file, buf, count, ppos);
333  
334         /* Skip file flushing code if there was an error, or if nothing
335 Index: linux-2.4.24/fs/ext3/Makefile
336 ===================================================================
337 --- linux-2.4.24.orig/fs/ext3/Makefile  2004-02-05 18:44:25.000000000 +0300
338 +++ linux-2.4.24/fs/ext3/Makefile       2004-02-05 20:35:11.000000000 +0300
339 @@ -14,7 +14,7 @@
340  obj-y    := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
341                 ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
342                 xattr_trusted.o extents.o
343 -export-objs += extents.o
344 +export-objs += extents.o balloc.o
345  
346  obj-m    := $(O_TARGET)
347  
348 Index: linux-2.4.24/include/linux/ext3_fs.h
349 ===================================================================
350 --- linux-2.4.24.orig/include/linux/ext3_fs.h   2004-01-30 00:09:37.000000000 +0300
351 +++ linux-2.4.24/include/linux/ext3_fs.h        2004-02-05 20:35:11.000000000 +0300
352 @@ -58,6 +58,8 @@
353  #define ext3_debug(f, a...)    do {} while (0)
354  #endif
355  
356 +#define EXT3_MULTIBLOCK_ALLOCATOR      1
357 +
358  /*
359   * Special inodes numbers
360   */
361 @@ -667,6 +669,7 @@
362  extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
363                                                     unsigned int block_group,
364                                                     struct buffer_head ** bh);
365 +extern int ext3_new_blocks(handle_t*, struct inode*, int*, unsigned long, int*);
366  
367  /* dir.c */
368  extern int ext3_check_dir_entry(const char *, struct inode *,