Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs into for-2.6.34-incoming
[safe/jmp/linux-2.6] / fs / ext3 / resize.c
index 7a9dac1..54351ac 100644 (file)
@@ -48,60 +48,60 @@ static int verify_group_input(struct super_block *sb,
                       free_blocks_count, input->reserved_blocks);
 
        if (group != sbi->s_groups_count)
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Cannot add at group %u (only %lu groups)",
                             input->group, sbi->s_groups_count);
        else if ((start - le32_to_cpu(es->s_first_data_block)) %
                 EXT3_BLOCKS_PER_GROUP(sb))
-               ext3_warning(sb, __FUNCTION__, "Last group not full");
+               ext3_warning(sb, __func__, "Last group not full");
        else if (input->reserved_blocks > input->blocks_count / 5)
-               ext3_warning(sb, __FUNCTION__, "Reserved blocks too high (%u)",
+               ext3_warning(sb, __func__, "Reserved blocks too high (%u)",
                             input->reserved_blocks);
        else if (free_blocks_count < 0)
-               ext3_warning(sb, __FUNCTION__, "Bad blocks count %u",
+               ext3_warning(sb, __func__, "Bad blocks count %u",
                             input->blocks_count);
        else if (!(bh = sb_bread(sb, end - 1)))
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Cannot read last block ("E3FSBLK")",
                             end - 1);
        else if (outside(input->block_bitmap, start, end))
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Block bitmap not in group (block %u)",
                             input->block_bitmap);
        else if (outside(input->inode_bitmap, start, end))
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Inode bitmap not in group (block %u)",
                             input->inode_bitmap);
        else if (outside(input->inode_table, start, end) ||
                 outside(itend - 1, start, end))
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Inode table not in group (blocks %u-"E3FSBLK")",
                             input->inode_table, itend - 1);
        else if (input->inode_bitmap == input->block_bitmap)
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Block bitmap same as inode bitmap (%u)",
                             input->block_bitmap);
        else if (inside(input->block_bitmap, input->inode_table, itend))
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Block bitmap (%u) in inode table (%u-"E3FSBLK")",
                             input->block_bitmap, input->inode_table, itend-1);
        else if (inside(input->inode_bitmap, input->inode_table, itend))
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Inode bitmap (%u) in inode table (%u-"E3FSBLK")",
                             input->inode_bitmap, input->inode_table, itend-1);
        else if (inside(input->block_bitmap, start, metaend))
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Block bitmap (%u) in GDT table"
                             " ("E3FSBLK"-"E3FSBLK")",
                             input->block_bitmap, start, metaend - 1);
        else if (inside(input->inode_bitmap, start, metaend))
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Inode bitmap (%u) in GDT table"
                             " ("E3FSBLK"-"E3FSBLK")",
                             input->inode_bitmap, start, metaend - 1);
        else if (inside(input->inode_table, start, metaend) ||
                 inside(itend - 1, start, metaend))
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Inode table (%u-"E3FSBLK") overlaps"
                             "GDT table ("E3FSBLK"-"E3FSBLK")",
                             input->inode_table, itend - 1, start, metaend - 1);
@@ -209,7 +209,7 @@ static int setup_new_group_blocks(struct super_block *sb,
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_resize_lock);
        if (input->group != sbi->s_groups_count) {
                err = -EBUSY;
                goto exit_journal;
@@ -266,7 +266,7 @@ static int setup_new_group_blocks(struct super_block *sb,
                        goto exit_bh;
 
                if (IS_ERR(gdb = bclean(handle, sb, block))) {
-                       err = PTR_ERR(bh);
+                       err = PTR_ERR(gdb);
                        goto exit_bh;
                }
                ext3_journal_dirty_metadata(handle, gdb);
@@ -324,7 +324,7 @@ exit_bh:
        brelse(bh);
 
 exit_journal:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_resize_lock);
        if ((err2 = ext3_journal_stop(handle)) && !err)
                err = err2;
 
@@ -386,7 +386,7 @@ static int verify_reserved_gdb(struct super_block *sb,
 
        while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) {
                if (le32_to_cpu(*p++) != grp * EXT3_BLOCKS_PER_GROUP(sb) + blk){
-                       ext3_warning(sb, __FUNCTION__,
+                       ext3_warning(sb, __func__,
                                     "reserved GDT "E3FSBLK
                                     " missing grp %d ("E3FSBLK")",
                                     blk, grp,
@@ -440,7 +440,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
         */
        if (EXT3_SB(sb)->s_sbh->b_blocknr !=
            le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                        "won't resize using backup superblock at %llu",
                        (unsigned long long)EXT3_SB(sb)->s_sbh->b_blocknr);
                return -EPERM;
@@ -464,7 +464,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
 
        data = (__le32 *)dind->b_data;
        if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "new group %u GDT block "E3FSBLK" not reserved",
                             input->group, gdblock);
                err = -EINVAL;
@@ -488,7 +488,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
                        GFP_NOFS);
        if (!n_group_desc) {
                err = -ENOMEM;
-               ext3_warning (sb, __FUNCTION__,
+               ext3_warning (sb, __func__,
                              "not enough memory for %lu groups", gdb_num + 1);
                goto exit_inode;
        }
@@ -580,13 +580,14 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        }
 
        blk = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + EXT3_SB(sb)->s_gdb_count;
-       data = (__le32 *)dind->b_data + EXT3_SB(sb)->s_gdb_count;
+       data = (__le32 *)dind->b_data + (EXT3_SB(sb)->s_gdb_count %
+                                        EXT3_ADDR_PER_BLOCK(sb));
        end = (__le32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb);
 
        /* Get each reserved primary GDT block and verify it holds backups */
        for (res = 0; res < reserved_gdb; res++, blk++) {
                if (le32_to_cpu(*data) != blk) {
-                       ext3_warning(sb, __FUNCTION__,
+                       ext3_warning(sb, __func__,
                                     "reserved block "E3FSBLK
                                     " not at offset %ld",
                                     blk,
@@ -661,11 +662,12 @@ exit_free:
  * important part is that the new block and inode counts are in the backup
  * superblocks, and the location of the new group metadata in the GDT backups.
  *
- * We do not need lock_super() for this, because these blocks are not
- * otherwise touched by the filesystem code when it is mounted.  We don't
- * need to worry about last changing from sbi->s_groups_count, because the
- * worst that can happen is that we do not copy the full number of backups
- * at this time.  The resize which changed s_groups_count will backup again.
+ * We do not need take the s_resize_lock for this, because these
+ * blocks are not otherwise touched by the filesystem code when it is
+ * mounted.  We don't need to worry about last changing from
+ * sbi->s_groups_count, because the worst that can happen is that we
+ * do not copy the full number of backups at this time.  The resize
+ * which changed s_groups_count will backup again.
  */
 static void update_backups(struct super_block *sb,
                           int blk_off, char *data, int size)
@@ -730,7 +732,7 @@ static void update_backups(struct super_block *sb,
         */
 exit_err:
        if (err) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "can't update backup for group %d (err %d), "
                             "forcing fsck on next reboot", group, err);
                sbi->s_mount_state &= ~EXT3_VALID_FS;
@@ -770,33 +772,34 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
 
        if (gdb_off == 0 && !EXT3_HAS_RO_COMPAT_FEATURE(sb,
                                        EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "Can't resize non-sparse filesystem further");
                return -EPERM;
        }
 
        if (le32_to_cpu(es->s_blocks_count) + input->blocks_count <
            le32_to_cpu(es->s_blocks_count)) {
-               ext3_warning(sb, __FUNCTION__, "blocks_count overflow\n");
+               ext3_warning(sb, __func__, "blocks_count overflow\n");
                return -EINVAL;
        }
 
        if (le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb) <
            le32_to_cpu(es->s_inodes_count)) {
-               ext3_warning(sb, __FUNCTION__, "inodes_count overflow\n");
+               ext3_warning(sb, __func__, "inodes_count overflow\n");
                return -EINVAL;
        }
 
        if (reserved_gdb || gdb_off == 0) {
                if (!EXT3_HAS_COMPAT_FEATURE(sb,
-                                            EXT3_FEATURE_COMPAT_RESIZE_INODE)){
-                       ext3_warning(sb, __FUNCTION__,
+                                            EXT3_FEATURE_COMPAT_RESIZE_INODE)
+                   || !le16_to_cpu(es->s_reserved_gdt_blocks)) {
+                       ext3_warning(sb, __func__,
                                     "No reserved GDT blocks, can't resize");
                        return -EPERM;
                }
                inode = ext3_iget(sb, EXT3_RESIZE_INO);
                if (IS_ERR(inode)) {
-                       ext3_warning(sb, __FUNCTION__,
+                       ext3_warning(sb, __func__,
                                     "Error opening resize inode");
                        return PTR_ERR(inode);
                }
@@ -823,9 +826,9 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
                goto exit_put;
        }
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_resize_lock);
        if (input->group != sbi->s_groups_count) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "multiple resizers run on filesystem!");
                err = -EBUSY;
                goto exit_journal;
@@ -854,7 +857,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
        /*
         * OK, now we've set up the new group.  Time to make it active.
         *
-        * Current kernels don't lock all allocations via lock_super(),
+        * We do not lock all allocations via s_resize_lock
         * so we have to be safe wrt. concurrent accesses the group
         * data.  So we need to be careful to set all of the relevant
         * group descriptor data etc. *before* we enable the group.
@@ -898,12 +901,12 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
         *
         * The precise rules we use are:
         *
-        * * Writers of s_groups_count *must* hold lock_super
+        * * Writers of s_groups_count *must* hold s_resize_lock
         * AND
         * * Writers must perform a smp_wmb() after updating all dependent
         *   data and before modifying the groups count
         *
-        * * Readers must hold lock_super() over the access
+        * * Readers must hold s_resize_lock over the access
         * OR
         * * Readers must perform an smp_rmb() after reading the groups count
         *   and before reading any dependent data.
@@ -932,10 +935,9 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
                           EXT3_INODES_PER_GROUP(sb));
 
        ext3_journal_dirty_metadata(handle, sbi->s_sbh);
-       sb->s_dirt = 1;
 
 exit_journal:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_resize_lock);
        if ((err2 = ext3_journal_stop(handle)) && !err)
                err = err2;
        if (!err) {
@@ -972,7 +974,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
 
        /* We don't need to worry about locking wrt other resizers just
         * yet: we're going to revalidate es->s_blocks_count after
-        * taking lock_super() below. */
+        * taking the s_resize_lock below. */
        o_blocks_count = le32_to_cpu(es->s_blocks_count);
        o_groups_count = EXT3_SB(sb)->s_groups_count;
 
@@ -988,13 +990,13 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
                        " too large to resize to %lu blocks safely\n",
                        sb->s_id, n_blocks_count);
                if (sizeof(sector_t) < 8)
-                       ext3_warning(sb, __FUNCTION__,
-                       "CONFIG_LBD not enabled\n");
+                       ext3_warning(sb, __func__,
+                       "CONFIG_LBDAF not enabled\n");
                return -EINVAL;
        }
 
        if (n_blocks_count < o_blocks_count) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "can't shrink FS - resize aborted");
                return -EBUSY;
        }
@@ -1004,7 +1006,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
                EXT3_BLOCKS_PER_GROUP(sb);
 
        if (last == 0) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "need to use ext2online to resize further");
                return -EPERM;
        }
@@ -1012,7 +1014,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
        add = EXT3_BLOCKS_PER_GROUP(sb) - last;
 
        if (o_blocks_count + add < o_blocks_count) {
-               ext3_warning(sb, __FUNCTION__, "blocks_count overflow");
+               ext3_warning(sb, __func__, "blocks_count overflow");
                return -EINVAL;
        }
 
@@ -1020,7 +1022,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
                add = n_blocks_count - o_blocks_count;
 
        if (o_blocks_count + add < n_blocks_count)
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "will only finish group ("E3FSBLK
                             " blocks, %u new)",
                             o_blocks_count + add, add);
@@ -1028,7 +1030,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
        /* See if the device is actually as big as what was requested */
        bh = sb_bread(sb, o_blocks_count + add -1);
        if (!bh) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "can't read last block, resize aborted");
                return -ENOSPC;
        }
@@ -1040,15 +1042,15 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
        handle = ext3_journal_start_sb(sb, 3);
        if (IS_ERR(handle)) {
                err = PTR_ERR(handle);
-               ext3_warning(sb, __FUNCTION__, "error %d on journal start",err);
+               ext3_warning(sb, __func__, "error %d on journal start",err);
                goto exit_put;
        }
 
-       lock_super(sb);
+       mutex_lock(&EXT3_SB(sb)->s_resize_lock);
        if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "multiple resizers run on filesystem!");
-               unlock_super(sb);
+               mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
                ext3_journal_stop(handle);
                err = -EBUSY;
                goto exit_put;
@@ -1056,16 +1058,15 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
 
        if ((err = ext3_journal_get_write_access(handle,
                                                 EXT3_SB(sb)->s_sbh))) {
-               ext3_warning(sb, __FUNCTION__,
+               ext3_warning(sb, __func__,
                             "error %d on journal write access", err);
-               unlock_super(sb);
+               mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
                ext3_journal_stop(handle);
                goto exit_put;
        }
        es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
        ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-       sb->s_dirt = 1;
-       unlock_super(sb);
+       mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
        ext3_debug("freeing blocks %lu through "E3FSBLK"\n", o_blocks_count,
                   o_blocks_count + add);
        ext3_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks);