From 8f84454e331e975bf44ded069d7c75d7f678968d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 28 Oct 2023 05:40:55 +0200 Subject: [PATCH] Replace revert with upstream patch regarding dm-crypt bug Fixes QubesOS/qubes-issues#8575 --- ...-allocate-compound-pages-if-possible.patch | 105 ------------------ ...-provide-the-max_mapping_size-method.patch | 43 +++++++ kernel.spec.in | 2 +- 3 files changed, 44 insertions(+), 106 deletions(-) delete mode 100644 0001-Revert-dm-crypt-allocate-compound-pages-if-possible.patch create mode 100644 0001-swiotlb-xen-provide-the-max_mapping_size-method.patch diff --git a/0001-Revert-dm-crypt-allocate-compound-pages-if-possible.patch b/0001-Revert-dm-crypt-allocate-compound-pages-if-possible.patch deleted file mode 100644 index 52295871..00000000 --- a/0001-Revert-dm-crypt-allocate-compound-pages-if-possible.patch +++ /dev/null @@ -1,105 +0,0 @@ -From d0e755841f1f934bf153eb3fbb70de0e94c5a052 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= - -Date: Sat, 21 Oct 2023 05:42:53 +0200 -Subject: [PATCH] Revert "dm crypt: allocate compound pages if possible" - -This commit causes occasional freeze of the storage I/O. Revert until -real fix is developed. - -This reverts commit 5054e778fcd9cd29ddaa8109077cd235527e4f94. ---- - drivers/md/dm-crypt.c | 49 +++++++++++++------------------------------ - 1 file changed, 14 insertions(+), 35 deletions(-) - -diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c -index dc0463bf3c2c..2585ce883a48 100644 ---- a/drivers/md/dm-crypt.c -+++ b/drivers/md/dm-crypt.c -@@ -1669,9 +1669,6 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone); - * In order to not degrade performance with excessive locking, we try - * non-blocking allocations without a mutex first but on failure we fallback - * to blocking allocations with a mutex. -- * -- * In order to reduce allocation overhead, we try to allocate compound pages in -- * the first pass. If they are not available, we fall back to the mempool. - */ - static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) - { -@@ -1679,8 +1676,8 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) - struct bio *clone; - unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; - gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM; -- unsigned int remaining_size; -- unsigned int order = MAX_ORDER - 1; -+ unsigned int i, len, remaining_size; -+ struct page *page; - - retry: - if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM)) -@@ -1693,34 +1690,19 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) - - remaining_size = size; - -- while (remaining_size) { -- struct page *pages; -- unsigned size_to_add; -- unsigned remaining_order = __fls((remaining_size + PAGE_SIZE - 1) >> PAGE_SHIFT); -- order = min(order, remaining_order); -- -- while (order > 0) { -- pages = alloc_pages(gfp_mask -- | __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | __GFP_COMP, -- order); -- if (likely(pages != NULL)) -- goto have_pages; -- order--; -- } -- -- pages = mempool_alloc(&cc->page_pool, gfp_mask); -- if (!pages) { -+ for (i = 0; i < nr_iovecs; i++) { -+ page = mempool_alloc(&cc->page_pool, gfp_mask); -+ if (!page) { - crypt_free_buffer_pages(cc, clone); - bio_put(clone); - gfp_mask |= __GFP_DIRECT_RECLAIM; -- order = 0; - goto retry; - } - --have_pages: -- size_to_add = min((unsigned)PAGE_SIZE << order, remaining_size); -- __bio_add_page(clone, pages, size_to_add, 0); -- remaining_size -= size_to_add; -+ len = (remaining_size > PAGE_SIZE) ? PAGE_SIZE : remaining_size; -+ -+ __bio_add_page(clone, page, len, 0); -+ remaining_size -= len; - } - - /* Allocate space for integrity tags */ -@@ -1738,15 +1720,12 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) - - static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) - { -- struct folio_iter fi; -+ struct bio_vec *bv; -+ struct bvec_iter_all iter_all; - -- if (clone->bi_vcnt > 0) { /* bio_for_each_folio_all crashes with an empty bio */ -- bio_for_each_folio_all(fi, clone) { -- if (folio_test_large(fi.folio)) -- folio_put(fi.folio); -- else -- mempool_free(&fi.folio->page, &cc->page_pool); -- } -+ bio_for_each_segment_all(bv, clone, iter_all) { -+ BUG_ON(!bv->bv_page); -+ mempool_free(bv->bv_page, &cc->page_pool); - } - } - --- -2.41.0 - diff --git a/0001-swiotlb-xen-provide-the-max_mapping_size-method.patch b/0001-swiotlb-xen-provide-the-max_mapping_size-method.patch new file mode 100644 index 00000000..2ed6c811 --- /dev/null +++ b/0001-swiotlb-xen-provide-the-max_mapping_size-method.patch @@ -0,0 +1,43 @@ +Date: Mon, 6 Nov 2023 18:12:30 +0100 (CET) +From: Keith Busch +Subject: [PATCH v2] swiotlb-xen: provide the "max_mapping_size" method + +There's a bug that when using the XEN hypervisor with bios with large +multi-page bio vectors on NVMe, the kernel deadlocks [1]. + +The deadlocks are caused by inability to map a large bio vector - +dma_map_sgtable always returns an error, this gets propagated to the block +layer as BLK_STS_RESOURCE and the block layer retries the request +indefinitely. + +XEN uses the swiotlb framework to map discontiguous pages into contiguous +runs that are submitted to the PCIe device. The swiotlb framework has a +limitation on the length of a mapping - this needs to be announced with +the max_mapping_size method to make sure that the hardware drivers do not +create larger mappings. + +Without max_mapping_size, the NVMe block driver would create large +mappings that overrun the maximum mapping size. + +Reported-by: Marek Marczykowski-Górecki +Link: https://lore.kernel.org/stable/ZTNH0qtmint%2FzLJZ@mail-itl/ [1] +Tested-by: Marek Marczykowski-Górecki +Suggested-by: Christoph Hellwig +Cc: stable@vger.kernel.org +Signed-off-by: Keith Busch +Signed-off-by: Mikulas Patocka + +--- + drivers/xen/swiotlb-xen.c | 1 + + 1 file changed, 1 insertion(+) + +Index: linux-stable/drivers/xen/swiotlb-xen.c +=================================================================== +--- linux-stable.orig/drivers/xen/swiotlb-xen.c 2023-11-03 17:57:18.000000000 +0100 ++++ linux-stable/drivers/xen/swiotlb-xen.c 2023-11-06 15:30:59.000000000 +0100 +@@ -405,4 +405,5 @@ const struct dma_map_ops xen_swiotlb_dma + .get_sgtable = dma_common_get_sgtable, + .alloc_pages = dma_common_alloc_pages, + .free_pages = dma_common_free_pages, ++ .max_mapping_size = swiotlb_max_mapping_size, + }; diff --git a/kernel.spec.in b/kernel.spec.in index cb6c8f89..d558eb92 100644 --- a/kernel.spec.in +++ b/kernel.spec.in @@ -145,7 +145,7 @@ Patch26: 0001-sound-Disable-SG-buffer.patch Patch27: 0001-amdgpu-timeout.patch Patch28: 0001-iwlwifi-avoid-writing-to-MSI-X-page-when-MSI-X-is-no.patch Patch29: 0001-xen-pciback-Consider-INTx-disabled-when-MSI-MSI-X-is.patch -Patch30: 0001-Revert-dm-crypt-allocate-compound-pages-if-possible.patch +Patch30: 0001-swiotlb-xen-provide-the-max_mapping_size-method.patch # S0ix support: Patch61: xen-events-Add-wakeup-support-to-xen-pirq.patch