]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/gnu/ext2fs/ext2_linux_balloc.c
This commit was generated by cvs2svn to compensate for changes in r43892,
[FreeBSD/FreeBSD.git] / sys / gnu / ext2fs / ext2_linux_balloc.c
1 /*
2  *  modified for Lites 1.1
3  *
4  *  Aug 1995, Godmar Back (gback@cs.utah.edu)
5  *  University of Utah, Department of Computer Science
6  */
7 /*
8  *  linux/fs/ext2/balloc.c
9  *
10  * Copyright (C) 1992, 1993, 1994, 1995
11  * Remy Card (card@masi.ibp.fr)
12  * Laboratoire MASI - Institut Blaise Pascal
13  * Universite Pierre et Marie Curie (Paris VI)
14  *
15  *  Enhanced block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
16  */
17
18 /*
19  * The free blocks are managed by bitmaps.  A file system contains several
20  * blocks groups.  Each group contains 1 bitmap block for blocks, 1 bitmap
21  * block for inodes, N blocks for the inode table and data blocks.
22  *
23  * The file system contains group descriptors which are located after the
24  * super block.  Each descriptor contains the number of the bitmap block and
25  * the free blocks count in the block.  The descriptors are loaded in memory
26  * when a file system is mounted (see ext2_read_super).
27  */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/proc.h>
32 #include <sys/mount.h>
33 #include <sys/vnode.h>
34
35 #include <ufs/ufs/quota.h>
36 #include <ufs/ufs/ufsmount.h>
37 #include <gnu/ext2fs/ext2_extern.h>
38 #include <gnu/ext2fs/ext2_fs.h>
39 #include <gnu/ext2fs/ext2_fs_sb.h>
40 #include <gnu/ext2fs/fs.h>
41
42 #ifdef __i386__
43 #include <gnu/ext2fs/i386-bitops.h>
44 #else
45 #error Provide an bitops.h file, please !
46 #endif
47
48 #define in_range(b, first, len)         ((b) >= (first) && (b) <= (first) + (len) - 1)
49
50 /* got rid of get_group_desc since it can already be found in 
51  * ext2_linux_ialloc.c
52  */
53
54 static void read_block_bitmap (struct mount * mp,
55                                unsigned int block_group,
56                                unsigned long bitmap_nr)
57 {
58         struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
59         struct ext2_group_desc * gdp;
60         struct buffer_head * bh;
61         int    error;
62         
63         gdp = get_group_desc (mp, block_group, NULL);
64         if ((error = bread (VFSTOUFS(mp)->um_devvp, 
65                 fsbtodb(sb, gdp->bg_block_bitmap),sb->s_blocksize, NOCRED, &bh)) != 0)
66                 panic ( "read_block_bitmap: "
67                             "Cannot read block bitmap - "
68                             "block_group = %d, block_bitmap = %lu",
69                             block_group, (unsigned long) gdp->bg_block_bitmap);
70         sb->s_block_bitmap_number[bitmap_nr] = block_group;
71         sb->s_block_bitmap[bitmap_nr] = bh;
72         LCK_BUF(bh)
73 }
74
75 /*
76  * load_block_bitmap loads the block bitmap for a blocks group
77  *
78  * It maintains a cache for the last bitmaps loaded.  This cache is managed
79  * with a LRU algorithm.
80  *
81  * Notes:
82  * 1/ There is one cache per mounted file system.
83  * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
84  *    this function reads the bitmap without maintaining a LRU cache.
85  */
86 static int load__block_bitmap (struct mount * mp,
87                                unsigned int block_group)
88 {
89         int i, j;
90         struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
91         unsigned long block_bitmap_number;
92         struct buffer_head * block_bitmap;
93
94         if (block_group >= sb->s_groups_count)
95                 panic ( "load_block_bitmap: "
96                             "block_group >= groups_count - "
97                             "block_group = %d, groups_count = %lu",
98                             block_group, sb->s_groups_count);
99
100         if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED) {
101                 if (sb->s_block_bitmap[block_group]) {
102                         if (sb->s_block_bitmap_number[block_group] !=
103                             block_group)
104                                 panic ( "load_block_bitmap: "
105                                             "block_group != block_bitmap_number");
106                         else
107                                 return block_group;
108                 } else {
109                         read_block_bitmap (mp, block_group, block_group);
110                         return block_group;
111                 }
112         }
113
114         for (i = 0; i < sb->s_loaded_block_bitmaps &&
115                     sb->s_block_bitmap_number[i] != block_group; i++)
116                 ;
117         if (i < sb->s_loaded_block_bitmaps &&
118             sb->s_block_bitmap_number[i] == block_group) {
119                 block_bitmap_number = sb->s_block_bitmap_number[i];
120                 block_bitmap = sb->s_block_bitmap[i];
121                 for (j = i; j > 0; j--) {
122                         sb->s_block_bitmap_number[j] =
123                                 sb->s_block_bitmap_number[j - 1];
124                         sb->s_block_bitmap[j] =
125                                 sb->s_block_bitmap[j - 1];
126                 }
127                 sb->s_block_bitmap_number[0] = block_bitmap_number;
128                 sb->s_block_bitmap[0] = block_bitmap;
129         } else {
130                 if (sb->s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
131                         sb->s_loaded_block_bitmaps++;
132                 else
133                         ULCK_BUF(sb->s_block_bitmap[EXT2_MAX_GROUP_LOADED - 1])
134
135                 for (j = sb->s_loaded_block_bitmaps - 1; j > 0;  j--) {
136                         sb->s_block_bitmap_number[j] =
137                                 sb->s_block_bitmap_number[j - 1];
138                         sb->s_block_bitmap[j] =
139                                 sb->s_block_bitmap[j - 1];
140                 }
141                 read_block_bitmap (mp, block_group, 0);
142         }
143         return 0;
144 }
145
146 static __inline int load_block_bitmap (struct mount * mp,
147                                        unsigned int block_group)
148 {
149         struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
150         if (sb->s_loaded_block_bitmaps > 0 &&
151             sb->s_block_bitmap_number[0] == block_group)
152                 return 0;
153         
154         if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED && 
155             sb->s_block_bitmap_number[block_group] == block_group &&
156             sb->s_block_bitmap[block_group]) 
157                 return block_group;
158
159         return load__block_bitmap (mp, block_group);
160 }
161
162 void ext2_free_blocks (struct mount * mp, unsigned long block,
163                        unsigned long count)
164 {
165         struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
166         struct buffer_head * bh;
167         struct buffer_head * bh2;
168         unsigned long block_group;
169         unsigned long bit;
170         unsigned long i;
171         int bitmap_nr;
172         struct ext2_group_desc * gdp;
173         struct ext2_super_block * es = sb->s_es;
174
175         if (!sb) {
176                 printf ("ext2_free_blocks: nonexistent device");
177                 return;
178         }
179         lock_super (VFSTOUFS(mp)->um_devvp);
180         if (block < es->s_first_data_block || 
181             (block + count) > es->s_blocks_count) {
182                 printf ( "ext2_free_blocks: "
183                             "Freeing blocks not in datazone - "
184                             "block = %lu, count = %lu", block, count);
185                 unlock_super (VFSTOUFS(mp)->um_devvp);
186                 return;
187         }
188
189         ext2_debug ("freeing blocks %lu to %lu\n", block, block+count-1);
190
191         block_group = (block - es->s_first_data_block) /
192                       EXT2_BLOCKS_PER_GROUP(sb);
193         bit = (block - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb);
194         if (bit + count > EXT2_BLOCKS_PER_GROUP(sb))
195                 panic ( "ext2_free_blocks: "
196                             "Freeing blocks across group boundary - "
197                             "Block = %lu, count = %lu",
198                             block, count);
199         bitmap_nr = load_block_bitmap (mp, block_group);
200         bh = sb->s_block_bitmap[bitmap_nr];
201         gdp = get_group_desc (mp, block_group, &bh2);
202
203         if (/* test_opt (sb, CHECK_STRICT) &&   assume always strict ! */
204             (in_range (gdp->bg_block_bitmap, block, count) ||
205              in_range (gdp->bg_inode_bitmap, block, count) ||
206              in_range (block, gdp->bg_inode_table,
207                        sb->s_itb_per_group) ||
208              in_range (block + count - 1, gdp->bg_inode_table,
209                        sb->s_itb_per_group)))
210                 panic ( "ext2_free_blocks: "
211                             "Freeing blocks in system zones - "
212                             "Block = %lu, count = %lu",
213                             block, count);
214
215         for (i = 0; i < count; i++) {
216                 if (!clear_bit (bit + i, bh->b_data))
217                         printf ("ext2_free_blocks: "
218                                       "bit already cleared for block %lu", 
219                                       block);
220                 else {
221                         gdp->bg_free_blocks_count++;
222                         es->s_free_blocks_count++;
223                 }
224         }
225
226         mark_buffer_dirty(bh2);
227         mark_buffer_dirty(bh);
228 /****
229         if (sb->s_flags & MS_SYNCHRONOUS) {
230                 ll_rw_block (WRITE, 1, &bh);
231                 wait_on_buffer (bh);
232         }
233 ****/
234         sb->s_dirt = 1;
235         unlock_super (VFSTOUFS(mp)->um_devvp);
236         return;
237 }
238
239 /*
240  * ext2_new_block uses a goal block to assist allocation.  If the goal is
241  * free, or there is a free block within 32 blocks of the goal, that block
242  * is allocated.  Otherwise a forward search is made for a free block; within 
243  * each block group the search first looks for an entire free byte in the block
244  * bitmap, and then for any free bit if that fails.
245  */
246 int ext2_new_block (struct mount * mp, unsigned long goal,
247                     u_int32_t * prealloc_count,
248                     u_int32_t * prealloc_block)
249 {
250         struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
251         struct buffer_head * bh;
252         struct buffer_head * bh2;
253         char * p, * r;
254         int i, j, k, tmp;
255         int bitmap_nr;
256         struct ext2_group_desc * gdp;
257         struct ext2_super_block * es = sb->s_es;
258
259 #ifdef EXT2FS_DEBUG
260         static int goal_hits = 0, goal_attempts = 0;
261 #endif
262         if (!sb) {
263                 printf ("ext2_new_block: nonexistent device");
264                 return 0;
265         }
266         lock_super (VFSTOUFS(mp)->um_devvp);
267
268         ext2_debug ("goal=%lu.\n", goal);
269
270 repeat:
271         /*
272          * First, test whether the goal block is free.
273          */
274         if (goal < es->s_first_data_block || goal >= es->s_blocks_count)
275                 goal = es->s_first_data_block;
276         i = (goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb);
277         gdp = get_group_desc (mp, i, &bh2);
278         if (gdp->bg_free_blocks_count > 0) {
279                 j = ((goal - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb));
280 #ifdef EXT2FS_DEBUG
281                 if (j)
282                         goal_attempts++;
283 #endif
284                 bitmap_nr = load_block_bitmap (mp, i);
285                 bh = sb->s_block_bitmap[bitmap_nr];
286
287                 ext2_debug ("goal is at %d:%d.\n", i, j); 
288
289                 if (!test_bit(j, bh->b_data)) {
290 #ifdef EXT2FS_DEBUG
291                         goal_hits++;
292                         ext2_debug ("goal bit allocated.\n");
293 #endif
294                         goto got_block;
295                 }
296                 if (j) {
297                         /*
298                          * The goal was occupied; search forward for a free 
299                          * block within the next XX blocks.
300                          *
301                          * end_goal is more or less random, but it has to be
302                          * less than EXT2_BLOCKS_PER_GROUP. Aligning up to the
303                          * next 64-bit boundary is simple..
304                          */
305                         int end_goal = (j + 63) & ~63;
306                         j = find_next_zero_bit(bh->b_data, end_goal, j);
307                         if (j < end_goal)
308                                 goto got_block;
309                 }
310         
311                 ext2_debug ("Bit not found near goal\n");
312
313                 /*
314                  * There has been no free block found in the near vicinity
315                  * of the goal: do a search forward through the block groups,
316                  * searching in each group first for an entire free byte in
317                  * the bitmap and then for any free bit.
318                  * 
319                  * Search first in the remainder of the current group; then,
320                  * cyclicly search through the rest of the groups.
321                  */
322                 p = ((char *) bh->b_data) + (j >> 3);
323                 r = memscan(p, 0, (EXT2_BLOCKS_PER_GROUP(sb) - j + 7) >> 3);
324                 k = (r - ((char *) bh->b_data)) << 3;
325                 if (k < EXT2_BLOCKS_PER_GROUP(sb)) {
326                         j = k;
327                         goto search_back;
328                 }
329                 k = find_next_zero_bit ((unsigned long *) bh->b_data, 
330                                         EXT2_BLOCKS_PER_GROUP(sb),
331                                         j);
332                 if (k < EXT2_BLOCKS_PER_GROUP(sb)) {
333                         j = k;
334                         goto got_block;
335                 }
336         }
337
338         ext2_debug ("Bit not found in block group %d.\n", i); 
339
340         /*
341          * Now search the rest of the groups.  We assume that 
342          * i and gdp correctly point to the last group visited.
343          */
344         for (k = 0; k < sb->s_groups_count; k++) {
345                 i++;
346                 if (i >= sb->s_groups_count)
347                         i = 0;
348                 gdp = get_group_desc (mp, i, &bh2);
349                 if (gdp->bg_free_blocks_count > 0)
350                         break;
351         }
352         if (k >= sb->s_groups_count) {
353                 unlock_super (VFSTOUFS(mp)->um_devvp);
354                 return 0;
355         }
356         bitmap_nr = load_block_bitmap (mp, i);
357         bh = sb->s_block_bitmap[bitmap_nr];
358         r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);
359         j = (r - bh->b_data) << 3;
360
361         if (j < EXT2_BLOCKS_PER_GROUP(sb))
362                 goto search_back;
363         else
364                 j = find_first_zero_bit ((unsigned long *) bh->b_data,
365                                          EXT2_BLOCKS_PER_GROUP(sb));
366         if (j >= EXT2_BLOCKS_PER_GROUP(sb)) {
367                 printf ( "ext2_new_block: "
368                          "Free blocks count corrupted for block group %d", i);
369                 unlock_super (VFSTOUFS(mp)->um_devvp);
370                 return 0;
371         }
372
373 search_back:
374         /* 
375          * We have succeeded in finding a free byte in the block
376          * bitmap.  Now search backwards up to 7 bits to find the
377          * start of this group of free blocks.
378          */
379         for (k = 0; k < 7 && j > 0 && !test_bit (j - 1, bh->b_data); k++, j--);
380         
381 got_block:
382
383         ext2_debug ("using block group %d(%d)\n", i, gdp->bg_free_blocks_count);
384
385         tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + es->s_first_data_block;
386
387         if (/* test_opt (sb, CHECK_STRICT) && we are always strict. */
388             (tmp == gdp->bg_block_bitmap ||
389              tmp == gdp->bg_inode_bitmap ||
390              in_range (tmp, gdp->bg_inode_table, sb->s_itb_per_group)))
391                 panic ( "ext2_new_block: "
392                             "Allocating block in system zone - "
393                             "%dth block = %u in group %u", j, tmp, i);
394
395         if (set_bit (j, bh->b_data)) {
396                 printf ( "ext2_new_block: "
397                          "bit already set for block %d", j);
398                 goto repeat;
399         }
400
401         ext2_debug ("found bit %d\n", j);
402
403         /*
404          * Do block preallocation now if required.
405          */
406 #ifdef EXT2_PREALLOCATE
407         if (prealloc_block) {
408                 *prealloc_count = 0;
409                 *prealloc_block = tmp + 1;
410                 for (k = 1;
411                      k < 8 && (j + k) < EXT2_BLOCKS_PER_GROUP(sb); k++) {
412                         if (set_bit (j + k, bh->b_data))
413                                 break;
414                         (*prealloc_count)++;
415                 }       
416                 gdp->bg_free_blocks_count -= *prealloc_count;
417                 es->s_free_blocks_count -= *prealloc_count;
418                 ext2_debug ("Preallocated a further %lu bits.\n",
419                             *prealloc_count); 
420         }
421 #endif
422
423         j = tmp;
424
425         mark_buffer_dirty(bh);
426 /****
427         if (sb->s_flags & MS_SYNCHRONOUS) {
428                 ll_rw_block (WRITE, 1, &bh);
429                 wait_on_buffer (bh);
430         }
431 ****/
432         if (j >= es->s_blocks_count) {
433                 printf ( "ext2_new_block: "
434                             "block >= blocks count - "
435                             "block_group = %d, block=%d", i, j);
436                 unlock_super (VFSTOUFS(mp)->um_devvp);
437                 return 0;
438         }
439
440         ext2_debug ("allocating block %d. "
441                     "Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
442
443         gdp->bg_free_blocks_count--;
444         mark_buffer_dirty(bh2);
445         es->s_free_blocks_count--;
446         sb->s_dirt = 1;
447         unlock_super (VFSTOUFS(mp)->um_devvp);
448         return j;
449 }
450
451 #ifdef unused
452 static unsigned long ext2_count_free_blocks (struct mount * mp)
453 {
454         struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
455 #ifdef EXT2FS_DEBUG
456         struct ext2_super_block * es;
457         unsigned long desc_count, bitmap_count, x;
458         int bitmap_nr;
459         struct ext2_group_desc * gdp;
460         int i;
461         
462         lock_super (VFSTOUFS(mp)->um_devvp);
463         es = sb->s_es;
464         desc_count = 0;
465         bitmap_count = 0;
466         gdp = NULL;
467         for (i = 0; i < sb->s_groups_count; i++) {
468                 gdp = get_group_desc (mp, i, NULL);
469                 desc_count += gdp->bg_free_blocks_count;
470                 bitmap_nr = load_block_bitmap (mp, i);
471                 x = ext2_count_free (sb->s_block_bitmap[bitmap_nr],
472                                      sb->s_blocksize);
473                 ext2_debug ("group %d: stored = %d, counted = %lu\n",
474                         i, gdp->bg_free_blocks_count, x);
475                 bitmap_count += x;
476         }
477         ext2_debug( "stored = %lu, computed = %lu, %lu\n",
478                es->s_free_blocks_count, desc_count, bitmap_count);
479         unlock_super (VFSTOUFS(mp)->um_devvp);
480         return bitmap_count;
481 #else
482         return sb->s_es->s_free_blocks_count;
483 #endif
484 }
485 #endif /* unused */
486
487 static __inline int block_in_use (unsigned long block,
488                                   struct ext2_sb_info * sb,
489                                   unsigned char * map)
490 {
491         return test_bit ((block - sb->s_es->s_first_data_block) %
492                          EXT2_BLOCKS_PER_GROUP(sb), map);
493 }
494
495 #ifdef unused
496 static void ext2_check_blocks_bitmap (struct mount * mp)
497 {
498         struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
499         struct buffer_head * bh;
500         struct ext2_super_block * es;
501         unsigned long desc_count, bitmap_count, x;
502         unsigned long desc_blocks;
503         int bitmap_nr;
504         struct ext2_group_desc * gdp;
505         int i, j;
506
507         lock_super (VFSTOUFS(mp)->um_devvp);
508         es = sb->s_es;
509         desc_count = 0;
510         bitmap_count = 0;
511         gdp = NULL;
512         desc_blocks = (sb->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
513                       EXT2_DESC_PER_BLOCK(sb);
514         for (i = 0; i < sb->s_groups_count; i++) {
515                 gdp = get_group_desc (mp, i, NULL);
516                 desc_count += gdp->bg_free_blocks_count;
517                 bitmap_nr = load_block_bitmap (mp, i);
518                 bh = sb->s_block_bitmap[bitmap_nr];
519
520                 if (!test_bit (0, bh->b_data))
521                         printf ( "ext2_check_blocks_bitmap: "
522                                     "Superblock in group %d is marked free", i);
523
524                 for (j = 0; j < desc_blocks; j++)
525                         if (!test_bit (j + 1, bh->b_data))
526                                 printf ("ext2_check_blocks_bitmap: "
527                                             "Descriptor block #%d in group "
528                                             "%d is marked free", j, i);
529
530                 if (!block_in_use (gdp->bg_block_bitmap, sb, bh->b_data))
531                         printf ("ext2_check_blocks_bitmap: "
532                                     "Block bitmap for group %d is marked free",
533                                     i);
534
535                 if (!block_in_use (gdp->bg_inode_bitmap, sb, bh->b_data))
536                         printf ("ext2_check_blocks_bitmap: "
537                                     "Inode bitmap for group %d is marked free",
538                                     i);
539
540                 for (j = 0; j < sb->s_itb_per_group; j++)
541                         if (!block_in_use (gdp->bg_inode_table + j, sb, bh->b_data))
542                                 printf ("ext2_check_blocks_bitmap: "
543                                             "Block #%d of the inode table in "
544                                             "group %d is marked free", j, i);
545
546                 x = ext2_count_free (bh, sb->s_blocksize);
547                 if (gdp->bg_free_blocks_count != x)
548                         printf ("ext2_check_blocks_bitmap: "
549                                     "Wrong free blocks count for group %d, "
550                                     "stored = %d, counted = %lu", i,
551                                     gdp->bg_free_blocks_count, x);
552                 bitmap_count += x;
553         }
554         if (es->s_free_blocks_count != bitmap_count)
555                 printf ("ext2_check_blocks_bitmap: "
556                             "Wrong free blocks count in super block, "
557                             "stored = %lu, counted = %lu",
558                             (unsigned long) es->s_free_blocks_count, bitmap_count);
559         unlock_super (VFSTOUFS(mp)->um_devvp);
560 }
561 #endif /* unused */
562
563 /*
564  *  this function is taken from 
565  *  linux/fs/ext2/bitmap.c
566  */
567
568 static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
569
570 unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
571 {
572         unsigned int i;
573         unsigned long sum = 0;
574
575         if (!map)
576                 return (0);
577         for (i = 0; i < numchars; i++)
578                 sum += nibblemap[map->b_data[i] & 0xf] +
579                         nibblemap[(map->b_data[i] >> 4) & 0xf];
580         return (sum);
581 }