]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ext4/inode.c
ext4: Rework the ext4_da_writepages() function
[linux-2.6-omap-h63xx.git] / fs / ext4 / inode.c
index 9843b046c2358974bff4bea0449583c688c27358..8dd22eade42cd356e197887f6fc53a2404e1943d 100644 (file)
@@ -41,6 +41,8 @@
 #include "acl.h"
 #include "ext4_extents.h"
 
+#define MPAGE_DA_EXTENT_TAIL 0x01
+
 static inline int ext4_begin_ordered_truncate(struct inode *inode,
                                              loff_t new_size)
 {
@@ -191,6 +193,7 @@ static int ext4_journal_test_restart(handle_t *handle, struct inode *inode)
 void ext4_delete_inode (struct inode * inode)
 {
        handle_t *handle;
+       int err;
 
        if (ext4_should_order_data(inode))
                ext4_begin_ordered_truncate(inode, 0);
@@ -199,8 +202,9 @@ void ext4_delete_inode (struct inode * inode)
        if (is_bad_inode(inode))
                goto no_delete;
 
-       handle = start_transaction(inode);
+       handle = ext4_journal_start(inode, blocks_for_truncate(inode)+3);
        if (IS_ERR(handle)) {
+               ext4_std_error(inode->i_sb, PTR_ERR(handle));
                /*
                 * If we're going to skip the normal cleanup, we still need to
                 * make sure that the in-core orphan linked list is properly
@@ -213,8 +217,34 @@ void ext4_delete_inode (struct inode * inode)
        if (IS_SYNC(inode))
                handle->h_sync = 1;
        inode->i_size = 0;
+       err = ext4_mark_inode_dirty(handle, inode);
+       if (err) {
+               ext4_warning(inode->i_sb, __func__,
+                            "couldn't mark inode dirty (err %d)", err);
+               goto stop_handle;
+       }
        if (inode->i_blocks)
                ext4_truncate(inode);
+
+       /*
+        * ext4_ext_truncate() doesn't reserve any slop when it
+        * restarts journal transactions; therefore there may not be
+        * enough credits left in the handle to remove the inode from
+        * the orphan list and set the dtime field.
+        */
+       if (handle->h_buffer_credits < 3) {
+               err = ext4_journal_extend(handle, 3);
+               if (err > 0)
+                       err = ext4_journal_restart(handle, 3);
+               if (err != 0) {
+                       ext4_warning(inode->i_sb, __func__,
+                                    "couldn't extend journal (err %d)", err);
+               stop_handle:
+                       ext4_journal_stop(handle);
+                       goto no_delete;
+               }
+       }
+
        /*
         * Kill off the orphan record which ext4_truncate created.
         * AKPM: I think this can be inside the above `if'.
@@ -952,23 +982,74 @@ out:
        return err;
 }
 
-/* Maximum number of blocks we map for direct IO at once. */
-#define DIO_MAX_BLOCKS 4096
 /*
- * Number of credits we need for writing DIO_MAX_BLOCKS:
- * We need sb + group descriptor + bitmap + inode -> 4
- * For B blocks with A block pointers per block we need:
- * 1 (triple ind.) + (B/A/A + 2) (doubly ind.) + (B/A + 2) (indirect).
- * If we plug in 4096 for B and 256 for A (for 1KB block size), we get 25.
+ * Calculate the number of metadata blocks need to reserve
+ * to allocate @blocks for non extent file based file
  */
-#define DIO_CREDITS 25
+static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks)
+{
+       int icap = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+       int ind_blks, dind_blks, tind_blks;
 
+       /* number of new indirect blocks needed */
+       ind_blks = (blocks + icap - 1) / icap;
+
+       dind_blks = (ind_blks + icap - 1) / icap;
+
+       tind_blks = 1;
+
+       return ind_blks + dind_blks + tind_blks;
+}
 
 /*
+ * Calculate the number of metadata blocks need to reserve
+ * to allocate given number of blocks
+ */
+static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
+{
+       if (!blocks)
+               return 0;
+
+       if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
+               return ext4_ext_calc_metadata_amount(inode, blocks);
+
+       return ext4_indirect_calc_metadata_amount(inode, blocks);
+}
+
+static void ext4_da_update_reserve_space(struct inode *inode, int used)
+{
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+       int total, mdb, mdb_free;
+
+       spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+       /* recalculate the number of metablocks still need to be reserved */
+       total = EXT4_I(inode)->i_reserved_data_blocks - used;
+       mdb = ext4_calc_metadata_amount(inode, total);
+
+       /* figure out how many metablocks to release */
+       BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
+       mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb;
+
+       /* Account for allocated meta_blocks */
+       mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks;
+
+       /* update fs free blocks counter for truncate case */
+       percpu_counter_add(&sbi->s_freeblocks_counter, mdb_free);
+
+       /* update per-inode reservations */
+       BUG_ON(used  > EXT4_I(inode)->i_reserved_data_blocks);
+       EXT4_I(inode)->i_reserved_data_blocks -= used;
+
+       BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
+       EXT4_I(inode)->i_reserved_meta_blocks = mdb;
+       EXT4_I(inode)->i_allocated_meta_blocks = 0;
+       spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+}
+
+/*
+ * The ext4_get_blocks_wrap() function try to look up the requested blocks,
+ * and returns if the blocks are already mapped.
  *
- *
- * ext4_ext4 get_block() wrapper function
- * It will do a look up first, and returns if the blocks already mapped.
  * Otherwise it takes the write lock of the i_data_sem and allocate blocks
  * and store the allocated blocks in the result buffer head and mark it
  * mapped.
@@ -1069,26 +1150,30 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
                 * which were deferred till now
                 */
                if ((retval > 0) && buffer_delay(bh))
-                       ext4_da_release_space(inode, retval, 0);
+                       ext4_da_update_reserve_space(inode, retval);
        }
 
        up_write((&EXT4_I(inode)->i_data_sem));
        return retval;
 }
 
+/* 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)
 {
        handle_t *handle = ext4_journal_current_handle();
        int ret = 0, started = 0;
        unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+       int dio_credits;
 
        if (create && !handle) {
                /* Direct IO write... */
                if (max_blocks > DIO_MAX_BLOCKS)
                        max_blocks = DIO_MAX_BLOCKS;
-               handle = ext4_journal_start(inode, DIO_CREDITS +
-                             2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb));
+               dio_credits = ext4_chunk_trans_blocks(inode, max_blocks);
+               handle = ext4_journal_start(inode, dio_credits);
                if (IS_ERR(handle)) {
                        ret = PTR_ERR(handle);
                        goto out;
@@ -1336,12 +1421,8 @@ static int ext4_ordered_write_end(struct file *file,
 {
        handle_t *handle = ext4_journal_current_handle();
        struct inode *inode = mapping->host;
-       unsigned from, to;
        int ret = 0, ret2;
 
-       from = pos & (PAGE_CACHE_SIZE - 1);
-       to = from + len;
-
        ret = ext4_jbd2_file_inode(handle, inode);
 
        if (ret == 0) {
@@ -1437,36 +1518,6 @@ static int ext4_journalled_write_end(struct file *file,
 
        return ret ? ret : copied;
 }
-/*
- * Calculate the number of metadata blocks need to reserve
- * to allocate @blocks for non extent file based file
- */
-static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks)
-{
-       int icap = EXT4_ADDR_PER_BLOCK(inode->i_sb);
-       int ind_blks, dind_blks, tind_blks;
-
-       /* number of new indirect blocks needed */
-       ind_blks = (blocks + icap - 1) / icap;
-
-       dind_blks = (ind_blks + icap - 1) / icap;
-
-       tind_blks = 1;
-
-       return ind_blks + dind_blks + tind_blks;
-}
-
-/*
- * Calculate the number of metadata blocks need to reserve
- * to allocate given number of blocks
- */
-static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
-{
-       if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
-               return ext4_ext_calc_metadata_amount(inode, blocks);
-
-       return ext4_indirect_calc_metadata_amount(inode, blocks);
-}
 
 static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
 {
@@ -1490,7 +1541,6 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
                spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
                return -ENOSPC;
        }
-
        /* reduce fs free blocks counter */
        percpu_counter_sub(&sbi->s_freeblocks_counter, total);
 
@@ -1501,35 +1551,49 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
        return 0;       /* success */
 }
 
-void ext4_da_release_space(struct inode *inode, int used, int to_free)
+static void ext4_da_release_space(struct inode *inode, int to_free)
 {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        int total, mdb, mdb_free, release;
 
+       if (!to_free)
+               return;         /* Nothing to release, exit */
+
        spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+
+       if (!EXT4_I(inode)->i_reserved_data_blocks) {
+               /*
+                * if there is no reserved blocks, but we try to free some
+                * then the counter is messed up somewhere.
+                * but since this function is called from invalidate
+                * page, it's harmless to return without any action
+                */
+               printk(KERN_INFO "ext4 delalloc try to release %d reserved "
+                           "blocks for inode %lu, but there is no reserved "
+                           "data blocks\n", to_free, inode->i_ino);
+               spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+               return;
+       }
+
        /* recalculate the number of metablocks still need to be reserved */
-       total = EXT4_I(inode)->i_reserved_data_blocks - used - to_free;
+       total = EXT4_I(inode)->i_reserved_data_blocks - to_free;
        mdb = ext4_calc_metadata_amount(inode, total);
 
        /* figure out how many metablocks to release */
        BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
        mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb;
 
-       /* Account for allocated meta_blocks */
-       mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks;
-
        release = to_free + mdb_free;
 
        /* update fs free blocks counter for truncate case */
        percpu_counter_add(&sbi->s_freeblocks_counter, release);
 
        /* update per-inode reservations */
-       BUG_ON(used + to_free > EXT4_I(inode)->i_reserved_data_blocks);
-       EXT4_I(inode)->i_reserved_data_blocks -= (used + to_free);
+       BUG_ON(to_free > EXT4_I(inode)->i_reserved_data_blocks);
+       EXT4_I(inode)->i_reserved_data_blocks -= to_free;
 
        BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
        EXT4_I(inode)->i_reserved_meta_blocks = mdb;
-       EXT4_I(inode)->i_allocated_meta_blocks = 0;
        spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 }
 
@@ -1551,7 +1615,7 @@ static void ext4_da_page_release_reservation(struct page *page,
                }
                curr_off = next_off;
        } while ((bh = bh->b_this_page) != head);
-       ext4_da_release_space(page->mapping->host, 0, to_release);
+       ext4_da_release_space(page->mapping->host, to_release);
 }
 
 /*
@@ -1564,11 +1628,13 @@ struct mpage_da_data {
        unsigned long first_page, next_page;    /* extent of pages */
        get_block_t *get_block;
        struct writeback_control *wbc;
+       int io_done;
+       long pages_written;
 };
 
 /*
  * mpage_da_submit_io - walks through extent of pages and try to write
- * them with __mpage_writepage()
+ * them with writepage() call back
  *
  * @mpd->inode: inode
  * @mpd->first_page: first page of the extent
@@ -1583,18 +1649,11 @@ struct mpage_da_data {
 static int mpage_da_submit_io(struct mpage_da_data *mpd)
 {
        struct address_space *mapping = mpd->inode->i_mapping;
-       struct mpage_data mpd_pp = {
-               .bio = NULL,
-               .last_block_in_bio = 0,
-               .get_block = mpd->get_block,
-               .use_writepage = 1,
-       };
        int ret = 0, err, nr_pages, i;
        unsigned long index, end;
        struct pagevec pvec;
 
        BUG_ON(mpd->next_page <= mpd->first_page);
-
        pagevec_init(&pvec, 0);
        index = mpd->first_page;
        end = mpd->next_page - 1;
@@ -1612,8 +1671,9 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
                                break;
                        index++;
 
-                       err = __mpage_writepage(page, mpd->wbc, &mpd_pp);
-
+                       err = mapping->a_ops->writepage(page, mpd->wbc);
+                       if (!err)
+                               mpd->pages_written++;
                        /*
                         * In error case, we have to continue because
                         * remaining pages are still locked
@@ -1624,9 +1684,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
                }
                pagevec_release(&pvec);
        }
-       if (mpd_pp.bio)
-               mpage_bio_submit(WRITE, mpd_pp.bio);
-
        return ret;
 }
 
@@ -1649,7 +1706,7 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical,
        int blocks = exbh->b_size >> inode->i_blkbits;
        sector_t pblock = exbh->b_blocknr, cur_logical;
        struct buffer_head *head, *bh;
-       unsigned long index, end;
+       pgoff_t index, end;
        struct pagevec pvec;
        int nr_pages, i;
 
@@ -1692,6 +1749,13 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical,
                                if (buffer_delay(bh)) {
                                        bh->b_blocknr = pblock;
                                        clear_buffer_delay(bh);
+                                       bh->b_bdev = inode->i_sb->s_bdev;
+                               } else if (buffer_unwritten(bh)) {
+                                       bh->b_blocknr = pblock;
+                                       clear_buffer_unwritten(bh);
+                                       set_buffer_mapped(bh);
+                                       set_buffer_new(bh);
+                                       bh->b_bdev = inode->i_sb->s_bdev;
                                } else if (buffer_mapped(bh))
                                        BUG_ON(bh->b_blocknr != pblock);
 
@@ -1727,13 +1791,11 @@ static inline void __unmap_underlying_blocks(struct inode *inode,
  *
  * The function skips space we know is already mapped to disk blocks.
  *
- * The function ignores errors ->get_block() returns, thus real
- * error handling is postponed to __mpage_writepage()
  */
 static void mpage_da_map_blocks(struct mpage_da_data *mpd)
 {
+       int err = 0;
        struct buffer_head *lbh = &mpd->lbh;
-       int err = 0, remain = lbh->b_size;
        sector_t next = lbh->b_blocknr;
        struct buffer_head new;
 
@@ -1743,38 +1805,36 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd)
        if (buffer_mapped(lbh) && !buffer_delay(lbh))
                return;
 
-       while (remain) {
-               new.b_state = lbh->b_state;
-               new.b_blocknr = 0;
-               new.b_size = remain;
-               err = mpd->get_block(mpd->inode, next, &new, 1);
-               if (err) {
-                       /*
-                        * Rather than implement own error handling
-                        * here, we just leave remaining blocks
-                        * unallocated and try again with ->writepage()
-                        */
-                       break;
-               }
-               BUG_ON(new.b_size == 0);
+       new.b_state = lbh->b_state;
+       new.b_blocknr = 0;
+       new.b_size = lbh->b_size;
 
-               if (buffer_new(&new))
-                       __unmap_underlying_blocks(mpd->inode, &new);
+       /*
+        * If we didn't accumulate anything
+        * to write simply return
+        */
+       if (!new.b_size)
+               return;
+       err = mpd->get_block(mpd->inode, next, &new, 1);
+       if (err)
+               return;
+       BUG_ON(new.b_size == 0);
 
-               /*
-                * If blocks are delayed marked, we need to
-                * put actual blocknr and drop delayed bit
-                */
-               if (buffer_delay(lbh))
-                       mpage_put_bnr_to_bhs(mpd, next, &new);
+       if (buffer_new(&new))
+               __unmap_underlying_blocks(mpd->inode, &new);
 
-               /* go for the remaining blocks */
-               next += new.b_size >> mpd->inode->i_blkbits;
-               remain -= new.b_size;
-       }
+       /*
+        * If blocks are delayed marked, we need to
+        * put actual blocknr and drop delayed bit
+        */
+       if (buffer_delay(lbh) || buffer_unwritten(lbh))
+               mpage_put_bnr_to_bhs(mpd, next, &new);
+
+       return;
 }
 
-#define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | (1 << BH_Delay))
+#define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \
+               (1 << BH_Delay) | (1 << BH_Unwritten))
 
 /*
  * mpage_add_bh_to_extent - try to add one more block to extent of blocks
@@ -1816,13 +1876,9 @@ static void mpage_add_bh_to_extent(struct mpage_da_data *mpd,
         * need to flush current  extent and start new one
         */
        mpage_da_map_blocks(mpd);
-
-       /*
-        * Now start a new extent
-        */
-       lbh->b_size = bh->b_size;
-       lbh->b_state = bh->b_state & BH_FLAGS;
-       lbh->b_blocknr = logical;
+       mpage_da_submit_io(mpd);
+       mpd->io_done = 1;
+       return;
 }
 
 /*
@@ -1842,17 +1898,35 @@ static int __mpage_da_writepage(struct page *page,
        struct buffer_head *bh, *head, fake;
        sector_t logical;
 
+       if (mpd->io_done) {
+               /*
+                * Rest of the page in the page_vec
+                * redirty then and skip then. We will
+                * try to to write them again after
+                * starting a new transaction
+                */
+               redirty_page_for_writepage(wbc, page);
+               unlock_page(page);
+               return MPAGE_DA_EXTENT_TAIL;
+       }
        /*
         * Can we merge this page to current extent?
         */
        if (mpd->next_page != page->index) {
                /*
                 * Nope, we can't. So, we map non-allocated blocks
-                * and start IO on them using __mpage_writepage()
+                * and start IO on them using writepage()
                 */
                if (mpd->next_page != mpd->first_page) {
                        mpage_da_map_blocks(mpd);
                        mpage_da_submit_io(mpd);
+                       /*
+                        * skip rest of the page in the page_vec
+                        */
+                       mpd->io_done = 1;
+                       redirty_page_for_writepage(wbc, page);
+                       unlock_page(page);
+                       return MPAGE_DA_EXTENT_TAIL;
                }
 
                /*
@@ -1883,6 +1957,8 @@ static int __mpage_da_writepage(struct page *page,
                set_buffer_dirty(bh);
                set_buffer_uptodate(bh);
                mpage_add_bh_to_extent(mpd, logical, bh);
+               if (mpd->io_done)
+                       return MPAGE_DA_EXTENT_TAIL;
        } else {
                /*
                 * Page with regular buffer heads, just add all dirty ones
@@ -1891,8 +1967,12 @@ static int __mpage_da_writepage(struct page *page,
                bh = head;
                do {
                        BUG_ON(buffer_locked(bh));
-                       if (buffer_dirty(bh))
+                       if (buffer_dirty(bh) &&
+                               (!buffer_mapped(bh) || buffer_delay(bh))) {
                                mpage_add_bh_to_extent(mpd, logical, bh);
+                               if (mpd->io_done)
+                                       return MPAGE_DA_EXTENT_TAIL;
+                       }
                        logical++;
                } while ((bh = bh->b_this_page) != head);
        }
@@ -1911,22 +1991,13 @@ static int __mpage_da_writepage(struct page *page,
  *
  * This is a library function, which implements the writepages()
  * address_space_operation.
- *
- * In order to avoid duplication of logic that deals with partial pages,
- * multiple bio per page, etc, we find non-allocated blocks, allocate
- * them with minimal calls to ->get_block() and re-use __mpage_writepage()
- *
- * It's important that we call __mpage_writepage() only once for each
- * involved page, otherwise we'd have to implement more complicated logic
- * to deal with pages w/o PG_lock or w/ PG_writeback and so on.
- *
- * See comments to mpage_writepages()
  */
 static int mpage_da_writepages(struct address_space *mapping,
                               struct writeback_control *wbc,
                               get_block_t get_block)
 {
        struct mpage_da_data mpd;
+       long to_write;
        int ret;
 
        if (!get_block)
@@ -1940,17 +2011,22 @@ static int mpage_da_writepages(struct address_space *mapping,
        mpd.first_page = 0;
        mpd.next_page = 0;
        mpd.get_block = get_block;
+       mpd.io_done = 0;
+       mpd.pages_written = 0;
+
+       to_write = wbc->nr_to_write;
 
        ret = write_cache_pages(mapping, wbc, __mpage_da_writepage, &mpd);
 
        /*
         * Handle last extent of pages
         */
-       if (mpd.next_page != mpd.first_page) {
+       if (!mpd.io_done && mpd.next_page != mpd.first_page) {
                mpage_da_map_blocks(&mpd);
                mpage_da_submit_io(&mpd);
        }
 
+       wbc->nr_to_write = to_write - mpd.pages_written;
        return ret;
 }
 
@@ -2165,10 +2241,10 @@ static int ext4_da_writepage(struct page *page,
  * for DIO, writepages, and truncate
  */
 #define EXT4_MAX_WRITEBACK_PAGES      DIO_MAX_BLOCKS
-#define EXT4_MAX_WRITEBACK_CREDITS    DIO_CREDITS
+#define EXT4_MAX_WRITEBACK_CREDITS    25
 
 static int ext4_da_writepages(struct address_space *mapping,
-                               struct writeback_control *wbc)
+                             struct writeback_control *wbc)
 {
        struct inode *inode = mapping->host;
        handle_t *handle = NULL;
@@ -2176,42 +2252,53 @@ static int ext4_da_writepages(struct address_space *mapping,
        int ret = 0;
        long to_write;
        loff_t range_start = 0;
+       long pages_skipped = 0;
 
        /*
         * No pages to write? This is mainly a kludge to avoid starting
         * a transaction for special inodes like journal inode on last iput()
         * because that could violate lock ordering on umount
         */
-       if (!mapping->nrpages)
+       if (!mapping->nrpages || !mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
                return 0;
 
-       /*
-        * Estimate the worse case needed credits to write out
-        * EXT4_MAX_BUF_BLOCKS pages
-        */
-       needed_blocks = EXT4_MAX_WRITEBACK_CREDITS;
-
-       to_write = wbc->nr_to_write;
-       if (!wbc->range_cyclic) {
+       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;
-       }
 
-       while (!ret && to_write) {
+       range_start =  wbc->range_start;
+       pages_skipped = wbc->pages_skipped;
+
+restart_loop:
+       to_write = wbc->nr_to_write;
+       while (!ret && to_write > 0) {
+
+               /*
+                * we  insert one extent at a time. So we need
+                * credit needed for single extent allocation.
+                * journalled mode is currently not supported
+                * by delalloc
+                */
+               BUG_ON(ext4_should_journal_data(inode));
+               needed_blocks = EXT4_DATA_TRANS_BLOCKS(inode->i_sb);
+
                /* start a new transaction*/
                handle = ext4_journal_start(inode, needed_blocks);
                if (IS_ERR(handle)) {
                        ret = PTR_ERR(handle);
+                       printk(KERN_EMERG "%s: jbd2_start: "
+                              "%ld pages, ino %lu; err %d\n", __func__,
+                               wbc->nr_to_write, inode->i_ino, ret);
+                       dump_stack();
                        goto out_writepages;
                }
                if (ext4_should_order_data(inode)) {
                        /*
                         * With ordered mode we need to add
-                        * the inode to the journal handle
+                        * the inode to the journal handl
                         * when we do block allocation.
                         */
                        ret = ext4_jbd2_file_inode(handle, inode);
@@ -2219,20 +2306,20 @@ static int ext4_da_writepages(struct address_space *mapping,
                                ext4_journal_stop(handle);
                                goto out_writepages;
                        }
-
                }
-               /*
-                * set the max dirty pages could be write at a time
-                * to fit into the reserved transaction credits
-                */
-               if (wbc->nr_to_write > EXT4_MAX_WRITEBACK_PAGES)
-                       wbc->nr_to_write = EXT4_MAX_WRITEBACK_PAGES;
 
                to_write -= wbc->nr_to_write;
                ret = mpage_da_writepages(mapping, wbc,
-                                               ext4_da_get_block_write);
+                                         ext4_da_get_block_write);
                ext4_journal_stop(handle);
-               if (wbc->nr_to_write) {
+               if (ret == MPAGE_DA_EXTENT_TAIL) {
+                       /*
+                        * got one extent now try with
+                        * rest of the pages
+                        */
+                       to_write += wbc->nr_to_write;
+                       ret = 0;
+               } else if (wbc->nr_to_write) {
                        /*
                         * There is no more writeout needed
                         * or we requested for a noblocking writeout
@@ -2244,10 +2331,18 @@ static int ext4_da_writepages(struct address_space *mapping,
                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;
+       }
+
 out_writepages:
        wbc->nr_to_write = to_write;
-       if (range_start)
-               wbc->range_start = range_start;
+       wbc->range_start = range_start;
        return ret;
 }
 
@@ -2280,8 +2375,11 @@ retry:
        }
 
        page = __grab_cache_page(mapping, index);
-       if (!page)
-               return -ENOMEM;
+       if (!page) {
+               ext4_journal_stop(handle);
+               ret = -ENOMEM;
+               goto out;
+       }
        *pagep = page;
 
        ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
@@ -3434,6 +3532,9 @@ void ext4_truncate(struct inode *inode)
         * modify the block allocation tree.
         */
        down_write(&ei->i_data_sem);
+
+       ext4_discard_reservation(inode);
+
        /*
         * The orphan list entry will now protect us from any crash which
         * occurs before the truncate completes, so it is now safe to propagate
@@ -3503,8 +3604,6 @@ do_indirects:
                ;
        }
 
-       ext4_discard_reservation(inode);
-
        up_write(&ei->i_data_sem);
        inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
        ext4_mark_inode_dirty(handle, inode);
@@ -3590,6 +3689,16 @@ static int __ext4_get_inode_loc(struct inode *inode,
        }
        if (!buffer_uptodate(bh)) {
                lock_buffer(bh);
+
+               /*
+                * If the buffer has the write error flag, we have failed
+                * to write out another inode in the same block.  In this
+                * case, we don't have to read the block because we may
+                * read the old inode data successfully.
+                */
+               if (buffer_write_io_error(bh) && !buffer_uptodate(bh))
+                       set_buffer_uptodate(bh);
+
                if (buffer_uptodate(bh)) {
                        /* someone brought it uptodate while we waited */
                        unlock_buffer(bh);
@@ -4262,56 +4371,130 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
        return 0;
 }
 
+static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
+                                     int chunk)
+{
+       int indirects;
+
+       /* if nrblocks are contiguous */
+       if (chunk) {
+               /*
+                * With N contiguous data blocks, it need at most
+                * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks
+                * 2 dindirect blocks
+                * 1 tindirect block
+                */
+               indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb);
+               return indirects + 3;
+       }
+       /*
+        * if nrblocks are not contiguous, worse case, each block touch
+        * a indirect block, and each indirect block touch a double indirect
+        * block, plus a triple indirect block
+        */
+       indirects = nrblocks * 2 + 1;
+       return indirects;
+}
+
+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);
+}
 /*
- * How many blocks doth make a writepage()?
- *
- * With N blocks per page, it may be:
- * N data blocks
- * 2 indirect block
- * 2 dindirect
- * 1 tindirect
- * N+5 bitmap blocks (from the above)
- * N+5 group descriptor summary blocks
- * 1 inode block
- * 1 superblock.
- * 2 * EXT4_SINGLEDATA_TRANS_BLOCKS for the quote files
+ * Account for index blocks, block groups bitmaps and block group
+ * descriptor blocks if modify datablocks and index blocks
+ * worse case, the indexs blocks spread over different block groups
  *
- * 3 * (N + 5) + 2 + 2 * EXT4_SINGLEDATA_TRANS_BLOCKS
+ * If datablocks are discontiguous, they are possible to spread over
+ * different block groups too. If they are contiugous, with flexbg,
+ * they could still across block group boundary.
  *
- * With ordered or writeback data it's the same, less the N data blocks.
+ * Also account for superblock, inode, quota and xattr blocks
+ */
+int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+{
+       int groups, gdpblocks;
+       int idxblocks;
+       int ret = 0;
+
+       /*
+        * How many index blocks need to touch to modify nrblocks?
+        * The "Chunk" flag indicating whether the nrblocks is
+        * physically contiguous on disk
+        *
+        * For Direct IO and fallocate, they calls get_block to allocate
+        * one single extent at a time, so they could set the "Chunk" flag
+        */
+       idxblocks = ext4_index_trans_blocks(inode, nrblocks, chunk);
+
+       ret = idxblocks;
+
+       /*
+        * Now let's see how many group bitmaps and group descriptors need
+        * to account
+        */
+       groups = idxblocks;
+       if (chunk)
+               groups += 1;
+       else
+               groups += nrblocks;
+
+       gdpblocks = groups;
+       if (groups > EXT4_SB(inode->i_sb)->s_groups_count)
+               groups = EXT4_SB(inode->i_sb)->s_groups_count;
+       if (groups > EXT4_SB(inode->i_sb)->s_gdb_count)
+               gdpblocks = EXT4_SB(inode->i_sb)->s_gdb_count;
+
+       /* bitmaps and block group descriptor blocks */
+       ret += groups + gdpblocks;
+
+       /* Blocks for super block, inode, quota and xattr blocks */
+       ret += EXT4_META_TRANS_BLOCKS(inode->i_sb);
+
+       return ret;
+}
+
+/*
+ * Calulate the total number of credits to reserve to fit
+ * the modification of a single pages into a single transaction,
+ * which may include multiple chunks of block allocations.
  *
- * If the inode's direct blocks can hold an integral number of pages then a
- * page cannot straddle two indirect blocks, and we can only touch one indirect
- * and dindirect block, and the "5" above becomes "3".
+ * This could be called via ext4_write_begin() or later
+ * ext4_da_writepages() in delalyed allocation case.
  *
- * This still overestimates under most circumstances.  If we were to pass the
- * start and end offsets in here as well we could do block_to_path() on each
- * block and work out the exact number of indirects which are touched.  Pah.
+ * In both case it's possible that we could allocating multiple
+ * chunks of blocks. We need to consider the worse case, when
+ * one new block per extent.
  */
-
 int ext4_writepage_trans_blocks(struct inode *inode)
 {
        int bpp = ext4_journal_blocks_per_page(inode);
-       int indirects = (EXT4_NDIR_BLOCKS % bpp) ? 5 : 3;
        int ret;
 
-       if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
-               return ext4_ext_writepage_trans_blocks(inode, bpp);
+       ret = ext4_meta_trans_blocks(inode, bpp, 0);
 
+       /* Account for data blocks for journalled mode */
        if (ext4_should_journal_data(inode))
-               ret = 3 * (bpp + indirects) + 2;
-       else
-               ret = 2 * (bpp + indirects) + 2;
-
-#ifdef CONFIG_QUOTA
-       /* We know that structure was already allocated during DQUOT_INIT so
-        * we will be updating only the data blocks + inodes */
-       ret += 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
-#endif
-
+               ret += bpp;
        return ret;
 }
 
+/*
+ * Calculate the journal credits for a chunk of data modification.
+ *
+ * This is called from DIO, fallocate or whoever calling
+ * ext4_get_blocks_wrap() to map/allocate a chunk of contigous disk blocks.
+ *
+ * journal buffers for data blocks are not included here, as DIO
+ * and fallocate do no need to journal data buffers.
+ */
+int ext4_chunk_trans_blocks(struct inode *inode, int nrblocks)
+{
+       return ext4_meta_trans_blocks(inode, nrblocks, 1);
+}
+
 /*
  * The caller must have previously called ext4_reserve_inode_write().
  * Give this, we know that the caller already has write access to iloc->bh.