btrfs: Add high priority workqueue support for btrfs_workqueue_struct
Add high priority function to btrfs_workqueue. This is implemented by embedding a btrfs_workqueue into a btrfs_workqueue and use some helper functions to differ the normal priority wq and high priority wq. So the high priority wq is completely independent from the normal workqueue. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Tested-by: David Sterba <dsterba@suse.cz> Signed-off-by: Josef Bacik <jbacik@fb.com>
This commit is contained in:
parent
08a9ff3264
commit
1ca08976ae
@ -730,7 +730,7 @@ void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
|
|||||||
spin_unlock_irqrestore(&worker->lock, flags);
|
spin_unlock_irqrestore(&worker->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct btrfs_workqueue_struct {
|
struct __btrfs_workqueue_struct {
|
||||||
struct workqueue_struct *normal_wq;
|
struct workqueue_struct *normal_wq;
|
||||||
/* List head pointing to ordered work list */
|
/* List head pointing to ordered work list */
|
||||||
struct list_head ordered_list;
|
struct list_head ordered_list;
|
||||||
@ -739,17 +739,25 @@ struct btrfs_workqueue_struct {
|
|||||||
spinlock_t list_lock;
|
spinlock_t list_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct btrfs_workqueue_struct *btrfs_alloc_workqueue(char *name,
|
struct btrfs_workqueue_struct {
|
||||||
int flags,
|
struct __btrfs_workqueue_struct *normal;
|
||||||
int max_active)
|
struct __btrfs_workqueue_struct *high;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct __btrfs_workqueue_struct
|
||||||
|
*__btrfs_alloc_workqueue(char *name, int flags, int max_active)
|
||||||
{
|
{
|
||||||
struct btrfs_workqueue_struct *ret = kzalloc(sizeof(*ret), GFP_NOFS);
|
struct __btrfs_workqueue_struct *ret = kzalloc(sizeof(*ret), GFP_NOFS);
|
||||||
|
|
||||||
if (unlikely(!ret))
|
if (unlikely(!ret))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret->normal_wq = alloc_workqueue("%s-%s", flags, max_active,
|
if (flags & WQ_HIGHPRI)
|
||||||
"btrfs", name);
|
ret->normal_wq = alloc_workqueue("%s-%s-high", flags,
|
||||||
|
max_active, "btrfs", name);
|
||||||
|
else
|
||||||
|
ret->normal_wq = alloc_workqueue("%s-%s", flags,
|
||||||
|
max_active, "btrfs", name);
|
||||||
if (unlikely(!ret->normal_wq)) {
|
if (unlikely(!ret->normal_wq)) {
|
||||||
kfree(ret);
|
kfree(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -760,7 +768,37 @@ struct btrfs_workqueue_struct *btrfs_alloc_workqueue(char *name,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_ordered_work(struct btrfs_workqueue_struct *wq)
|
static inline void
|
||||||
|
__btrfs_destroy_workqueue(struct __btrfs_workqueue_struct *wq);
|
||||||
|
|
||||||
|
struct btrfs_workqueue_struct *btrfs_alloc_workqueue(char *name,
|
||||||
|
int flags,
|
||||||
|
int max_active)
|
||||||
|
{
|
||||||
|
struct btrfs_workqueue_struct *ret = kzalloc(sizeof(*ret), GFP_NOFS);
|
||||||
|
|
||||||
|
if (unlikely(!ret))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret->normal = __btrfs_alloc_workqueue(name, flags & ~WQ_HIGHPRI,
|
||||||
|
max_active);
|
||||||
|
if (unlikely(!ret->normal)) {
|
||||||
|
kfree(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WQ_HIGHPRI) {
|
||||||
|
ret->high = __btrfs_alloc_workqueue(name, flags, max_active);
|
||||||
|
if (unlikely(!ret->high)) {
|
||||||
|
__btrfs_destroy_workqueue(ret->normal);
|
||||||
|
kfree(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_ordered_work(struct __btrfs_workqueue_struct *wq)
|
||||||
{
|
{
|
||||||
struct list_head *list = &wq->ordered_list;
|
struct list_head *list = &wq->ordered_list;
|
||||||
struct btrfs_work_struct *work;
|
struct btrfs_work_struct *work;
|
||||||
@ -804,7 +842,7 @@ static void run_ordered_work(struct btrfs_workqueue_struct *wq)
|
|||||||
static void normal_work_helper(struct work_struct *arg)
|
static void normal_work_helper(struct work_struct *arg)
|
||||||
{
|
{
|
||||||
struct btrfs_work_struct *work;
|
struct btrfs_work_struct *work;
|
||||||
struct btrfs_workqueue_struct *wq;
|
struct __btrfs_workqueue_struct *wq;
|
||||||
int need_order = 0;
|
int need_order = 0;
|
||||||
|
|
||||||
work = container_of(arg, struct btrfs_work_struct, normal_work);
|
work = container_of(arg, struct btrfs_work_struct, normal_work);
|
||||||
@ -840,7 +878,7 @@ void btrfs_init_work(struct btrfs_work_struct *work,
|
|||||||
work->flags = 0;
|
work->flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void btrfs_queue_work(struct btrfs_workqueue_struct *wq,
|
static inline void __btrfs_queue_work(struct __btrfs_workqueue_struct *wq,
|
||||||
struct btrfs_work_struct *work)
|
struct btrfs_work_struct *work)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -854,13 +892,42 @@ void btrfs_queue_work(struct btrfs_workqueue_struct *wq,
|
|||||||
queue_work(wq->normal_wq, &work->normal_work);
|
queue_work(wq->normal_wq, &work->normal_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
void btrfs_destroy_workqueue(struct btrfs_workqueue_struct *wq)
|
void btrfs_queue_work(struct btrfs_workqueue_struct *wq,
|
||||||
|
struct btrfs_work_struct *work)
|
||||||
|
{
|
||||||
|
struct __btrfs_workqueue_struct *dest_wq;
|
||||||
|
|
||||||
|
if (test_bit(WORK_HIGH_PRIO_BIT, &work->flags) && wq->high)
|
||||||
|
dest_wq = wq->high;
|
||||||
|
else
|
||||||
|
dest_wq = wq->normal;
|
||||||
|
__btrfs_queue_work(dest_wq, work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
__btrfs_destroy_workqueue(struct __btrfs_workqueue_struct *wq)
|
||||||
{
|
{
|
||||||
destroy_workqueue(wq->normal_wq);
|
destroy_workqueue(wq->normal_wq);
|
||||||
kfree(wq);
|
kfree(wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void btrfs_destroy_workqueue(struct btrfs_workqueue_struct *wq)
|
||||||
|
{
|
||||||
|
if (!wq)
|
||||||
|
return;
|
||||||
|
if (wq->high)
|
||||||
|
__btrfs_destroy_workqueue(wq->high);
|
||||||
|
__btrfs_destroy_workqueue(wq->normal);
|
||||||
|
}
|
||||||
|
|
||||||
void btrfs_workqueue_set_max(struct btrfs_workqueue_struct *wq, int max)
|
void btrfs_workqueue_set_max(struct btrfs_workqueue_struct *wq, int max)
|
||||||
{
|
{
|
||||||
workqueue_set_max_active(wq->normal_wq, max);
|
workqueue_set_max_active(wq->normal->normal_wq, max);
|
||||||
|
if (wq->high)
|
||||||
|
workqueue_set_max_active(wq->high->normal_wq, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
void btrfs_set_work_high_priority(struct btrfs_work_struct *work)
|
||||||
|
{
|
||||||
|
set_bit(WORK_HIGH_PRIO_BIT, &work->flags);
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,8 @@ void btrfs_requeue_work(struct btrfs_work *work);
|
|||||||
void btrfs_set_work_high_prio(struct btrfs_work *work);
|
void btrfs_set_work_high_prio(struct btrfs_work *work);
|
||||||
|
|
||||||
struct btrfs_workqueue_struct;
|
struct btrfs_workqueue_struct;
|
||||||
|
/* Internal use only */
|
||||||
|
struct __btrfs_workqueue_struct;
|
||||||
|
|
||||||
struct btrfs_work_struct {
|
struct btrfs_work_struct {
|
||||||
void (*func)(struct btrfs_work_struct *arg);
|
void (*func)(struct btrfs_work_struct *arg);
|
||||||
@ -130,7 +132,7 @@ struct btrfs_work_struct {
|
|||||||
/* Don't touch things below */
|
/* Don't touch things below */
|
||||||
struct work_struct normal_work;
|
struct work_struct normal_work;
|
||||||
struct list_head ordered_list;
|
struct list_head ordered_list;
|
||||||
struct btrfs_workqueue_struct *wq;
|
struct __btrfs_workqueue_struct *wq;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -145,4 +147,5 @@ void btrfs_queue_work(struct btrfs_workqueue_struct *wq,
|
|||||||
struct btrfs_work_struct *work);
|
struct btrfs_work_struct *work);
|
||||||
void btrfs_destroy_workqueue(struct btrfs_workqueue_struct *wq);
|
void btrfs_destroy_workqueue(struct btrfs_workqueue_struct *wq);
|
||||||
void btrfs_workqueue_set_max(struct btrfs_workqueue_struct *wq, int max);
|
void btrfs_workqueue_set_max(struct btrfs_workqueue_struct *wq, int max);
|
||||||
|
void btrfs_set_work_high_priority(struct btrfs_work_struct *work);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user