btrfs: change timing for qgroup reserved space for ordered extents to fix reserved...
[linux-2.6-block.git] / fs / btrfs / ordered-data.c
index e13b3d28c063b4f3bf015dc8c5a2a4abcdf044bd..c8bd7a4e67bb94c4d78cdc2762a27db064cedc5e 100644 (file)
@@ -15,6 +15,7 @@
 #include "disk-io.h"
 #include "compression.h"
 #include "delalloc-space.h"
+#include "qgroup.h"
 
 static struct kmem_cache *btrfs_ordered_extent_cache;
 
@@ -152,7 +153,8 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree,
        return ret;
 }
 
-/* allocate and add a new ordered_extent into the per-inode tree.
+/*
+ * Allocate and add a new ordered_extent into the per-inode tree.
  *
  * The tree is given a single reference on the ordered extent that was
  * inserted.
@@ -167,7 +169,24 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
        struct btrfs_ordered_inode_tree *tree;
        struct rb_node *node;
        struct btrfs_ordered_extent *entry;
+       int ret;
 
+       if (type == BTRFS_ORDERED_NOCOW || type == BTRFS_ORDERED_PREALLOC) {
+               /* For nocow write, we can release the qgroup rsv right now */
+               ret = btrfs_qgroup_free_data(inode, NULL, file_offset,
+                                            num_bytes);
+               if (ret < 0)
+                       return ret;
+               ret = 0;
+       } else {
+               /*
+                * The ordered extent has reserved qgroup space, release now
+                * and pass the reserved number for qgroup_record to free.
+                */
+               ret = btrfs_qgroup_release_data(inode, file_offset, num_bytes);
+               if (ret < 0)
+                       return ret;
+       }
        tree = &BTRFS_I(inode)->ordered_tree;
        entry = kmem_cache_zalloc(btrfs_ordered_extent_cache, GFP_NOFS);
        if (!entry)
@@ -181,6 +200,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
        entry->inode = igrab(inode);
        entry->compress_type = compress_type;
        entry->truncated_len = (u64)-1;
+       entry->qgroup_rsv = ret;
        if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE)
                set_bit(type, &entry->flags);