ext4: do not ask jbd2 to write data for delalloc buffers
[sfrench/cifs-2.6.git] / fs / ext4 / inode.c
index 4f7043ba44475326c830d04a1764a912b47b5504..17bfa42ac97132dff751baace2e73c4c9de3d120 100644 (file)
@@ -684,6 +684,24 @@ out_sem:
                ret = check_block_validity(inode, map);
                if (ret != 0)
                        return ret;
+
+               /*
+                * Inodes with freshly allocated blocks where contents will be
+                * visible after transaction commit must be on transaction's
+                * ordered data list.
+                */
+               if (map->m_flags & EXT4_MAP_NEW &&
+                   !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+                   !(flags & EXT4_GET_BLOCKS_ZERO) &&
+                   !IS_NOQUOTA(inode) &&
+                   ext4_should_order_data(inode)) {
+                       if (flags & EXT4_GET_BLOCKS_IO_SUBMIT)
+                               ret = ext4_jbd2_inode_add_wait(handle, inode);
+                       else
+                               ret = ext4_jbd2_inode_add_write(handle, inode);
+                       if (ret)
+                               return ret;
+               }
        }
        return retval;
 }
@@ -763,39 +781,47 @@ int ext4_get_block_unwritten(struct inode *inode, sector_t iblock,
 /* Maximum number of blocks we map for direct IO at once. */
 #define DIO_MAX_BLOCKS 4096
 
-static handle_t *start_dio_trans(struct inode *inode,
-                                struct buffer_head *bh_result)
+/*
+ * Get blocks function for the cases that need to start a transaction -
+ * generally difference cases of direct IO and DAX IO. It also handles retries
+ * in case of ENOSPC.
+ */
+static int ext4_get_block_trans(struct inode *inode, sector_t iblock,
+                               struct buffer_head *bh_result, int flags)
 {
        int dio_credits;
+       handle_t *handle;
+       int retries = 0;
+       int ret;
 
        /* Trim mapping request to maximum we can map at once for DIO */
        if (bh_result->b_size >> inode->i_blkbits > DIO_MAX_BLOCKS)
                bh_result->b_size = DIO_MAX_BLOCKS << inode->i_blkbits;
        dio_credits = ext4_chunk_trans_blocks(inode,
                                      bh_result->b_size >> inode->i_blkbits);
-       return ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, dio_credits);
+retry:
+       handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, dio_credits);
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+
+       ret = _ext4_get_block(inode, iblock, bh_result, flags);
+       ext4_journal_stop(handle);
+
+       if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+               goto retry;
+       return ret;
 }
 
 /* Get block function for DIO reads and writes to inodes without extents */
 int ext4_dio_get_block(struct inode *inode, sector_t iblock,
                       struct buffer_head *bh, int create)
 {
-       handle_t *handle;
-       int ret;
-
        /* We don't expect handle for direct IO */
        WARN_ON_ONCE(ext4_journal_current_handle());
 
-       if (create) {
-               handle = start_dio_trans(inode, bh);
-               if (IS_ERR(handle))
-                       return PTR_ERR(handle);
-       }
-       ret = _ext4_get_block(inode, iblock, bh,
-                             create ? EXT4_GET_BLOCKS_CREATE : 0);
-       if (create)
-               ext4_journal_stop(handle);
-       return ret;
+       if (!create)
+               return _ext4_get_block(inode, iblock, bh, 0);
+       return ext4_get_block_trans(inode, iblock, bh, EXT4_GET_BLOCKS_CREATE);
 }
 
 /*
@@ -806,18 +832,13 @@ int ext4_dio_get_block(struct inode *inode, sector_t iblock,
 static int ext4_dio_get_block_unwritten_async(struct inode *inode,
                sector_t iblock, struct buffer_head *bh_result, int create)
 {
-       handle_t *handle;
        int ret;
 
        /* We don't expect handle for direct IO */
        WARN_ON_ONCE(ext4_journal_current_handle());
 
-       handle = start_dio_trans(inode, bh_result);
-       if (IS_ERR(handle))
-               return PTR_ERR(handle);
-       ret = _ext4_get_block(inode, iblock, bh_result,
-                             EXT4_GET_BLOCKS_IO_CREATE_EXT);
-       ext4_journal_stop(handle);
+       ret = ext4_get_block_trans(inode, iblock, bh_result,
+                                  EXT4_GET_BLOCKS_IO_CREATE_EXT);
 
        /*
         * When doing DIO using unwritten extents, we need io_end to convert
@@ -850,18 +871,13 @@ static int ext4_dio_get_block_unwritten_async(struct inode *inode,
 static int ext4_dio_get_block_unwritten_sync(struct inode *inode,
                sector_t iblock, struct buffer_head *bh_result, int create)
 {
-       handle_t *handle;
        int ret;
 
        /* We don't expect handle for direct IO */
        WARN_ON_ONCE(ext4_journal_current_handle());
 
-       handle = start_dio_trans(inode, bh_result);
-       if (IS_ERR(handle))
-               return PTR_ERR(handle);
-       ret = _ext4_get_block(inode, iblock, bh_result,
-                             EXT4_GET_BLOCKS_IO_CREATE_EXT);
-       ext4_journal_stop(handle);
+       ret = ext4_get_block_trans(inode, iblock, bh_result,
+                                  EXT4_GET_BLOCKS_IO_CREATE_EXT);
 
        /*
         * Mark inode as having pending DIO writes to unwritten extents.
@@ -1291,15 +1307,6 @@ static int ext4_write_end(struct file *file,
        int i_size_changed = 0;
 
        trace_ext4_write_end(inode, pos, len, copied);
-       if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-               ret = ext4_jbd2_file_inode(handle, inode);
-               if (ret) {
-                       unlock_page(page);
-                       put_page(page);
-                       goto errout;
-               }
-       }
-
        if (ext4_has_inline_data(inode)) {
                ret = ext4_write_inline_data_end(inode, pos, len,
                                                 copied, page);
@@ -2315,7 +2322,8 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
         * the data was copied into the page cache.
         */
        get_blocks_flags = EXT4_GET_BLOCKS_CREATE |
-                          EXT4_GET_BLOCKS_METADATA_NOFAIL;
+                          EXT4_GET_BLOCKS_METADATA_NOFAIL |
+                          EXT4_GET_BLOCKS_IO_SUBMIT;
        dioread_nolock = ext4_should_dioread_nolock(inode);
        if (dioread_nolock)
                get_blocks_flags |= EXT4_GET_BLOCKS_IO_CREATE_EXT;
@@ -3536,10 +3544,7 @@ void ext4_set_aops(struct inode *inode)
 {
        switch (ext4_inode_journal_mode(inode)) {
        case EXT4_INODE_ORDERED_DATA_MODE:
-               ext4_set_inode_state(inode, EXT4_STATE_ORDERED_MODE);
-               break;
        case EXT4_INODE_WRITEBACK_DATA_MODE:
-               ext4_clear_inode_state(inode, EXT4_STATE_ORDERED_MODE);
                break;
        case EXT4_INODE_JOURNAL_DATA_MODE:
                inode->i_mapping->a_ops = &ext4_journalled_aops;
@@ -3632,8 +3637,8 @@ static int __ext4_block_zero_page_range(handle_t *handle,
        } else {
                err = 0;
                mark_buffer_dirty(bh);
-               if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE))
-                       err = ext4_jbd2_file_inode(handle, inode);
+               if (ext4_should_order_data(inode))
+                       err = ext4_jbd2_inode_add_write(handle, inode);
        }
 
 unlock: