| From 9bbf5feecc7eab2c370496c1c161bbfe62084028 Mon Sep 17 00:00:00 2001 |
| From: Coly Li <colyli@suse.de> |
| Date: Mon, 27 Feb 2023 23:23:17 +0800 |
| Subject: dm thin: fix deadlock when swapping to thin device |
| |
| From: Coly Li <colyli@suse.de> |
| |
| commit 9bbf5feecc7eab2c370496c1c161bbfe62084028 upstream. |
| |
| This is an already known issue that dm-thin volume cannot be used as |
| swap, otherwise a deadlock may happen when dm-thin internal memory |
| demand triggers swap I/O on the dm-thin volume itself. |
| |
| But thanks to commit a666e5c05e7c ("dm: fix deadlock when swapping to |
| encrypted device"), the limit_swap_bios target flag can also be used |
| for dm-thin to avoid the recursive I/O when it is used as swap. |
| |
| Fix is to simply set ti->limit_swap_bios to true in both pool_ctr() |
| and thin_ctr(). |
| |
| In my test, I create a dm-thin volume /dev/vg/swap and use it as swap |
| device. Then I run fio on another dm-thin volume /dev/vg/main and use |
| large --blocksize to trigger swap I/O onto /dev/vg/swap. |
| |
| The following fio command line is used in my test, |
| fio --name recursive-swap-io --lockmem 1 --iodepth 128 \ |
| --ioengine libaio --filename /dev/vg/main --rw randrw \ |
| --blocksize 1M --numjobs 32 --time_based --runtime=12h |
| |
| Without this fix, the whole system can be locked up within 15 seconds. |
| |
| With this fix, there is no any deadlock or hung task observed after |
| 2 hours of running fio. |
| |
| Furthermore, if blocksize is changed from 1M to 128M, after around 30 |
| seconds fio has no visible I/O, and the out-of-memory killer message |
| shows up in kernel message. After around 20 minutes all fio processes |
| are killed and the whole system is back to being alive. |
| |
| This is exactly what is expected when recursive I/O happens on dm-thin |
| volume when it is used as swap. |
| |
| Depends-on: a666e5c05e7c ("dm: fix deadlock when swapping to encrypted device") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Coly Li <colyli@suse.de> |
| Acked-by: Mikulas Patocka <mpatocka@redhat.com> |
| Signed-off-by: Mike Snitzer <snitzer@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/md/dm-thin.c | 2 ++ |
| 1 file changed, 2 insertions(+) |
| |
| --- a/drivers/md/dm-thin.c |
| +++ b/drivers/md/dm-thin.c |
| @@ -3357,6 +3357,7 @@ static int pool_ctr(struct dm_target *ti |
| pt->low_water_blocks = low_water_blocks; |
| pt->adjusted_pf = pt->requested_pf = pf; |
| ti->num_flush_bios = 1; |
| + ti->limit_swap_bios = true; |
| |
| /* |
| * Only need to enable discards if the pool should pass |
| @@ -4235,6 +4236,7 @@ static int thin_ctr(struct dm_target *ti |
| goto bad; |
| |
| ti->num_flush_bios = 1; |
| + ti->limit_swap_bios = true; |
| ti->flush_supported = true; |
| ti->accounts_remapped_io = true; |
| ti->per_io_data_size = sizeof(struct dm_thin_endio_hook); |