- Update to 3.3-rc2.
[linux-flexiantxendom0-3.2.10.git] / fs / ext4 / ialloc.c
index 926159d..2a6570a 100644 (file)
@@ -253,7 +253,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
                fatal = ext4_journal_get_write_access(handle, bh2);
        }
        ext4_lock_group(sb, block_group);
-       cleared = ext4_clear_bit(bit, bitmap_bh->b_data);
+       cleared = ext4_test_and_clear_bit(bit, bitmap_bh->b_data);
        if (fatal || !cleared) {
                ext4_unlock_group(sb, block_group);
                goto out;
@@ -352,14 +352,14 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
  */
 
 static int find_group_orlov(struct super_block *sb, struct inode *parent,
-                           ext4_group_t *group, int mode,
+                           ext4_group_t *group, umode_t mode,
                            const struct qstr *qstr)
 {
        ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        ext4_group_t real_ngroups = ext4_get_groups_count(sb);
        int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
-       unsigned int freei, avefreei;
+       unsigned int freei, avefreei, grp_free;
        ext4_fsblk_t freeb, avefreec;
        unsigned int ndirs;
        int max_dirs, min_inodes;
@@ -478,8 +478,8 @@ fallback_retry:
        for (i = 0; i < ngroups; i++) {
                grp = (parent_group + i) % ngroups;
                desc = ext4_get_group_desc(sb, grp, NULL);
-               if (desc && ext4_free_inodes_count(sb, desc) &&
-                   ext4_free_inodes_count(sb, desc) >= avefreei) {
+               grp_free = ext4_free_inodes_count(sb, desc);
+               if (desc && grp_free && grp_free >= avefreei) {
                        *group = grp;
                        return 0;
                }
@@ -498,7 +498,7 @@ fallback_retry:
 }
 
 static int find_group_other(struct super_block *sb, struct inode *parent,
-                           ext4_group_t *group, int mode)
+                           ext4_group_t *group, umode_t mode)
 {
        ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
        ext4_group_t i, last, ngroups = ext4_get_groups_count(sb);
@@ -603,7 +603,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
  */
 static int ext4_claim_inode(struct super_block *sb,
                        struct buffer_head *inode_bitmap_bh,
-                       unsigned long ino, ext4_group_t group, int mode)
+                       unsigned long ino, ext4_group_t group, umode_t mode)
 {
        int free = 0, retval = 0, count;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -619,7 +619,7 @@ static int ext4_claim_inode(struct super_block *sb,
         */
        down_read(&grp->alloc_sem);
        ext4_lock_group(sb, group);
-       if (ext4_set_bit(ino, inode_bitmap_bh->b_data)) {
+       if (ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data)) {
                /* not a free inode */
                retval = 1;
                goto err_ret;
@@ -691,7 +691,7 @@ err_ret:
  * For other inodes, search forward from the parent directory's block
  * group to find a free inode.
  */
-struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
                             const struct qstr *qstr, __u32 goal, uid_t *owner)
 {
        struct super_block *sb;
@@ -886,8 +886,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++;