Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

writeback: remove wb_writeback_work->single_wait/done

wb_writeback_work->single_wait/done are used for the wait mechanism
for synchronous wb_work (wb_writeback_work) items which are issued
when bdi_split_work_to_wbs() fails to allocate memory for asynchronous
wb_work items; however, there's no reason to use a separate wait
mechanism for this. bdi_split_work_to_wbs() can simply use on-stack
fallback wb_work item and separate wb_completion to wait for it.

This patch removes wb_work->single_wait/done and the related code and
make bdi_split_work_to_wbs() use on-stack fallback wb_work and
wb_completion instead.

Signed-off-by: Tejun Heo <tj@kernel.org>
Suggested-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jens Axboe <axboe@fb.com>

authored by

Tejun Heo and committed by
Jens Axboe
8a1270cd 1ed8d48c

+30 -86
+30 -86
fs/fs-writeback.c
··· 53 53 unsigned int for_background:1; 54 54 unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ 55 55 unsigned int auto_free:1; /* free on completion */ 56 - unsigned int single_wait:1; 57 - unsigned int single_done:1; 58 56 enum wb_reason reason; /* why was writeback initiated? */ 59 57 60 58 struct list_head list; /* pending work list */ ··· 179 181 trace_writeback_queue(wb->bdi, work); 180 182 181 183 spin_lock_bh(&wb->work_lock); 182 - if (!test_bit(WB_registered, &wb->state)) { 183 - if (work->single_wait) 184 - work->single_done = 1; 184 + if (!test_bit(WB_registered, &wb->state)) 185 185 goto out_unlock; 186 - } 187 186 if (work->done) 188 187 atomic_inc(&work->done->cnt); 189 188 list_add_tail(&work->list, &wb->work_list); ··· 733 738 EXPORT_SYMBOL_GPL(inode_congested); 734 739 735 740 /** 736 - * wb_wait_for_single_work - wait for completion of a single bdi_writeback_work 737 - * @bdi: bdi the work item was issued to 738 - * @work: work item to wait for 739 - * 740 - * Wait for the completion of @work which was issued to one of @bdi's 741 - * bdi_writeback's. The caller must have set @work->single_wait before 742 - * issuing it. This wait operates independently fo 743 - * wb_wait_for_completion() and also disables automatic freeing of @work. 744 - */ 745 - static void wb_wait_for_single_work(struct backing_dev_info *bdi, 746 - struct wb_writeback_work *work) 747 - { 748 - if (WARN_ON_ONCE(!work->single_wait)) 749 - return; 750 - 751 - wait_event(bdi->wb_waitq, work->single_done); 752 - 753 - /* 754 - * Paired with smp_wmb() in wb_do_writeback() and ensures that all 755 - * modifications to @work prior to assertion of ->single_done is 756 - * visible to the caller once this function returns. 757 - */ 758 - smp_rmb(); 759 - } 760 - 761 - /** 762 741 * wb_split_bdi_pages - split nr_pages to write according to bandwidth 763 742 * @wb: target bdi_writeback to split @nr_pages to 764 743 * @nr_pages: number of pages to write for the whole bdi ··· 761 792 } 762 793 763 794 /** 764 - * wb_clone_and_queue_work - clone a wb_writeback_work and issue it to a wb 765 - * @wb: target bdi_writeback 766 - * @base_work: source wb_writeback_work 767 - * 768 - * Try to make a clone of @base_work and issue it to @wb. If cloning 769 - * succeeds, %true is returned; otherwise, @base_work is issued directly 770 - * and %false is returned. In the latter case, the caller is required to 771 - * wait for @base_work's completion using wb_wait_for_single_work(). 772 - * 773 - * A clone is auto-freed on completion. @base_work never is. 774 - */ 775 - static bool wb_clone_and_queue_work(struct bdi_writeback *wb, 776 - struct wb_writeback_work *base_work) 777 - { 778 - struct wb_writeback_work *work; 779 - 780 - work = kmalloc(sizeof(*work), GFP_ATOMIC); 781 - if (work) { 782 - *work = *base_work; 783 - work->auto_free = 1; 784 - work->single_wait = 0; 785 - } else { 786 - work = base_work; 787 - work->auto_free = 0; 788 - work->single_wait = 1; 789 - } 790 - work->single_done = 0; 791 - wb_queue_work(wb, work); 792 - return work != base_work; 793 - } 794 - 795 - /** 796 795 * bdi_split_work_to_wbs - split a wb_writeback_work to all wb's of a bdi 797 796 * @bdi: target backing_dev_info 798 797 * @base_work: wb_writeback_work to issue ··· 775 838 struct wb_writeback_work *base_work, 776 839 bool skip_if_busy) 777 840 { 778 - long nr_pages = base_work->nr_pages; 779 841 int next_memcg_id = 0; 780 842 struct bdi_writeback *wb; 781 843 struct wb_iter iter; ··· 786 850 restart: 787 851 rcu_read_lock(); 788 852 bdi_for_each_wb(wb, bdi, &iter, next_memcg_id) { 853 + DEFINE_WB_COMPLETION_ONSTACK(fallback_work_done); 854 + struct wb_writeback_work fallback_work; 855 + struct wb_writeback_work *work; 856 + long nr_pages; 857 + 789 858 if (!wb_has_dirty_io(wb) || 790 859 (skip_if_busy && writeback_in_progress(wb))) 791 860 continue; 792 861 793 - base_work->nr_pages = wb_split_bdi_pages(wb, nr_pages); 794 - if (!wb_clone_and_queue_work(wb, base_work)) { 795 - next_memcg_id = wb->memcg_css->id + 1; 796 - rcu_read_unlock(); 797 - wb_wait_for_single_work(bdi, base_work); 798 - goto restart; 862 + nr_pages = wb_split_bdi_pages(wb, base_work->nr_pages); 863 + 864 + work = kmalloc(sizeof(*work), GFP_ATOMIC); 865 + if (work) { 866 + *work = *base_work; 867 + work->nr_pages = nr_pages; 868 + work->auto_free = 1; 869 + wb_queue_work(wb, work); 870 + continue; 799 871 } 872 + 873 + /* alloc failed, execute synchronously using on-stack fallback */ 874 + work = &fallback_work; 875 + *work = *base_work; 876 + work->nr_pages = nr_pages; 877 + work->auto_free = 0; 878 + work->done = &fallback_work_done; 879 + 880 + wb_queue_work(wb, work); 881 + 882 + next_memcg_id = wb->memcg_css->id + 1; 883 + rcu_read_unlock(); 884 + wb_wait_for_completion(bdi, &fallback_work_done); 885 + goto restart; 800 886 } 801 887 rcu_read_unlock(); 802 888 } ··· 860 902 if (bdi_has_dirty_io(bdi) && 861 903 (!skip_if_busy || !writeback_in_progress(&bdi->wb))) { 862 904 base_work->auto_free = 0; 863 - base_work->single_wait = 0; 864 - base_work->single_done = 0; 865 905 wb_queue_work(&bdi->wb, base_work); 866 906 } 867 907 } ··· 1750 1794 set_bit(WB_writeback_running, &wb->state); 1751 1795 while ((work = get_next_work_item(wb)) != NULL) { 1752 1796 struct wb_completion *done = work->done; 1753 - bool need_wake_up = false; 1754 1797 1755 1798 trace_writeback_exec(wb->bdi, work); 1756 1799 1757 1800 wrote += wb_writeback(wb, work); 1758 1801 1759 - if (work->single_wait) { 1760 - WARN_ON_ONCE(work->auto_free); 1761 - /* paired w/ rmb in wb_wait_for_single_work() */ 1762 - smp_wmb(); 1763 - work->single_done = 1; 1764 - need_wake_up = true; 1765 - } else if (work->auto_free) { 1802 + if (work->auto_free) 1766 1803 kfree(work); 1767 - } 1768 - 1769 1804 if (done && atomic_dec_and_test(&done->cnt)) 1770 - need_wake_up = true; 1771 - 1772 - if (need_wake_up) 1773 1805 wake_up_all(&wb->bdi->wb_waitq); 1774 1806 } 1775 1807