diff options
Diffstat (limited to 'fs/fs-writeback.c')
-rw-r--r-- | fs/fs-writeback.c | 153 |
1 files changed, 84 insertions, 69 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 245c430a2e41..08f5debd07d1 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -933,33 +933,36 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi, | |||
933 | 933 | ||
934 | #endif /* CONFIG_CGROUP_WRITEBACK */ | 934 | #endif /* CONFIG_CGROUP_WRITEBACK */ |
935 | 935 | ||
936 | void wb_start_writeback(struct bdi_writeback *wb, long nr_pages, | 936 | /* |
937 | bool range_cyclic, enum wb_reason reason) | 937 | * Add in the number of potentially dirty inodes, because each inode |
938 | * write can dirty pagecache in the underlying blockdev. | ||
939 | */ | ||
940 | static unsigned long get_nr_dirty_pages(void) | ||
938 | { | 941 | { |
939 | struct wb_writeback_work *work; | 942 | return global_node_page_state(NR_FILE_DIRTY) + |
943 | global_node_page_state(NR_UNSTABLE_NFS) + | ||
944 | get_nr_dirty_inodes(); | ||
945 | } | ||
940 | 946 | ||
947 | static void wb_start_writeback(struct bdi_writeback *wb, enum wb_reason reason) | ||
948 | { | ||
941 | if (!wb_has_dirty_io(wb)) | 949 | if (!wb_has_dirty_io(wb)) |
942 | return; | 950 | return; |
943 | 951 | ||
944 | /* | 952 | /* |
945 | * This is WB_SYNC_NONE writeback, so if allocation fails just | 953 | * All callers of this function want to start writeback of all |
946 | * wakeup the thread for old dirty data writeback | 954 | * dirty pages. Places like vmscan can call this at a very |
955 | * high frequency, causing pointless allocations of tons of | ||
956 | * work items and keeping the flusher threads busy retrieving | ||
957 | * that work. Ensure that we only allow one of them pending and | ||
958 | * inflight at the time. | ||
947 | */ | 959 | */ |
948 | work = kzalloc(sizeof(*work), | 960 | if (test_bit(WB_start_all, &wb->state) || |
949 | GFP_NOWAIT | __GFP_NOMEMALLOC | __GFP_NOWARN); | 961 | test_and_set_bit(WB_start_all, &wb->state)) |
950 | if (!work) { | ||
951 | trace_writeback_nowork(wb); | ||
952 | wb_wakeup(wb); | ||
953 | return; | 962 | return; |
954 | } | ||
955 | |||
956 | work->sync_mode = WB_SYNC_NONE; | ||
957 | work->nr_pages = nr_pages; | ||
958 | work->range_cyclic = range_cyclic; | ||
959 | work->reason = reason; | ||
960 | work->auto_free = 1; | ||
961 | 963 | ||
962 | wb_queue_work(wb, work); | 964 | wb->start_all_reason = reason; |
965 | wb_wakeup(wb); | ||
963 | } | 966 | } |
964 | 967 | ||
965 | /** | 968 | /** |
@@ -1814,17 +1817,6 @@ static struct wb_writeback_work *get_next_work_item(struct bdi_writeback *wb) | |||
1814 | return work; | 1817 | return work; |
1815 | } | 1818 | } |
1816 | 1819 | ||
1817 | /* | ||
1818 | * Add in the number of potentially dirty inodes, because each inode | ||
1819 | * write can dirty pagecache in the underlying blockdev. | ||
1820 | */ | ||
1821 | static unsigned long get_nr_dirty_pages(void) | ||
1822 | { | ||
1823 | return global_node_page_state(NR_FILE_DIRTY) + | ||
1824 | global_node_page_state(NR_UNSTABLE_NFS) + | ||
1825 | get_nr_dirty_inodes(); | ||
1826 | } | ||
1827 | |||
1828 | static long wb_check_background_flush(struct bdi_writeback *wb) | 1820 | static long wb_check_background_flush(struct bdi_writeback *wb) |
1829 | { | 1821 | { |
1830 | if (wb_over_bg_thresh(wb)) { | 1822 | if (wb_over_bg_thresh(wb)) { |
@@ -1877,6 +1869,30 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb) | |||
1877 | return 0; | 1869 | return 0; |
1878 | } | 1870 | } |
1879 | 1871 | ||
1872 | static long wb_check_start_all(struct bdi_writeback *wb) | ||
1873 | { | ||
1874 | long nr_pages; | ||
1875 | |||
1876 | if (!test_bit(WB_start_all, &wb->state)) | ||
1877 | return 0; | ||
1878 | |||
1879 | nr_pages = get_nr_dirty_pages(); | ||
1880 | if (nr_pages) { | ||
1881 | struct wb_writeback_work work = { | ||
1882 | .nr_pages = wb_split_bdi_pages(wb, nr_pages), | ||
1883 | .sync_mode = WB_SYNC_NONE, | ||
1884 | .range_cyclic = 1, | ||
1885 | .reason = wb->start_all_reason, | ||
1886 | }; | ||
1887 | |||
1888 | nr_pages = wb_writeback(wb, &work); | ||
1889 | } | ||
1890 | |||
1891 | clear_bit(WB_start_all, &wb->state); | ||
1892 | return nr_pages; | ||
1893 | } | ||
1894 | |||
1895 | |||
1880 | /* | 1896 | /* |
1881 | * Retrieve work items and do the writeback they describe | 1897 | * Retrieve work items and do the writeback they describe |
1882 | */ | 1898 | */ |
@@ -1893,6 +1909,11 @@ static long wb_do_writeback(struct bdi_writeback *wb) | |||
1893 | } | 1909 | } |
1894 | 1910 | ||
1895 | /* | 1911 | /* |
1912 | * Check for a flush-everything request | ||
1913 | */ | ||
1914 | wrote += wb_check_start_all(wb); | ||
1915 | |||
1916 | /* | ||
1896 | * Check for periodic writeback, kupdated() style | 1917 | * Check for periodic writeback, kupdated() style |
1897 | */ | 1918 | */ |
1898 | wrote += wb_check_old_data_flush(wb); | 1919 | wrote += wb_check_old_data_flush(wb); |
@@ -1947,10 +1968,33 @@ void wb_workfn(struct work_struct *work) | |||
1947 | } | 1968 | } |
1948 | 1969 | ||
1949 | /* | 1970 | /* |
1950 | * Start writeback of `nr_pages' pages. If `nr_pages' is zero, write back | 1971 | * Start writeback of `nr_pages' pages on this bdi. If `nr_pages' is zero, |
1951 | * the whole world. | 1972 | * write back the whole world. |
1952 | */ | 1973 | */ |
1953 | void wakeup_flusher_threads(long nr_pages, enum wb_reason reason) | 1974 | static void __wakeup_flusher_threads_bdi(struct backing_dev_info *bdi, |
1975 | enum wb_reason reason) | ||
1976 | { | ||
1977 | struct bdi_writeback *wb; | ||
1978 | |||
1979 | if (!bdi_has_dirty_io(bdi)) | ||
1980 | return; | ||
1981 | |||
1982 | list_for_each_entry_rcu(wb, &bdi->wb_list, bdi_node) | ||
1983 | wb_start_writeback(wb, reason); | ||
1984 | } | ||
1985 | |||
1986 | void wakeup_flusher_threads_bdi(struct backing_dev_info *bdi, | ||
1987 | enum wb_reason reason) | ||
1988 | { | ||
1989 | rcu_read_lock(); | ||
1990 | __wakeup_flusher_threads_bdi(bdi, reason); | ||
1991 | rcu_read_unlock(); | ||
1992 | } | ||
1993 | |||
1994 | /* | ||
1995 | * Wakeup the flusher threads to start writeback of all currently dirty pages | ||
1996 | */ | ||
1997 | void wakeup_flusher_threads(enum wb_reason reason) | ||
1954 | { | 1998 | { |
1955 | struct backing_dev_info *bdi; | 1999 | struct backing_dev_info *bdi; |
1956 | 2000 | ||
@@ -1960,20 +2004,9 @@ void wakeup_flusher_threads(long nr_pages, enum wb_reason reason) | |||
1960 | if (blk_needs_flush_plug(current)) | 2004 | if (blk_needs_flush_plug(current)) |
1961 | blk_schedule_flush_plug(current); | 2005 | blk_schedule_flush_plug(current); |
1962 | 2006 | ||
1963 | if (!nr_pages) | ||
1964 | nr_pages = get_nr_dirty_pages(); | ||
1965 | |||
1966 | rcu_read_lock(); | 2007 | rcu_read_lock(); |
1967 | list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) { | 2008 | list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) |
1968 | struct bdi_writeback *wb; | 2009 | __wakeup_flusher_threads_bdi(bdi, reason); |
1969 | |||
1970 | if (!bdi_has_dirty_io(bdi)) | ||
1971 | continue; | ||
1972 | |||
1973 | list_for_each_entry_rcu(wb, &bdi->wb_list, bdi_node) | ||
1974 | wb_start_writeback(wb, wb_split_bdi_pages(wb, nr_pages), | ||
1975 | false, reason); | ||
1976 | } | ||
1977 | rcu_read_unlock(); | 2010 | rcu_read_unlock(); |
1978 | } | 2011 | } |
1979 | 2012 | ||
@@ -2343,37 +2376,19 @@ void writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) | |||
2343 | EXPORT_SYMBOL(writeback_inodes_sb); | 2376 | EXPORT_SYMBOL(writeback_inodes_sb); |
2344 | 2377 | ||
2345 | /** | 2378 | /** |
2346 | * try_to_writeback_inodes_sb_nr - try to start writeback if none underway | 2379 | * try_to_writeback_inodes_sb - try to start writeback if none underway |
2347 | * @sb: the superblock | 2380 | * @sb: the superblock |
2348 | * @nr: the number of pages to write | 2381 | * @reason: reason why some writeback work was initiated |
2349 | * @reason: the reason of writeback | ||
2350 | * | 2382 | * |
2351 | * Invoke writeback_inodes_sb_nr if no writeback is currently underway. | 2383 | * Invoke __writeback_inodes_sb_nr if no writeback is currently underway. |
2352 | * Returns 1 if writeback was started, 0 if not. | ||
2353 | */ | 2384 | */ |
2354 | bool try_to_writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr, | 2385 | void try_to_writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) |
2355 | enum wb_reason reason) | ||
2356 | { | 2386 | { |
2357 | if (!down_read_trylock(&sb->s_umount)) | 2387 | if (!down_read_trylock(&sb->s_umount)) |
2358 | return false; | 2388 | return; |
2359 | 2389 | ||
2360 | __writeback_inodes_sb_nr(sb, nr, reason, true); | 2390 | __writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason, true); |
2361 | up_read(&sb->s_umount); | 2391 | up_read(&sb->s_umount); |
2362 | return true; | ||
2363 | } | ||
2364 | EXPORT_SYMBOL(try_to_writeback_inodes_sb_nr); | ||
2365 | |||
2366 | /** | ||
2367 | * try_to_writeback_inodes_sb - try to start writeback if none underway | ||
2368 | * @sb: the superblock | ||
2369 | * @reason: reason why some writeback work was initiated | ||
2370 | * | ||
2371 | * Implement by try_to_writeback_inodes_sb_nr() | ||
2372 | * Returns 1 if writeback was started, 0 if not. | ||
2373 | */ | ||
2374 | bool try_to_writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) | ||
2375 | { | ||
2376 | return try_to_writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason); | ||
2377 | } | 2392 | } |
2378 | EXPORT_SYMBOL(try_to_writeback_inodes_sb); | 2393 | EXPORT_SYMBOL(try_to_writeback_inodes_sb); |
2379 | 2394 | ||