* Account for the allocated meta blocks.  We will never
         * fail EDQUOT for metdata, but we do account for it.
         */
-       if (!(*errp) &&
-           ext4_test_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED)) {
+       if (!(*errp) && (flags & EXT4_MB_DELALLOC_RESERVED)) {
                spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
                spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
                dquot_alloc_block_nofail(inode,
 
        ext4_lblk_t next;
        int mb_flags = 0, unwritten;
 
+       if (gb_flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+               mb_flags |= EXT4_MB_DELALLOC_RESERVED;
        if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
                EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
                return -EIO;
         * We're gonna add a new leaf in the tree.
         */
        if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
-               mb_flags = EXT4_MB_USE_RESERVED;
+               mb_flags |= EXT4_MB_USE_RESERVED;
        err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
                                       ppath, newext);
        if (err)
                ar.flags = 0;
        if (flags & EXT4_GET_BLOCKS_NO_NORMALIZE)
                ar.flags |= EXT4_MB_HINT_NOPREALLOC;
+       if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+               ar.flags |= EXT4_MB_DELALLOC_RESERVED;
        newblock = ext4_mb_new_blocks(handle, &ar, &err);
        if (!newblock)
                goto out2;
 
                        new_blocks[i] = ext4_mb_new_blocks(handle, ar, &err);
                } else
                        ar->goal = new_blocks[i] = ext4_new_meta_blocks(handle,
-                                   ar->inode, ar->goal, 0, NULL, &err);
+                                       ar->inode, ar->goal,
+                                       ar->flags & EXT4_MB_DELALLOC_RESERVED,
+                                       NULL, &err);
                if (err) {
                        i--;
                        goto failed;
        ar.logical = map->m_lblk;
        if (S_ISREG(inode->i_mode))
                ar.flags = EXT4_MB_HINT_DATA;
+       if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+               ar.flags |= EXT4_MB_DELALLOC_RESERVED;
 
        ar.goal = ext4_find_goal(inode, map->m_lblk, partial);
 
 
         * EDQUOT check, as blocks and quotas have been already
         * reserved when data being copied into pagecache.
         */
-       if (ext4_test_inode_state(ar->inode, EXT4_STATE_DELALLOC_RESERVED))
+       if (ext4_test_inode_state(ar->inode, EXT4_STATE_DELALLOC_RESERVED)) {
+               WARN_ON((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0);
                ar->flags |= EXT4_MB_DELALLOC_RESERVED;
-       else {
+       }
+
+       if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0) {
                /* Without delayed allocation we need to verify
                 * there is enough free blocks to do block allocation
                 * and verify allocation doesn't exceed the quota limits.
        if (inquota && ar->len < inquota)
                dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
        if (!ar->len) {
-               if (!ext4_test_inode_state(ar->inode,
-                                          EXT4_STATE_DELALLOC_RESERVED))
+               if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0)
                        /* release all the reserved blocks if non delalloc */
                        percpu_counter_sub(&sbi->s_dirtyclusters_counter,
                                                reserv_clstrs);
 
                        if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
                                goal = goal & EXT4_MAX_BLOCK_FILE_PHYS;
 
-                       /*
-                        * take i_data_sem because we will test
-                        * i_delalloc_reserved_flag in ext4_mb_new_blocks
-                        */
-                       down_read(&EXT4_I(inode)->i_data_sem);
                        block = ext4_new_meta_blocks(handle, inode, goal, 0,
                                                     NULL, &error);
-                       up_read((&EXT4_I(inode)->i_data_sem));
                        if (error)
                                goto cleanup;