These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / btrfs / ordered-data.c
index 760c4a5..8c27292 100644 (file)
@@ -198,9 +198,6 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
        entry->file_offset = file_offset;
        entry->start = start;
        entry->len = len;
-       if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) &&
-           !(type == BTRFS_ORDERED_NOCOW))
-               entry->csum_bytes_left = disk_len;
        entry->disk_len = disk_len;
        entry->bytes_left = len;
        entry->inode = igrab(inode);
@@ -286,10 +283,6 @@ void btrfs_add_ordered_sum(struct inode *inode,
        tree = &BTRFS_I(inode)->ordered_tree;
        spin_lock_irq(&tree->lock);
        list_add_tail(&sum->list, &entry->list);
-       WARN_ON(entry->csum_bytes_left < sum->len);
-       entry->csum_bytes_left -= sum->len;
-       if (entry->csum_bytes_left == 0)
-               wake_up(&entry->wait);
        spin_unlock_irq(&tree->lock);
 }
 
@@ -352,6 +345,9 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode,
 
        if (entry->bytes_left == 0) {
                ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
+               /*
+                * Implicit memory barrier after test_and_set_bit
+                */
                if (waitqueue_active(&entry->wait))
                        wake_up(&entry->wait);
        } else {
@@ -416,6 +412,9 @@ have_entry:
 
        if (entry->bytes_left == 0) {
                ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
+               /*
+                * Implicit memory barrier after test_and_set_bit
+                */
                if (waitqueue_active(&entry->wait))
                        wake_up(&entry->wait);
        } else {
@@ -491,15 +490,16 @@ void btrfs_wait_logged_extents(struct btrfs_trans_handle *trans,
 
        spin_lock_irq(&log->log_extents_lock[index]);
        while (!list_empty(&log->logged_list[index])) {
+               struct inode *inode;
                ordered = list_first_entry(&log->logged_list[index],
                                           struct btrfs_ordered_extent,
                                           log_list);
                list_del_init(&ordered->log_list);
+               inode = ordered->inode;
                spin_unlock_irq(&log->log_extents_lock[index]);
 
                if (!test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags) &&
                    !test_bit(BTRFS_ORDERED_DIRECT, &ordered->flags)) {
-                       struct inode *inode = ordered->inode;
                        u64 start = ordered->file_offset;
                        u64 end = ordered->file_offset + ordered->len - 1;
 
@@ -509,7 +509,26 @@ void btrfs_wait_logged_extents(struct btrfs_trans_handle *trans,
                wait_event(ordered->wait, test_bit(BTRFS_ORDERED_IO_DONE,
                                                   &ordered->flags));
 
-               list_add_tail(&ordered->trans_list, &trans->ordered);
+               /*
+                * In order to keep us from losing our ordered extent
+                * information when committing the transaction we have to make
+                * sure that any logged extents are completed when we go to
+                * commit the transaction.  To do this we simply increase the
+                * current transactions pending_ordered counter and decrement it
+                * when the ordered extent completes.
+                */
+               if (!test_bit(BTRFS_ORDERED_COMPLETE, &ordered->flags)) {
+                       struct btrfs_ordered_inode_tree *tree;
+
+                       tree = &BTRFS_I(inode)->ordered_tree;
+                       spin_lock_irq(&tree->lock);
+                       if (!test_bit(BTRFS_ORDERED_COMPLETE, &ordered->flags)) {
+                               set_bit(BTRFS_ORDERED_PENDING, &ordered->flags);
+                               atomic_inc(&trans->transaction->pending_ordered);
+                       }
+                       spin_unlock_irq(&tree->lock);
+               }
+               btrfs_put_ordered_extent(ordered);
                spin_lock_irq(&log->log_extents_lock[index]);
        }
        spin_unlock_irq(&log->log_extents_lock[index]);
@@ -545,6 +564,10 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
        trace_btrfs_ordered_extent_put(entry->inode, entry);
 
        if (atomic_dec_and_test(&entry->refs)) {
+               ASSERT(list_empty(&entry->log_list));
+               ASSERT(list_empty(&entry->trans_list));
+               ASSERT(list_empty(&entry->root_extent_list));
+               ASSERT(RB_EMPTY_NODE(&entry->rb_node));
                if (entry->inode)
                        btrfs_add_delayed_iput(entry->inode);
                while (!list_empty(&entry->list)) {
@@ -567,16 +590,47 @@ void btrfs_remove_ordered_extent(struct inode *inode,
        struct btrfs_ordered_inode_tree *tree;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct rb_node *node;
+       bool dec_pending_ordered = false;
 
        tree = &BTRFS_I(inode)->ordered_tree;
        spin_lock_irq(&tree->lock);
        node = &entry->rb_node;
        rb_erase(node, &tree->tree);
+       RB_CLEAR_NODE(node);
        if (tree->last == node)
                tree->last = NULL;
        set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags);
+       if (test_and_clear_bit(BTRFS_ORDERED_PENDING, &entry->flags))
+               dec_pending_ordered = true;
        spin_unlock_irq(&tree->lock);
 
+       /*
+        * The current running transaction is waiting on us, we need to let it
+        * know that we're complete and wake it up.
+        */
+       if (dec_pending_ordered) {
+               struct btrfs_transaction *trans;
+
+               /*
+                * The checks for trans are just a formality, it should be set,
+                * but if it isn't we don't want to deref/assert under the spin
+                * lock, so be nice and check if trans is set, but ASSERT() so
+                * if it isn't set a developer will notice.
+                */
+               spin_lock(&root->fs_info->trans_lock);
+               trans = root->fs_info->running_transaction;
+               if (trans)
+                       atomic_inc(&trans->use_count);
+               spin_unlock(&root->fs_info->trans_lock);
+
+               ASSERT(trans);
+               if (trans) {
+                       if (atomic_dec_and_test(&trans->pending_ordered))
+                               wake_up(&trans->pending_wait);
+                       btrfs_put_transaction(trans);
+               }
+       }
+
        spin_lock(&root->ordered_extent_lock);
        list_del_init(&entry->root_extent_list);
        root->nr_ordered_extents--;
@@ -844,6 +898,20 @@ out:
        return entry;
 }
 
+bool btrfs_have_ordered_extents_in_range(struct inode *inode,
+                                        u64 file_offset,
+                                        u64 len)
+{
+       struct btrfs_ordered_extent *oe;
+
+       oe = btrfs_lookup_ordered_range(inode, file_offset, len);
+       if (oe) {
+               btrfs_put_ordered_extent(oe);
+               return true;
+       }
+       return false;
+}
+
 /*
  * lookup and return any extent before 'file_offset'.  NULL is returned
  * if none is found