Merge tag 'drm-intel-fixes-2016-06-30' of git://anongit.freedesktop.org/drm-intel...
[cascardo/linux.git] / fs / btrfs / ordered-data.c
index 0de7da5..aca8264 100644 (file)
@@ -661,14 +661,15 @@ 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)
+int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr,
+                              const u64 range_start, const u64 range_len)
 {
-       struct list_head splice, works;
+       LIST_HEAD(splice);
+       LIST_HEAD(skipped);
+       LIST_HEAD(works);
        struct btrfs_ordered_extent *ordered, *next;
        int count = 0;
-
-       INIT_LIST_HEAD(&splice);
-       INIT_LIST_HEAD(&works);
+       const u64 range_end = range_start + range_len;
 
        mutex_lock(&root->ordered_extent_mutex);
        spin_lock(&root->ordered_extent_lock);
@@ -676,6 +677,14 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
        while (!list_empty(&splice) && nr) {
                ordered = list_first_entry(&splice, struct btrfs_ordered_extent,
                                           root_extent_list);
+
+               if (range_end <= ordered->start ||
+                   ordered->start + ordered->disk_len <= range_start) {
+                       list_move_tail(&ordered->root_extent_list, &skipped);
+                       cond_resched_lock(&root->ordered_extent_lock);
+                       continue;
+               }
+
                list_move_tail(&ordered->root_extent_list,
                               &root->ordered_extents);
                atomic_inc(&ordered->refs);
@@ -694,6 +703,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
                        nr--;
                count++;
        }
+       list_splice_tail(&skipped, &root->ordered_extents);
        list_splice_tail(&splice, &root->ordered_extents);
        spin_unlock(&root->ordered_extent_lock);
 
@@ -708,11 +718,13 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
        return count;
 }
 
-void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr)
+int btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
+                             const u64 range_start, const u64 range_len)
 {
        struct btrfs_root *root;
        struct list_head splice;
        int done;
+       int total_done = 0;
 
        INIT_LIST_HEAD(&splice);
 
@@ -728,8 +740,10 @@ 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,
+                                                 range_start, range_len);
                btrfs_put_fs_root(root);
+               total_done += done;
 
                spin_lock(&fs_info->ordered_root_lock);
                if (nr != -1) {
@@ -740,6 +754,8 @@ 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);
+
+       return total_done;
 }
 
 /*
@@ -952,6 +968,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
        struct rb_node *prev = NULL;
        struct btrfs_ordered_extent *test;
        int ret = 1;
+       u64 orig_offset = offset;
 
        spin_lock_irq(&tree->lock);
        if (ordered) {
@@ -967,7 +984,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
 
        /* truncate file */
        if (disk_i_size > i_size) {
-               BTRFS_I(inode)->disk_i_size = i_size;
+               BTRFS_I(inode)->disk_i_size = orig_offset;
                ret = 0;
                goto out;
        }