diff options
author | Chris Mason <chris.mason@oracle.com> | 2011-12-15 13:43:49 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2011-12-15 13:43:49 -0500 |
commit | 567a45e917343c952806bb9f5c19aab0139bd519 (patch) | |
tree | b1d6dac31a3a2836d24662139f21bb1ddc2522d3 /fs | |
parent | e755d9ab387c4c2401dce5b6f435432a829f41cb (diff) | |
parent | e65cbb94e036058128a5dec6398be2fd64cf88ba (diff) |
Merge branch 'for-chris' of http://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-work into integration
Conflicts:
fs/btrfs/inode.c
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/async-thread.c | 115 | ||||
-rw-r--r-- | fs/btrfs/async-thread.h | 4 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 34 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 45 | ||||
-rw-r--r-- | fs/btrfs/file.c | 6 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 96 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 2 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 2 | ||||
-rw-r--r-- | fs/btrfs/scrub.c | 8 | ||||
-rw-r--r-- | fs/btrfs/super.c | 13 |
11 files changed, 211 insertions, 117 deletions
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 203e849dc9c9..cb97174e2366 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c | |||
@@ -64,6 +64,8 @@ struct btrfs_worker_thread { | |||
64 | int idle; | 64 | int idle; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | static int __btrfs_start_workers(struct btrfs_workers *workers); | ||
68 | |||
67 | /* | 69 | /* |
68 | * btrfs_start_workers uses kthread_run, which can block waiting for memory | 70 | * btrfs_start_workers uses kthread_run, which can block waiting for memory |
69 | * for a very long time. It will actually throttle on page writeback, | 71 | * for a very long time. It will actually throttle on page writeback, |
@@ -88,27 +90,10 @@ static void start_new_worker_func(struct btrfs_work *work) | |||
88 | { | 90 | { |
89 | struct worker_start *start; | 91 | struct worker_start *start; |
90 | start = container_of(work, struct worker_start, work); | 92 | start = container_of(work, struct worker_start, work); |
91 | btrfs_start_workers(start->queue, 1); | 93 | __btrfs_start_workers(start->queue); |
92 | kfree(start); | 94 | kfree(start); |
93 | } | 95 | } |
94 | 96 | ||
95 | static int start_new_worker(struct btrfs_workers *queue) | ||
96 | { | ||
97 | struct worker_start *start; | ||
98 | int ret; | ||
99 | |||
100 | start = kzalloc(sizeof(*start), GFP_NOFS); | ||
101 | if (!start) | ||
102 | return -ENOMEM; | ||
103 | |||
104 | start->work.func = start_new_worker_func; | ||
105 | start->queue = queue; | ||
106 | ret = btrfs_queue_worker(queue->atomic_worker_start, &start->work); | ||
107 | if (ret) | ||
108 | kfree(start); | ||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | /* | 97 | /* |
113 | * helper function to move a thread onto the idle list after it | 98 | * helper function to move a thread onto the idle list after it |
114 | * has finished some requests. | 99 | * has finished some requests. |
@@ -153,12 +138,20 @@ static void check_busy_worker(struct btrfs_worker_thread *worker) | |||
153 | static void check_pending_worker_creates(struct btrfs_worker_thread *worker) | 138 | static void check_pending_worker_creates(struct btrfs_worker_thread *worker) |
154 | { | 139 | { |
155 | struct btrfs_workers *workers = worker->workers; | 140 | struct btrfs_workers *workers = worker->workers; |
141 | struct worker_start *start; | ||
156 | unsigned long flags; | 142 | unsigned long flags; |
157 | 143 | ||
158 | rmb(); | 144 | rmb(); |
159 | if (!workers->atomic_start_pending) | 145 | if (!workers->atomic_start_pending) |
160 | return; | 146 | return; |
161 | 147 | ||
148 | start = kzalloc(sizeof(*start), GFP_NOFS); | ||
149 | if (!start) | ||
150 | return; | ||
151 | |||
152 | start->work.func = start_new_worker_func; | ||
153 | start->queue = workers; | ||
154 | |||
162 | spin_lock_irqsave(&workers->lock, flags); | 155 | spin_lock_irqsave(&workers->lock, flags); |
163 | if (!workers->atomic_start_pending) | 156 | if (!workers->atomic_start_pending) |
164 | goto out; | 157 | goto out; |
@@ -170,10 +163,11 @@ static void check_pending_worker_creates(struct btrfs_worker_thread *worker) | |||
170 | 163 | ||
171 | workers->num_workers_starting += 1; | 164 | workers->num_workers_starting += 1; |
172 | spin_unlock_irqrestore(&workers->lock, flags); | 165 | spin_unlock_irqrestore(&workers->lock, flags); |
173 | start_new_worker(workers); | 166 | btrfs_queue_worker(workers->atomic_worker_start, &start->work); |
174 | return; | 167 | return; |
175 | 168 | ||
176 | out: | 169 | out: |
170 | kfree(start); | ||
177 | spin_unlock_irqrestore(&workers->lock, flags); | 171 | spin_unlock_irqrestore(&workers->lock, flags); |
178 | } | 172 | } |
179 | 173 | ||
@@ -462,56 +456,55 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max, | |||
462 | * starts new worker threads. This does not enforce the max worker | 456 | * starts new worker threads. This does not enforce the max worker |
463 | * count in case you need to temporarily go past it. | 457 | * count in case you need to temporarily go past it. |
464 | */ | 458 | */ |
465 | static int __btrfs_start_workers(struct btrfs_workers *workers, | 459 | static int __btrfs_start_workers(struct btrfs_workers *workers) |
466 | int num_workers) | ||
467 | { | 460 | { |
468 | struct btrfs_worker_thread *worker; | 461 | struct btrfs_worker_thread *worker; |
469 | int ret = 0; | 462 | int ret = 0; |
470 | int i; | ||
471 | 463 | ||
472 | for (i = 0; i < num_workers; i++) { | 464 | worker = kzalloc(sizeof(*worker), GFP_NOFS); |
473 | worker = kzalloc(sizeof(*worker), GFP_NOFS); | 465 | if (!worker) { |
474 | if (!worker) { | 466 | ret = -ENOMEM; |
475 | ret = -ENOMEM; | 467 | goto fail; |
476 | goto fail; | 468 | } |
477 | } | ||
478 | 469 | ||
479 | INIT_LIST_HEAD(&worker->pending); | 470 | INIT_LIST_HEAD(&worker->pending); |
480 | INIT_LIST_HEAD(&worker->prio_pending); | 471 | INIT_LIST_HEAD(&worker->prio_pending); |
481 | INIT_LIST_HEAD(&worker->worker_list); | 472 | INIT_LIST_HEAD(&worker->worker_list); |
482 | spin_lock_init(&worker->lock); | 473 | spin_lock_init(&worker->lock); |
483 | 474 | ||
484 | atomic_set(&worker->num_pending, 0); | 475 | atomic_set(&worker->num_pending, 0); |
485 | atomic_set(&worker->refs, 1); | 476 | atomic_set(&worker->refs, 1); |
486 | worker->workers = workers; | 477 | worker->workers = workers; |
487 | worker->task = kthread_run(worker_loop, worker, | 478 | worker->task = kthread_run(worker_loop, worker, |
488 | "btrfs-%s-%d", workers->name, | 479 | "btrfs-%s-%d", workers->name, |
489 | workers->num_workers + i); | 480 | workers->num_workers + 1); |
490 | if (IS_ERR(worker->task)) { | 481 | if (IS_ERR(worker->task)) { |
491 | ret = PTR_ERR(worker->task); | 482 | ret = PTR_ERR(worker->task); |
492 | kfree(worker); | 483 | kfree(worker); |
493 | goto fail; | 484 | goto fail; |
494 | } | ||
495 | spin_lock_irq(&workers->lock); | ||
496 | list_add_tail(&worker->worker_list, &workers->idle_list); | ||
497 | worker->idle = 1; | ||
498 | workers->num_workers++; | ||
499 | workers->num_workers_starting--; | ||
500 | WARN_ON(workers->num_workers_starting < 0); | ||
501 | spin_unlock_irq(&workers->lock); | ||
502 | } | 485 | } |
486 | spin_lock_irq(&workers->lock); | ||
487 | list_add_tail(&worker->worker_list, &workers->idle_list); | ||
488 | worker->idle = 1; | ||
489 | workers->num_workers++; | ||
490 | workers->num_workers_starting--; | ||
491 | WARN_ON(workers->num_workers_starting < 0); | ||
492 | spin_unlock_irq(&workers->lock); | ||
493 | |||
503 | return 0; | 494 | return 0; |
504 | fail: | 495 | fail: |
505 | btrfs_stop_workers(workers); | 496 | spin_lock_irq(&workers->lock); |
497 | workers->num_workers_starting--; | ||
498 | spin_unlock_irq(&workers->lock); | ||
506 | return ret; | 499 | return ret; |
507 | } | 500 | } |
508 | 501 | ||
509 | int btrfs_start_workers(struct btrfs_workers *workers, int num_workers) | 502 | int btrfs_start_workers(struct btrfs_workers *workers) |
510 | { | 503 | { |
511 | spin_lock_irq(&workers->lock); | 504 | spin_lock_irq(&workers->lock); |
512 | workers->num_workers_starting += num_workers; | 505 | workers->num_workers_starting++; |
513 | spin_unlock_irq(&workers->lock); | 506 | spin_unlock_irq(&workers->lock); |
514 | return __btrfs_start_workers(workers, num_workers); | 507 | return __btrfs_start_workers(workers); |
515 | } | 508 | } |
516 | 509 | ||
517 | /* | 510 | /* |
@@ -568,6 +561,7 @@ static struct btrfs_worker_thread *find_worker(struct btrfs_workers *workers) | |||
568 | struct btrfs_worker_thread *worker; | 561 | struct btrfs_worker_thread *worker; |
569 | unsigned long flags; | 562 | unsigned long flags; |
570 | struct list_head *fallback; | 563 | struct list_head *fallback; |
564 | int ret; | ||
571 | 565 | ||
572 | again: | 566 | again: |
573 | spin_lock_irqsave(&workers->lock, flags); | 567 | spin_lock_irqsave(&workers->lock, flags); |
@@ -584,7 +578,9 @@ again: | |||
584 | workers->num_workers_starting++; | 578 | workers->num_workers_starting++; |
585 | spin_unlock_irqrestore(&workers->lock, flags); | 579 | spin_unlock_irqrestore(&workers->lock, flags); |
586 | /* we're below the limit, start another worker */ | 580 | /* we're below the limit, start another worker */ |
587 | __btrfs_start_workers(workers, 1); | 581 | ret = __btrfs_start_workers(workers); |
582 | if (ret) | ||
583 | goto fallback; | ||
588 | goto again; | 584 | goto again; |
589 | } | 585 | } |
590 | } | 586 | } |
@@ -665,7 +661,7 @@ void btrfs_set_work_high_prio(struct btrfs_work *work) | |||
665 | /* | 661 | /* |
666 | * places a struct btrfs_work into the pending queue of one of the kthreads | 662 | * places a struct btrfs_work into the pending queue of one of the kthreads |
667 | */ | 663 | */ |
668 | int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) | 664 | void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) |
669 | { | 665 | { |
670 | struct btrfs_worker_thread *worker; | 666 | struct btrfs_worker_thread *worker; |
671 | unsigned long flags; | 667 | unsigned long flags; |
@@ -673,7 +669,7 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) | |||
673 | 669 | ||
674 | /* don't requeue something already on a list */ | 670 | /* don't requeue something already on a list */ |
675 | if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags)) | 671 | if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags)) |
676 | goto out; | 672 | return; |
677 | 673 | ||
678 | worker = find_worker(workers); | 674 | worker = find_worker(workers); |
679 | if (workers->ordered) { | 675 | if (workers->ordered) { |
@@ -712,7 +708,4 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) | |||
712 | if (wake) | 708 | if (wake) |
713 | wake_up_process(worker->task); | 709 | wake_up_process(worker->task); |
714 | spin_unlock_irqrestore(&worker->lock, flags); | 710 | spin_unlock_irqrestore(&worker->lock, flags); |
715 | |||
716 | out: | ||
717 | return 0; | ||
718 | } | 711 | } |
diff --git a/fs/btrfs/async-thread.h b/fs/btrfs/async-thread.h index 5077746cf85e..f34cc31fa3c9 100644 --- a/fs/btrfs/async-thread.h +++ b/fs/btrfs/async-thread.h | |||
@@ -109,8 +109,8 @@ struct btrfs_workers { | |||
109 | char *name; | 109 | char *name; |
110 | }; | 110 | }; |
111 | 111 | ||
112 | int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work); | 112 | void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work); |
113 | int btrfs_start_workers(struct btrfs_workers *workers, int num_workers); | 113 | int btrfs_start_workers(struct btrfs_workers *workers); |
114 | int btrfs_stop_workers(struct btrfs_workers *workers); | 114 | int btrfs_stop_workers(struct btrfs_workers *workers); |
115 | void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max, | 115 | void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max, |
116 | struct btrfs_workers *async_starter); | 116 | struct btrfs_workers *async_starter); |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 50634abef9b4..67385033323d 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -2692,7 +2692,8 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); | |||
2692 | int btrfs_readpage(struct file *file, struct page *page); | 2692 | int btrfs_readpage(struct file *file, struct page *page); |
2693 | void btrfs_evict_inode(struct inode *inode); | 2693 | void btrfs_evict_inode(struct inode *inode); |
2694 | int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); | 2694 | int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); |
2695 | void btrfs_dirty_inode(struct inode *inode, int flags); | 2695 | int btrfs_dirty_inode(struct inode *inode); |
2696 | int btrfs_update_time(struct file *file); | ||
2696 | struct inode *btrfs_alloc_inode(struct super_block *sb); | 2697 | struct inode *btrfs_alloc_inode(struct super_block *sb); |
2697 | void btrfs_destroy_inode(struct inode *inode); | 2698 | void btrfs_destroy_inode(struct inode *inode); |
2698 | int btrfs_drop_inode(struct inode *inode); | 2699 | int btrfs_drop_inode(struct inode *inode); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 94abc25392f6..3f9d5551e582 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -2194,19 +2194,27 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
2194 | fs_info->endio_meta_write_workers.idle_thresh = 2; | 2194 | fs_info->endio_meta_write_workers.idle_thresh = 2; |
2195 | fs_info->readahead_workers.idle_thresh = 2; | 2195 | fs_info->readahead_workers.idle_thresh = 2; |
2196 | 2196 | ||
2197 | btrfs_start_workers(&fs_info->workers, 1); | 2197 | /* |
2198 | btrfs_start_workers(&fs_info->generic_worker, 1); | 2198 | * btrfs_start_workers can really only fail because of ENOMEM so just |
2199 | btrfs_start_workers(&fs_info->submit_workers, 1); | 2199 | * return -ENOMEM if any of these fail. |
2200 | btrfs_start_workers(&fs_info->delalloc_workers, 1); | 2200 | */ |
2201 | btrfs_start_workers(&fs_info->fixup_workers, 1); | 2201 | ret = btrfs_start_workers(&fs_info->workers); |
2202 | btrfs_start_workers(&fs_info->endio_workers, 1); | 2202 | ret |= btrfs_start_workers(&fs_info->generic_worker); |
2203 | btrfs_start_workers(&fs_info->endio_meta_workers, 1); | 2203 | ret |= btrfs_start_workers(&fs_info->submit_workers); |
2204 | btrfs_start_workers(&fs_info->endio_meta_write_workers, 1); | 2204 | ret |= btrfs_start_workers(&fs_info->delalloc_workers); |
2205 | btrfs_start_workers(&fs_info->endio_write_workers, 1); | 2205 | ret |= btrfs_start_workers(&fs_info->fixup_workers); |
2206 | btrfs_start_workers(&fs_info->endio_freespace_worker, 1); | 2206 | ret |= btrfs_start_workers(&fs_info->endio_workers); |
2207 | btrfs_start_workers(&fs_info->delayed_workers, 1); | 2207 | ret |= btrfs_start_workers(&fs_info->endio_meta_workers); |
2208 | btrfs_start_workers(&fs_info->caching_workers, 1); | 2208 | ret |= btrfs_start_workers(&fs_info->endio_meta_write_workers); |
2209 | btrfs_start_workers(&fs_info->readahead_workers, 1); | 2209 | ret |= btrfs_start_workers(&fs_info->endio_write_workers); |
2210 | ret |= btrfs_start_workers(&fs_info->endio_freespace_worker); | ||
2211 | ret |= btrfs_start_workers(&fs_info->delayed_workers); | ||
2212 | ret |= btrfs_start_workers(&fs_info->caching_workers); | ||
2213 | ret |= btrfs_start_workers(&fs_info->readahead_workers); | ||
2214 | if (ret) { | ||
2215 | ret = -ENOMEM; | ||
2216 | goto fail_sb_buffer; | ||
2217 | } | ||
2210 | 2218 | ||
2211 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); | 2219 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); |
2212 | fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, | 2220 | fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 05e1386b8bec..8603ee4e3dfd 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2822,7 +2822,7 @@ out_free: | |||
2822 | btrfs_release_path(path); | 2822 | btrfs_release_path(path); |
2823 | out: | 2823 | out: |
2824 | spin_lock(&block_group->lock); | 2824 | spin_lock(&block_group->lock); |
2825 | if (!ret) | 2825 | if (!ret && dcs == BTRFS_DC_SETUP) |
2826 | block_group->cache_generation = trans->transid; | 2826 | block_group->cache_generation = trans->transid; |
2827 | block_group->disk_cache_state = dcs; | 2827 | block_group->disk_cache_state = dcs; |
2828 | spin_unlock(&block_group->lock); | 2828 | spin_unlock(&block_group->lock); |
@@ -4203,12 +4203,17 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4203 | struct btrfs_root *root = BTRFS_I(inode)->root; | 4203 | struct btrfs_root *root = BTRFS_I(inode)->root; |
4204 | struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; | 4204 | struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; |
4205 | u64 to_reserve = 0; | 4205 | u64 to_reserve = 0; |
4206 | u64 csum_bytes; | ||
4206 | unsigned nr_extents = 0; | 4207 | unsigned nr_extents = 0; |
4208 | int extra_reserve = 0; | ||
4207 | int flush = 1; | 4209 | int flush = 1; |
4208 | int ret; | 4210 | int ret; |
4209 | 4211 | ||
4212 | /* Need to be holding the i_mutex here if we aren't free space cache */ | ||
4210 | if (btrfs_is_free_space_inode(root, inode)) | 4213 | if (btrfs_is_free_space_inode(root, inode)) |
4211 | flush = 0; | 4214 | flush = 0; |
4215 | else | ||
4216 | WARN_ON(!mutex_is_locked(&inode->i_mutex)); | ||
4212 | 4217 | ||
4213 | if (flush && btrfs_transaction_in_commit(root->fs_info)) | 4218 | if (flush && btrfs_transaction_in_commit(root->fs_info)) |
4214 | schedule_timeout(1); | 4219 | schedule_timeout(1); |
@@ -4219,11 +4224,9 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4219 | BTRFS_I(inode)->outstanding_extents++; | 4224 | BTRFS_I(inode)->outstanding_extents++; |
4220 | 4225 | ||
4221 | if (BTRFS_I(inode)->outstanding_extents > | 4226 | if (BTRFS_I(inode)->outstanding_extents > |
4222 | BTRFS_I(inode)->reserved_extents) { | 4227 | BTRFS_I(inode)->reserved_extents) |
4223 | nr_extents = BTRFS_I(inode)->outstanding_extents - | 4228 | nr_extents = BTRFS_I(inode)->outstanding_extents - |
4224 | BTRFS_I(inode)->reserved_extents; | 4229 | BTRFS_I(inode)->reserved_extents; |
4225 | BTRFS_I(inode)->reserved_extents += nr_extents; | ||
4226 | } | ||
4227 | 4230 | ||
4228 | /* | 4231 | /* |
4229 | * Add an item to reserve for updating the inode when we complete the | 4232 | * Add an item to reserve for updating the inode when we complete the |
@@ -4231,11 +4234,12 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4231 | */ | 4234 | */ |
4232 | if (!BTRFS_I(inode)->delalloc_meta_reserved) { | 4235 | if (!BTRFS_I(inode)->delalloc_meta_reserved) { |
4233 | nr_extents++; | 4236 | nr_extents++; |
4234 | BTRFS_I(inode)->delalloc_meta_reserved = 1; | 4237 | extra_reserve = 1; |
4235 | } | 4238 | } |
4236 | 4239 | ||
4237 | to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); | 4240 | to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); |
4238 | to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); | 4241 | to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); |
4242 | csum_bytes = BTRFS_I(inode)->csum_bytes; | ||
4239 | spin_unlock(&BTRFS_I(inode)->lock); | 4243 | spin_unlock(&BTRFS_I(inode)->lock); |
4240 | 4244 | ||
4241 | ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); | 4245 | ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); |
@@ -4245,22 +4249,35 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4245 | 4249 | ||
4246 | spin_lock(&BTRFS_I(inode)->lock); | 4250 | spin_lock(&BTRFS_I(inode)->lock); |
4247 | dropped = drop_outstanding_extent(inode); | 4251 | dropped = drop_outstanding_extent(inode); |
4248 | to_free = calc_csum_metadata_size(inode, num_bytes, 0); | ||
4249 | spin_unlock(&BTRFS_I(inode)->lock); | ||
4250 | to_free += btrfs_calc_trans_metadata_size(root, dropped); | ||
4251 | |||
4252 | /* | 4252 | /* |
4253 | * Somebody could have come in and twiddled with the | 4253 | * If the inodes csum_bytes is the same as the original |
4254 | * reservation, so if we have to free more than we would have | 4254 | * csum_bytes then we know we haven't raced with any free()ers |
4255 | * reserved from this reservation go ahead and release those | 4255 | * so we can just reduce our inodes csum bytes and carry on. |
4256 | * bytes. | 4256 | * Otherwise we have to do the normal free thing to account for |
4257 | * the case that the free side didn't free up its reserve | ||
4258 | * because of this outstanding reservation. | ||
4257 | */ | 4259 | */ |
4258 | to_free -= to_reserve; | 4260 | if (BTRFS_I(inode)->csum_bytes == csum_bytes) |
4261 | calc_csum_metadata_size(inode, num_bytes, 0); | ||
4262 | else | ||
4263 | to_free = calc_csum_metadata_size(inode, num_bytes, 0); | ||
4264 | spin_unlock(&BTRFS_I(inode)->lock); | ||
4265 | if (dropped) | ||
4266 | to_free += btrfs_calc_trans_metadata_size(root, dropped); | ||
4267 | |||
4259 | if (to_free) | 4268 | if (to_free) |
4260 | btrfs_block_rsv_release(root, block_rsv, to_free); | 4269 | btrfs_block_rsv_release(root, block_rsv, to_free); |
4261 | return ret; | 4270 | return ret; |
4262 | } | 4271 | } |
4263 | 4272 | ||
4273 | spin_lock(&BTRFS_I(inode)->lock); | ||
4274 | if (extra_reserve) { | ||
4275 | BTRFS_I(inode)->delalloc_meta_reserved = 1; | ||
4276 | nr_extents--; | ||
4277 | } | ||
4278 | BTRFS_I(inode)->reserved_extents += nr_extents; | ||
4279 | spin_unlock(&BTRFS_I(inode)->lock); | ||
4280 | |||
4264 | block_rsv_add_bytes(block_rsv, to_reserve, 1); | 4281 | block_rsv_add_bytes(block_rsv, to_reserve, 1); |
4265 | 4282 | ||
4266 | return 0; | 4283 | return 0; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index f2e928289600..cc7492c823f3 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1387,7 +1387,11 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1387 | goto out; | 1387 | goto out; |
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | file_update_time(file); | 1390 | err = btrfs_update_time(file); |
1391 | if (err) { | ||
1392 | mutex_unlock(&inode->i_mutex); | ||
1393 | goto out; | ||
1394 | } | ||
1391 | BTRFS_I(inode)->sequence++; | 1395 | BTRFS_I(inode)->sequence++; |
1392 | 1396 | ||
1393 | start_pos = round_down(pos, root->sectorsize); | 1397 | start_pos = round_down(pos, root->sectorsize); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d4a9195c7f0d..740e67bbe249 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/falloc.h> | 38 | #include <linux/falloc.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/ratelimit.h> | 40 | #include <linux/ratelimit.h> |
41 | #include <linux/mount.h> | ||
41 | #include "compat.h" | 42 | #include "compat.h" |
42 | #include "ctree.h" | 43 | #include "ctree.h" |
43 | #include "disk-io.h" | 44 | #include "disk-io.h" |
@@ -2031,7 +2032,7 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) | |||
2031 | /* insert an orphan item to track this unlinked/truncated file */ | 2032 | /* insert an orphan item to track this unlinked/truncated file */ |
2032 | if (insert >= 1) { | 2033 | if (insert >= 1) { |
2033 | ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); | 2034 | ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); |
2034 | BUG_ON(ret); | 2035 | BUG_ON(ret && ret != -EEXIST); |
2035 | } | 2036 | } |
2036 | 2037 | ||
2037 | /* insert an orphan item to track subvolume contains orphan files */ | 2038 | /* insert an orphan item to track subvolume contains orphan files */ |
@@ -2223,7 +2224,14 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) | |||
2223 | continue; | 2224 | continue; |
2224 | } | 2225 | } |
2225 | nr_truncate++; | 2226 | nr_truncate++; |
2227 | /* | ||
2228 | * Need to hold the imutex for reservation purposes, not | ||
2229 | * a huge deal here but I have a WARN_ON in | ||
2230 | * btrfs_delalloc_reserve_space to catch offenders. | ||
2231 | */ | ||
2232 | mutex_lock(&inode->i_mutex); | ||
2226 | ret = btrfs_truncate(inode); | 2233 | ret = btrfs_truncate(inode); |
2234 | mutex_unlock(&inode->i_mutex); | ||
2227 | } else { | 2235 | } else { |
2228 | nr_unlink++; | 2236 | nr_unlink++; |
2229 | } | 2237 | } |
@@ -3426,7 +3434,6 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) | |||
3426 | i_size_write(inode, newsize); | 3434 | i_size_write(inode, newsize); |
3427 | btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); | 3435 | btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); |
3428 | ret = btrfs_update_inode(trans, root, inode); | 3436 | ret = btrfs_update_inode(trans, root, inode); |
3429 | |||
3430 | btrfs_end_transaction_throttle(trans, root); | 3437 | btrfs_end_transaction_throttle(trans, root); |
3431 | } else { | 3438 | } else { |
3432 | 3439 | ||
@@ -3467,9 +3474,9 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
3467 | 3474 | ||
3468 | if (attr->ia_valid) { | 3475 | if (attr->ia_valid) { |
3469 | setattr_copy(inode, attr); | 3476 | setattr_copy(inode, attr); |
3470 | mark_inode_dirty(inode); | 3477 | err = btrfs_dirty_inode(inode); |
3471 | 3478 | ||
3472 | if (attr->ia_valid & ATTR_MODE) | 3479 | if (!err && attr->ia_valid & ATTR_MODE) |
3473 | err = btrfs_acl_chmod(inode); | 3480 | err = btrfs_acl_chmod(inode); |
3474 | } | 3481 | } |
3475 | 3482 | ||
@@ -4245,42 +4252,80 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
4245 | * FIXME, needs more benchmarking...there are no reasons other than performance | 4252 | * FIXME, needs more benchmarking...there are no reasons other than performance |
4246 | * to keep or drop this code. | 4253 | * to keep or drop this code. |
4247 | */ | 4254 | */ |
4248 | void btrfs_dirty_inode(struct inode *inode, int flags) | 4255 | int btrfs_dirty_inode(struct inode *inode) |
4249 | { | 4256 | { |
4250 | struct btrfs_root *root = BTRFS_I(inode)->root; | 4257 | struct btrfs_root *root = BTRFS_I(inode)->root; |
4251 | struct btrfs_trans_handle *trans; | 4258 | struct btrfs_trans_handle *trans; |
4252 | int ret; | 4259 | int ret; |
4253 | 4260 | ||
4254 | if (BTRFS_I(inode)->dummy_inode) | 4261 | if (BTRFS_I(inode)->dummy_inode) |
4255 | return; | 4262 | return 0; |
4256 | 4263 | ||
4257 | trans = btrfs_join_transaction(root); | 4264 | trans = btrfs_join_transaction(root); |
4258 | BUG_ON(IS_ERR(trans)); | 4265 | if (IS_ERR(trans)) |
4266 | return PTR_ERR(trans); | ||
4259 | 4267 | ||
4260 | ret = btrfs_update_inode(trans, root, inode); | 4268 | ret = btrfs_update_inode(trans, root, inode); |
4261 | if (ret && ret == -ENOSPC) { | 4269 | if (ret && ret == -ENOSPC) { |
4262 | /* whoops, lets try again with the full transaction */ | 4270 | /* whoops, lets try again with the full transaction */ |
4263 | btrfs_end_transaction(trans, root); | 4271 | btrfs_end_transaction(trans, root); |
4264 | trans = btrfs_start_transaction(root, 1); | 4272 | trans = btrfs_start_transaction(root, 1); |
4265 | if (IS_ERR(trans)) { | 4273 | if (IS_ERR(trans)) |
4266 | printk_ratelimited(KERN_ERR "btrfs: fail to " | 4274 | return PTR_ERR(trans); |
4267 | "dirty inode %llu error %ld\n", | ||
4268 | (unsigned long long)btrfs_ino(inode), | ||
4269 | PTR_ERR(trans)); | ||
4270 | return; | ||
4271 | } | ||
4272 | 4275 | ||
4273 | ret = btrfs_update_inode(trans, root, inode); | 4276 | ret = btrfs_update_inode(trans, root, inode); |
4274 | if (ret) { | ||
4275 | printk_ratelimited(KERN_ERR "btrfs: fail to " | ||
4276 | "dirty inode %llu error %d\n", | ||
4277 | (unsigned long long)btrfs_ino(inode), | ||
4278 | ret); | ||
4279 | } | ||
4280 | } | 4277 | } |
4281 | btrfs_end_transaction(trans, root); | 4278 | btrfs_end_transaction(trans, root); |
4282 | if (BTRFS_I(inode)->delayed_node) | 4279 | if (BTRFS_I(inode)->delayed_node) |
4283 | btrfs_balance_delayed_items(root); | 4280 | btrfs_balance_delayed_items(root); |
4281 | |||
4282 | return ret; | ||
4283 | } | ||
4284 | |||
4285 | /* | ||
4286 | * This is a copy of file_update_time. We need this so we can return error on | ||
4287 | * ENOSPC for updating the inode in the case of file write and mmap writes. | ||
4288 | */ | ||
4289 | int btrfs_update_time(struct file *file) | ||
4290 | { | ||
4291 | struct inode *inode = file->f_path.dentry->d_inode; | ||
4292 | struct timespec now; | ||
4293 | int ret; | ||
4294 | enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; | ||
4295 | |||
4296 | /* First try to exhaust all avenues to not sync */ | ||
4297 | if (IS_NOCMTIME(inode)) | ||
4298 | return 0; | ||
4299 | |||
4300 | now = current_fs_time(inode->i_sb); | ||
4301 | if (!timespec_equal(&inode->i_mtime, &now)) | ||
4302 | sync_it = S_MTIME; | ||
4303 | |||
4304 | if (!timespec_equal(&inode->i_ctime, &now)) | ||
4305 | sync_it |= S_CTIME; | ||
4306 | |||
4307 | if (IS_I_VERSION(inode)) | ||
4308 | sync_it |= S_VERSION; | ||
4309 | |||
4310 | if (!sync_it) | ||
4311 | return 0; | ||
4312 | |||
4313 | /* Finally allowed to write? Takes lock. */ | ||
4314 | if (mnt_want_write_file(file)) | ||
4315 | return 0; | ||
4316 | |||
4317 | /* Only change inode inside the lock region */ | ||
4318 | if (sync_it & S_VERSION) | ||
4319 | inode_inc_iversion(inode); | ||
4320 | if (sync_it & S_CTIME) | ||
4321 | inode->i_ctime = now; | ||
4322 | if (sync_it & S_MTIME) | ||
4323 | inode->i_mtime = now; | ||
4324 | ret = btrfs_dirty_inode(inode); | ||
4325 | if (!ret) | ||
4326 | mark_inode_dirty_sync(inode); | ||
4327 | mnt_drop_write(file->f_path.mnt); | ||
4328 | return ret; | ||
4284 | } | 4329 | } |
4285 | 4330 | ||
4286 | /* | 4331 | /* |
@@ -6358,7 +6403,12 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
6358 | u64 page_start; | 6403 | u64 page_start; |
6359 | u64 page_end; | 6404 | u64 page_end; |
6360 | 6405 | ||
6406 | /* Need this to keep space reservations serialized */ | ||
6407 | mutex_lock(&inode->i_mutex); | ||
6361 | ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); | 6408 | ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); |
6409 | mutex_unlock(&inode->i_mutex); | ||
6410 | if (!ret) | ||
6411 | ret = btrfs_update_time(vma->vm_file); | ||
6362 | if (ret) { | 6412 | if (ret) { |
6363 | if (ret == -ENOMEM) | 6413 | if (ret == -ENOMEM) |
6364 | ret = VM_FAULT_OOM; | 6414 | ret = VM_FAULT_OOM; |
@@ -6570,8 +6620,9 @@ static int btrfs_truncate(struct inode *inode) | |||
6570 | /* Just need the 1 for updating the inode */ | 6620 | /* Just need the 1 for updating the inode */ |
6571 | trans = btrfs_start_transaction(root, 1); | 6621 | trans = btrfs_start_transaction(root, 1); |
6572 | if (IS_ERR(trans)) { | 6622 | if (IS_ERR(trans)) { |
6573 | err = PTR_ERR(trans); | 6623 | ret = err = PTR_ERR(trans); |
6574 | goto out; | 6624 | trans = NULL; |
6625 | break; | ||
6575 | } | 6626 | } |
6576 | } | 6627 | } |
6577 | 6628 | ||
@@ -7415,6 +7466,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { | |||
7415 | .follow_link = page_follow_link_light, | 7466 | .follow_link = page_follow_link_light, |
7416 | .put_link = page_put_link, | 7467 | .put_link = page_put_link, |
7417 | .getattr = btrfs_getattr, | 7468 | .getattr = btrfs_getattr, |
7469 | .setattr = btrfs_setattr, | ||
7418 | .permission = btrfs_permission, | 7470 | .permission = btrfs_permission, |
7419 | .setxattr = btrfs_setxattr, | 7471 | .setxattr = btrfs_setxattr, |
7420 | .getxattr = btrfs_getxattr, | 7472 | .getxattr = btrfs_getxattr, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 40eaa9fdf07c..c04f02c7d5bb 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -858,8 +858,10 @@ static int cluster_pages_for_defrag(struct inode *inode, | |||
858 | return 0; | 858 | return 0; |
859 | file_end = (isize - 1) >> PAGE_CACHE_SHIFT; | 859 | file_end = (isize - 1) >> PAGE_CACHE_SHIFT; |
860 | 860 | ||
861 | mutex_lock(&inode->i_mutex); | ||
861 | ret = btrfs_delalloc_reserve_space(inode, | 862 | ret = btrfs_delalloc_reserve_space(inode, |
862 | num_pages << PAGE_CACHE_SHIFT); | 863 | num_pages << PAGE_CACHE_SHIFT); |
864 | mutex_unlock(&inode->i_mutex); | ||
863 | if (ret) | 865 | if (ret) |
864 | return ret; | 866 | return ret; |
865 | again: | 867 | again: |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index dff29d5e151a..cfb55434a469 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -2947,7 +2947,9 @@ static int relocate_file_extent_cluster(struct inode *inode, | |||
2947 | index = (cluster->start - offset) >> PAGE_CACHE_SHIFT; | 2947 | index = (cluster->start - offset) >> PAGE_CACHE_SHIFT; |
2948 | last_index = (cluster->end - offset) >> PAGE_CACHE_SHIFT; | 2948 | last_index = (cluster->end - offset) >> PAGE_CACHE_SHIFT; |
2949 | while (index <= last_index) { | 2949 | while (index <= last_index) { |
2950 | mutex_lock(&inode->i_mutex); | ||
2950 | ret = btrfs_delalloc_reserve_metadata(inode, PAGE_CACHE_SIZE); | 2951 | ret = btrfs_delalloc_reserve_metadata(inode, PAGE_CACHE_SIZE); |
2952 | mutex_unlock(&inode->i_mutex); | ||
2951 | if (ret) | 2953 | if (ret) |
2952 | goto out; | 2954 | goto out; |
2953 | 2955 | ||
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index c27bcb67f330..ddf2c90d3fc0 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -1535,18 +1535,22 @@ static noinline_for_stack int scrub_supers(struct scrub_dev *sdev) | |||
1535 | static noinline_for_stack int scrub_workers_get(struct btrfs_root *root) | 1535 | static noinline_for_stack int scrub_workers_get(struct btrfs_root *root) |
1536 | { | 1536 | { |
1537 | struct btrfs_fs_info *fs_info = root->fs_info; | 1537 | struct btrfs_fs_info *fs_info = root->fs_info; |
1538 | int ret = 0; | ||
1538 | 1539 | ||
1539 | mutex_lock(&fs_info->scrub_lock); | 1540 | mutex_lock(&fs_info->scrub_lock); |
1540 | if (fs_info->scrub_workers_refcnt == 0) { | 1541 | if (fs_info->scrub_workers_refcnt == 0) { |
1541 | btrfs_init_workers(&fs_info->scrub_workers, "scrub", | 1542 | btrfs_init_workers(&fs_info->scrub_workers, "scrub", |
1542 | fs_info->thread_pool_size, &fs_info->generic_worker); | 1543 | fs_info->thread_pool_size, &fs_info->generic_worker); |
1543 | fs_info->scrub_workers.idle_thresh = 4; | 1544 | fs_info->scrub_workers.idle_thresh = 4; |
1544 | btrfs_start_workers(&fs_info->scrub_workers, 1); | 1545 | ret = btrfs_start_workers(&fs_info->scrub_workers); |
1546 | if (ret) | ||
1547 | goto out; | ||
1545 | } | 1548 | } |
1546 | ++fs_info->scrub_workers_refcnt; | 1549 | ++fs_info->scrub_workers_refcnt; |
1550 | out: | ||
1547 | mutex_unlock(&fs_info->scrub_lock); | 1551 | mutex_unlock(&fs_info->scrub_lock); |
1548 | 1552 | ||
1549 | return 0; | 1553 | return ret; |
1550 | } | 1554 | } |
1551 | 1555 | ||
1552 | static noinline_for_stack void scrub_workers_put(struct btrfs_root *root) | 1556 | static noinline_for_stack void scrub_workers_put(struct btrfs_root *root) |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 41495dce4db0..34a8b6112ea4 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <linux/cleancache.h> | 42 | #include <linux/cleancache.h> |
43 | #include <linux/mnt_namespace.h> | 43 | #include <linux/mnt_namespace.h> |
44 | #include <linux/ratelimit.h> | ||
44 | #include "compat.h" | 45 | #include "compat.h" |
45 | #include "delayed-inode.h" | 46 | #include "delayed-inode.h" |
46 | #include "ctree.h" | 47 | #include "ctree.h" |
@@ -1297,6 +1298,16 @@ static int btrfs_unfreeze(struct super_block *sb) | |||
1297 | return 0; | 1298 | return 0; |
1298 | } | 1299 | } |
1299 | 1300 | ||
1301 | static void btrfs_fs_dirty_inode(struct inode *inode, int flags) | ||
1302 | { | ||
1303 | int ret; | ||
1304 | |||
1305 | ret = btrfs_dirty_inode(inode); | ||
1306 | if (ret) | ||
1307 | printk_ratelimited(KERN_ERR "btrfs: fail to dirty inode %Lu " | ||
1308 | "error %d\n", btrfs_ino(inode), ret); | ||
1309 | } | ||
1310 | |||
1300 | static const struct super_operations btrfs_super_ops = { | 1311 | static const struct super_operations btrfs_super_ops = { |
1301 | .drop_inode = btrfs_drop_inode, | 1312 | .drop_inode = btrfs_drop_inode, |
1302 | .evict_inode = btrfs_evict_inode, | 1313 | .evict_inode = btrfs_evict_inode, |
@@ -1304,7 +1315,7 @@ static const struct super_operations btrfs_super_ops = { | |||
1304 | .sync_fs = btrfs_sync_fs, | 1315 | .sync_fs = btrfs_sync_fs, |
1305 | .show_options = btrfs_show_options, | 1316 | .show_options = btrfs_show_options, |
1306 | .write_inode = btrfs_write_inode, | 1317 | .write_inode = btrfs_write_inode, |
1307 | .dirty_inode = btrfs_dirty_inode, | 1318 | .dirty_inode = btrfs_fs_dirty_inode, |
1308 | .alloc_inode = btrfs_alloc_inode, | 1319 | .alloc_inode = btrfs_alloc_inode, |
1309 | .destroy_inode = btrfs_destroy_inode, | 1320 | .destroy_inode = btrfs_destroy_inode, |
1310 | .statfs = btrfs_statfs, | 1321 | .statfs = btrfs_statfs, |