]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ext3/balloc.c
natsemi: fix oops, link back netdevice from private-struct
[linux-2.6-omap-h63xx.git] / fs / ext3 / balloc.c
index b41a7d7e20f006bc7e85a6e4b2315cf38ee2fdc9..7a87d15523be62f1d33c72c4d8a2eba359d45237 100644 (file)
@@ -32,7 +32,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 ext3_read_super).
+ * when a file system is mounted (see ext3_fill_super).
  */
 
 
@@ -80,6 +80,14 @@ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
        return desc + offset;
 }
 
+static inline int
+block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map)
+{
+       return ext3_test_bit ((block -
+               le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
+                        EXT3_BLOCKS_PER_GROUP(sb), map);
+}
+
 /**
  * read_block_bitmap()
  * @sb:                        super block
@@ -93,20 +101,51 @@ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
 static struct buffer_head *
 read_block_bitmap(struct super_block *sb, unsigned int block_group)
 {
+       int i;
        struct ext3_group_desc * desc;
        struct buffer_head * bh = NULL;
+       ext3_fsblk_t bitmap_blk;
 
        desc = ext3_get_group_desc (sb, block_group, NULL);
        if (!desc)
-               goto error_out;
-       bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
+               return NULL;
+       bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
+       bh = sb_bread(sb, bitmap_blk);
        if (!bh)
-               ext3_error (sb, "read_block_bitmap",
+               ext3_error (sb, __FUNCTION__,
                            "Cannot read block bitmap - "
                            "block_group = %d, block_bitmap = %u",
                            block_group, le32_to_cpu(desc->bg_block_bitmap));
-error_out:
+
+       /* check whether block bitmap block number is set */
+       if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
+               /* bad block bitmap */
+               goto error_out;
+       }
+       /* check whether the inode bitmap block number is set */
+       bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap);
+       if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
+               /* bad block bitmap */
+               goto error_out;
+       }
+       /* check whether the inode table block number is set */
+       bitmap_blk = le32_to_cpu(desc->bg_inode_table);
+       for (i = 0; i < EXT3_SB(sb)->s_itb_per_group; i++, bitmap_blk++) {
+               if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
+                       /* bad block bitmap */
+                       goto error_out;
+               }
+       }
+
        return bh;
+
+error_out:
+       brelse(bh);
+       ext3_error(sb, __FUNCTION__,
+                       "Invalid block bitmap - "
+                       "block_group = %d, block = %lu",
+                       block_group, bitmap_blk);
+       return NULL;
 }
 /*
  * The reservation window structure operations
@@ -144,7 +183,7 @@ restart:
 
        printk("Block Allocation Reservation Windows Map (%s):\n", fn);
        while (n) {
-               rsv = list_entry(n, struct ext3_reserve_window_node, rsv_node);
+               rsv = rb_entry(n, struct ext3_reserve_window_node, rsv_node);
                if (verbose)
                        printk("reservation window 0x%p "
                               "start:  %lu, end:  %lu\n",
@@ -570,7 +609,7 @@ do_more:
                cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
                        group_freed);
        spin_unlock(sb_bgl_lock(sbi, block_group));
-       percpu_counter_mod(&sbi->s_freeblocks_counter, count);
+       percpu_counter_add(&sbi->s_freeblocks_counter, count);
 
        /* We dirtied the bitmap block */
        BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
@@ -730,7 +769,7 @@ find_next_usable_block(ext3_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 && ext3_test_allocatable(next, bh))
@@ -949,7 +988,7 @@ static int find_next_reservable_window(
 
                prev = rsv;
                next = rb_next(&rsv->rsv_node);
-               rsv = list_entry(next,struct ext3_reserve_window_node,rsv_node);
+               rsv = rb_entry(next,struct ext3_reserve_window_node,rsv_node);
 
                /*
                 * Reached the last reservation, we can just append to the
@@ -1148,7 +1187,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
@@ -1193,7 +1232,7 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
        if (!next)
                my_rsv->rsv_end += size;
        else {
-               next_rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node);
+               next_rsv = rb_entry(next, struct ext3_reserve_window_node, rsv_node);
 
                if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
                        my_rsv->rsv_end += size;
@@ -1271,7 +1310,7 @@ ext3_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 < EXT3_BLOCKS_PER_GROUP(sb)
+        * 0 <= grp_goal < EXT3_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
         */
@@ -1307,10 +1346,14 @@ ext3_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)) {
@@ -1511,10 +1554,8 @@ retry_alloc:
                if (group_no >= ngroups)
                        group_no = 0;
                gdp = ext3_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
@@ -1548,6 +1589,7 @@ retry_alloc:
         */
        if (my_rsv) {
                my_rsv = NULL;
+               windowsz = 0;
                group_no = goal_group;
                goto retry_alloc;
        }
@@ -1630,7 +1672,7 @@ allocated:
        gdp->bg_free_blocks_count =
                        cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num);
        spin_unlock(sb_bgl_lock(sbi, group_no));
-       percpu_counter_mod(&sbi->s_freeblocks_counter, -num);
+       percpu_counter_sub(&sbi->s_freeblocks_counter, num);
 
        BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor");
        err = ext3_journal_dirty_metadata(handle, gdp_bh);
@@ -1730,13 +1772,6 @@ ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb)
 #endif
 }
 
-static inline int
-block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map)
-{
-       return ext3_test_bit ((block -
-               le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
-                        EXT3_BLOCKS_PER_GROUP(sb), map);
-}
 
 static inline int test_root(int a, int b)
 {