Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd0aca2d authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe
Browse files

block: fix queue bounce limit setting



Impact: don't set GFP_DMA in q->bounce_gfp unnecessarily

All DMA address limits are expressed in terms of the last addressable
unit (byte or page) instead of one plus that.  However, when
determining bounce_gfp for 64bit machines in blk_queue_bounce_limit(),
it compares the specified limit against 0x100000000UL to determine
whether it's below 4G ending up falsely setting GFP_DMA in
q->bounce_gfp.

As DMA zone is very small on x86_64, this makes larger SG_IO transfers
very eager to trigger OOM killer.  Fix it.  While at it, rename the
parameter to @dma_mask for clarity and convert comment to proper
winged style.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 25636e28
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -157,25 +157,27 @@ EXPORT_SYMBOL(blk_queue_make_request);
/**
 * blk_queue_bounce_limit - set bounce buffer limit for queue
 * @q: the request queue for the device
 * @dma_addr:   bus address limit
 * @dma_mask: the maximum address the device can handle
 *
 * Description:
 *    Different hardware can have different requirements as to what pages
 *    it can do I/O directly to. A low level driver can call
 *    blk_queue_bounce_limit to have lower memory pages allocated as bounce
 *    buffers for doing I/O to pages residing above @dma_addr.
 *    buffers for doing I/O to pages residing above @dma_mask.
 **/
void blk_queue_bounce_limit(struct request_queue *q, u64 dma_addr)
void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)
{
	unsigned long b_pfn = dma_addr >> PAGE_SHIFT;
	unsigned long b_pfn = dma_mask >> PAGE_SHIFT;
	int dma = 0;

	q->bounce_gfp = GFP_NOIO;
#if BITS_PER_LONG == 64
	/* Assume anything <= 4GB can be handled by IOMMU.
	   Actually some IOMMUs can handle everything, but I don't
	   know of a way to test this here. */
	if (b_pfn < (min_t(u64, 0x100000000UL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
	/*
	 * Assume anything <= 4GB can be handled by IOMMU.  Actually
	 * some IOMMUs can handle everything, but I don't know of a
	 * way to test this here.
	 */
	if (b_pfn < (min_t(u64, 0xffffffffUL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
		dma = 1;
	q->bounce_pfn = max_low_pfn;
#else