]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/btrfs/ordered-data.c
Btrfs: wake up the tasks that wait for the io earlier
[mirror_ubuntu-bionic-kernel.git] / fs / btrfs / ordered-data.c
index 69582d5b69d1f6064a77a409760a3ba1886b6d92..a75eaa286b8a91bdad4e26de0ed02b08df62e3b8 100644 (file)
@@ -336,22 +336,26 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode,
                      entry->len);
        *file_offset = dec_end;
        if (dec_start > dec_end) {
-               printk(KERN_CRIT "bad ordering dec_start %llu end %llu\n",
-                      dec_start, dec_end);
+               btrfs_crit(BTRFS_I(inode)->root->fs_info,
+                       "bad ordering dec_start %llu end %llu", dec_start, dec_end);
        }
        to_dec = dec_end - dec_start;
        if (to_dec > entry->bytes_left) {
-               printk(KERN_CRIT "bad ordered accounting left %llu size %llu\n",
-                      entry->bytes_left, to_dec);
+               btrfs_crit(BTRFS_I(inode)->root->fs_info,
+                       "bad ordered accounting left %llu size %llu",
+                       entry->bytes_left, to_dec);
        }
        entry->bytes_left -= to_dec;
        if (!uptodate)
                set_bit(BTRFS_ORDERED_IOERR, &entry->flags);
 
-       if (entry->bytes_left == 0)
+       if (entry->bytes_left == 0) {
                ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
-       else
+               if (waitqueue_active(&entry->wait))
+                       wake_up(&entry->wait);
+       } else {
                ret = 1;
+       }
 out:
        if (!ret && cached && entry) {
                *cached = entry;
@@ -401,17 +405,21 @@ have_entry:
        }
 
        if (io_size > entry->bytes_left) {
-               printk(KERN_CRIT "bad ordered accounting left %llu size %llu\n",
+               btrfs_crit(BTRFS_I(inode)->root->fs_info,
+                          "bad ordered accounting left %llu size %llu",
                       entry->bytes_left, io_size);
        }
        entry->bytes_left -= io_size;
        if (!uptodate)
                set_bit(BTRFS_ORDERED_IOERR, &entry->flags);
 
-       if (entry->bytes_left == 0)
+       if (entry->bytes_left == 0) {
                ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
-       else
+               if (waitqueue_active(&entry->wait))
+                       wake_up(&entry->wait);
+       } else {
                ret = 1;
+       }
 out:
        if (!ret && cached && entry) {
                *cached = entry;
@@ -422,27 +430,48 @@ out:
 }
 
 /* Needs to either be called under a log transaction or the log_mutex */
-void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode)
+void btrfs_get_logged_extents(struct inode *inode,
+                             struct list_head *logged_list)
 {
        struct btrfs_ordered_inode_tree *tree;
        struct btrfs_ordered_extent *ordered;
        struct rb_node *n;
-       int index = log->log_transid % 2;
 
        tree = &BTRFS_I(inode)->ordered_tree;
        spin_lock_irq(&tree->lock);
        for (n = rb_first(&tree->tree); n; n = rb_next(n)) {
                ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node);
-               spin_lock(&log->log_extents_lock[index]);
-               if (list_empty(&ordered->log_list)) {
-                       list_add_tail(&ordered->log_list, &log->logged_list[index]);
-                       atomic_inc(&ordered->refs);
-               }
-               spin_unlock(&log->log_extents_lock[index]);
+               if (!list_empty(&ordered->log_list))
+                       continue;
+               list_add_tail(&ordered->log_list, logged_list);
+               atomic_inc(&ordered->refs);
        }
        spin_unlock_irq(&tree->lock);
 }
 
+void btrfs_put_logged_extents(struct list_head *logged_list)
+{
+       struct btrfs_ordered_extent *ordered;
+
+       while (!list_empty(logged_list)) {
+               ordered = list_first_entry(logged_list,
+                                          struct btrfs_ordered_extent,
+                                          log_list);
+               list_del_init(&ordered->log_list);
+               btrfs_put_ordered_extent(ordered);
+       }
+}
+
+void btrfs_submit_logged_extents(struct list_head *logged_list,
+                                struct btrfs_root *log)
+{
+       int index = log->log_transid % 2;
+
+       spin_lock_irq(&log->log_extents_lock[index]);
+       list_splice_tail(logged_list, &log->logged_list[index]);
+       spin_unlock_irq(&log->log_extents_lock[index]);
+}
+
 void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid)
 {
        struct btrfs_ordered_extent *ordered;
@@ -520,7 +549,8 @@ void btrfs_remove_ordered_extent(struct inode *inode,
        spin_lock_irq(&tree->lock);
        node = &entry->rb_node;
        rb_erase(node, &tree->tree);
-       tree->last = NULL;
+       if (tree->last == node)
+               tree->last = NULL;
        set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags);
        spin_unlock_irq(&tree->lock);
 
@@ -565,7 +595,7 @@ static void btrfs_run_ordered_extent_work(struct btrfs_work *work)
  * wait for all the ordered extents in a root.  This is done when balancing
  * space between drives.
  */
-int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
+static int __btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
 {
        struct list_head splice, works;
        struct btrfs_ordered_extent *ordered, *next;
@@ -574,7 +604,6 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
        INIT_LIST_HEAD(&splice);
        INIT_LIST_HEAD(&works);
 
-       mutex_lock(&root->fs_info->ordered_operations_mutex);
        spin_lock(&root->ordered_extent_lock);
        list_splice_init(&root->ordered_extents, &splice);
        while (!list_empty(&splice) && nr) {
@@ -585,10 +614,11 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
                atomic_inc(&ordered->refs);
                spin_unlock(&root->ordered_extent_lock);
 
-               ordered->flush_work.func = btrfs_run_ordered_extent_work;
+               btrfs_init_work(&ordered->flush_work,
+                               btrfs_run_ordered_extent_work, NULL, NULL);
                list_add_tail(&ordered->work_list, &works);
-               btrfs_queue_worker(&root->fs_info->flush_workers,
-                                  &ordered->flush_work);
+               btrfs_queue_work(root->fs_info->flush_workers,
+                                &ordered->flush_work);
 
                cond_resched();
                spin_lock(&root->ordered_extent_lock);
@@ -605,6 +635,16 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
                btrfs_put_ordered_extent(ordered);
                cond_resched();
        }
+
+       return count;
+}
+
+int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
+{
+       int count;
+
+       mutex_lock(&root->fs_info->ordered_operations_mutex);
+       count = __btrfs_wait_ordered_extents(root, nr);
        mutex_unlock(&root->fs_info->ordered_operations_mutex);
 
        return count;
@@ -618,6 +658,7 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr)
 
        INIT_LIST_HEAD(&splice);
 
+       mutex_lock(&fs_info->ordered_operations_mutex);
        spin_lock(&fs_info->ordered_root_lock);
        list_splice_init(&fs_info->ordered_roots, &splice);
        while (!list_empty(&splice) && nr) {
@@ -629,7 +670,7 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr)
                               &fs_info->ordered_roots);
                spin_unlock(&fs_info->ordered_root_lock);
 
-               done = btrfs_wait_ordered_extents(root, nr);
+               done = __btrfs_wait_ordered_extents(root, nr);
                btrfs_put_fs_root(root);
 
                spin_lock(&fs_info->ordered_root_lock);
@@ -640,6 +681,7 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr)
        }
        list_splice_tail(&splice, &fs_info->ordered_roots);
        spin_unlock(&fs_info->ordered_root_lock);
+       mutex_unlock(&fs_info->ordered_operations_mutex);
 }
 
 /*
@@ -701,8 +743,8 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans,
                        goto out;
                }
                list_add_tail(&work->list, &works);
-               btrfs_queue_worker(&root->fs_info->flush_workers,
-                                  &work->work);
+               btrfs_queue_work(root->fs_info->flush_workers,
+                                &work->work);
 
                cond_resched();
                spin_lock(&root->fs_info->ordered_root_lock);