num_pages *= 16;
        num_pages *= PAGE_CACHE_SIZE;
 
-       ret = btrfs_check_data_free_space(inode, num_pages, num_pages);
+       ret = __btrfs_check_data_free_space(inode, 0, num_pages);
        if (ret)
                goto out_put;
 
                                              &alloc_hint);
        if (!ret)
                dcs = BTRFS_DC_SETUP;
-       btrfs_free_reserved_data_space(inode, num_pages);
+       __btrfs_free_reserved_data_space(inode, 0, num_pages);
 
 out_put:
        iput(inode);
 
                }
 
                reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
-               ret = btrfs_check_data_free_space(inode, reserve_bytes, write_bytes);
-               if (ret == -ENOSPC &&
-                   (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
-                                             BTRFS_INODE_PREALLOC))) {
+
+               if (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
+                                            BTRFS_INODE_PREALLOC)) {
                        ret = check_can_nocow(inode, pos, &write_bytes);
+                       if (ret < 0)
+                               break;
                        if (ret > 0) {
+                               /*
+                                * For nodata cow case, no need to reserve
+                                * data space.
+                                */
                                only_release_metadata = true;
                                /*
                                 * our prealloc extent may be smaller than
                                num_pages = DIV_ROUND_UP(write_bytes + offset,
                                                         PAGE_CACHE_SIZE);
                                reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
-                               ret = 0;
-                       } else {
-                               ret = -ENOSPC;
+                               goto reserve_metadata;
                        }
                }
-
-               if (ret)
+               ret = __btrfs_check_data_free_space(inode, pos, write_bytes);
+               if (ret < 0)
                        break;
 
+reserve_metadata:
                ret = btrfs_delalloc_reserve_metadata(inode, reserve_bytes);
                if (ret) {
                        if (!only_release_metadata)
-                               btrfs_free_reserved_data_space(inode,
-                                                              reserve_bytes);
+                               __btrfs_free_reserved_data_space(inode, pos,
+                                                                write_bytes);
                        else
                                btrfs_end_write_no_snapshoting(root);
                        break;
        /*
         * Make sure we have enough space before we do the
         * allocation.
+        * XXX: The behavior must be changed to do accurate check first
+        * and then check data reserved space.
         */
-       ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start, alloc_end - alloc_start);
+       ret = btrfs_check_data_free_space(inode, alloc_start,
+                                         alloc_end - alloc_start);
        if (ret)
                return ret;
 
 out:
        mutex_unlock(&inode->i_mutex);
        /* Let go of our reservation. */
-       btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
+       __btrfs_free_reserved_data_space(inode, alloc_start,
+                                        alloc_end - alloc_start);
        return ret;
 }
 
 
        BUG_ON(cluster->start != cluster->boundary[0]);
        mutex_lock(&inode->i_mutex);
 
-       ret = btrfs_check_data_free_space(inode, cluster->end +
-                                         1 - cluster->start, 0);
+       ret = __btrfs_check_data_free_space(inode, cluster->start,
+                                           cluster->end + 1 - cluster->start);
        if (ret)
                goto out;
 
                        break;
                nr++;
        }
-       btrfs_free_reserved_data_space(inode, cluster->end +
-                                      1 - cluster->start);
+       __btrfs_free_reserved_data_space(inode, cluster->start,
+                                        cluster->end + 1 - cluster->start);
 out:
        mutex_unlock(&inode->i_mutex);
        return ret;