Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / fs / ext4 / migrate.c
index b57b98f..16ac228 100644 (file)
 #include <linux/module.h>
 #include <linux/slab.h>
 #include "ext4_jbd2.h"
-#include "ext4_extents.h"
 
 /*
  * The contiguous blocks details which can be
  * represented by a single extent
  */
-struct list_blocks_struct {
-       ext4_lblk_t first_block, last_block;
+struct migrate_struct {
+       ext4_lblk_t first_block, last_block, curr_block;
        ext4_fsblk_t first_pblock, last_pblock;
 };
 
 static int finish_range(handle_t *handle, struct inode *inode,
-                               struct list_blocks_struct *lb)
+                               struct migrate_struct *lb)
 
 {
        int retval = 0, needed;
@@ -87,8 +86,7 @@ err_out:
 }
 
 static int update_extent_range(handle_t *handle, struct inode *inode,
-                               ext4_fsblk_t pblock, ext4_lblk_t blk_num,
-                               struct list_blocks_struct *lb)
+                              ext4_fsblk_t pblock, struct migrate_struct *lb)
 {
        int retval;
        /*
@@ -96,9 +94,10 @@ static int update_extent_range(handle_t *handle, struct inode *inode,
         */
        if (lb->first_pblock &&
                (lb->last_pblock+1 == pblock) &&
-               (lb->last_block+1 == blk_num)) {
+               (lb->last_block+1 == lb->curr_block)) {
                lb->last_pblock = pblock;
-               lb->last_block = blk_num;
+               lb->last_block = lb->curr_block;
+               lb->curr_block++;
                return 0;
        }
        /*
@@ -106,64 +105,49 @@ static int update_extent_range(handle_t *handle, struct inode *inode,
         */
        retval = finish_range(handle, inode, lb);
        lb->first_pblock = lb->last_pblock = pblock;
-       lb->first_block = lb->last_block = blk_num;
-
+       lb->first_block = lb->last_block = lb->curr_block;
+       lb->curr_block++;
        return retval;
 }
 
 static int update_ind_extent_range(handle_t *handle, struct inode *inode,
-                                  ext4_fsblk_t pblock, ext4_lblk_t *blk_nump,
-                                  struct list_blocks_struct *lb)
+                                  ext4_fsblk_t pblock,
+                                  struct migrate_struct *lb)
 {
        struct buffer_head *bh;
        __le32 *i_data;
        int i, retval = 0;
-       ext4_lblk_t blk_count = *blk_nump;
        unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
 
-       if (!pblock) {
-               /* Only update the file block number */
-               *blk_nump += max_entries;
-               return 0;
-       }
-
        bh = sb_bread(inode->i_sb, pblock);
        if (!bh)
                return -EIO;
 
        i_data = (__le32 *)bh->b_data;
-       for (i = 0; i < max_entries; i++, blk_count++) {
+       for (i = 0; i < max_entries; i++) {
                if (i_data[i]) {
                        retval = update_extent_range(handle, inode,
-                                               le32_to_cpu(i_data[i]),
-                                               blk_count, lb);
+                                               le32_to_cpu(i_data[i]), lb);
                        if (retval)
                                break;
+               } else {
+                       lb->curr_block++;
                }
        }
-
-       /* Update the file block number */
-       *blk_nump = blk_count;
        put_bh(bh);
        return retval;
 
 }
 
 static int update_dind_extent_range(handle_t *handle, struct inode *inode,
-                                   ext4_fsblk_t pblock, ext4_lblk_t *blk_nump,
-                                   struct list_blocks_struct *lb)
+                                   ext4_fsblk_t pblock,
+                                   struct migrate_struct *lb)
 {
        struct buffer_head *bh;
        __le32 *i_data;
        int i, retval = 0;
-       ext4_lblk_t blk_count = *blk_nump;
        unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
 
-       if (!pblock) {
-               /* Only update the file block number */
-               *blk_nump += max_entries * max_entries;
-               return 0;
-       }
        bh = sb_bread(inode->i_sb, pblock);
        if (!bh)
                return -EIO;
@@ -172,38 +156,28 @@ static int update_dind_extent_range(handle_t *handle, struct inode *inode,
        for (i = 0; i < max_entries; i++) {
                if (i_data[i]) {
                        retval = update_ind_extent_range(handle, inode,
-                                               le32_to_cpu(i_data[i]),
-                                               &blk_count, lb);
+                                               le32_to_cpu(i_data[i]), lb);
                        if (retval)
                                break;
                } else {
                        /* Only update the file block number */
-                       blk_count += max_entries;
+                       lb->curr_block += max_entries;
                }
        }
-
-       /* Update the file block number */
-       *blk_nump = blk_count;
        put_bh(bh);
        return retval;
 
 }
 
 static int update_tind_extent_range(handle_t *handle, struct inode *inode,
-                                    ext4_fsblk_t pblock, ext4_lblk_t *blk_nump,
-                                    struct list_blocks_struct *lb)
+                                   ext4_fsblk_t pblock,
+                                   struct migrate_struct *lb)
 {
        struct buffer_head *bh;
        __le32 *i_data;
        int i, retval = 0;
-       ext4_lblk_t blk_count = *blk_nump;
        unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
 
-       if (!pblock) {
-               /* Only update the file block number */
-               *blk_nump += max_entries * max_entries * max_entries;
-               return 0;
-       }
        bh = sb_bread(inode->i_sb, pblock);
        if (!bh)
                return -EIO;
@@ -212,16 +186,14 @@ static int update_tind_extent_range(handle_t *handle, struct inode *inode,
        for (i = 0; i < max_entries; i++) {
                if (i_data[i]) {
                        retval = update_dind_extent_range(handle, inode,
-                                               le32_to_cpu(i_data[i]),
-                                               &blk_count, lb);
+                                               le32_to_cpu(i_data[i]), lb);
                        if (retval)
                                break;
-               } else
+               } else {
                        /* Only update the file block number */
-                       blk_count += max_entries * max_entries;
+                       lb->curr_block += max_entries * max_entries;
+               }
        }
-       /* Update the file block number */
-       *blk_nump = blk_count;
        put_bh(bh);
        return retval;
 
@@ -462,12 +434,12 @@ int ext4_ext_migrate(struct inode *inode)
        handle_t *handle;
        int retval = 0, i;
        __le32 *i_data;
-       ext4_lblk_t blk_count = 0;
        struct ext4_inode_info *ei;
        struct inode *tmp_inode = NULL;
-       struct list_blocks_struct lb;
+       struct migrate_struct lb;
        unsigned long max_entries;
        __u32 goal;
+       uid_t owner[2];
 
        /*
         * If the filesystem does not support extents, or the inode
@@ -495,10 +467,12 @@ int ext4_ext_migrate(struct inode *inode)
        }
        goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) *
                EXT4_INODES_PER_GROUP(inode->i_sb)) + 1;
+       owner[0] = inode->i_uid;
+       owner[1] = inode->i_gid;
        tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode,
-                                  S_IFREG, NULL, goal);
+                                  S_IFREG, NULL, goal, owner);
        if (IS_ERR(tmp_inode)) {
-               retval = -ENOMEM;
+               retval = PTR_ERR(inode);
                ext4_journal_stop(handle);
                return retval;
        }
@@ -507,7 +481,7 @@ int ext4_ext_migrate(struct inode *inode)
         * Set the i_nlink to zero so it will be deleted later
         * when we drop inode reference.
         */
-       tmp_inode->i_nlink = 0;
+       clear_nlink(tmp_inode);
 
        ext4_ext_tree_init(handle, tmp_inode);
        ext4_orphan_add(handle, tmp_inode);
@@ -551,35 +525,32 @@ int ext4_ext_migrate(struct inode *inode)
 
        /* 32 bit block address 4 bytes */
        max_entries = inode->i_sb->s_blocksize >> 2;
-       for (i = 0; i < EXT4_NDIR_BLOCKS; i++, blk_count++) {
+       for (i = 0; i < EXT4_NDIR_BLOCKS; i++) {
                if (i_data[i]) {
                        retval = update_extent_range(handle, tmp_inode,
-                                               le32_to_cpu(i_data[i]),
-                                               blk_count, &lb);
+                                               le32_to_cpu(i_data[i]), &lb);
                        if (retval)
                                goto err_out;
-               }
+               } else
+                       lb.curr_block++;
        }
        if (i_data[EXT4_IND_BLOCK]) {
                retval = update_ind_extent_range(handle, tmp_inode,
-                                       le32_to_cpu(i_data[EXT4_IND_BLOCK]),
-                                       &blk_count, &lb);
+                               le32_to_cpu(i_data[EXT4_IND_BLOCK]), &lb);
                        if (retval)
                                goto err_out;
        } else
-               blk_count +=  max_entries;
+               lb.curr_block += max_entries;
        if (i_data[EXT4_DIND_BLOCK]) {
                retval = update_dind_extent_range(handle, tmp_inode,
-                                       le32_to_cpu(i_data[EXT4_DIND_BLOCK]),
-                                       &blk_count, &lb);
+                               le32_to_cpu(i_data[EXT4_DIND_BLOCK]), &lb);
                        if (retval)
                                goto err_out;
        } else
-               blk_count += max_entries * max_entries;
+               lb.curr_block += max_entries * max_entries;
        if (i_data[EXT4_TIND_BLOCK]) {
                retval = update_tind_extent_range(handle, tmp_inode,
-                                       le32_to_cpu(i_data[EXT4_TIND_BLOCK]),
-                                       &blk_count, &lb);
+                               le32_to_cpu(i_data[EXT4_TIND_BLOCK]), &lb);
                        if (retval)
                                goto err_out;
        }