diff mbox

[1/2] remove mapping from balance_dirty_pages*()

Message ID 1470769707-26079-2-git-send-email-jbacik@fb.com (mailing list archive)
State New, archived
Headers show

Commit Message

Josef Bacik Aug. 9, 2016, 7:08 p.m. UTC
The only reason we pass in the mapping is to get the inode in order to see if
writeback cgroups is enabled, and even then it only checks the bdi and a super
block flag.  balance_dirty_pages() doesn't even use the mapping.  Since
balance_dirty_pages*() works on a bdi level, just pass in the bdi and super
block directly so we can avoid using mapping.  This will allow us to still use
balance_dirty_pages for dirty metadata pages that are not backed by an
address_mapping.

Signed-off-by: Josef Bacik <jbacik@fb.com>
---
 fs/btrfs/disk-io.c          |  4 ++--
 fs/btrfs/file.c             |  3 ++-
 fs/btrfs/ioctl.c            |  3 ++-
 fs/btrfs/relocation.c       |  3 ++-
 fs/buffer.c                 |  3 ++-
 fs/iomap.c                  |  3 ++-
 include/linux/backing-dev.h | 23 +++++++++++++++++------
 include/linux/writeback.h   |  3 ++-
 mm/filemap.c                |  4 +++-
 mm/memory.c                 |  9 +++++++--
 mm/page-writeback.c         | 15 +++++++--------
 11 files changed, 48 insertions(+), 25 deletions(-)

Comments

kernel test robot Aug. 9, 2016, 7:30 p.m. UTC | #1
Hi Josef,

[auto build test WARNING on linus/master]
[also build test WARNING on v4.8-rc1 next-20160809]
[cannot apply to linux/master]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Josef-Bacik/Provide-accounting-for-dirty-metadata/20160810-031219
config: x86_64-randconfig-x019-201632 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   In file included from include/linux/linkage.h:4:0,
                    from include/linux/kernel.h:6,
                    from mm/page-writeback.c:14:
   mm/page-writeback.c: In function 'balance_dirty_pages_ratelimited':
   mm/page-writeback.c:1873:6: error: implicit declaration of function 'bdi_cgwb_enabled' [-Werror=implicit-function-declaration]
     if (bdi_cgwb_enabled(bdi, sb))
         ^
   include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^~~~
>> mm/page-writeback.c:1873:2: note: in expansion of macro 'if'
     if (bdi_cgwb_enabled(bdi, sb))
     ^~
   cc1: some warnings being treated as errors

vim +/if +1873 mm/page-writeback.c

  1857	 *
  1858	 * On really big machines, get_writeback_state is expensive, so try to avoid
  1859	 * calling it too often (ratelimiting).  But once we're over the dirty memory
  1860	 * limit we decrease the ratelimiting by a lot, to prevent individual processes
  1861	 * from overshooting the limit by (ratelimit_pages) each.
  1862	 */
  1863	void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
  1864					     struct super_block *sb)
  1865	{
  1866		struct bdi_writeback *wb = NULL;
  1867		int ratelimit;
  1868		int *p;
  1869	
  1870		if (!bdi_cap_account_dirty(bdi))
  1871			return;
  1872	
> 1873		if (bdi_cgwb_enabled(bdi, sb))
  1874			wb = wb_get_create_current(bdi, GFP_KERNEL);
  1875		if (!wb)
  1876			wb = &bdi->wb;
  1877	
  1878		ratelimit = current->nr_dirtied_pause;
  1879		if (wb->dirty_exceeded)
  1880			ratelimit = min(ratelimit, 32 >> (PAGE_SHIFT - 10));
  1881	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Aug. 9, 2016, 7:32 p.m. UTC | #2
Hi Josef,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.8-rc1 next-20160809]
[cannot apply to linux/master]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Josef-Bacik/Provide-accounting-for-dirty-metadata/20160810-031219
config: x86_64-randconfig-x013-201632 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   mm/page-writeback.c: In function 'balance_dirty_pages_ratelimited':
>> mm/page-writeback.c:1873:6: error: implicit declaration of function 'bdi_cgwb_enabled' [-Werror=implicit-function-declaration]
     if (bdi_cgwb_enabled(bdi, sb))
         ^~~~~~~~~~~~~~~~
   Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size
   Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:set_bit
   Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:clear_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:test_and_set_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:test_and_set_bit_lock
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:test_and_clear_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:constant_test_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:variable_test_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls64
   Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u64
   Cyclomatic Complexity 1 arch/x86/include/asm/current.h:get_current
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:atomic_inc
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:atomic_dec_and_test
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic64_64.h:atomic64_read
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic64_64.h:atomic64_inc
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic64_64.h:atomic64_dec
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic64_64.h:atomic64_add_return
   Cyclomatic Complexity 1 include/asm-generic/atomic-long.h:atomic_long_read
   Cyclomatic Complexity 1 include/asm-generic/atomic-long.h:atomic_long_add_return
   Cyclomatic Complexity 1 include/asm-generic/atomic-long.h:atomic_long_inc
   Cyclomatic Complexity 1 include/asm-generic/atomic-long.h:atomic_long_dec
   Cyclomatic Complexity 2 arch/x86/include/asm/jump_label.h:arch_static_branch
   Cyclomatic Complexity 1 include/linux/jump_label.h:static_key_false
   Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_save_flags
   Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_restore
   Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_disable
   Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_irq_save
   Cyclomatic Complexity 1 include/linux/math64.h:div_u64_rem
   Cyclomatic Complexity 1 include/linux/math64.h:div64_u64
   Cyclomatic Complexity 1 include/linux/math64.h:div64_s64
   Cyclomatic Complexity 1 include/linux/math64.h:div_u64
   Cyclomatic Complexity 1 arch/x86/include/asm/irqflags.h:arch_irqs_disabled_flags
   Cyclomatic Complexity 2 include/linux/thread_info.h:test_ti_thread_flag
   Cyclomatic Complexity 5 arch/x86/include/asm/preempt.h:__preempt_count_add
   Cyclomatic Complexity 5 arch/x86/include/asm/preempt.h:__preempt_count_sub
   Cyclomatic Complexity 1 include/linux/spinlock.h:spinlock_check
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_lock
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_lock_bh
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_lock_irq
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock_bh
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock_irq
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock_irqrestore
   Cyclomatic Complexity 1 include/linux/rcupdate.h:rcu_read_lock_sched_notrace
   Cyclomatic Complexity 1 include/linux/rcupdate.h:rcu_read_unlock_sched_notrace
   Cyclomatic Complexity 1 include/linux/mmzone.h:populated_zone
   Cyclomatic Complexity 1 include/linux/percpu_counter.h:percpu_counter_add
   Cyclomatic Complexity 1 include/linux/percpu_counter.h:__percpu_counter_add
   Cyclomatic Complexity 1 include/linux/percpu_counter.h:percpu_counter_read
   Cyclomatic Complexity 1 include/linux/percpu_counter.h:percpu_counter_read_positive
   Cyclomatic Complexity 1 include/linux/percpu_counter.h:percpu_counter_sum_positive
   Cyclomatic Complexity 3 include/linux/page-flags.h:compound_head
   Cyclomatic Complexity 1 include/linux/page-flags.h:PageLocked
   Cyclomatic Complexity 1 include/linux/page-flags.h:PageError
   Cyclomatic Complexity 1 include/linux/page-flags.h:PageDirty
   Cyclomatic Complexity 1 include/linux/page-flags.h:ClearPageDirty
   Cyclomatic Complexity 1 include/linux/page-flags.h:TestSetPageDirty
   Cyclomatic Complexity 1 include/linux/page-flags.h:TestClearPageDirty
   Cyclomatic Complexity 1 include/linux/page-flags.h:PagePrivate
   Cyclomatic Complexity 1 include/linux/page-flags.h:PageWriteback
   Cyclomatic Complexity 1 include/linux/page-flags.h:TestSetPageWriteback
   Cyclomatic Complexity 1 include/linux/page-flags.h:TestClearPageWriteback
   Cyclomatic Complexity 1 include/linux/page-flags.h:PageReclaim
   Cyclomatic Complexity 1 include/linux/page-flags.h:ClearPageReclaim
   Cyclomatic Complexity 1 include/linux/page-flags.h:PageSwapCache
   Cyclomatic Complexity 2 include/linux/page-flags.h:PageUptodate
   Cyclomatic Complexity 2 include/linux/page_ref.h:page_ref_inc
   Cyclomatic Complexity 2 include/linux/page_ref.h:page_ref_dec_and_test
   Cyclomatic Complexity 1 include/linux/mm.h:put_page_testzero
   Cyclomatic Complexity 1 include/linux/mm.h:page_zonenum
   Cyclomatic Complexity 1 include/linux/mm.h:get_zone_device_page
   Cyclomatic Complexity 1 include/linux/mm.h:put_zone_device_page
   Cyclomatic Complexity 1 include/linux/mm.h:is_zone_device_page
   Cyclomatic Complexity 2 include/linux/mm.h:get_page
   Cyclomatic Complexity 3 include/linux/mm.h:put_page
   Cyclomatic Complexity 1 include/linux/mm.h:page_zone
   Cyclomatic Complexity 1 include/linux/mm.h:page_pgdat
   Cyclomatic Complexity 1 include/linux/vmstat.h:global_page_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:global_node_page_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:zone_page_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:__inc_zone_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:__inc_node_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:__dec_zone_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:__dec_node_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:__inc_zone_page_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:__inc_node_page_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:__dec_zone_page_state
   Cyclomatic Complexity 1 include/linux/vmstat.h:__dec_node_page_state
   Cyclomatic Complexity 2 include/linux/mm.h:page_index
   Cyclomatic Complexity 1 include/linux/signal.h:sigismember
   Cyclomatic Complexity 1 include/linux/sched.h:test_tsk_thread_flag
   Cyclomatic Complexity 1 include/linux/sched.h:signal_pending
   Cyclomatic Complexity 1 include/linux/sched.h:__fatal_signal_pending
   Cyclomatic Complexity 3 include/linux/sched.h:fatal_signal_pending
   Cyclomatic Complexity 1 include/linux/backing-dev-defs.h:wb_put
   Cyclomatic Complexity 1 include/linux/writeback.h:inode_attach_wb
   Cyclomatic Complexity 1 include/linux/memcontrol.h:lock_page_memcg
   Cyclomatic Complexity 1 include/linux/memcontrol.h:unlock_page_memcg

vim +/bdi_cgwb_enabled +1873 mm/page-writeback.c

  1867		int ratelimit;
  1868		int *p;
  1869	
  1870		if (!bdi_cap_account_dirty(bdi))
  1871			return;
  1872	
> 1873		if (bdi_cgwb_enabled(bdi, sb))
  1874			wb = wb_get_create_current(bdi, GFP_KERNEL);
  1875		if (!wb)
  1876			wb = &bdi->wb;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Aug. 9, 2016, 8:12 p.m. UTC | #3
Hi Josef,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.8-rc1 next-20160809]
[cannot apply to linux/master]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Josef-Bacik/Provide-accounting-for-dirty-metadata/20160810-031219
config: x86_64-randconfig-s3-08100114 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   fs/ntfs/attrib.c: In function 'ntfs_attr_set':
>> fs/ntfs/attrib.c:2548:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> fs/ntfs/attrib.c:2548:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/attrib.c:2589:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/attrib.c:2589:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/attrib.c:2606:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/attrib.c:2606:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   fs/ntfs/file.c: In function 'ntfs_attr_extend_initialized':
>> fs/ntfs/file.c:279:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from fs/ntfs/file.c:22:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> fs/ntfs/file.c:279:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from fs/ntfs/file.c:22:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/file.c: In function 'ntfs_perform_write':
   fs/ntfs/file.c:1917:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from fs/ntfs/file.c:22:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/file.c:1917:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from fs/ntfs/file.c:22:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/balance_dirty_pages_ratelimited +2548 fs/ntfs/attrib.c

a3ac1414 Cong Wang          2011-11-25  2542  		kaddr = kmap_atomic(page);
^1da177e Linus Torvalds     2005-04-16  2543  		memset(kaddr + start_ofs, val, size - start_ofs);
^1da177e Linus Torvalds     2005-04-16  2544  		flush_dcache_page(page);
a3ac1414 Cong Wang          2011-11-25  2545  		kunmap_atomic(kaddr);
^1da177e Linus Torvalds     2005-04-16  2546  		set_page_dirty(page);
09cbfeaf Kirill A. Shutemov 2016-04-01  2547  		put_page(page);
bfab36e8 Anton Altaparmakov 2007-10-12 @2548  		balance_dirty_pages_ratelimited(mapping);
bfab36e8 Anton Altaparmakov 2007-10-12  2549  		cond_resched();
^1da177e Linus Torvalds     2005-04-16  2550  		if (idx == end)
^1da177e Linus Torvalds     2005-04-16  2551  			goto done;

:::::: The code at line 2548 was first introduced by commit
:::::: bfab36e81611e60573b84eb4e4b4c8d8545b2320 NTFS: Fix a mount time deadlock.

:::::: TO: Anton Altaparmakov <aia21@cam.ac.uk>
:::::: CC: Linus Torvalds <torvalds@woody.linux-foundation.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Aug. 9, 2016, 8:50 p.m. UTC | #4
Hi Josef,

[auto build test WARNING on linus/master]
[also build test WARNING on v4.8-rc1 next-20160809]
[cannot apply to linux/master]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Josef-Bacik/Provide-accounting-for-dirty-metadata/20160810-031219
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   include/linux/compiler.h:230:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> drivers/mtd/devices/block2mtd.c:74:64: sparse: not enough arguments for function balance_dirty_pages_ratelimited
   drivers/mtd/devices/block2mtd.c:165:56: sparse: not enough arguments for function balance_dirty_pages_ratelimited
   drivers/mtd/devices/block2mtd.c: In function '_block2mtd_erase':
   drivers/mtd/devices/block2mtd.c:74:37: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
        balance_dirty_pages_ratelimited(mapping);
                                        ^~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from drivers/mtd/devices/block2mtd.c:23:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mtd/devices/block2mtd.c:74:5: error: too few arguments to function 'balance_dirty_pages_ratelimited'
        balance_dirty_pages_ratelimited(mapping);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from drivers/mtd/devices/block2mtd.c:23:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mtd/devices/block2mtd.c: In function '_block2mtd_write':
   drivers/mtd/devices/block2mtd.c:165:36: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
       balance_dirty_pages_ratelimited(mapping);
                                       ^~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from drivers/mtd/devices/block2mtd.c:23:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mtd/devices/block2mtd.c:165:4: error: too few arguments to function 'balance_dirty_pages_ratelimited'
       balance_dirty_pages_ratelimited(mapping);
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from drivers/mtd/devices/block2mtd.c:23:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   include/linux/compiler.h:230:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> fs/ntfs/attrib.c:2548:48: sparse: not enough arguments for function balance_dirty_pages_ratelimited
   fs/ntfs/attrib.c:2589:48: sparse: not enough arguments for function balance_dirty_pages_ratelimited
   fs/ntfs/attrib.c:2606:48: sparse: not enough arguments for function balance_dirty_pages_ratelimited
   fs/ntfs/attrib.c: In function 'ntfs_attr_set':
   fs/ntfs/attrib.c:2548:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/attrib.c:2548:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/attrib.c:2589:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/attrib.c:2589:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/attrib.c:2606:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/attrib.c:2606:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/memcontrol.h:30:0,
                    from include/linux/swap.h:8,
                    from fs/ntfs/attrib.c:26:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   include/linux/compiler.h:230:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> fs/ntfs/file.c:279:48: sparse: not enough arguments for function balance_dirty_pages_ratelimited
   fs/ntfs/file.c:1917:48: sparse: not enough arguments for function balance_dirty_pages_ratelimited
   fs/ntfs/file.c: In function 'ntfs_attr_extend_initialized':
   fs/ntfs/file.c:279:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from fs/ntfs/file.c:22:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/file.c:279:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from fs/ntfs/file.c:22:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/file.c: In function 'ntfs_perform_write':
   fs/ntfs/file.c:1917:35: error: passing argument 1 of 'balance_dirty_pages_ratelimited' from incompatible pointer type [-Werror=incompatible-pointer-types]
      balance_dirty_pages_ratelimited(mapping);
                                      ^~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from fs/ntfs/file.c:22:
   include/linux/writeback.h:367:6: note: expected 'struct backing_dev_info *' but argument is of type 'struct address_space *'
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/ntfs/file.c:1917:3: error: too few arguments to function 'balance_dirty_pages_ratelimited'
      balance_dirty_pages_ratelimited(mapping);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/backing-dev.h:15:0,
                    from fs/ntfs/file.c:22:
   include/linux/writeback.h:367:6: note: declared here
    void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +74 drivers/mtd/devices/block2mtd.c

^1da177e Linus Torvalds     2005-04-16  58  	int pages = len >> PAGE_SHIFT;
^1da177e Linus Torvalds     2005-04-16  59  	u_long *p;
^1da177e Linus Torvalds     2005-04-16  60  	u_long *max;
^1da177e Linus Torvalds     2005-04-16  61  
^1da177e Linus Torvalds     2005-04-16  62  	while (pages) {
21d31f1f Joern Engel        2007-02-20  63  		page = page_read(mapping, index);
^1da177e Linus Torvalds     2005-04-16  64  		if (IS_ERR(page))
^1da177e Linus Torvalds     2005-04-16  65  			return PTR_ERR(page);
^1da177e Linus Torvalds     2005-04-16  66  
0ffb74cc Joern Engel        2007-02-20  67  		max = page_address(page) + PAGE_SIZE;
0ffb74cc Joern Engel        2007-02-20  68  		for (p=page_address(page); p<max; p++)
^1da177e Linus Torvalds     2005-04-16  69  			if (*p != -1UL) {
^1da177e Linus Torvalds     2005-04-16  70  				lock_page(page);
^1da177e Linus Torvalds     2005-04-16  71  				memset(page_address(page), 0xff, PAGE_SIZE);
^1da177e Linus Torvalds     2005-04-16  72  				set_page_dirty(page);
^1da177e Linus Torvalds     2005-04-16  73  				unlock_page(page);
031da73f NeilBrown          2012-12-12 @74  				balance_dirty_pages_ratelimited(mapping);
^1da177e Linus Torvalds     2005-04-16  75  				break;
^1da177e Linus Torvalds     2005-04-16  76  			}
^1da177e Linus Torvalds     2005-04-16  77  
09cbfeaf Kirill A. Shutemov 2016-04-01  78  		put_page(page);
^1da177e Linus Torvalds     2005-04-16  79  		pages--;
^1da177e Linus Torvalds     2005-04-16  80  		index++;
^1da177e Linus Torvalds     2005-04-16  81  	}
^1da177e Linus Torvalds     2005-04-16  82  	return 0;

:::::: The code at line 74 was first introduced by commit
:::::: 031da73fca29ebba3eea5a512746e01d52e542cd mtd: block2mtd: throttle writes by calling balance_dirty_pages_ratelimited.

:::::: TO: NeilBrown <neilb@suse.de>
:::::: CC: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jan Kara Aug. 10, 2016, 8:27 a.m. UTC | #5
On Tue 09-08-16 15:08:26, Josef Bacik wrote:
> The only reason we pass in the mapping is to get the inode in order to see if
> writeback cgroups is enabled, and even then it only checks the bdi and a super
> block flag.  balance_dirty_pages() doesn't even use the mapping.  Since
> balance_dirty_pages*() works on a bdi level, just pass in the bdi and super
> block directly so we can avoid using mapping.  This will allow us to still use
> balance_dirty_pages for dirty metadata pages that are not backed by an
> address_mapping.
>
> Signed-off-by: Josef Bacik <jbacik@fb.com>

The patch looks good. You can add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/btrfs/disk-io.c          |  4 ++--
>  fs/btrfs/file.c             |  3 ++-
>  fs/btrfs/ioctl.c            |  3 ++-
>  fs/btrfs/relocation.c       |  3 ++-
>  fs/buffer.c                 |  3 ++-
>  fs/iomap.c                  |  3 ++-
>  include/linux/backing-dev.h | 23 +++++++++++++++++------
>  include/linux/writeback.h   |  3 ++-
>  mm/filemap.c                |  4 +++-
>  mm/memory.c                 |  9 +++++++--
>  mm/page-writeback.c         | 15 +++++++--------
>  11 files changed, 48 insertions(+), 25 deletions(-)
> 
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 17346f7..c1d951a 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -4024,8 +4024,8 @@ static void __btrfs_btree_balance_dirty(struct btrfs_root *root,
>  	ret = percpu_counter_compare(&root->fs_info->dirty_metadata_bytes,
>  				     BTRFS_DIRTY_METADATA_THRESH);
>  	if (ret > 0) {
> -		balance_dirty_pages_ratelimited(
> -				   root->fs_info->btree_inode->i_mapping);
> +		balance_dirty_pages_ratelimited(&root->fs_info->bdi,
> +						root->fs_info->sb);
>  	}
>  }
>  
> diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> index 9404121..f060b08 100644
> --- a/fs/btrfs/file.c
> +++ b/fs/btrfs/file.c
> @@ -1686,7 +1686,8 @@ again:
>  
>  		cond_resched();
>  
> -		balance_dirty_pages_ratelimited(inode->i_mapping);
> +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> +						inode->i_sb);
>  		if (dirty_pages < (root->nodesize >> PAGE_SHIFT) + 1)
>  			btrfs_btree_balance_dirty(root);
>  
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 14ed1e9..a222bad 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -1410,7 +1410,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
>  		}
>  
>  		defrag_count += ret;
> -		balance_dirty_pages_ratelimited(inode->i_mapping);
> +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> +						inode->i_sb);
>  		inode_unlock(inode);
>  
>  		if (newer_than) {
> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> index 4598e29..7fc6ea7 100644
> --- a/fs/btrfs/relocation.c
> +++ b/fs/btrfs/relocation.c
> @@ -3202,7 +3202,8 @@ static int relocate_file_extent_cluster(struct inode *inode,
>  		put_page(page);
>  
>  		index++;
> -		balance_dirty_pages_ratelimited(inode->i_mapping);
> +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> +						inode->i_sb);
>  		btrfs_throttle(BTRFS_I(inode)->root);
>  	}
>  	WARN_ON(nr != cluster->nr);
> diff --git a/fs/buffer.c b/fs/buffer.c
> index 9c8eb9b..9bbe30d 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -2386,7 +2386,8 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
>  		BUG_ON(err != len);
>  		err = 0;
>  
> -		balance_dirty_pages_ratelimited(mapping);
> +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> +						inode->i_sb);
>  
>  		if (unlikely(fatal_signal_pending(current))) {
>  			err = -EINTR;
> diff --git a/fs/iomap.c b/fs/iomap.c
> index 48141b8..937e266 100644
> --- a/fs/iomap.c
> +++ b/fs/iomap.c
> @@ -226,7 +226,8 @@ again:
>  		written += copied;
>  		length -= copied;
>  
> -		balance_dirty_pages_ratelimited(inode->i_mapping);
> +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> +						inode->i_sb);
>  	} while (iov_iter_count(i) && length);
>  
>  	return written ? written : status;
> diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
> index 491a917..3b76eeb 100644
> --- a/include/linux/backing-dev.h
> +++ b/include/linux/backing-dev.h
> @@ -252,8 +252,9 @@ void wb_blkcg_offline(struct blkcg *blkcg);
>  int inode_congested(struct inode *inode, int cong_bits);
>  
>  /**
> - * inode_cgwb_enabled - test whether cgroup writeback is enabled on an inode
> - * @inode: inode of interest
> + * bdi_cgwb_enabled - test wether cgroup writeback is enabled on a filesystem
> + * @bdi: the bdi we care about
> + * @sb: the super for the bdi
>   *
>   * cgroup writeback requires support from both the bdi and filesystem.
>   * Also, both memcg and iocg have to be on the default hierarchy.  Test
> @@ -262,15 +263,25 @@ int inode_congested(struct inode *inode, int cong_bits);
>   * Note that the test result may change dynamically on the same inode
>   * depending on how memcg and iocg are configured.
>   */
> -static inline bool inode_cgwb_enabled(struct inode *inode)
> +static inline bool bdi_cgwb_enabled(struct backing_dev_info *bdi,
> +				    struct super_block *sb)
>  {
> -	struct backing_dev_info *bdi = inode_to_bdi(inode);
> -
>  	return cgroup_subsys_on_dfl(memory_cgrp_subsys) &&
>  		cgroup_subsys_on_dfl(io_cgrp_subsys) &&
>  		bdi_cap_account_dirty(bdi) &&
>  		(bdi->capabilities & BDI_CAP_CGROUP_WRITEBACK) &&
> -		(inode->i_sb->s_iflags & SB_I_CGROUPWB);
> +		(sb->s_iflags & SB_I_CGROUPWB);
> +}
> +
> +/**
> + * inode_cgwb_enabled - test whether cgroup writeback is enabled on an inode
> + * @inode: inode of interest
> + *
> + * Does the inode have cgroup writeback support.
> + */
> +static inline bool inode_cgwb_enabled(struct inode *inode)
> +{
> +	return bdi_cgwb_enabled(inode_to_bdi(inode), inode->i_sb);
>  }
>  
>  /**
> diff --git a/include/linux/writeback.h b/include/linux/writeback.h
> index fc1e16c..256ffc3 100644
> --- a/include/linux/writeback.h
> +++ b/include/linux/writeback.h
> @@ -364,7 +364,8 @@ unsigned long wb_calc_thresh(struct bdi_writeback *wb, unsigned long thresh);
>  
>  void wb_update_bandwidth(struct bdi_writeback *wb, unsigned long start_time);
>  void page_writeback_init(void);
> -void balance_dirty_pages_ratelimited(struct address_space *mapping);
> +void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
> +				     struct super_block *sb);
>  bool wb_over_bg_thresh(struct bdi_writeback *wb);
>  
>  typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc,
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 3083ded..abb0e98 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -2667,6 +2667,7 @@ ssize_t generic_perform_write(struct file *file,
>  				struct iov_iter *i, loff_t pos)
>  {
>  	struct address_space *mapping = file->f_mapping;
> +	struct inode *inode = mapping->host;
>  	const struct address_space_operations *a_ops = mapping->a_ops;
>  	long status = 0;
>  	ssize_t written = 0;
> @@ -2746,7 +2747,8 @@ again:
>  		pos += copied;
>  		written += copied;
>  
> -		balance_dirty_pages_ratelimited(mapping);
> +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> +						inode->i_sb);
>  	} while (iov_iter_count(i));
>  
>  	return written ? written : status;
> diff --git a/mm/memory.c b/mm/memory.c
> index 83be99d..d43e73b 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -64,6 +64,7 @@
>  #include <linux/debugfs.h>
>  #include <linux/userfaultfd_k.h>
>  #include <linux/dax.h>
> +#include <linux/backing-dev.h>
>  
>  #include <asm/io.h>
>  #include <asm/mmu_context.h>
> @@ -2105,11 +2106,13 @@ static inline int wp_page_reuse(struct fault_env *fe, pte_t orig_pte,
>  		put_page(page);
>  
>  		if ((dirtied || page_mkwrite) && mapping) {
> +			struct inode *inode = mapping->host;
>  			/*
>  			 * Some device drivers do not set page.mapping
>  			 * but still dirty their pages
>  			 */
> -			balance_dirty_pages_ratelimited(mapping);
> +			balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> +							inode->i_sb);
>  		}
>  
>  		if (!page_mkwrite)
> @@ -3291,11 +3294,13 @@ static int do_shared_fault(struct fault_env *fe, pgoff_t pgoff)
>  	mapping = page_rmapping(fault_page);
>  	unlock_page(fault_page);
>  	if ((dirtied || vma->vm_ops->page_mkwrite) && mapping) {
> +		struct inode *inode = mapping->host;
>  		/*
>  		 * Some device drivers do not set page.mapping but still
>  		 * dirty their pages
>  		 */
> -		balance_dirty_pages_ratelimited(mapping);
> +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> +						inode->i_sb);
>  	}
>  
>  	if (!vma->vm_ops->page_mkwrite)
> diff --git a/mm/page-writeback.c b/mm/page-writeback.c
> index f4cd7d8..121a6e3 100644
> --- a/mm/page-writeback.c
> +++ b/mm/page-writeback.c
> @@ -1559,8 +1559,7 @@ static inline void wb_dirty_limits(struct dirty_throttle_control *dtc)
>   * If we're over `background_thresh' then the writeback threads are woken to
>   * perform some writeout.
>   */
> -static void balance_dirty_pages(struct address_space *mapping,
> -				struct bdi_writeback *wb,
> +static void balance_dirty_pages(struct bdi_writeback *wb,
>  				unsigned long pages_dirtied)
>  {
>  	struct dirty_throttle_control gdtc_stor = { GDTC_INIT(wb) };
> @@ -1849,7 +1848,8 @@ DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0;
>  
>  /**
>   * balance_dirty_pages_ratelimited - balance dirty memory state
> - * @mapping: address_space which was dirtied
> + * @bdi: the bdi that was dirtied
> + * @sb: the super block that was dirtied
>   *
>   * Processes which are dirtying memory should call in here once for each page
>   * which was newly dirtied.  The function will periodically check the system's
> @@ -1860,10 +1860,9 @@ DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0;
>   * limit we decrease the ratelimiting by a lot, to prevent individual processes
>   * from overshooting the limit by (ratelimit_pages) each.
>   */
> -void balance_dirty_pages_ratelimited(struct address_space *mapping)
> +void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
> +				     struct super_block *sb)
>  {
> -	struct inode *inode = mapping->host;
> -	struct backing_dev_info *bdi = inode_to_bdi(inode);
>  	struct bdi_writeback *wb = NULL;
>  	int ratelimit;
>  	int *p;
> @@ -1871,7 +1870,7 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping)
>  	if (!bdi_cap_account_dirty(bdi))
>  		return;
>  
> -	if (inode_cgwb_enabled(inode))
> +	if (bdi_cgwb_enabled(bdi, sb))
>  		wb = wb_get_create_current(bdi, GFP_KERNEL);
>  	if (!wb)
>  		wb = &bdi->wb;
> @@ -1909,7 +1908,7 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping)
>  	preempt_enable();
>  
>  	if (unlikely(current->nr_dirtied >= ratelimit))
> -		balance_dirty_pages(mapping, wb, current->nr_dirtied);
> +		balance_dirty_pages(wb, current->nr_dirtied);
>  
>  	wb_put(wb);
>  }
> -- 
> 1.8.3.1
> 
>
Jan Kara Aug. 10, 2016, 8:29 a.m. UTC | #6
On Wed 10-08-16 10:27:33, Jan Kara wrote:
> On Tue 09-08-16 15:08:26, Josef Bacik wrote:
> > The only reason we pass in the mapping is to get the inode in order to see if
> > writeback cgroups is enabled, and even then it only checks the bdi and a super
> > block flag.  balance_dirty_pages() doesn't even use the mapping.  Since
> > balance_dirty_pages*() works on a bdi level, just pass in the bdi and super
> > block directly so we can avoid using mapping.  This will allow us to still use
> > balance_dirty_pages for dirty metadata pages that are not backed by an
> > address_mapping.
> >
> > Signed-off-by: Josef Bacik <jbacik@fb.com>
> 
> The patch looks good. You can add:
> 
> Reviewed-by: Jan Kara <jack@suse.cz>

Well, modulo those build failures which obviously need to be sorted out...
But they should be trivial to deal with.

								Honza

> > ---
> >  fs/btrfs/disk-io.c          |  4 ++--
> >  fs/btrfs/file.c             |  3 ++-
> >  fs/btrfs/ioctl.c            |  3 ++-
> >  fs/btrfs/relocation.c       |  3 ++-
> >  fs/buffer.c                 |  3 ++-
> >  fs/iomap.c                  |  3 ++-
> >  include/linux/backing-dev.h | 23 +++++++++++++++++------
> >  include/linux/writeback.h   |  3 ++-
> >  mm/filemap.c                |  4 +++-
> >  mm/memory.c                 |  9 +++++++--
> >  mm/page-writeback.c         | 15 +++++++--------
> >  11 files changed, 48 insertions(+), 25 deletions(-)
> > 
> > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> > index 17346f7..c1d951a 100644
> > --- a/fs/btrfs/disk-io.c
> > +++ b/fs/btrfs/disk-io.c
> > @@ -4024,8 +4024,8 @@ static void __btrfs_btree_balance_dirty(struct btrfs_root *root,
> >  	ret = percpu_counter_compare(&root->fs_info->dirty_metadata_bytes,
> >  				     BTRFS_DIRTY_METADATA_THRESH);
> >  	if (ret > 0) {
> > -		balance_dirty_pages_ratelimited(
> > -				   root->fs_info->btree_inode->i_mapping);
> > +		balance_dirty_pages_ratelimited(&root->fs_info->bdi,
> > +						root->fs_info->sb);
> >  	}
> >  }
> >  
> > diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> > index 9404121..f060b08 100644
> > --- a/fs/btrfs/file.c
> > +++ b/fs/btrfs/file.c
> > @@ -1686,7 +1686,8 @@ again:
> >  
> >  		cond_resched();
> >  
> > -		balance_dirty_pages_ratelimited(inode->i_mapping);
> > +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> > +						inode->i_sb);
> >  		if (dirty_pages < (root->nodesize >> PAGE_SHIFT) + 1)
> >  			btrfs_btree_balance_dirty(root);
> >  
> > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> > index 14ed1e9..a222bad 100644
> > --- a/fs/btrfs/ioctl.c
> > +++ b/fs/btrfs/ioctl.c
> > @@ -1410,7 +1410,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
> >  		}
> >  
> >  		defrag_count += ret;
> > -		balance_dirty_pages_ratelimited(inode->i_mapping);
> > +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> > +						inode->i_sb);
> >  		inode_unlock(inode);
> >  
> >  		if (newer_than) {
> > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> > index 4598e29..7fc6ea7 100644
> > --- a/fs/btrfs/relocation.c
> > +++ b/fs/btrfs/relocation.c
> > @@ -3202,7 +3202,8 @@ static int relocate_file_extent_cluster(struct inode *inode,
> >  		put_page(page);
> >  
> >  		index++;
> > -		balance_dirty_pages_ratelimited(inode->i_mapping);
> > +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> > +						inode->i_sb);
> >  		btrfs_throttle(BTRFS_I(inode)->root);
> >  	}
> >  	WARN_ON(nr != cluster->nr);
> > diff --git a/fs/buffer.c b/fs/buffer.c
> > index 9c8eb9b..9bbe30d 100644
> > --- a/fs/buffer.c
> > +++ b/fs/buffer.c
> > @@ -2386,7 +2386,8 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
> >  		BUG_ON(err != len);
> >  		err = 0;
> >  
> > -		balance_dirty_pages_ratelimited(mapping);
> > +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> > +						inode->i_sb);
> >  
> >  		if (unlikely(fatal_signal_pending(current))) {
> >  			err = -EINTR;
> > diff --git a/fs/iomap.c b/fs/iomap.c
> > index 48141b8..937e266 100644
> > --- a/fs/iomap.c
> > +++ b/fs/iomap.c
> > @@ -226,7 +226,8 @@ again:
> >  		written += copied;
> >  		length -= copied;
> >  
> > -		balance_dirty_pages_ratelimited(inode->i_mapping);
> > +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> > +						inode->i_sb);
> >  	} while (iov_iter_count(i) && length);
> >  
> >  	return written ? written : status;
> > diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
> > index 491a917..3b76eeb 100644
> > --- a/include/linux/backing-dev.h
> > +++ b/include/linux/backing-dev.h
> > @@ -252,8 +252,9 @@ void wb_blkcg_offline(struct blkcg *blkcg);
> >  int inode_congested(struct inode *inode, int cong_bits);
> >  
> >  /**
> > - * inode_cgwb_enabled - test whether cgroup writeback is enabled on an inode
> > - * @inode: inode of interest
> > + * bdi_cgwb_enabled - test wether cgroup writeback is enabled on a filesystem
> > + * @bdi: the bdi we care about
> > + * @sb: the super for the bdi
> >   *
> >   * cgroup writeback requires support from both the bdi and filesystem.
> >   * Also, both memcg and iocg have to be on the default hierarchy.  Test
> > @@ -262,15 +263,25 @@ int inode_congested(struct inode *inode, int cong_bits);
> >   * Note that the test result may change dynamically on the same inode
> >   * depending on how memcg and iocg are configured.
> >   */
> > -static inline bool inode_cgwb_enabled(struct inode *inode)
> > +static inline bool bdi_cgwb_enabled(struct backing_dev_info *bdi,
> > +				    struct super_block *sb)
> >  {
> > -	struct backing_dev_info *bdi = inode_to_bdi(inode);
> > -
> >  	return cgroup_subsys_on_dfl(memory_cgrp_subsys) &&
> >  		cgroup_subsys_on_dfl(io_cgrp_subsys) &&
> >  		bdi_cap_account_dirty(bdi) &&
> >  		(bdi->capabilities & BDI_CAP_CGROUP_WRITEBACK) &&
> > -		(inode->i_sb->s_iflags & SB_I_CGROUPWB);
> > +		(sb->s_iflags & SB_I_CGROUPWB);
> > +}
> > +
> > +/**
> > + * inode_cgwb_enabled - test whether cgroup writeback is enabled on an inode
> > + * @inode: inode of interest
> > + *
> > + * Does the inode have cgroup writeback support.
> > + */
> > +static inline bool inode_cgwb_enabled(struct inode *inode)
> > +{
> > +	return bdi_cgwb_enabled(inode_to_bdi(inode), inode->i_sb);
> >  }
> >  
> >  /**
> > diff --git a/include/linux/writeback.h b/include/linux/writeback.h
> > index fc1e16c..256ffc3 100644
> > --- a/include/linux/writeback.h
> > +++ b/include/linux/writeback.h
> > @@ -364,7 +364,8 @@ unsigned long wb_calc_thresh(struct bdi_writeback *wb, unsigned long thresh);
> >  
> >  void wb_update_bandwidth(struct bdi_writeback *wb, unsigned long start_time);
> >  void page_writeback_init(void);
> > -void balance_dirty_pages_ratelimited(struct address_space *mapping);
> > +void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
> > +				     struct super_block *sb);
> >  bool wb_over_bg_thresh(struct bdi_writeback *wb);
> >  
> >  typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc,
> > diff --git a/mm/filemap.c b/mm/filemap.c
> > index 3083ded..abb0e98 100644
> > --- a/mm/filemap.c
> > +++ b/mm/filemap.c
> > @@ -2667,6 +2667,7 @@ ssize_t generic_perform_write(struct file *file,
> >  				struct iov_iter *i, loff_t pos)
> >  {
> >  	struct address_space *mapping = file->f_mapping;
> > +	struct inode *inode = mapping->host;
> >  	const struct address_space_operations *a_ops = mapping->a_ops;
> >  	long status = 0;
> >  	ssize_t written = 0;
> > @@ -2746,7 +2747,8 @@ again:
> >  		pos += copied;
> >  		written += copied;
> >  
> > -		balance_dirty_pages_ratelimited(mapping);
> > +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> > +						inode->i_sb);
> >  	} while (iov_iter_count(i));
> >  
> >  	return written ? written : status;
> > diff --git a/mm/memory.c b/mm/memory.c
> > index 83be99d..d43e73b 100644
> > --- a/mm/memory.c
> > +++ b/mm/memory.c
> > @@ -64,6 +64,7 @@
> >  #include <linux/debugfs.h>
> >  #include <linux/userfaultfd_k.h>
> >  #include <linux/dax.h>
> > +#include <linux/backing-dev.h>
> >  
> >  #include <asm/io.h>
> >  #include <asm/mmu_context.h>
> > @@ -2105,11 +2106,13 @@ static inline int wp_page_reuse(struct fault_env *fe, pte_t orig_pte,
> >  		put_page(page);
> >  
> >  		if ((dirtied || page_mkwrite) && mapping) {
> > +			struct inode *inode = mapping->host;
> >  			/*
> >  			 * Some device drivers do not set page.mapping
> >  			 * but still dirty their pages
> >  			 */
> > -			balance_dirty_pages_ratelimited(mapping);
> > +			balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> > +							inode->i_sb);
> >  		}
> >  
> >  		if (!page_mkwrite)
> > @@ -3291,11 +3294,13 @@ static int do_shared_fault(struct fault_env *fe, pgoff_t pgoff)
> >  	mapping = page_rmapping(fault_page);
> >  	unlock_page(fault_page);
> >  	if ((dirtied || vma->vm_ops->page_mkwrite) && mapping) {
> > +		struct inode *inode = mapping->host;
> >  		/*
> >  		 * Some device drivers do not set page.mapping but still
> >  		 * dirty their pages
> >  		 */
> > -		balance_dirty_pages_ratelimited(mapping);
> > +		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
> > +						inode->i_sb);
> >  	}
> >  
> >  	if (!vma->vm_ops->page_mkwrite)
> > diff --git a/mm/page-writeback.c b/mm/page-writeback.c
> > index f4cd7d8..121a6e3 100644
> > --- a/mm/page-writeback.c
> > +++ b/mm/page-writeback.c
> > @@ -1559,8 +1559,7 @@ static inline void wb_dirty_limits(struct dirty_throttle_control *dtc)
> >   * If we're over `background_thresh' then the writeback threads are woken to
> >   * perform some writeout.
> >   */
> > -static void balance_dirty_pages(struct address_space *mapping,
> > -				struct bdi_writeback *wb,
> > +static void balance_dirty_pages(struct bdi_writeback *wb,
> >  				unsigned long pages_dirtied)
> >  {
> >  	struct dirty_throttle_control gdtc_stor = { GDTC_INIT(wb) };
> > @@ -1849,7 +1848,8 @@ DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0;
> >  
> >  /**
> >   * balance_dirty_pages_ratelimited - balance dirty memory state
> > - * @mapping: address_space which was dirtied
> > + * @bdi: the bdi that was dirtied
> > + * @sb: the super block that was dirtied
> >   *
> >   * Processes which are dirtying memory should call in here once for each page
> >   * which was newly dirtied.  The function will periodically check the system's
> > @@ -1860,10 +1860,9 @@ DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0;
> >   * limit we decrease the ratelimiting by a lot, to prevent individual processes
> >   * from overshooting the limit by (ratelimit_pages) each.
> >   */
> > -void balance_dirty_pages_ratelimited(struct address_space *mapping)
> > +void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
> > +				     struct super_block *sb)
> >  {
> > -	struct inode *inode = mapping->host;
> > -	struct backing_dev_info *bdi = inode_to_bdi(inode);
> >  	struct bdi_writeback *wb = NULL;
> >  	int ratelimit;
> >  	int *p;
> > @@ -1871,7 +1870,7 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping)
> >  	if (!bdi_cap_account_dirty(bdi))
> >  		return;
> >  
> > -	if (inode_cgwb_enabled(inode))
> > +	if (bdi_cgwb_enabled(bdi, sb))
> >  		wb = wb_get_create_current(bdi, GFP_KERNEL);
> >  	if (!wb)
> >  		wb = &bdi->wb;
> > @@ -1909,7 +1908,7 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping)
> >  	preempt_enable();
> >  
> >  	if (unlikely(current->nr_dirtied >= ratelimit))
> > -		balance_dirty_pages(mapping, wb, current->nr_dirtied);
> > +		balance_dirty_pages(wb, current->nr_dirtied);
> >  
> >  	wb_put(wb);
> >  }
> > -- 
> > 1.8.3.1
> > 
> > 
> -- 
> Jan Kara <jack@suse.com>
> SUSE Labs, CR
Tejun Heo Aug. 10, 2016, 7:56 p.m. UTC | #7
On Tue, Aug 09, 2016 at 03:08:26PM -0400, Josef Bacik wrote:
> The only reason we pass in the mapping is to get the inode in order to see if
> writeback cgroups is enabled, and even then it only checks the bdi and a super
> block flag.  balance_dirty_pages() doesn't even use the mapping.  Since
> balance_dirty_pages*() works on a bdi level, just pass in the bdi and super
> block directly so we can avoid using mapping.  This will allow us to still use
> balance_dirty_pages for dirty metadata pages that are not backed by an
> address_mapping.
> 
> Signed-off-by: Josef Bacik <jbacik@fb.com>

Acked-by: Tejun Heo <tj@kernel.org>

Thanks.
diff mbox

Patch

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 17346f7..c1d951a 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4024,8 +4024,8 @@  static void __btrfs_btree_balance_dirty(struct btrfs_root *root,
 	ret = percpu_counter_compare(&root->fs_info->dirty_metadata_bytes,
 				     BTRFS_DIRTY_METADATA_THRESH);
 	if (ret > 0) {
-		balance_dirty_pages_ratelimited(
-				   root->fs_info->btree_inode->i_mapping);
+		balance_dirty_pages_ratelimited(&root->fs_info->bdi,
+						root->fs_info->sb);
 	}
 }
 
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 9404121..f060b08 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1686,7 +1686,8 @@  again:
 
 		cond_resched();
 
-		balance_dirty_pages_ratelimited(inode->i_mapping);
+		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
+						inode->i_sb);
 		if (dirty_pages < (root->nodesize >> PAGE_SHIFT) + 1)
 			btrfs_btree_balance_dirty(root);
 
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 14ed1e9..a222bad 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1410,7 +1410,8 @@  int btrfs_defrag_file(struct inode *inode, struct file *file,
 		}
 
 		defrag_count += ret;
-		balance_dirty_pages_ratelimited(inode->i_mapping);
+		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
+						inode->i_sb);
 		inode_unlock(inode);
 
 		if (newer_than) {
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 4598e29..7fc6ea7 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -3202,7 +3202,8 @@  static int relocate_file_extent_cluster(struct inode *inode,
 		put_page(page);
 
 		index++;
-		balance_dirty_pages_ratelimited(inode->i_mapping);
+		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
+						inode->i_sb);
 		btrfs_throttle(BTRFS_I(inode)->root);
 	}
 	WARN_ON(nr != cluster->nr);
diff --git a/fs/buffer.c b/fs/buffer.c
index 9c8eb9b..9bbe30d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2386,7 +2386,8 @@  static int cont_expand_zero(struct file *file, struct address_space *mapping,
 		BUG_ON(err != len);
 		err = 0;
 
-		balance_dirty_pages_ratelimited(mapping);
+		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
+						inode->i_sb);
 
 		if (unlikely(fatal_signal_pending(current))) {
 			err = -EINTR;
diff --git a/fs/iomap.c b/fs/iomap.c
index 48141b8..937e266 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -226,7 +226,8 @@  again:
 		written += copied;
 		length -= copied;
 
-		balance_dirty_pages_ratelimited(inode->i_mapping);
+		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
+						inode->i_sb);
 	} while (iov_iter_count(i) && length);
 
 	return written ? written : status;
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 491a917..3b76eeb 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -252,8 +252,9 @@  void wb_blkcg_offline(struct blkcg *blkcg);
 int inode_congested(struct inode *inode, int cong_bits);
 
 /**
- * inode_cgwb_enabled - test whether cgroup writeback is enabled on an inode
- * @inode: inode of interest
+ * bdi_cgwb_enabled - test wether cgroup writeback is enabled on a filesystem
+ * @bdi: the bdi we care about
+ * @sb: the super for the bdi
  *
  * cgroup writeback requires support from both the bdi and filesystem.
  * Also, both memcg and iocg have to be on the default hierarchy.  Test
@@ -262,15 +263,25 @@  int inode_congested(struct inode *inode, int cong_bits);
  * Note that the test result may change dynamically on the same inode
  * depending on how memcg and iocg are configured.
  */
-static inline bool inode_cgwb_enabled(struct inode *inode)
+static inline bool bdi_cgwb_enabled(struct backing_dev_info *bdi,
+				    struct super_block *sb)
 {
-	struct backing_dev_info *bdi = inode_to_bdi(inode);
-
 	return cgroup_subsys_on_dfl(memory_cgrp_subsys) &&
 		cgroup_subsys_on_dfl(io_cgrp_subsys) &&
 		bdi_cap_account_dirty(bdi) &&
 		(bdi->capabilities & BDI_CAP_CGROUP_WRITEBACK) &&
-		(inode->i_sb->s_iflags & SB_I_CGROUPWB);
+		(sb->s_iflags & SB_I_CGROUPWB);
+}
+
+/**
+ * inode_cgwb_enabled - test whether cgroup writeback is enabled on an inode
+ * @inode: inode of interest
+ *
+ * Does the inode have cgroup writeback support.
+ */
+static inline bool inode_cgwb_enabled(struct inode *inode)
+{
+	return bdi_cgwb_enabled(inode_to_bdi(inode), inode->i_sb);
 }
 
 /**
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index fc1e16c..256ffc3 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -364,7 +364,8 @@  unsigned long wb_calc_thresh(struct bdi_writeback *wb, unsigned long thresh);
 
 void wb_update_bandwidth(struct bdi_writeback *wb, unsigned long start_time);
 void page_writeback_init(void);
-void balance_dirty_pages_ratelimited(struct address_space *mapping);
+void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
+				     struct super_block *sb);
 bool wb_over_bg_thresh(struct bdi_writeback *wb);
 
 typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc,
diff --git a/mm/filemap.c b/mm/filemap.c
index 3083ded..abb0e98 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2667,6 +2667,7 @@  ssize_t generic_perform_write(struct file *file,
 				struct iov_iter *i, loff_t pos)
 {
 	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
 	const struct address_space_operations *a_ops = mapping->a_ops;
 	long status = 0;
 	ssize_t written = 0;
@@ -2746,7 +2747,8 @@  again:
 		pos += copied;
 		written += copied;
 
-		balance_dirty_pages_ratelimited(mapping);
+		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
+						inode->i_sb);
 	} while (iov_iter_count(i));
 
 	return written ? written : status;
diff --git a/mm/memory.c b/mm/memory.c
index 83be99d..d43e73b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -64,6 +64,7 @@ 
 #include <linux/debugfs.h>
 #include <linux/userfaultfd_k.h>
 #include <linux/dax.h>
+#include <linux/backing-dev.h>
 
 #include <asm/io.h>
 #include <asm/mmu_context.h>
@@ -2105,11 +2106,13 @@  static inline int wp_page_reuse(struct fault_env *fe, pte_t orig_pte,
 		put_page(page);
 
 		if ((dirtied || page_mkwrite) && mapping) {
+			struct inode *inode = mapping->host;
 			/*
 			 * Some device drivers do not set page.mapping
 			 * but still dirty their pages
 			 */
-			balance_dirty_pages_ratelimited(mapping);
+			balance_dirty_pages_ratelimited(inode_to_bdi(inode),
+							inode->i_sb);
 		}
 
 		if (!page_mkwrite)
@@ -3291,11 +3294,13 @@  static int do_shared_fault(struct fault_env *fe, pgoff_t pgoff)
 	mapping = page_rmapping(fault_page);
 	unlock_page(fault_page);
 	if ((dirtied || vma->vm_ops->page_mkwrite) && mapping) {
+		struct inode *inode = mapping->host;
 		/*
 		 * Some device drivers do not set page.mapping but still
 		 * dirty their pages
 		 */
-		balance_dirty_pages_ratelimited(mapping);
+		balance_dirty_pages_ratelimited(inode_to_bdi(inode),
+						inode->i_sb);
 	}
 
 	if (!vma->vm_ops->page_mkwrite)
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index f4cd7d8..121a6e3 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1559,8 +1559,7 @@  static inline void wb_dirty_limits(struct dirty_throttle_control *dtc)
  * If we're over `background_thresh' then the writeback threads are woken to
  * perform some writeout.
  */
-static void balance_dirty_pages(struct address_space *mapping,
-				struct bdi_writeback *wb,
+static void balance_dirty_pages(struct bdi_writeback *wb,
 				unsigned long pages_dirtied)
 {
 	struct dirty_throttle_control gdtc_stor = { GDTC_INIT(wb) };
@@ -1849,7 +1848,8 @@  DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0;
 
 /**
  * balance_dirty_pages_ratelimited - balance dirty memory state
- * @mapping: address_space which was dirtied
+ * @bdi: the bdi that was dirtied
+ * @sb: the super block that was dirtied
  *
  * Processes which are dirtying memory should call in here once for each page
  * which was newly dirtied.  The function will periodically check the system's
@@ -1860,10 +1860,9 @@  DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0;
  * limit we decrease the ratelimiting by a lot, to prevent individual processes
  * from overshooting the limit by (ratelimit_pages) each.
  */
-void balance_dirty_pages_ratelimited(struct address_space *mapping)
+void balance_dirty_pages_ratelimited(struct backing_dev_info *bdi,
+				     struct super_block *sb)
 {
-	struct inode *inode = mapping->host;
-	struct backing_dev_info *bdi = inode_to_bdi(inode);
 	struct bdi_writeback *wb = NULL;
 	int ratelimit;
 	int *p;
@@ -1871,7 +1870,7 @@  void balance_dirty_pages_ratelimited(struct address_space *mapping)
 	if (!bdi_cap_account_dirty(bdi))
 		return;
 
-	if (inode_cgwb_enabled(inode))
+	if (bdi_cgwb_enabled(bdi, sb))
 		wb = wb_get_create_current(bdi, GFP_KERNEL);
 	if (!wb)
 		wb = &bdi->wb;
@@ -1909,7 +1908,7 @@  void balance_dirty_pages_ratelimited(struct address_space *mapping)
 	preempt_enable();
 
 	if (unlikely(current->nr_dirtied >= ratelimit))
-		balance_dirty_pages(mapping, wb, current->nr_dirtied);
+		balance_dirty_pages(wb, current->nr_dirtied);
 
 	wb_put(wb);
 }