1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0 28b712842SChris Mason /* 38b712842SChris Mason * Copyright (C) 2007 Oracle. All rights reserved. 408a9ff32SQu Wenruo * Copyright (C) 2014 Fujitsu. All rights reserved. 58b712842SChris Mason */ 68b712842SChris Mason 78b712842SChris Mason #include <linux/kthread.h> 85a0e3ad6STejun Heo #include <linux/slab.h> 98b712842SChris Mason #include <linux/list.h> 108b712842SChris Mason #include <linux/spinlock.h> 118b712842SChris Mason #include <linux/freezer.h> 128b712842SChris Mason #include "async-thread.h" 1352483bc2SQu Wenruo #include "ctree.h" 148b712842SChris Mason 15f64ce7b8SDavid Sterba enum { 16f64ce7b8SDavid Sterba WORK_DONE_BIT, 17f64ce7b8SDavid Sterba WORK_ORDER_DONE_BIT, 18f64ce7b8SDavid Sterba WORK_HIGH_PRIO_BIT, 19f64ce7b8SDavid Sterba }; 204a69a410SChris Mason 210bd9289cSQu Wenruo #define NO_THRESHOLD (-1) 220bd9289cSQu Wenruo #define DFT_THRESHOLD (32) 230bd9289cSQu Wenruo 24d458b054SQu Wenruo struct __btrfs_workqueue { 2508a9ff32SQu Wenruo struct workqueue_struct *normal_wq; 26cb001095SJeff Mahoney 27cb001095SJeff Mahoney /* File system this workqueue services */ 28cb001095SJeff Mahoney struct btrfs_fs_info *fs_info; 29cb001095SJeff Mahoney 3008a9ff32SQu Wenruo /* List head pointing to ordered work list */ 3108a9ff32SQu Wenruo struct list_head ordered_list; 3208a9ff32SQu Wenruo 3308a9ff32SQu Wenruo /* Spinlock for ordered_list */ 3408a9ff32SQu Wenruo spinlock_t list_lock; 350bd9289cSQu Wenruo 360bd9289cSQu Wenruo /* Thresholding related variants */ 370bd9289cSQu Wenruo atomic_t pending; 38c6dd6ea5SQu Wenruo 39c6dd6ea5SQu Wenruo /* Up limit of concurrency workers */ 40c6dd6ea5SQu Wenruo int limit_active; 41c6dd6ea5SQu Wenruo 42c6dd6ea5SQu Wenruo /* Current number of concurrency workers */ 43c6dd6ea5SQu Wenruo int current_active; 44c6dd6ea5SQu Wenruo 45c6dd6ea5SQu Wenruo /* Threshold to change current_active */ 460bd9289cSQu Wenruo int thresh; 470bd9289cSQu Wenruo unsigned int count; 480bd9289cSQu Wenruo spinlock_t thres_lock; 4908a9ff32SQu Wenruo }; 5008a9ff32SQu Wenruo 51d458b054SQu Wenruo struct btrfs_workqueue { 52d458b054SQu Wenruo struct __btrfs_workqueue *normal; 53d458b054SQu Wenruo struct __btrfs_workqueue *high; 541ca08976SQu Wenruo }; 551ca08976SQu Wenruo 56cb001095SJeff Mahoney struct btrfs_fs_info * 579a35b637SJeff Mahoney btrfs_workqueue_owner(const struct __btrfs_workqueue *wq) 58cb001095SJeff Mahoney { 59cb001095SJeff Mahoney return wq->fs_info; 60cb001095SJeff Mahoney } 61cb001095SJeff Mahoney 62cb001095SJeff Mahoney struct btrfs_fs_info * 639a35b637SJeff Mahoney btrfs_work_owner(const struct btrfs_work *work) 64cb001095SJeff Mahoney { 65cb001095SJeff Mahoney return work->wq->fs_info; 66cb001095SJeff Mahoney } 67cb001095SJeff Mahoney 689a35b637SJeff Mahoney bool btrfs_workqueue_normal_congested(const struct btrfs_workqueue *wq) 692939e1a8SMaxim Patlasov { 702939e1a8SMaxim Patlasov /* 712939e1a8SMaxim Patlasov * We could compare wq->normal->pending with num_online_cpus() 722939e1a8SMaxim Patlasov * to support "thresh == NO_THRESHOLD" case, but it requires 732939e1a8SMaxim Patlasov * moving up atomic_inc/dec in thresh_queue/exec_hook. Let's 742939e1a8SMaxim Patlasov * postpone it until someone needs the support of that case. 752939e1a8SMaxim Patlasov */ 762939e1a8SMaxim Patlasov if (wq->normal->thresh == NO_THRESHOLD) 772939e1a8SMaxim Patlasov return false; 782939e1a8SMaxim Patlasov 792939e1a8SMaxim Patlasov return atomic_read(&wq->normal->pending) > wq->normal->thresh * 2; 802939e1a8SMaxim Patlasov } 812939e1a8SMaxim Patlasov 829e0af237SLiu Bo static struct __btrfs_workqueue * 83cb001095SJeff Mahoney __btrfs_alloc_workqueue(struct btrfs_fs_info *fs_info, const char *name, 84cb001095SJeff Mahoney unsigned int flags, int limit_active, int thresh) 8508a9ff32SQu Wenruo { 8661dd5ae6SDavid Sterba struct __btrfs_workqueue *ret = kzalloc(sizeof(*ret), GFP_KERNEL); 8708a9ff32SQu Wenruo 885d99a998SDavid Sterba if (!ret) 8908a9ff32SQu Wenruo return NULL; 9008a9ff32SQu Wenruo 91cb001095SJeff Mahoney ret->fs_info = fs_info; 92c6dd6ea5SQu Wenruo ret->limit_active = limit_active; 930bd9289cSQu Wenruo atomic_set(&ret->pending, 0); 940bd9289cSQu Wenruo if (thresh == 0) 950bd9289cSQu Wenruo thresh = DFT_THRESHOLD; 960bd9289cSQu Wenruo /* For low threshold, disabling threshold is a better choice */ 970bd9289cSQu Wenruo if (thresh < DFT_THRESHOLD) { 98c6dd6ea5SQu Wenruo ret->current_active = limit_active; 990bd9289cSQu Wenruo ret->thresh = NO_THRESHOLD; 1000bd9289cSQu Wenruo } else { 101c6dd6ea5SQu Wenruo /* 102c6dd6ea5SQu Wenruo * For threshold-able wq, let its concurrency grow on demand. 103c6dd6ea5SQu Wenruo * Use minimal max_active at alloc time to reduce resource 104c6dd6ea5SQu Wenruo * usage. 105c6dd6ea5SQu Wenruo */ 106c6dd6ea5SQu Wenruo ret->current_active = 1; 1070bd9289cSQu Wenruo ret->thresh = thresh; 1080bd9289cSQu Wenruo } 1090bd9289cSQu Wenruo 1101ca08976SQu Wenruo if (flags & WQ_HIGHPRI) 111ce3ded10SDavid Sterba ret->normal_wq = alloc_workqueue("btrfs-%s-high", flags, 112ce3ded10SDavid Sterba ret->current_active, name); 1131ca08976SQu Wenruo else 114ce3ded10SDavid Sterba ret->normal_wq = alloc_workqueue("btrfs-%s", flags, 115ce3ded10SDavid Sterba ret->current_active, name); 1165d99a998SDavid Sterba if (!ret->normal_wq) { 11708a9ff32SQu Wenruo kfree(ret); 11808a9ff32SQu Wenruo return NULL; 11908a9ff32SQu Wenruo } 12008a9ff32SQu Wenruo 12108a9ff32SQu Wenruo INIT_LIST_HEAD(&ret->ordered_list); 12208a9ff32SQu Wenruo spin_lock_init(&ret->list_lock); 1230bd9289cSQu Wenruo spin_lock_init(&ret->thres_lock); 124c3a46891SQu Wenruo trace_btrfs_workqueue_alloc(ret, name, flags & WQ_HIGHPRI); 12508a9ff32SQu Wenruo return ret; 12608a9ff32SQu Wenruo } 12708a9ff32SQu Wenruo 1281ca08976SQu Wenruo static inline void 129d458b054SQu Wenruo __btrfs_destroy_workqueue(struct __btrfs_workqueue *wq); 1301ca08976SQu Wenruo 131cb001095SJeff Mahoney struct btrfs_workqueue *btrfs_alloc_workqueue(struct btrfs_fs_info *fs_info, 132cb001095SJeff Mahoney const char *name, 1336f011058SDavid Sterba unsigned int flags, 134c6dd6ea5SQu Wenruo int limit_active, 1350bd9289cSQu Wenruo int thresh) 1361ca08976SQu Wenruo { 13761dd5ae6SDavid Sterba struct btrfs_workqueue *ret = kzalloc(sizeof(*ret), GFP_KERNEL); 1381ca08976SQu Wenruo 1395d99a998SDavid Sterba if (!ret) 1401ca08976SQu Wenruo return NULL; 1411ca08976SQu Wenruo 142cb001095SJeff Mahoney ret->normal = __btrfs_alloc_workqueue(fs_info, name, 143cb001095SJeff Mahoney flags & ~WQ_HIGHPRI, 144c6dd6ea5SQu Wenruo limit_active, thresh); 1455d99a998SDavid Sterba if (!ret->normal) { 1461ca08976SQu Wenruo kfree(ret); 1471ca08976SQu Wenruo return NULL; 1481ca08976SQu Wenruo } 1491ca08976SQu Wenruo 1501ca08976SQu Wenruo if (flags & WQ_HIGHPRI) { 151cb001095SJeff Mahoney ret->high = __btrfs_alloc_workqueue(fs_info, name, flags, 152cb001095SJeff Mahoney limit_active, thresh); 1535d99a998SDavid Sterba if (!ret->high) { 1541ca08976SQu Wenruo __btrfs_destroy_workqueue(ret->normal); 1551ca08976SQu Wenruo kfree(ret); 1561ca08976SQu Wenruo return NULL; 1571ca08976SQu Wenruo } 1581ca08976SQu Wenruo } 1591ca08976SQu Wenruo return ret; 1601ca08976SQu Wenruo } 1611ca08976SQu Wenruo 1620bd9289cSQu Wenruo /* 1630bd9289cSQu Wenruo * Hook for threshold which will be called in btrfs_queue_work. 1640bd9289cSQu Wenruo * This hook WILL be called in IRQ handler context, 1650bd9289cSQu Wenruo * so workqueue_set_max_active MUST NOT be called in this hook 1660bd9289cSQu Wenruo */ 167d458b054SQu Wenruo static inline void thresh_queue_hook(struct __btrfs_workqueue *wq) 1680bd9289cSQu Wenruo { 1690bd9289cSQu Wenruo if (wq->thresh == NO_THRESHOLD) 1700bd9289cSQu Wenruo return; 1710bd9289cSQu Wenruo atomic_inc(&wq->pending); 1720bd9289cSQu Wenruo } 1730bd9289cSQu Wenruo 1740bd9289cSQu Wenruo /* 1750bd9289cSQu Wenruo * Hook for threshold which will be called before executing the work, 1760bd9289cSQu Wenruo * This hook is called in kthread content. 1770bd9289cSQu Wenruo * So workqueue_set_max_active is called here. 1780bd9289cSQu Wenruo */ 179d458b054SQu Wenruo static inline void thresh_exec_hook(struct __btrfs_workqueue *wq) 1800bd9289cSQu Wenruo { 181c6dd6ea5SQu Wenruo int new_current_active; 1820bd9289cSQu Wenruo long pending; 1830bd9289cSQu Wenruo int need_change = 0; 1840bd9289cSQu Wenruo 1850bd9289cSQu Wenruo if (wq->thresh == NO_THRESHOLD) 1860bd9289cSQu Wenruo return; 1870bd9289cSQu Wenruo 1880bd9289cSQu Wenruo atomic_dec(&wq->pending); 1890bd9289cSQu Wenruo spin_lock(&wq->thres_lock); 1900bd9289cSQu Wenruo /* 1910bd9289cSQu Wenruo * Use wq->count to limit the calling frequency of 1920bd9289cSQu Wenruo * workqueue_set_max_active. 1930bd9289cSQu Wenruo */ 1940bd9289cSQu Wenruo wq->count++; 1950bd9289cSQu Wenruo wq->count %= (wq->thresh / 4); 1960bd9289cSQu Wenruo if (!wq->count) 1970bd9289cSQu Wenruo goto out; 198c6dd6ea5SQu Wenruo new_current_active = wq->current_active; 1990bd9289cSQu Wenruo 2000bd9289cSQu Wenruo /* 2010bd9289cSQu Wenruo * pending may be changed later, but it's OK since we really 2020bd9289cSQu Wenruo * don't need it so accurate to calculate new_max_active. 2030bd9289cSQu Wenruo */ 2040bd9289cSQu Wenruo pending = atomic_read(&wq->pending); 2050bd9289cSQu Wenruo if (pending > wq->thresh) 206c6dd6ea5SQu Wenruo new_current_active++; 2070bd9289cSQu Wenruo if (pending < wq->thresh / 2) 208c6dd6ea5SQu Wenruo new_current_active--; 209c6dd6ea5SQu Wenruo new_current_active = clamp_val(new_current_active, 1, wq->limit_active); 210c6dd6ea5SQu Wenruo if (new_current_active != wq->current_active) { 2110bd9289cSQu Wenruo need_change = 1; 212c6dd6ea5SQu Wenruo wq->current_active = new_current_active; 2130bd9289cSQu Wenruo } 2140bd9289cSQu Wenruo out: 2150bd9289cSQu Wenruo spin_unlock(&wq->thres_lock); 2160bd9289cSQu Wenruo 2170bd9289cSQu Wenruo if (need_change) { 218c6dd6ea5SQu Wenruo workqueue_set_max_active(wq->normal_wq, wq->current_active); 2190bd9289cSQu Wenruo } 2200bd9289cSQu Wenruo } 2210bd9289cSQu Wenruo 222c495dcd6SOmar Sandoval static void run_ordered_work(struct __btrfs_workqueue *wq, 223c495dcd6SOmar Sandoval struct btrfs_work *self) 22408a9ff32SQu Wenruo { 22508a9ff32SQu Wenruo struct list_head *list = &wq->ordered_list; 226d458b054SQu Wenruo struct btrfs_work *work; 22708a9ff32SQu Wenruo spinlock_t *lock = &wq->list_lock; 22808a9ff32SQu Wenruo unsigned long flags; 229c495dcd6SOmar Sandoval bool free_self = false; 23008a9ff32SQu Wenruo 23108a9ff32SQu Wenruo while (1) { 23208a9ff32SQu Wenruo spin_lock_irqsave(lock, flags); 23308a9ff32SQu Wenruo if (list_empty(list)) 23408a9ff32SQu Wenruo break; 235d458b054SQu Wenruo work = list_entry(list->next, struct btrfs_work, 23608a9ff32SQu Wenruo ordered_list); 23708a9ff32SQu Wenruo if (!test_bit(WORK_DONE_BIT, &work->flags)) 23808a9ff32SQu Wenruo break; 23908a9ff32SQu Wenruo 24008a9ff32SQu Wenruo /* 24108a9ff32SQu Wenruo * we are going to call the ordered done function, but 24208a9ff32SQu Wenruo * we leave the work item on the list as a barrier so 24308a9ff32SQu Wenruo * that later work items that are done don't have their 24408a9ff32SQu Wenruo * functions called before this one returns 24508a9ff32SQu Wenruo */ 24608a9ff32SQu Wenruo if (test_and_set_bit(WORK_ORDER_DONE_BIT, &work->flags)) 24708a9ff32SQu Wenruo break; 24852483bc2SQu Wenruo trace_btrfs_ordered_sched(work); 24908a9ff32SQu Wenruo spin_unlock_irqrestore(lock, flags); 25008a9ff32SQu Wenruo work->ordered_func(work); 25108a9ff32SQu Wenruo 25208a9ff32SQu Wenruo /* now take the lock again and drop our item from the list */ 25308a9ff32SQu Wenruo spin_lock_irqsave(lock, flags); 25408a9ff32SQu Wenruo list_del(&work->ordered_list); 25508a9ff32SQu Wenruo spin_unlock_irqrestore(lock, flags); 25608a9ff32SQu Wenruo 257c495dcd6SOmar Sandoval if (work == self) { 25808a9ff32SQu Wenruo /* 259c495dcd6SOmar Sandoval * This is the work item that the worker is currently 260c495dcd6SOmar Sandoval * executing. 261c495dcd6SOmar Sandoval * 262c495dcd6SOmar Sandoval * The kernel workqueue code guarantees non-reentrancy 263c495dcd6SOmar Sandoval * of work items. I.e., if a work item with the same 264c495dcd6SOmar Sandoval * address and work function is queued twice, the second 265c495dcd6SOmar Sandoval * execution is blocked until the first one finishes. A 266c495dcd6SOmar Sandoval * work item may be freed and recycled with the same 267c495dcd6SOmar Sandoval * work function; the workqueue code assumes that the 268c495dcd6SOmar Sandoval * original work item cannot depend on the recycled work 269c495dcd6SOmar Sandoval * item in that case (see find_worker_executing_work()). 270c495dcd6SOmar Sandoval * 271a0cac0ecSOmar Sandoval * Note that different types of Btrfs work can depend on 272a0cac0ecSOmar Sandoval * each other, and one type of work on one Btrfs 273a0cac0ecSOmar Sandoval * filesystem may even depend on the same type of work 274a0cac0ecSOmar Sandoval * on another Btrfs filesystem via, e.g., a loop device. 275a0cac0ecSOmar Sandoval * Therefore, we must not allow the current work item to 276a0cac0ecSOmar Sandoval * be recycled until we are really done, otherwise we 277a0cac0ecSOmar Sandoval * break the above assumption and can deadlock. 278c495dcd6SOmar Sandoval */ 279c495dcd6SOmar Sandoval free_self = true; 280c495dcd6SOmar Sandoval } else { 281c495dcd6SOmar Sandoval /* 282c495dcd6SOmar Sandoval * We don't want to call the ordered free functions with 283c9eb55dbSOmar Sandoval * the lock held. 28408a9ff32SQu Wenruo */ 28508a9ff32SQu Wenruo work->ordered_free(work); 286c9eb55dbSOmar Sandoval /* NB: work must not be dereferenced past this point. */ 287c9eb55dbSOmar Sandoval trace_btrfs_all_work_done(wq->fs_info, work); 28808a9ff32SQu Wenruo } 289c495dcd6SOmar Sandoval } 29008a9ff32SQu Wenruo spin_unlock_irqrestore(lock, flags); 291c495dcd6SOmar Sandoval 292c495dcd6SOmar Sandoval if (free_self) { 293c495dcd6SOmar Sandoval self->ordered_free(self); 294c9eb55dbSOmar Sandoval /* NB: self must not be dereferenced past this point. */ 295c9eb55dbSOmar Sandoval trace_btrfs_all_work_done(wq->fs_info, self); 296c495dcd6SOmar Sandoval } 29708a9ff32SQu Wenruo } 29808a9ff32SQu Wenruo 299a0cac0ecSOmar Sandoval static void btrfs_work_helper(struct work_struct *normal_work) 30008a9ff32SQu Wenruo { 301a0cac0ecSOmar Sandoval struct btrfs_work *work = container_of(normal_work, struct btrfs_work, 302a0cac0ecSOmar Sandoval normal_work); 303d458b054SQu Wenruo struct __btrfs_workqueue *wq; 30408a9ff32SQu Wenruo int need_order = 0; 30508a9ff32SQu Wenruo 30608a9ff32SQu Wenruo /* 30708a9ff32SQu Wenruo * We should not touch things inside work in the following cases: 30808a9ff32SQu Wenruo * 1) after work->func() if it has no ordered_free 30908a9ff32SQu Wenruo * Since the struct is freed in work->func(). 31008a9ff32SQu Wenruo * 2) after setting WORK_DONE_BIT 31108a9ff32SQu Wenruo * The work may be freed in other threads almost instantly. 31208a9ff32SQu Wenruo * So we save the needed things here. 31308a9ff32SQu Wenruo */ 31408a9ff32SQu Wenruo if (work->ordered_func) 31508a9ff32SQu Wenruo need_order = 1; 31608a9ff32SQu Wenruo wq = work->wq; 31708a9ff32SQu Wenruo 31852483bc2SQu Wenruo trace_btrfs_work_sched(work); 3190bd9289cSQu Wenruo thresh_exec_hook(wq); 32008a9ff32SQu Wenruo work->func(work); 32108a9ff32SQu Wenruo if (need_order) { 32208a9ff32SQu Wenruo set_bit(WORK_DONE_BIT, &work->flags); 323c495dcd6SOmar Sandoval run_ordered_work(wq, work); 324c9eb55dbSOmar Sandoval } else { 325c9eb55dbSOmar Sandoval /* NB: work must not be dereferenced past this point. */ 326c9eb55dbSOmar Sandoval trace_btrfs_all_work_done(wq->fs_info, work); 32708a9ff32SQu Wenruo } 32808a9ff32SQu Wenruo } 32908a9ff32SQu Wenruo 330a0cac0ecSOmar Sandoval void btrfs_init_work(struct btrfs_work *work, btrfs_func_t func, 331a0cac0ecSOmar Sandoval btrfs_func_t ordered_func, btrfs_func_t ordered_free) 33208a9ff32SQu Wenruo { 33308a9ff32SQu Wenruo work->func = func; 33408a9ff32SQu Wenruo work->ordered_func = ordered_func; 33508a9ff32SQu Wenruo work->ordered_free = ordered_free; 336a0cac0ecSOmar Sandoval INIT_WORK(&work->normal_work, btrfs_work_helper); 33708a9ff32SQu Wenruo INIT_LIST_HEAD(&work->ordered_list); 33808a9ff32SQu Wenruo work->flags = 0; 33908a9ff32SQu Wenruo } 34008a9ff32SQu Wenruo 341d458b054SQu Wenruo static inline void __btrfs_queue_work(struct __btrfs_workqueue *wq, 342d458b054SQu Wenruo struct btrfs_work *work) 34308a9ff32SQu Wenruo { 34408a9ff32SQu Wenruo unsigned long flags; 34508a9ff32SQu Wenruo 34608a9ff32SQu Wenruo work->wq = wq; 3470bd9289cSQu Wenruo thresh_queue_hook(wq); 34808a9ff32SQu Wenruo if (work->ordered_func) { 34908a9ff32SQu Wenruo spin_lock_irqsave(&wq->list_lock, flags); 35008a9ff32SQu Wenruo list_add_tail(&work->ordered_list, &wq->ordered_list); 35108a9ff32SQu Wenruo spin_unlock_irqrestore(&wq->list_lock, flags); 35208a9ff32SQu Wenruo } 35352483bc2SQu Wenruo trace_btrfs_work_queued(work); 3540a95b851SQu Wenruo queue_work(wq->normal_wq, &work->normal_work); 35508a9ff32SQu Wenruo } 35608a9ff32SQu Wenruo 357d458b054SQu Wenruo void btrfs_queue_work(struct btrfs_workqueue *wq, 358d458b054SQu Wenruo struct btrfs_work *work) 3591ca08976SQu Wenruo { 360d458b054SQu Wenruo struct __btrfs_workqueue *dest_wq; 3611ca08976SQu Wenruo 3621ca08976SQu Wenruo if (test_bit(WORK_HIGH_PRIO_BIT, &work->flags) && wq->high) 3631ca08976SQu Wenruo dest_wq = wq->high; 3641ca08976SQu Wenruo else 3651ca08976SQu Wenruo dest_wq = wq->normal; 3661ca08976SQu Wenruo __btrfs_queue_work(dest_wq, work); 3671ca08976SQu Wenruo } 3681ca08976SQu Wenruo 3691ca08976SQu Wenruo static inline void 370d458b054SQu Wenruo __btrfs_destroy_workqueue(struct __btrfs_workqueue *wq) 37108a9ff32SQu Wenruo { 37208a9ff32SQu Wenruo destroy_workqueue(wq->normal_wq); 373c3a46891SQu Wenruo trace_btrfs_workqueue_destroy(wq); 37408a9ff32SQu Wenruo kfree(wq); 37508a9ff32SQu Wenruo } 37608a9ff32SQu Wenruo 377d458b054SQu Wenruo void btrfs_destroy_workqueue(struct btrfs_workqueue *wq) 3781ca08976SQu Wenruo { 3791ca08976SQu Wenruo if (!wq) 3801ca08976SQu Wenruo return; 3811ca08976SQu Wenruo if (wq->high) 3821ca08976SQu Wenruo __btrfs_destroy_workqueue(wq->high); 3831ca08976SQu Wenruo __btrfs_destroy_workqueue(wq->normal); 384ef66af10SFilipe Manana kfree(wq); 3851ca08976SQu Wenruo } 3861ca08976SQu Wenruo 387c6dd6ea5SQu Wenruo void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int limit_active) 38808a9ff32SQu Wenruo { 389800ee224SSergei Trofimovich if (!wq) 390800ee224SSergei Trofimovich return; 391c6dd6ea5SQu Wenruo wq->normal->limit_active = limit_active; 3921ca08976SQu Wenruo if (wq->high) 393c6dd6ea5SQu Wenruo wq->high->limit_active = limit_active; 3941ca08976SQu Wenruo } 3951ca08976SQu Wenruo 396d458b054SQu Wenruo void btrfs_set_work_high_priority(struct btrfs_work *work) 3971ca08976SQu Wenruo { 3981ca08976SQu Wenruo set_bit(WORK_HIGH_PRIO_BIT, &work->flags); 39908a9ff32SQu Wenruo } 400