]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/extent-tree.c
Merge tag 'stable/for-linus-3.15-tag2' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / fs / btrfs / extent-tree.c
index 32312e09f0f5999d05aaabafceebcce62b685568..c6b6a6e3e735ce73bf06a735a9ee85533d94e4bf 100644 (file)
@@ -549,7 +549,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
        caching_ctl->block_group = cache;
        caching_ctl->progress = cache->key.objectid;
        atomic_set(&caching_ctl->count, 1);
-       caching_ctl->work.func = caching_thread;
+       btrfs_init_work(&caching_ctl->work, caching_thread, NULL, NULL);
 
        spin_lock(&cache->lock);
        /*
@@ -640,7 +640,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 
        btrfs_get_block_group(cache);
 
-       btrfs_queue_worker(&fs_info->caching_workers, &caching_ctl->work);
+       btrfs_queue_work(fs_info->caching_workers, &caching_ctl->work);
 
        return ret;
 }
@@ -3971,7 +3971,7 @@ static int can_overcommit(struct btrfs_root *root,
 }
 
 static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root,
-                                        unsigned long nr_pages)
+                                        unsigned long nr_pages, int nr_items)
 {
        struct super_block *sb = root->fs_info->sb;
 
@@ -3986,9 +3986,9 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root,
                 * the filesystem is readonly(all dirty pages are written to
                 * the disk).
                 */
-               btrfs_start_delalloc_roots(root->fs_info, 0);
+               btrfs_start_delalloc_roots(root->fs_info, 0, nr_items);
                if (!current->journal_info)
-                       btrfs_wait_ordered_roots(root->fs_info, -1);
+                       btrfs_wait_ordered_roots(root->fs_info, nr_items);
        }
 }
 
@@ -4045,7 +4045,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
        while (delalloc_bytes && loops < 3) {
                max_reclaim = min(delalloc_bytes, to_reclaim);
                nr_pages = max_reclaim >> PAGE_CACHE_SHIFT;
-               btrfs_writeback_inodes_sb_nr(root, nr_pages);
+               btrfs_writeback_inodes_sb_nr(root, nr_pages, items);
                /*
                 * We need to wait for the async pages to actually start before
                 * we do anything.
@@ -4112,13 +4112,9 @@ static int may_commit_transaction(struct btrfs_root *root,
                goto commit;
 
        /* See if there is enough pinned space to make this reservation */
-       spin_lock(&space_info->lock);
        if (percpu_counter_compare(&space_info->total_bytes_pinned,
-                                  bytes) >= 0) {
-               spin_unlock(&space_info->lock);
+                                  bytes) >= 0)
                goto commit;
-       }
-       spin_unlock(&space_info->lock);
 
        /*
         * See if there is some space in the delayed insertion reservation for
@@ -4127,16 +4123,13 @@ static int may_commit_transaction(struct btrfs_root *root,
        if (space_info != delayed_rsv->space_info)
                return -ENOSPC;
 
-       spin_lock(&space_info->lock);
        spin_lock(&delayed_rsv->lock);
        if (percpu_counter_compare(&space_info->total_bytes_pinned,
                                   bytes - delayed_rsv->size) >= 0) {
                spin_unlock(&delayed_rsv->lock);
-               spin_unlock(&space_info->lock);
                return -ENOSPC;
        }
        spin_unlock(&delayed_rsv->lock);
-       spin_unlock(&space_info->lock);
 
 commit:
        trans = btrfs_join_transaction(root);
@@ -4181,7 +4174,7 @@ static int flush_space(struct btrfs_root *root,
                break;
        case FLUSH_DELALLOC:
        case FLUSH_DELALLOC_WAIT:
-               shrink_delalloc(root, num_bytes, orig_bytes,
+               shrink_delalloc(root, num_bytes * 2, orig_bytes,
                                state == FLUSH_DELALLOC_WAIT);
                break;
        case ALLOC_CHUNK:
@@ -8938,3 +8931,38 @@ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range)
        range->len = trimmed;
        return ret;
 }
+
+/*
+ * btrfs_{start,end}_write() is similar to mnt_{want, drop}_write(),
+ * they are used to prevent the some tasks writing data into the page cache
+ * by nocow before the subvolume is snapshoted, but flush the data into
+ * the disk after the snapshot creation.
+ */
+void btrfs_end_nocow_write(struct btrfs_root *root)
+{
+       percpu_counter_dec(&root->subv_writers->counter);
+       /*
+        * Make sure counter is updated before we wake up
+        * waiters.
+        */
+       smp_mb();
+       if (waitqueue_active(&root->subv_writers->wait))
+               wake_up(&root->subv_writers->wait);
+}
+
+int btrfs_start_nocow_write(struct btrfs_root *root)
+{
+       if (unlikely(atomic_read(&root->will_be_snapshoted)))
+               return 0;
+
+       percpu_counter_inc(&root->subv_writers->counter);
+       /*
+        * Make sure counter is updated before we check for snapshot creation.
+        */
+       smp_mb();
+       if (unlikely(atomic_read(&root->will_be_snapshoted))) {
+               btrfs_end_nocow_write(root);
+               return 0;
+       }
+       return 1;
+}