aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2014-02-27 21:46:04 -0500
committerJosef Bacik <jbacik@fb.com>2014-03-10 15:17:03 -0400
commit1ca08976ae94f3594dd7303584581cf8099ce47e (patch)
tree36266c4bd75ea9807f8936c40d1e13803b3fd83a /fs/btrfs
parent08a9ff3264181986d1d692a4e6fce3669700c9f8 (diff)
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>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/async-thread.c91
-rw-r--r--fs/btrfs/async-thread.h5
2 files changed, 83 insertions, 13 deletions
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c
index 905de02e4386..193c84964db9 100644
--- a/fs/btrfs/async-thread.c
+++ b/fs/btrfs/async-thread.c
@@ -730,7 +730,7 @@ void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
730 spin_unlock_irqrestore(&worker->lock, flags); 730 spin_unlock_irqrestore(&worker->lock, flags);
731} 731}
732 732
733struct btrfs_workqueue_struct { 733struct __btrfs_workqueue_struct {
734 struct workqueue_struct *normal_wq; 734 struct workqueue_struct *normal_wq;
735 /* List head pointing to ordered work list */ 735 /* List head pointing to ordered work list */
736 struct list_head ordered_list; 736 struct list_head ordered_list;
@@ -739,6 +739,38 @@ struct btrfs_workqueue_struct {
739 spinlock_t list_lock; 739 spinlock_t list_lock;
740}; 740};
741 741
742struct btrfs_workqueue_struct {
743 struct __btrfs_workqueue_struct *normal;
744 struct __btrfs_workqueue_struct *high;
745};
746
747static inline struct __btrfs_workqueue_struct
748*__btrfs_alloc_workqueue(char *name, int flags, int max_active)
749{
750 struct __btrfs_workqueue_struct *ret = kzalloc(sizeof(*ret), GFP_NOFS);
751
752 if (unlikely(!ret))
753 return NULL;
754
755 if (flags & WQ_HIGHPRI)
756 ret->normal_wq = alloc_workqueue("%s-%s-high", flags,
757 max_active, "btrfs", name);
758 else
759 ret->normal_wq = alloc_workqueue("%s-%s", flags,
760 max_active, "btrfs", name);
761 if (unlikely(!ret->normal_wq)) {
762 kfree(ret);
763 return NULL;
764 }
765
766 INIT_LIST_HEAD(&ret->ordered_list);
767 spin_lock_init(&ret->list_lock);
768 return ret;
769}
770
771static inline void
772__btrfs_destroy_workqueue(struct __btrfs_workqueue_struct *wq);
773
742struct btrfs_workqueue_struct *btrfs_alloc_workqueue(char *name, 774struct btrfs_workqueue_struct *btrfs_alloc_workqueue(char *name,
743 int flags, 775 int flags,
744 int max_active) 776 int max_active)
@@ -748,19 +780,25 @@ struct btrfs_workqueue_struct *btrfs_alloc_workqueue(char *name,
748 if (unlikely(!ret)) 780 if (unlikely(!ret))
749 return NULL; 781 return NULL;
750 782
751 ret->normal_wq = alloc_workqueue("%s-%s", flags, max_active, 783 ret->normal = __btrfs_alloc_workqueue(name, flags & ~WQ_HIGHPRI,
752 "btrfs", name); 784 max_active);
753 if (unlikely(!ret->normal_wq)) { 785 if (unlikely(!ret->normal)) {
754 kfree(ret); 786 kfree(ret);
755 return NULL; 787 return NULL;
756 } 788 }
757 789
758 INIT_LIST_HEAD(&ret->ordered_list); 790 if (flags & WQ_HIGHPRI) {
759 spin_lock_init(&ret->list_lock); 791 ret->high = __btrfs_alloc_workqueue(name, flags, max_active);
792 if (unlikely(!ret->high)) {
793 __btrfs_destroy_workqueue(ret->normal);
794 kfree(ret);
795 return NULL;
796 }
797 }
760 return ret; 798 return ret;
761} 799}
762 800
763static void run_ordered_work(struct btrfs_workqueue_struct *wq) 801static void run_ordered_work(struct __btrfs_workqueue_struct *wq)
764{ 802{
765 struct list_head *list = &wq->ordered_list; 803 struct list_head *list = &wq->ordered_list;
766 struct btrfs_work_struct *work; 804 struct btrfs_work_struct *work;
@@ -804,7 +842,7 @@ static void run_ordered_work(struct btrfs_workqueue_struct *wq)
804static void normal_work_helper(struct work_struct *arg) 842static void normal_work_helper(struct work_struct *arg)
805{ 843{
806 struct btrfs_work_struct *work; 844 struct btrfs_work_struct *work;
807 struct btrfs_workqueue_struct *wq; 845 struct __btrfs_workqueue_struct *wq;
808 int need_order = 0; 846 int need_order = 0;
809 847
810 work = container_of(arg, struct btrfs_work_struct, normal_work); 848 work = container_of(arg, struct btrfs_work_struct, normal_work);
@@ -840,8 +878,8 @@ void btrfs_init_work(struct btrfs_work_struct *work,
840 work->flags = 0; 878 work->flags = 0;
841} 879}
842 880
843void btrfs_queue_work(struct btrfs_workqueue_struct *wq, 881static inline void __btrfs_queue_work(struct __btrfs_workqueue_struct *wq,
844 struct btrfs_work_struct *work) 882 struct btrfs_work_struct *work)
845{ 883{
846 unsigned long flags; 884 unsigned long flags;
847 885
@@ -854,13 +892,42 @@ void btrfs_queue_work(struct btrfs_workqueue_struct *wq,
854 queue_work(wq->normal_wq, &work->normal_work); 892 queue_work(wq->normal_wq, &work->normal_work);
855} 893}
856 894
857void btrfs_destroy_workqueue(struct btrfs_workqueue_struct *wq) 895void btrfs_queue_work(struct btrfs_workqueue_struct *wq,
896 struct btrfs_work_struct *work)
897{
898 struct __btrfs_workqueue_struct *dest_wq;
899
900 if (test_bit(WORK_HIGH_PRIO_BIT, &work->flags) && wq->high)
901 dest_wq = wq->high;
902 else
903 dest_wq = wq->normal;
904 __btrfs_queue_work(dest_wq, work);
905}
906
907static inline void
908__btrfs_destroy_workqueue(struct __btrfs_workqueue_struct *wq)
858{ 909{
859 destroy_workqueue(wq->normal_wq); 910 destroy_workqueue(wq->normal_wq);
860 kfree(wq); 911 kfree(wq);
861} 912}
862 913
914void btrfs_destroy_workqueue(struct btrfs_workqueue_struct *wq)
915{
916 if (!wq)
917 return;
918 if (wq->high)
919 __btrfs_destroy_workqueue(wq->high);
920 __btrfs_destroy_workqueue(wq->normal);
921}
922
863void btrfs_workqueue_set_max(struct btrfs_workqueue_struct *wq, int max) 923void btrfs_workqueue_set_max(struct btrfs_workqueue_struct *wq, int max)
864{ 924{
865 workqueue_set_max_active(wq->normal_wq, max); 925 workqueue_set_max_active(wq->normal->normal_wq, max);
926 if (wq->high)
927 workqueue_set_max_active(wq->high->normal_wq, max);
928}
929
930void btrfs_set_work_high_priority(struct btrfs_work_struct *work)
931{
932 set_bit(WORK_HIGH_PRIO_BIT, &work->flags);
866} 933}
diff --git a/fs/btrfs/async-thread.h b/fs/btrfs/async-thread.h
index 9d8da53f6dd9..fce623cfe3da 100644
--- a/fs/btrfs/async-thread.h
+++ b/fs/btrfs/async-thread.h
@@ -121,6 +121,8 @@ void btrfs_requeue_work(struct btrfs_work *work);
121void btrfs_set_work_high_prio(struct btrfs_work *work); 121void btrfs_set_work_high_prio(struct btrfs_work *work);
122 122
123struct btrfs_workqueue_struct; 123struct btrfs_workqueue_struct;
124/* Internal use only */
125struct __btrfs_workqueue_struct;
124 126
125struct btrfs_work_struct { 127struct btrfs_work_struct {
126 void (*func)(struct btrfs_work_struct *arg); 128 void (*func)(struct btrfs_work_struct *arg);
@@ -130,7 +132,7 @@ struct btrfs_work_struct {
130 /* Don't touch things below */ 132 /* Don't touch things below */
131 struct work_struct normal_work; 133 struct work_struct normal_work;
132 struct list_head ordered_list; 134 struct list_head ordered_list;
133 struct btrfs_workqueue_struct *wq; 135 struct __btrfs_workqueue_struct *wq;
134 unsigned long flags; 136 unsigned long flags;
135}; 137};
136 138
@@ -145,4 +147,5 @@ void btrfs_queue_work(struct btrfs_workqueue_struct *wq,
145 struct btrfs_work_struct *work); 147 struct btrfs_work_struct *work);
146void btrfs_destroy_workqueue(struct btrfs_workqueue_struct *wq); 148void btrfs_destroy_workqueue(struct btrfs_workqueue_struct *wq);
147void btrfs_workqueue_set_max(struct btrfs_workqueue_struct *wq, int max); 149void btrfs_workqueue_set_max(struct btrfs_workqueue_struct *wq, int max);
150void btrfs_set_work_high_priority(struct btrfs_work_struct *work);
148#endif 151#endif