netlink: make sure nladdr has correct size in netlink_connect()
[pandora-kernel.git] / fs / ext4 / ialloc.c
index 00beb4f..9603b79 100644 (file)
@@ -102,6 +102,7 @@ static struct buffer_head *
 ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
 {
        struct ext4_group_desc *desc;
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct buffer_head *bh = NULL;
        ext4_fsblk_t bitmap_blk;
 
@@ -110,6 +111,12 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
                return NULL;
 
        bitmap_blk = ext4_inode_bitmap(sb, desc);
+       if ((bitmap_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) ||
+           (bitmap_blk >= ext4_blocks_count(sbi->s_es))) {
+               ext4_error(sb, "Invalid inode bitmap blk %llu in "
+                          "block_group %u", bitmap_blk, block_group);
+               return NULL;
+       }
        bh = sb_getblk(sb, bitmap_blk);
        if (unlikely(!bh)) {
                ext4_error(sb, "Cannot read inode bitmap - "
@@ -294,8 +301,8 @@ error_return:
 }
 
 struct orlov_stats {
+       __u64 free_clusters;
        __u32 free_inodes;
-       __u32 free_clusters;
        __u32 used_dirs;
 };
 
@@ -312,7 +319,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
 
        if (flex_size > 1) {
                stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
-               stats->free_clusters = atomic_read(&flex_group[g].free_clusters);
+               stats->free_clusters = atomic64_read(&flex_group[g].free_clusters);
                stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
                return;
        }
@@ -813,6 +820,10 @@ got:
                struct buffer_head *block_bitmap_bh;
 
                block_bitmap_bh = ext4_read_block_bitmap(sb, group);
+               if (!block_bitmap_bh) {
+                       err = -EIO;
+                       goto out;
+               }
                BUFFER_TRACE(block_bitmap_bh, "get block bitmap access");
                err = ext4_journal_get_write_access(handle, block_bitmap_bh);
                if (err) {
@@ -885,8 +896,12 @@ got:
        if (IS_DIRSYNC(inode))
                ext4_handle_sync(handle);
        if (insert_inode_locked(inode) < 0) {
-               err = -EINVAL;
-               goto fail_drop;
+               /*
+                * Likely a bitmap corruption causing inode to be allocated
+                * twice.
+                */
+               err = -EIO;
+               goto fail;
        }
        spin_lock(&sbi->s_next_gen_lock);
        inode->i_generation = sbi->s_next_generation++;
@@ -991,11 +1006,13 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
                goto iget_failed;
 
        /*
-        * If the orphans has i_nlinks > 0 then it should be able to be
-        * truncated, otherwise it won't be removed from the orphan list
-        * during processing and an infinite loop will result.
+        * If the orphans has i_nlinks > 0 then it should be able to
+        * be truncated, otherwise it won't be removed from the orphan
+        * list during processing and an infinite loop will result.
+        * Similarly, it must not be a bad inode.
         */
-       if (inode->i_nlink && !ext4_can_truncate(inode))
+       if ((inode->i_nlink && !ext4_can_truncate(inode)) ||
+           is_bad_inode(inode))
                goto bad_orphan;
 
        if (NEXT_ORPHAN(inode) > max_ino)
@@ -1053,7 +1070,8 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
                if (!bitmap_bh)
                        continue;
 
-               x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8);
+               x = ext4_count_free(bitmap_bh->b_data,
+                                   EXT4_INODES_PER_GROUP(sb) / 8);
                printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n",
                        (unsigned long) i, ext4_free_inodes_count(sb, gdp), x);
                bitmap_count += x;