Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm: respect REQ_NOWAIT flag in normal bios issued to DM

Update DM core's normal IO submission to allocate required memory
using GFP_NOWAIT if REQ_NOWAIT is set.

Tested with simple test provided in commit a9ce385344f916 ("dm: don't
attempt to queue IO under RCU protection") that was enhanced to check
error codes. Also tested using fio's pvsync2 with nowait=1.

But testing with induced GFP_NOWAIT allocation failures wasn't
performed (yet).

Signed-off-by: Mike Snitzer <snitzer@kernel.org>

+29 -11
+29 -11
drivers/md/dm.c
··· 570 570 dm_io_acct(io, true); 571 571 } 572 572 573 - static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) 573 + static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio, gfp_t gfp_mask) 574 574 { 575 575 struct dm_io *io; 576 576 struct dm_target_io *tio; 577 577 struct bio *clone; 578 578 579 - clone = bio_alloc_clone(NULL, bio, GFP_NOIO, &md->mempools->io_bs); 579 + clone = bio_alloc_clone(NULL, bio, gfp_mask, &md->mempools->io_bs); 580 + if (unlikely(!clone)) 581 + return NULL; 580 582 tio = clone_to_tio(clone); 581 583 tio->flags = 0; 582 584 dm_tio_set_flag(tio, DM_TIO_INSIDE_DM_IO); ··· 1716 1714 if (unlikely(!ti)) 1717 1715 return BLK_STS_IOERR; 1718 1716 1719 - if (unlikely((ci->bio->bi_opf & REQ_NOWAIT) != 0) && 1720 - unlikely(!dm_target_supports_nowait(ti->type))) 1721 - return BLK_STS_NOTSUPP; 1722 - 1723 1717 if (unlikely(ci->is_abnormal_io)) 1724 1718 return __process_abnormal_io(ci, ti); 1725 1719 ··· 1727 1729 1728 1730 len = min_t(sector_t, max_io_len(ti, ci->sector), ci->sector_count); 1729 1731 setup_split_accounting(ci, len); 1730 - clone = alloc_tio(ci, ti, 0, &len, GFP_NOIO); 1732 + 1733 + if (unlikely(ci->bio->bi_opf & REQ_NOWAIT)) { 1734 + if (unlikely(!dm_target_supports_nowait(ti->type))) 1735 + return BLK_STS_NOTSUPP; 1736 + 1737 + clone = alloc_tio(ci, ti, 0, &len, GFP_NOWAIT); 1738 + if (unlikely(!clone)) 1739 + return BLK_STS_AGAIN; 1740 + } else { 1741 + clone = alloc_tio(ci, ti, 0, &len, GFP_NOIO); 1742 + } 1731 1743 __map_bio(clone); 1732 1744 1733 1745 ci->sector += len; ··· 1746 1738 return BLK_STS_OK; 1747 1739 } 1748 1740 1749 - static void init_clone_info(struct clone_info *ci, struct mapped_device *md, 1741 + static void init_clone_info(struct clone_info *ci, struct dm_io *io, 1750 1742 struct dm_table *map, struct bio *bio, bool is_abnormal) 1751 1743 { 1752 1744 ci->map = map; 1753 - ci->io = alloc_io(md, bio); 1745 + ci->io = io; 1754 1746 ci->bio = bio; 1755 1747 ci->is_abnormal_io = is_abnormal; 1756 1748 ci->submit_as_polled = false; ··· 1785 1777 return; 1786 1778 } 1787 1779 1788 - init_clone_info(&ci, md, map, bio, is_abnormal); 1789 - io = ci.io; 1780 + /* Only support nowait for normal IO */ 1781 + if (unlikely(bio->bi_opf & REQ_NOWAIT) && !is_abnormal) { 1782 + io = alloc_io(md, bio, GFP_NOWAIT); 1783 + if (unlikely(!io)) { 1784 + /* Unable to do anything without dm_io. */ 1785 + bio_wouldblock_error(bio); 1786 + return; 1787 + } 1788 + } else { 1789 + io = alloc_io(md, bio, GFP_NOIO); 1790 + } 1791 + init_clone_info(&ci, io, map, bio, is_abnormal); 1790 1792 1791 1793 if (bio->bi_opf & REQ_PREFLUSH) { 1792 1794 __send_empty_flush(&ci);