• Coly Li's avatar
    bcache: avoid oversize memory allocation by small stripe_size · baf8fb7e
    Coly Li authored
    Arraies bcache->stripe_sectors_dirty and bcache->full_dirty_stripes are
    used for dirty data writeback, their sizes are decided by backing device
    capacity and stripe size. Larger backing device capacity or smaller
    stripe size make these two arraies occupies more dynamic memory space.
    
    Currently bcache->stripe_size is directly inherited from
    queue->limits.io_opt of underlying storage device. For normal hard
    drives, its limits.io_opt is 0, and bcache sets the corresponding
    stripe_size to 1TB (1<<31 sectors), it works fine 10+ years. But for
    devices do declare value for queue->limits.io_opt, small stripe_size
    (comparing to 1TB) becomes an issue for oversize memory allocations of
    bcache->stripe_sectors_dirty and bcache->full_dirty_stripes, while the
    capacity of hard drives gets much larger in recent decade.
    
    For example a raid5 array assembled by three 20TB hardrives, the raid
    device capacity is 40TB with typical 512KB limits.io_opt. After the math
    calculation in bcache code, these two arraies will occupy 400MB dynamic
    memory. Even worse Andrea Tomassetti reports that a 4KB limits.io_opt is
    declared on a new 2TB hard drive, then these two arraies request 2GB and
    512MB dynamic memory from kzalloc(). The result is that bcache device
    always fails to initialize on his system.
    
    To avoid the oversize memory allocation, bcache->stripe_size should not
    directly inherited by queue->limits.io_opt from the underlying device.
    This patch defines BCH_MIN_STRIPE_SZ (4MB) as minimal bcache stripe size
    and set bcache device's stripe size against the declared limits.io_opt
    value from the underlying storage device,
    - If the declared limits.io_opt > BCH_MIN_STRIPE_SZ, bcache device will
      set its stripe size directly by this limits.io_opt value.
    - If the declared limits.io_opt < BCH_MIN_STRIPE_SZ, bcache device will
      set its stripe size by a value multiplying limits.io_opt and euqal or
      large than BCH_MIN_STRIPE_SZ.
    
    Then the minimal stripe size of a bcache device will always be >= 4MB.
    For a 40TB raid5 device with 512KB limits.io_opt, memory occupied by
    bcache->stripe_sectors_dirty and bcache->full_dirty_stripes will be 50MB
    in total. For a 2TB hard drive with 4KB limits.io_opt, memory occupied
    by these two arraies will be 2.5MB in total.
    
    Such mount of memory allocated for bcache->stripe_sectors_dirty and
    bcache->full_dirty_stripes is reasonable for most of storage devices.
    Reported-by: default avatarAndrea Tomassetti <andrea.tomassetti-opensource@devo.com>
    Signed-off-by: default avatarColy Li <colyli@suse.de>
    Reviewed-by: default avatarEric Wheeler <bcache@lists.ewheeler.net>
    Link: https://lore.kernel.org/r/20231120052503.6122-2-colyli@suse.deSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
    baf8fb7e
super.c 71.7 KB