NFS: remove white space from nfs4xdr.c
[safe/jmp/linux-2.6] / fs / ext4 / inode.c
index 634f0bc..be21a5a 100644 (file)
@@ -486,18 +486,9 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
 static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
                Indirect *partial)
 {
-       struct ext4_block_alloc_info *block_i;
-
-       block_i =  EXT4_I(inode)->i_block_alloc_info;
-
        /*
-        * try the heuristic for sequential allocation,
-        * failing that at least try to get decent locality.
+        * XXX need to get goal block from mballoc's data structures
         */
-       if (block_i && (block == block_i->last_alloc_logical_block + 1)
-               && (block_i->last_alloc_physical_block != 0)) {
-               return block_i->last_alloc_physical_block + 1;
-       }
 
        return ext4_find_near(inode, partial);
 }
@@ -757,10 +748,8 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
 {
        int i;
        int err = 0;
-       struct ext4_block_alloc_info *block_i;
        ext4_fsblk_t current_block;
 
-       block_i = EXT4_I(inode)->i_block_alloc_info;
        /*
         * If we're splicing into a [td]indirect block (as opposed to the
         * inode) then we need to get write access to the [td]indirect block
@@ -786,17 +775,6 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
                        *(where->p + i) = cpu_to_le32(current_block++);
        }
 
-       /*
-        * update the most recently allocated logical & physical block
-        * in i_block_alloc_info, to assist find the proper goal block for next
-        * allocation
-        */
-       if (block_i) {
-               block_i->last_alloc_logical_block = block + blks - 1;
-               block_i->last_alloc_physical_block =
-                               le32_to_cpu(where[num].key) + blks - 1;
-       }
-
        /* We are done with atomic stuff, now do the rest of housekeeping */
 
        inode->i_ctime = ext4_current_time(inode);
@@ -914,12 +892,8 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
                goto cleanup;
 
        /*
-        * Okay, we need to do block allocation.  Lazily initialize the block
-        * allocation info here if necessary
+        * Okay, we need to do block allocation.
        */
-       if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
-               ext4_init_block_alloc_info(inode);
-
        goal = ext4_find_goal(inode, iblock, partial);
 
        /* the number of blocks need to allocate for [d,t]indirect blocks */
@@ -1161,8 +1135,8 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
 /* Maximum number of blocks we map for direct IO at once. */
 #define DIO_MAX_BLOCKS 4096
 
-static int ext4_get_block(struct inode *inode, sector_t iblock,
-                       struct buffer_head *bh_result, int create)
+int ext4_get_block(struct inode *inode, sector_t iblock,
+                  struct buffer_head *bh_result, int create)
 {
        handle_t *handle = ext4_journal_current_handle();
        int ret = 0, started = 0;
@@ -1434,16 +1408,18 @@ static int ext4_ordered_write_end(struct file *file,
        ret = ext4_jbd2_file_inode(handle, inode);
 
        if (ret == 0) {
-               /*
-                * generic_write_end() will run mark_inode_dirty() if i_size
-                * changes.  So let's piggyback the i_disksize mark_inode_dirty
-                * into that.
-                */
                loff_t new_i_size;
 
                new_i_size = pos + copied;
-               if (new_i_size > EXT4_I(inode)->i_disksize)
-                       EXT4_I(inode)->i_disksize = new_i_size;
+               if (new_i_size > EXT4_I(inode)->i_disksize) {
+                       ext4_update_i_disksize(inode, new_i_size);
+                       /* We need to mark inode dirty even if
+                        * new_i_size is less that inode->i_size
+                        * bu greater than i_disksize.(hint delalloc)
+                        */
+                       ext4_mark_inode_dirty(handle, inode);
+               }
+
                ret2 = generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
                copied = ret2;
@@ -1468,8 +1444,14 @@ static int ext4_writeback_write_end(struct file *file,
        loff_t new_i_size;
 
        new_i_size = pos + copied;
-       if (new_i_size > EXT4_I(inode)->i_disksize)
-               EXT4_I(inode)->i_disksize = new_i_size;
+       if (new_i_size > EXT4_I(inode)->i_disksize) {
+               ext4_update_i_disksize(inode, new_i_size);
+               /* We need to mark inode dirty even if
+                * new_i_size is less that inode->i_size
+                * bu greater than i_disksize.(hint delalloc)
+                */
+               ext4_mark_inode_dirty(handle, inode);
+       }
 
        ret2 = generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
@@ -1494,6 +1476,7 @@ static int ext4_journalled_write_end(struct file *file,
        int ret = 0, ret2;
        int partial = 0;
        unsigned from, to;
+       loff_t new_i_size;
 
        from = pos & (PAGE_CACHE_SIZE - 1);
        to = from + len;
@@ -1508,11 +1491,12 @@ static int ext4_journalled_write_end(struct file *file,
                                to, &partial, write_end_fn);
        if (!partial)
                SetPageUptodate(page);
-       if (pos+copied > inode->i_size)
+       new_i_size = pos + copied;
+       if (new_i_size > inode->i_size)
                i_size_write(inode, pos+copied);
        EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
-       if (inode->i_size > EXT4_I(inode)->i_disksize) {
-               EXT4_I(inode)->i_disksize = inode->i_size;
+       if (new_i_size > EXT4_I(inode)->i_disksize) {
+               ext4_update_i_disksize(inode, new_i_size);
                ret2 = ext4_mark_inode_dirty(handle, inode);
                if (!ret)
                        ret = ret2;
@@ -1664,6 +1648,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
        int ret = 0, err, nr_pages, i;
        unsigned long index, end;
        struct pagevec pvec;
+       long pages_skipped;
 
        BUG_ON(mpd->next_page <= mpd->first_page);
        pagevec_init(&pvec, 0);
@@ -1671,20 +1656,30 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
        end = mpd->next_page - 1;
 
        while (index <= end) {
-               /* XXX: optimize tail */
-               nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE);
+               /*
+                * We can use PAGECACHE_TAG_DIRTY lookup here because
+                * even though we have cleared the dirty flag on the page
+                * We still keep the page in the radix tree with tag
+                * PAGECACHE_TAG_DIRTY. See clear_page_dirty_for_io.
+                * The PAGECACHE_TAG_DIRTY is cleared in set_page_writeback
+                * which is called via the below writepage callback.
+                */
+               nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+                                       PAGECACHE_TAG_DIRTY,
+                                       min(end - index,
+                                       (pgoff_t)PAGEVEC_SIZE-1) + 1);
                if (nr_pages == 0)
                        break;
                for (i = 0; i < nr_pages; i++) {
                        struct page *page = pvec.pages[i];
 
-                       index = page->index;
-                       if (index > end)
-                               break;
-                       index++;
-
+                       pages_skipped = mpd->wbc->pages_skipped;
                        err = mapping->a_ops->writepage(page, mpd->wbc);
-                       if (!err)
+                       if (!err && (pages_skipped == mpd->wbc->pages_skipped))
+                               /*
+                                * have successfully written the page
+                                * without skipping the same
+                                */
                                mpd->pages_written++;
                        /*
                         * In error case, we have to continue because
@@ -2120,7 +2115,6 @@ static int mpage_da_writepages(struct address_space *mapping,
                               struct writeback_control *wbc,
                               struct mpage_da_data *mpd)
 {
-       long to_write;
        int ret;
 
        if (!mpd->get_block)
@@ -2135,19 +2129,18 @@ static int mpage_da_writepages(struct address_space *mapping,
        mpd->pages_written = 0;
        mpd->retval = 0;
 
-       to_write = wbc->nr_to_write;
-
        ret = write_cache_pages(mapping, wbc, __mpage_da_writepage, mpd);
-
        /*
         * Handle last extent of pages
         */
        if (!mpd->io_done && mpd->next_page != mpd->first_page) {
                if (mpage_da_map_blocks(mpd) == 0)
                        mpage_da_submit_io(mpd);
-       }
 
-       wbc->nr_to_write = to_write - mpd->pages_written;
+               mpd->io_done = 1;
+               ret = MPAGE_DA_EXTENT_TAIL;
+       }
+       wbc->nr_to_write -= mpd->pages_written;
        return ret;
 }
 
@@ -2227,18 +2220,9 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
                if (disksize > i_size_read(inode))
                        disksize = i_size_read(inode);
                if (disksize > EXT4_I(inode)->i_disksize) {
-                       /*
-                        * XXX: replace with spinlock if seen contended -bzzz
-                        */
-                       down_write(&EXT4_I(inode)->i_data_sem);
-                       if (disksize > EXT4_I(inode)->i_disksize)
-                               EXT4_I(inode)->i_disksize = disksize;
-                       up_write(&EXT4_I(inode)->i_data_sem);
-
-                       if (EXT4_I(inode)->i_disksize == disksize) {
-                               ret = ext4_mark_inode_dirty(handle, inode);
-                               return ret;
-                       }
+                       ext4_update_i_disksize(inode, disksize);
+                       ret = ext4_mark_inode_dirty(handle, inode);
+                       return ret;
                }
                ret = 0;
        }
@@ -2345,6 +2329,8 @@ static int ext4_da_writepage(struct page *page,
                        unlock_page(page);
                        return 0;
                }
+               /* now mark the buffer_heads as dirty and uptodate */
+               block_commit_write(page, 0, PAGE_CACHE_SIZE);
        }
 
        if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
@@ -2385,12 +2371,14 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode)
 static int ext4_da_writepages(struct address_space *mapping,
                              struct writeback_control *wbc)
 {
+       pgoff_t index;
+       int range_whole = 0;
        handle_t *handle = NULL;
-       loff_t range_start = 0;
        struct mpage_da_data mpd;
        struct inode *inode = mapping->host;
+       int no_nrwrite_index_update;
+       long pages_written = 0, pages_skipped;
        int needed_blocks, ret = 0, nr_to_writebump = 0;
-       long to_write, pages_skipped = 0;
        struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
 
        /*
@@ -2410,23 +2398,26 @@ static int ext4_da_writepages(struct address_space *mapping,
                nr_to_writebump = sbi->s_mb_stream_request - wbc->nr_to_write;
                wbc->nr_to_write = sbi->s_mb_stream_request;
        }
+       if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
+               range_whole = 1;
 
-       if (!wbc->range_cyclic)
-               /*
-                * If range_cyclic is not set force range_cont
-                * and save the old writeback_index
-                */
-               wbc->range_cont = 1;
-
-       range_start =  wbc->range_start;
-       pages_skipped = wbc->pages_skipped;
+       if (wbc->range_cyclic)
+               index = mapping->writeback_index;
+       else
+               index = wbc->range_start >> PAGE_CACHE_SHIFT;
 
        mpd.wbc = wbc;
        mpd.inode = mapping->host;
 
-restart_loop:
-       to_write = wbc->nr_to_write;
-       while (!ret && to_write > 0) {
+       /*
+        * we don't want write_cache_pages to update
+        * nr_to_write and writeback_index
+        */
+       no_nrwrite_index_update = wbc->no_nrwrite_index_update;
+       wbc->no_nrwrite_index_update = 1;
+       pages_skipped = wbc->pages_skipped;
+
+       while (!ret && wbc->nr_to_write > 0) {
 
                /*
                 * we  insert one extent at a time. So we need
@@ -2447,48 +2438,53 @@ restart_loop:
                        dump_stack();
                        goto out_writepages;
                }
-               to_write -= wbc->nr_to_write;
-
                mpd.get_block = ext4_da_get_block_write;
                ret = mpage_da_writepages(mapping, wbc, &mpd);
 
                ext4_journal_stop(handle);
 
-               if (mpd.retval == -ENOSPC)
+               if (mpd.retval == -ENOSPC) {
+                       /* commit the transaction which would
+                        * free blocks released in the transaction
+                        * and try again
+                        */
                        jbd2_journal_force_commit_nested(sbi->s_journal);
-
-               /* reset the retry count */
-               if (ret == MPAGE_DA_EXTENT_TAIL) {
+                       wbc->pages_skipped = pages_skipped;
+                       ret = 0;
+               } else if (ret == MPAGE_DA_EXTENT_TAIL) {
                        /*
                         * got one extent now try with
                         * rest of the pages
                         */
-                       to_write += wbc->nr_to_write;
+                       pages_written += mpd.pages_written;
+                       wbc->pages_skipped = pages_skipped;
                        ret = 0;
-               } else if (wbc->nr_to_write) {
+               } else if (wbc->nr_to_write)
                        /*
                         * There is no more writeout needed
                         * or we requested for a noblocking writeout
                         * and we found the device congested
                         */
-                       to_write += wbc->nr_to_write;
                        break;
-               }
-               wbc->nr_to_write = to_write;
-       }
-
-       if (wbc->range_cont && (pages_skipped != wbc->pages_skipped)) {
-               /* We skipped pages in this loop */
-               wbc->range_start = range_start;
-               wbc->nr_to_write = to_write +
-                               wbc->pages_skipped - pages_skipped;
-               wbc->pages_skipped = pages_skipped;
-               goto restart_loop;
        }
+       if (pages_skipped != wbc->pages_skipped)
+               printk(KERN_EMERG "This should not happen leaving %s "
+                               "with nr_to_write = %ld ret = %d\n",
+                               __func__, wbc->nr_to_write, ret);
+
+       /* Update index */
+       index += pages_written;
+       if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
+               /*
+                * set the writeback_index so that range_cyclic
+                * mode will write it back later
+                */
+               mapping->writeback_index = index;
 
 out_writepages:
-       wbc->nr_to_write = to_write - nr_to_writebump;
-       wbc->range_start = range_start;
+       if (!no_nrwrite_index_update)
+               wbc->no_nrwrite_index_update = 0;
+       wbc->nr_to_write -= nr_to_writebump;
        return ret;
 }
 
@@ -2654,6 +2650,11 @@ static int ext4_da_write_end(struct file *file,
                                EXT4_I(inode)->i_disksize = new_i_size;
                        }
                        up_write(&EXT4_I(inode)->i_data_sem);
+                       /* We need to mark inode dirty even if
+                        * new_i_size is less that inode->i_size
+                        * bu greater than i_disksize.(hint delalloc)
+                        */
+                       ext4_mark_inode_dirty(handle, inode);
                }
        }
        ret2 = generic_write_end(file, mapping, pos, len, copied,
@@ -3732,7 +3733,7 @@ void ext4_truncate(struct inode *inode)
         */
        down_write(&ei->i_data_sem);
 
-       ext4_discard_reservation(inode);
+       ext4_discard_preallocations(inode);
 
        /*
         * The orphan list entry will now protect us from any crash which
@@ -3827,41 +3828,6 @@ out_stop:
        ext4_journal_stop(handle);
 }
 
-static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
-               unsigned long ino, struct ext4_iloc *iloc)
-{
-       ext4_group_t block_group;
-       unsigned long offset;
-       ext4_fsblk_t block;
-       struct ext4_group_desc *gdp;
-
-       if (!ext4_valid_inum(sb, ino)) {
-               /*
-                * This error is already checked for in namei.c unless we are
-                * looking at an NFS filehandle, in which case no error
-                * report is needed
-                */
-               return 0;
-       }
-
-       block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
-       gdp = ext4_get_group_desc(sb, block_group, NULL);
-       if (!gdp)
-               return 0;
-
-       /*
-        * Figure out the offset within the block group inode table
-        */
-       offset = ((ino - 1) % EXT4_INODES_PER_GROUP(sb)) *
-               EXT4_INODE_SIZE(sb);
-       block = ext4_inode_table(sb, gdp) +
-               (offset >> EXT4_BLOCK_SIZE_BITS(sb));
-
-       iloc->block_group = block_group;
-       iloc->offset = offset & (EXT4_BLOCK_SIZE(sb) - 1);
-       return block;
-}
-
 /*
  * ext4_get_inode_loc returns with an extra refcount against the inode's
  * underlying buffer_head on success. If 'in_mem' is true, we have all
@@ -3871,19 +3837,35 @@ static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
 static int __ext4_get_inode_loc(struct inode *inode,
                                struct ext4_iloc *iloc, int in_mem)
 {
-       ext4_fsblk_t block;
-       struct buffer_head *bh;
+       struct ext4_group_desc  *gdp;
+       struct buffer_head      *bh;
+       struct super_block      *sb = inode->i_sb;
+       ext4_fsblk_t            block;
+       int                     inodes_per_block, inode_offset;
+
+       iloc->bh = 0;
+       if (!ext4_valid_inum(sb, inode->i_ino))
+               return -EIO;
 
-       block = ext4_get_inode_block(inode->i_sb, inode->i_ino, iloc);
-       if (!block)
+       iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb);
+       gdp = ext4_get_group_desc(sb, iloc->block_group, NULL);
+       if (!gdp)
                return -EIO;
 
-       bh = sb_getblk(inode->i_sb, block);
+       /*
+        * Figure out the offset within the block group inode table
+        */
+       inodes_per_block = (EXT4_BLOCK_SIZE(sb) / EXT4_INODE_SIZE(sb));
+       inode_offset = ((inode->i_ino - 1) %
+                       EXT4_INODES_PER_GROUP(sb));
+       block = ext4_inode_table(sb, gdp) + (inode_offset / inodes_per_block);
+       iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb);
+
+       bh = sb_getblk(sb, block);
        if (!bh) {
-               ext4_error (inode->i_sb, "ext4_get_inode_loc",
-                               "unable to read inode block - "
-                               "inode=%lu, block=%llu",
-                                inode->i_ino, block);
+               ext4_error(sb, "ext4_get_inode_loc", "unable to read "
+                          "inode block - inode=%lu, block=%llu",
+                          inode->i_ino, block);
                return -EIO;
        }
        if (!buffer_uptodate(bh)) {
@@ -3911,28 +3893,12 @@ static int __ext4_get_inode_loc(struct inode *inode,
                 */
                if (in_mem) {
                        struct buffer_head *bitmap_bh;
-                       struct ext4_group_desc *desc;
-                       int inodes_per_buffer;
-                       int inode_offset, i;
-                       ext4_group_t block_group;
-                       int start;
-
-                       block_group = (inode->i_ino - 1) /
-                                       EXT4_INODES_PER_GROUP(inode->i_sb);
-                       inodes_per_buffer = bh->b_size /
-                               EXT4_INODE_SIZE(inode->i_sb);
-                       inode_offset = ((inode->i_ino - 1) %
-                                       EXT4_INODES_PER_GROUP(inode->i_sb));
-                       start = inode_offset & ~(inodes_per_buffer - 1);
+                       int i, start;
 
-                       /* Is the inode bitmap in cache? */
-                       desc = ext4_get_group_desc(inode->i_sb,
-                                               block_group, NULL);
-                       if (!desc)
-                               goto make_io;
+                       start = inode_offset & ~(inodes_per_block - 1);
 
-                       bitmap_bh = sb_getblk(inode->i_sb,
-                               ext4_inode_bitmap(inode->i_sb, desc));
+                       /* Is the inode bitmap in cache? */
+                       bitmap_bh = sb_getblk(sb, ext4_inode_bitmap(sb, gdp));
                        if (!bitmap_bh)
                                goto make_io;
 
@@ -3945,14 +3911,14 @@ static int __ext4_get_inode_loc(struct inode *inode,
                                brelse(bitmap_bh);
                                goto make_io;
                        }
-                       for (i = start; i < start + inodes_per_buffer; i++) {
+                       for (i = start; i < start + inodes_per_block; i++) {
                                if (i == inode_offset)
                                        continue;
                                if (ext4_test_bit(i, bitmap_bh->b_data))
                                        break;
                        }
                        brelse(bitmap_bh);
-                       if (i == start + inodes_per_buffer) {
+                       if (i == start + inodes_per_block) {
                                /* all other inodes are free, so skip I/O */
                                memset(bh->b_data, 0, bh->b_size);
                                set_buffer_uptodate(bh);
@@ -3963,6 +3929,36 @@ static int __ext4_get_inode_loc(struct inode *inode,
 
 make_io:
                /*
+                * If we need to do any I/O, try to pre-readahead extra
+                * blocks from the inode table.
+                */
+               if (EXT4_SB(sb)->s_inode_readahead_blks) {
+                       ext4_fsblk_t b, end, table;
+                       unsigned num;
+
+                       table = ext4_inode_table(sb, gdp);
+                       /* Make sure s_inode_readahead_blks is a power of 2 */
+                       while (EXT4_SB(sb)->s_inode_readahead_blks &
+                              (EXT4_SB(sb)->s_inode_readahead_blks-1))
+                               EXT4_SB(sb)->s_inode_readahead_blks = 
+                                  (EXT4_SB(sb)->s_inode_readahead_blks &
+                                   (EXT4_SB(sb)->s_inode_readahead_blks-1));
+                       b = block & ~(EXT4_SB(sb)->s_inode_readahead_blks-1);
+                       if (table > b)
+                               b = table;
+                       end = b + EXT4_SB(sb)->s_inode_readahead_blks;
+                       num = EXT4_INODES_PER_GROUP(sb);
+                       if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+                                      EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
+                               num -= le16_to_cpu(gdp->bg_itable_unused);
+                       table += num / inodes_per_block;
+                       if (end > table)
+                               end = table;
+                       while (b <= end)
+                               sb_breadahead(sb, b++);
+               }
+
+               /*
                 * There are other valid inodes in the buffer, this inode
                 * has in-inode xattrs, or we don't have this inode in memory.
                 * Read the block from disk.
@@ -3972,10 +3968,9 @@ make_io:
                submit_bh(READ_META, bh);
                wait_on_buffer(bh);
                if (!buffer_uptodate(bh)) {
-                       ext4_error(inode->i_sb, "ext4_get_inode_loc",
-                                       "unable to read inode block - "
-                                       "inode=%lu, block=%llu",
-                                       inode->i_ino, block);
+                       ext4_error(sb, __func__,
+                                  "unable to read inode block - inode=%lu, "
+                                  "block=%llu", inode->i_ino, block);
                        brelse(bh);
                        return -EIO;
                }
@@ -4067,11 +4062,10 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
                return inode;
 
        ei = EXT4_I(inode);
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
        ei->i_acl = EXT4_ACL_NOT_CACHED;
        ei->i_default_acl = EXT4_ACL_NOT_CACHED;
 #endif
-       ei->i_block_alloc_info = NULL;
 
        ret = __ext4_get_inode_loc(inode, &iloc, 0);
        if (ret < 0)
@@ -4202,7 +4196,6 @@ static int ext4_inode_blocks_set(handle_t *handle,
        struct inode *inode = &(ei->vfs_inode);
        u64 i_blocks = inode->i_blocks;
        struct super_block *sb = inode->i_sb;
-       int err = 0;
 
        if (i_blocks <= ~0U) {
                /*
@@ -4212,36 +4205,27 @@ static int ext4_inode_blocks_set(handle_t *handle,
                raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
                raw_inode->i_blocks_high = 0;
                ei->i_flags &= ~EXT4_HUGE_FILE_FL;
-       } else if (i_blocks <= 0xffffffffffffULL) {
+               return 0;
+       }
+       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE))
+               return -EFBIG;
+
+       if (i_blocks <= 0xffffffffffffULL) {
                /*
                 * i_blocks can be represented in a 48 bit variable
                 * as multiple of 512 bytes
                 */
-               err = ext4_update_rocompat_feature(handle, sb,
-                                           EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
-               if (err)
-                       goto  err_out;
-               /* i_block is stored in the split  48 bit fields */
                raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
                raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
                ei->i_flags &= ~EXT4_HUGE_FILE_FL;
        } else {
-               /*
-                * i_blocks should be represented in a 48 bit variable
-                * as multiple of  file system block size
-                */
-               err = ext4_update_rocompat_feature(handle, sb,
-                                           EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
-               if (err)
-                       goto  err_out;
                ei->i_flags |= EXT4_HUGE_FILE_FL;
                /* i_block is stored in file system block size */
                i_blocks = i_blocks >> (inode->i_blkbits - 9);
                raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
                raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
        }
-err_out:
-       return err;
+       return 0;
 }
 
 /*
@@ -4598,9 +4582,10 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
 static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
 {
        if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
-               return ext4_indirect_trans_blocks(inode, nrblocks, 0);
-       return ext4_ext_index_trans_blocks(inode, nrblocks, 0);
+               return ext4_indirect_trans_blocks(inode, nrblocks, chunk);
+       return ext4_ext_index_trans_blocks(inode, nrblocks, chunk);
 }
+
 /*
  * Account for index blocks, block groups bitmaps and block group
  * descriptor blocks if modify datablocks and index blocks