Whamcloud - gitweb
smash the HEAD with the contents of b_cmd. HEAD_PRE_CMD_SMASH and
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-mballoc-2.4.21-suse2.patch
1 Index: linux-2.4.21-suse2/fs/ext3/balloc.c
2 ===================================================================
3 --- linux-2.4.21-suse2.orig/fs/ext3/balloc.c    2003-06-13 18:51:37.000000000 +0400
4 +++ linux-2.4.21-suse2/fs/ext3/balloc.c 2004-02-06 11:07:16.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,303 @@
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 +       J_ASSERT(num && *num > 0);
198 +
199 +       if (DQUOT_ALLOC_BLOCK(inode, *num)) {
200 +               *errp = -EDQUOT;
201 +               return 0;
202 +       }
203 +
204 +       es = EXT3_SB(inode->i_sb)->s_es;
205 +
206 +       *errp = 0;
207 +       as.target_len = *num;
208 +       as.sb = sb;
209 +       as.inode = inode;
210 +       as.goal = goal;
211 +       as.start = -1;
212 +       as.len = 0;
213 +       as.num = 0;
214 +
215 +       if (goal < le32_to_cpu(es->s_first_data_block) ||
216 +           goal >= le32_to_cpu(es->s_blocks_count))
217 +               goal = le32_to_cpu(es->s_first_data_block);
218 +
219 +       lock_super(sb);
220 +       first_group = (goal - le32_to_cpu(es->s_first_data_block)) /
221 +                       EXT3_BLOCKS_PER_GROUP(sb);
222 +       goal = (goal - le32_to_cpu(es->s_first_data_block)) %
223 +                       EXT3_BLOCKS_PER_GROUP(sb);
224 +       group = first_group;
225 +       do {
226 +               err = ext3_find_extent_in_group(&as, group, goal, *num);
227 +               if (err < 0) 
228 +                       goto error_out;
229 +               else if (err)
230 +                       break;
231 +
232 +               /* reset goal for next groups */
233 +               goal = 0;
234 +
235 +               /* try next group */
236 +               if (++group == EXT3_SB(sb)->s_groups_count)
237 +                       group = 0;
238 +       } while (group != first_group);
239 +
240 +       if (as.len == 0) {
241 +               err = -ENOSPC;
242 +               goto error_out;
243 +       }
244 +
245 +       /* in the end we've found something, allocate it */
246 +       mbdebug("best extent: %u:%u\n", as.start, as.len);
247 +
248 +       group = (as.start - le32_to_cpu(es->s_first_data_block)) /
249 +               EXT3_BLOCKS_PER_GROUP(sb);
250 +       bit = (as.start - le32_to_cpu(es->s_first_data_block)) %
251 +               EXT3_BLOCKS_PER_GROUP(sb);
252 +       gdp = ext3_get_group_desc(sb, group, &bh);
253 +       if (!gdp) {
254 +               err = -EIO;
255 +               goto error_out; 
256 +       }
257 +
258 +       /* mark block(s) used in bitmap ... */
259 +       bitmap_nr = load_block_bitmap(sb, group);
260 +       if (bitmap_nr < 0) {
261 +               err = -EIO;
262 +               goto error_out;
263 +       }
264 +       bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
265 +       /* Make sure we use undo access for the bitmap, because it is
266 +           critical that we do the frozen_data COW on bitmap buffers in
267 +           all cases even if the buffer is in BJ_Forget state in the
268 +           committing transaction.  */
269 +       err = ext3_journal_get_undo_access(handle, bmbh);
270 +       if (err)
271 +               goto error_out;
272 +       err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
273 +       if (err)
274 +               goto error_out;
275 +       err = ext3_journal_get_write_access(handle, bh);
276 +       if (err)
277 +               goto error_out;
278 +       for (i = 0; i < as.len; i++) {
279 +               J_ASSERT(!ext3_test_bit(bit + i, bmbh->b_data));
280 +               if (buffer_jbd(bmbh) && bh2jh(bmbh)->b_committed_data)
281 +                       check_in_committed(bmbh, bit + i);
282 +               set_bit(bit + i, bmbh->b_data);
283 +       }
284 +       err = ext3_journal_dirty_metadata(handle, bmbh);
285 +       if (err)
286 +               goto error_out;
287 +
288 +       /* ... and correct group descriptor */
289 +       gdp->bg_free_blocks_count =
290 +               cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - as.len);
291 +       es->s_free_blocks_count =
292 +               cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - as.len);
293 +       err = ext3_journal_dirty_metadata(handle, bmbh);
294 +       if (err)
295 +               goto error_out;
296 +       err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
297 +       if (err)
298 +               goto error_out;
299 +       sb->s_dirt = 1;
300 +
301 +       if (*num != as.len)
302 +               DQUOT_FREE_BLOCK(inode, *num - as.len);
303 +       *num = as.len;
304 +
305 +out:
306 +       unlock_super(sb);
307 +       return as.start;
308 +
309 +error_out:
310 +       as.start = 0;
311 +       *errp = err;
312 +       goto out;
313 +}
314 +
315 +EXPORT_SYMBOL(ext3_new_blocks);
316 +
317 Index: linux-2.4.21-suse2/fs/ext3/file.c
318 ===================================================================
319 --- linux-2.4.21-suse2.orig/fs/ext3/file.c      2004-02-05 20:42:39.000000000 +0300
320 +++ linux-2.4.21-suse2/fs/ext3/file.c   2004-02-06 10:19:59.000000000 +0300
321 @@ -70,6 +70,18 @@
322         int ret, err;
323         struct inode *inode = file->f_dentry->d_inode;
324  
325 +#if 0
326 +       /* allocate all the space to be written */
327 +       if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
328 +               int blocksize = inode->i_sb->s_blocksize;
329 +               unsigned long start, end;
330 +
331 +               start = (unsigned long) *ppos / blocksize;
332 +               end = ((unsigned long) *ppos + count + blocksize - 1)
333 +                               / blocksize;
334 +               ext3_ext_allocate_nblocks(inode, start, end - start);
335 +       }
336 +#endif
337         ret = generic_file_write(file, buf, count, ppos);
338  
339         /* Skip file flushing code if there was an error, or if nothing
340 Index: linux-2.4.21-suse2/fs/ext3/Makefile
341 ===================================================================
342 --- linux-2.4.21-suse2.orig/fs/ext3/Makefile    2004-02-05 20:43:47.000000000 +0300
343 +++ linux-2.4.21-suse2/fs/ext3/Makefile 2004-02-06 10:19:59.000000000 +0300
344 @@ -14,7 +14,7 @@
345  obj-y    := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
346                 ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
347                 extents.o
348 -export-objs += extents.o
349 +export-objs += extents.o balloc.o
350  obj-m    := $(O_TARGET)
351  
352  export-objs += xattr.o
353 Index: linux-2.4.21-suse2/include/linux/ext3_fs.h
354 ===================================================================
355 --- linux-2.4.21-suse2.orig/include/linux/ext3_fs.h     2004-02-05 20:42:40.000000000 +0300
356 +++ linux-2.4.21-suse2/include/linux/ext3_fs.h  2004-02-06 10:19:59.000000000 +0300
357 @@ -58,6 +58,8 @@
358  #define ext3_debug(f, a...)    do {} while (0)
359  #endif
360  
361 +#define EXT3_MULTIBLOCK_ALLOCATOR      1
362 +
363  /*
364   * Special inodes numbers
365   */
366 @@ -668,6 +670,7 @@
367  extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
368                                                     unsigned int block_group,
369                                                     struct buffer_head ** bh);
370 +extern int ext3_new_blocks(handle_t*, struct inode*, int*, unsigned long, int*);
371  
372  /* dir.c */
373  extern int ext3_check_dir_entry(const char *, struct inode *,