]> err.no Git - linux-2.6/blobdiff - fs/ext4/balloc.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6] / fs / ext4 / balloc.c
index 6887151ccc479a7139bc1e50894a97e4de976c3b..8a23483ca8d0c3668e171bbc53c7a629a2403876 100644 (file)
  * balloc.c contains the blocks allocation and deallocation routines
  */
 
+/*
+ * Calculate the block group number and offset, given a block number
+ */
+void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+               unsigned long *blockgrpp, ext4_grpblk_t *offsetp)
+{
+        struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+       ext4_grpblk_t offset;
+
+        blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
+       offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb));
+       if (offsetp)
+               *offsetp = offset;
+       if (blockgrpp)
+               *blockgrpp = blocknr;
+
+}
+
 /*
  * The free blocks are managed by bitmaps.  A file system contains several
  * blocks groups.  Each group contains 1 bitmap block for blocks, 1 bitmap
@@ -32,7 +50,7 @@
  * The file system contains group descriptors which are located after the
  * super block.  Each descriptor contains the number of the bitmap block and
  * the free blocks count in the block.  The descriptors are loaded in memory
- * when a file system is mounted (see ext4_read_super).
+ * when a file system is mounted (see ext4_fill_super).
  */
 
 
@@ -74,10 +92,12 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
                return NULL;
        }
 
-       desc = (struct ext4_group_desc *) sbi->s_group_desc[group_desc]->b_data;
+       desc = (struct ext4_group_desc *)(
+               (__u8 *)sbi->s_group_desc[group_desc]->b_data +
+               offset * EXT4_DESC_SIZE(sb));
        if (bh)
                *bh = sbi->s_group_desc[group_desc];
-       return desc + offset;
+       return desc;
 }
 
 /**
@@ -99,13 +119,13 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
        desc = ext4_get_group_desc (sb, block_group, NULL);
        if (!desc)
                goto error_out;
-       bh = sb_bread(sb, ext4_block_bitmap(desc));
+       bh = sb_bread(sb, ext4_block_bitmap(sb, desc));
        if (!bh)
                ext4_error (sb, "read_block_bitmap",
                            "Cannot read block bitmap - "
-                           "block_group = %d, block_bitmap = "E3FSBLK,
+                           "block_group = %d, block_bitmap = %llu",
                            block_group,
-                           ext4_block_bitmap(desc));
+                           ext4_block_bitmap(sb, desc));
 error_out:
        return bh;
 }
@@ -145,10 +165,10 @@ restart:
 
        printk("Block Allocation Reservation Windows Map (%s):\n", fn);
        while (n) {
-               rsv = list_entry(n, struct ext4_reserve_window_node, rsv_node);
+               rsv = rb_entry(n, struct ext4_reserve_window_node, rsv_node);
                if (verbose)
                        printk("reservation window 0x%p "
-                              "start:  "E3FSBLK", end:  "E3FSBLK"\n",
+                              "start:  %llu, end:  %llu\n",
                               rsv, rsv->rsv_start, rsv->rsv_end);
                if (rsv->rsv_start && rsv->rsv_start >= rsv->rsv_end) {
                        printk("Bad reservation %p (start >= end)\n",
@@ -436,7 +456,7 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
            block + count > ext4_blocks_count(es)) {
                ext4_error (sb, "ext4_free_blocks",
                            "Freeing blocks not in datazone - "
-                           "block = "E3FSBLK", count = %lu", block, count);
+                           "block = %llu, count = %lu", block, count);
                goto error_return;
        }
 
@@ -461,14 +481,14 @@ do_more:
        if (!desc)
                goto error_return;
 
-       if (in_range(ext4_block_bitmap(desc), block, count) ||
-           in_range(ext4_inode_bitmap(desc), block, count) ||
-           in_range(block, ext4_inode_table(desc), sbi->s_itb_per_group) ||
-           in_range(block + count - 1, ext4_inode_table(desc),
+       if (in_range(ext4_block_bitmap(sb, desc), block, count) ||
+           in_range(ext4_inode_bitmap(sb, desc), block, count) ||
+           in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
+           in_range(block + count - 1, ext4_inode_table(sb, desc),
                     sbi->s_itb_per_group))
                ext4_error (sb, "ext4_free_blocks",
                            "Freeing blocks in system zones - "
-                           "Block = "E3FSBLK", count = %lu",
+                           "Block = %llu, count = %lu",
                            block, count);
 
        /*
@@ -552,7 +572,7 @@ do_more:
                                                bit + i, bitmap_bh->b_data)) {
                        jbd_unlock_bh_state(bitmap_bh);
                        ext4_error(sb, __FUNCTION__,
-                                  "bit already cleared for block "E3FSBLK,
+                                  "bit already cleared for block %llu",
                                   (ext4_fsblk_t)(block + i));
                        jbd_lock_bh_state(bitmap_bh);
                        BUFFER_TRACE(bitmap_bh, "bit already cleared");
@@ -727,7 +747,7 @@ find_next_usable_block(ext4_grpblk_t start, struct buffer_head *bh,
                here = 0;
 
        p = ((char *)bh->b_data) + (here >> 3);
-       r = memscan(p, 0, (maxblocks - here + 7) >> 3);
+       r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));
        next = (r - ((char *)bh->b_data)) << 3;
 
        if (next < maxblocks && next >= start && ext4_test_allocatable(next, bh))
@@ -946,7 +966,7 @@ static int find_next_reservable_window(
 
                prev = rsv;
                next = rb_next(&rsv->rsv_node);
-               rsv = list_entry(next,struct ext4_reserve_window_node,rsv_node);
+               rsv = rb_entry(next,struct ext4_reserve_window_node,rsv_node);
 
                /*
                 * Reached the last reservation, we can just append to the
@@ -1145,7 +1165,7 @@ retry:
         * check if the first free block is within the
         * free space we just reserved
         */
-       if (start_block >= my_rsv->rsv_start && start_block < my_rsv->rsv_end)
+       if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
                return 0;               /* success */
        /*
         * if the first free bit we found is out of the reservable space
@@ -1190,7 +1210,7 @@ static void try_to_extend_reservation(struct ext4_reserve_window_node *my_rsv,
        if (!next)
                my_rsv->rsv_end += size;
        else {
-               next_rsv = list_entry(next, struct ext4_reserve_window_node, rsv_node);
+               next_rsv = rb_entry(next, struct ext4_reserve_window_node, rsv_node);
 
                if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
                        my_rsv->rsv_end += size;
@@ -1268,7 +1288,7 @@ ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
        }
        /*
         * grp_goal is a group relative block number (if there is a goal)
-        * 0 < grp_goal < EXT4_BLOCKS_PER_GROUP(sb)
+        * 0 <= grp_goal < EXT4_BLOCKS_PER_GROUP(sb)
         * first block is a filesystem wide block number
         * first block is the block number of the first block in this group
         */
@@ -1304,10 +1324,14 @@ ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
                        if (!goal_in_my_reservation(&my_rsv->rsv_window,
                                                        grp_goal, group, sb))
                                grp_goal = -1;
-               } else if (grp_goal > 0 &&
-                         (my_rsv->rsv_end-grp_goal+1) < *count)
-                       try_to_extend_reservation(my_rsv, sb,
-                                       *count-my_rsv->rsv_end + grp_goal - 1);
+               } else if (grp_goal >= 0) {
+                       int curr = my_rsv->rsv_end -
+                                       (grp_goal + group_first_block) + 1;
+
+                       if (curr < *count)
+                               try_to_extend_reservation(my_rsv, sb,
+                                                       *count - curr);
+               }
 
                if ((my_rsv->rsv_start > group_last_block) ||
                                (my_rsv->rsv_end < group_first_block)) {
@@ -1505,10 +1529,8 @@ retry_alloc:
                if (group_no >= ngroups)
                        group_no = 0;
                gdp = ext4_get_group_desc(sb, group_no, &gdp_bh);
-               if (!gdp) {
-                       *errp = -EIO;
-                       goto out;
-               }
+               if (!gdp)
+                       goto io_error;
                free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
                /*
                 * skip this group if the number of
@@ -1542,6 +1564,7 @@ retry_alloc:
         */
        if (my_rsv) {
                my_rsv = NULL;
+               windowsz = 0;
                group_no = goal_group;
                goto retry_alloc;
        }
@@ -1561,15 +1584,15 @@ allocated:
 
        ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no);
 
-       if (in_range(ext4_block_bitmap(gdp), ret_block, num) ||
-           in_range(ext4_block_bitmap(gdp), ret_block, num) ||
-           in_range(ret_block, ext4_inode_table(gdp),
+       if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+           in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+           in_range(ret_block, ext4_inode_table(sb, gdp),
                     EXT4_SB(sb)->s_itb_per_group) ||
-           in_range(ret_block + num - 1, ext4_inode_table(gdp),
+           in_range(ret_block + num - 1, ext4_inode_table(sb, gdp),
                     EXT4_SB(sb)->s_itb_per_group))
                ext4_error(sb, "ext4_new_block",
                            "Allocating block in system zone - "
-                           "blocks from "E3FSBLK", length %lu",
+                           "blocks from %llu, length %lu",
                             ret_block, num);
 
        performed_allocation = 1;
@@ -1606,7 +1629,7 @@ allocated:
 
        if (ret_block + num - 1 >= ext4_blocks_count(es)) {
                ext4_error(sb, "ext4_new_block",
-                           "block("E3FSBLK") >= blocks count("E3FSBLK") - "
+                           "block(%llu) >= blocks count(%llu) - "
                            "block_group = %lu, es == %p ", ret_block,
                        ext4_blocks_count(es), group_no, es);
                goto out;
@@ -1705,8 +1728,8 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
                bitmap_count += x;
        }
        brelse(bitmap_bh);
-       printk("ext4_count_free_blocks: stored = "E3FSBLK
-               ", computed = "E3FSBLK", "E3FSBLK"\n",
+       printk("ext4_count_free_blocks: stored = %llu"
+               ", computed = %llu, %llu\n",
               EXT4_FREE_BLOCKS_COUNT(es),
                desc_count, bitmap_count);
        return bitmap_count;