btrfs: change timing for qgroup reserved space for ordered extents to fix reserved...
[linux-2.6-block.git] / fs / btrfs / ordered-data.c
index a65f189a5b9418e17e28ef90dfb7508e13b173be..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);
 
@@ -580,7 +600,7 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, u64 nr,
        while (!list_empty(&splice) && nr) {
                root = list_first_entry(&splice, struct btrfs_root,
                                        ordered_root);
-               root = btrfs_grab_fs_root(root);
+               root = btrfs_grab_root(root);
                BUG_ON(!root);
                list_move_tail(&root->ordered_root,
                               &fs_info->ordered_roots);
@@ -588,7 +608,7 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, u64 nr,
 
                done = btrfs_wait_ordered_extents(root, nr,
                                                  range_start, range_len);
-               btrfs_put_fs_root(root);
+               btrfs_put_root(root);
 
                spin_lock(&fs_info->ordered_root_lock);
                if (nr != U64_MAX) {
@@ -785,134 +805,6 @@ out:
        return entry;
 }
 
-/*
- * After an extent is done, call this to conditionally update the on disk
- * i_size.  i_size is updated to cover any fully written part of the file.
- */
-int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
-                               struct btrfs_ordered_extent *ordered)
-{
-       struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
-       u64 disk_i_size;
-       u64 new_i_size;
-       u64 i_size = i_size_read(inode);
-       struct rb_node *node;
-       struct rb_node *prev = NULL;
-       struct btrfs_ordered_extent *test;
-       int ret = 1;
-       u64 orig_offset = offset;
-
-       spin_lock_irq(&tree->lock);
-       if (ordered) {
-               offset = entry_end(ordered);
-               if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered->flags))
-                       offset = min(offset,
-                                    ordered->file_offset +
-                                    ordered->truncated_len);
-       } else {
-               offset = ALIGN(offset, btrfs_inode_sectorsize(inode));
-       }
-       disk_i_size = BTRFS_I(inode)->disk_i_size;
-
-       /*
-        * truncate file.
-        * If ordered is not NULL, then this is called from endio and
-        * disk_i_size will be updated by either truncate itself or any
-        * in-flight IOs which are inside the disk_i_size.
-        *
-        * Because btrfs_setsize() may set i_size with disk_i_size if truncate
-        * fails somehow, we need to make sure we have a precise disk_i_size by
-        * updating it as usual.
-        *
-        */
-       if (!ordered && disk_i_size > i_size) {
-               BTRFS_I(inode)->disk_i_size = orig_offset;
-               ret = 0;
-               goto out;
-       }
-
-       /*
-        * if the disk i_size is already at the inode->i_size, or
-        * this ordered extent is inside the disk i_size, we're done
-        */
-       if (disk_i_size == i_size)
-               goto out;
-
-       /*
-        * We still need to update disk_i_size if outstanding_isize is greater
-        * than disk_i_size.
-        */
-       if (offset <= disk_i_size &&
-           (!ordered || ordered->outstanding_isize <= disk_i_size))
-               goto out;
-
-       /*
-        * walk backward from this ordered extent to disk_i_size.
-        * if we find an ordered extent then we can't update disk i_size
-        * yet
-        */
-       if (ordered) {
-               node = rb_prev(&ordered->rb_node);
-       } else {
-               prev = tree_search(tree, offset);
-               /*
-                * we insert file extents without involving ordered struct,
-                * so there should be no ordered struct cover this offset
-                */
-               if (prev) {
-                       test = rb_entry(prev, struct btrfs_ordered_extent,
-                                       rb_node);
-                       BUG_ON(offset_in_entry(test, offset));
-               }
-               node = prev;
-       }
-       for (; node; node = rb_prev(node)) {
-               test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
-
-               /* We treat this entry as if it doesn't exist */
-               if (test_bit(BTRFS_ORDERED_UPDATED_ISIZE, &test->flags))
-                       continue;
-
-               if (entry_end(test) <= disk_i_size)
-                       break;
-               if (test->file_offset >= i_size)
-                       break;
-
-               /*
-                * We don't update disk_i_size now, so record this undealt
-                * i_size. Or we will not know the real i_size.
-                */
-               if (test->outstanding_isize < offset)
-                       test->outstanding_isize = offset;
-               if (ordered &&
-                   ordered->outstanding_isize > test->outstanding_isize)
-                       test->outstanding_isize = ordered->outstanding_isize;
-               goto out;
-       }
-       new_i_size = min_t(u64, offset, i_size);
-
-       /*
-        * Some ordered extents may completed before the current one, and
-        * we hold the real i_size in ->outstanding_isize.
-        */
-       if (ordered && ordered->outstanding_isize > new_i_size)
-               new_i_size = min_t(u64, ordered->outstanding_isize, i_size);
-       BTRFS_I(inode)->disk_i_size = new_i_size;
-       ret = 0;
-out:
-       /*
-        * We need to do this because we can't remove ordered extents until
-        * after the i_disk_size has been updated and then the inode has been
-        * updated to reflect the change, so we need to tell anybody who finds
-        * this ordered extent that we've already done all the real work, we
-        * just haven't completed all the other work.
-        */
-       if (ordered)
-               set_bit(BTRFS_ORDERED_UPDATED_ISIZE, &ordered->flags);
-       spin_unlock_irq(&tree->lock);
-       return ret;
-}
-
 /*
  * search the ordered extents for one corresponding to 'offset' and
  * try to find a checksum.  This is used because we allow pages to
@@ -963,7 +855,6 @@ out:
  * btrfs_flush_ordered_range - Lock the passed range and ensures all pending
  * ordered extents in it are run to completion.
  *
- * @tree:         IO tree used for locking out other users of the range
  * @inode:        Inode whose ordered tree is to be searched
  * @start:        Beginning of range to flush
  * @end:          Last byte of range to lock
@@ -973,8 +864,7 @@ out:
  * This function always returns with the given range locked, ensuring after it's
  * called no order extent can be pending.
  */
-void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
-                                       struct btrfs_inode *inode, u64 start,
+void btrfs_lock_and_flush_ordered_range(struct btrfs_inode *inode, u64 start,
                                        u64 end,
                                        struct extent_state **cached_state)
 {
@@ -986,7 +876,7 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
                cachedp = cached_state;
 
        while (1) {
-               lock_extent_bits(tree, start, end, cachedp);
+               lock_extent_bits(&inode->io_tree, start, end, cachedp);
                ordered = btrfs_lookup_ordered_range(inode, start,
                                                     end - start + 1);
                if (!ordered) {
@@ -999,7 +889,7 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
                                refcount_dec(&cache->refs);
                        break;
                }
-               unlock_extent_cached(tree, start, end, cachedp);
+               unlock_extent_cached(&inode->io_tree, start, end, cachedp);
                btrfs_start_ordered_extent(&inode->vfs_inode, ordered, 1);
                btrfs_put_ordered_extent(ordered);
        }