Skip to content

Commit f3e3dbc

Browse files
committed
Merge tag 'block-7.1-20260424' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux
Pull block fixes from Jens Axboe: - Series for zloop, fixing a variety of issues - t10-pi code cleanup - Fix for a merge window regression with the bio memory allocation mask - Fix for a merge window regression in ublk, caused by an issue with the maple tree iteration code at teardown - ublk self tests additions - Zoned device pgmap fixes - Various little cleanups and fixes * tag 'block-7.1-20260424' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux: (21 commits) Revert "floppy: fix reference leak on platform_device_register() failure" ublk: avoid unpinning pages under maple tree spinlock ublk: refactor common helper ublk_shmem_remove_ranges() ublk: fix maple tree lockdep warning in ublk_buf_cleanup selftests: ublk: add ublk auto integrity test selftests: ublk: enable test_integrity_02.sh on fio 3.42 selftests: ublk: remove unused argument to _cleanup block: only restrict bio allocation gfp mask asked to block block/blk-throttle: Add WQ_PERCPU to alloc_workqueue users block: Add WQ_PERCPU to alloc_workqueue users block: relax pgmap check in bio_add_page for compatible zone device pages block: add pgmap check to biovec_phys_mergeable floppy: fix reference leak on platform_device_register() failure ublk: use unchecked copy helpers for bio page data t10-pi: reduce ref tag code duplication zloop: remove irq-safe locking zloop: factor out zloop_mark_{full,empty} helpers zloop: set RQF_QUIET when completing requests on deleted devices zloop: improve the unaligned write pointer warning zloop: use vfs_truncate ...
2 parents fa58e6e + 895a9b3 commit f3e3dbc

61 files changed

Lines changed: 347 additions & 187 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

block/bio-integrity-auto.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ static int __init blk_integrity_auto_init(void)
125125
* Make it highpri CPU intensive wq with max concurrency of 1.
126126
*/
127127
kintegrityd_wq = alloc_workqueue("kintegrityd", WQ_MEM_RECLAIM |
128-
WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
128+
WQ_HIGHPRI | WQ_CPU_INTENSIVE | WQ_PERCPU, 1);
129129
if (!kintegrityd_wq)
130130
panic("Failed to create kintegrityd\n");
131131
return 0;

block/bio-integrity.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,10 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
231231
if (bip->bip_vcnt > 0) {
232232
struct bio_vec *bv = &bip->bip_vec[bip->bip_vcnt - 1];
233233

234-
if (!zone_device_pages_have_same_pgmap(bv->bv_page, page))
234+
if (!zone_device_pages_compatible(bv->bv_page, page))
235235
return 0;
236-
237-
if (bvec_try_merge_hw_page(q, bv, page, len, offset)) {
236+
if (zone_device_pages_have_same_pgmap(bv->bv_page, page) &&
237+
bvec_try_merge_hw_page(q, bv, page, len, offset)) {
238238
bip->bip_iter.bi_size += len;
239239
return len;
240240
}

block/bio.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,8 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs,
544544
if (WARN_ON_ONCE(!mempool_initialized(&bs->bvec_pool) && nr_vecs > 0))
545545
return NULL;
546546

547-
gfp = try_alloc_gfp(gfp);
547+
if (saved_gfp & __GFP_DIRECT_RECLAIM)
548+
gfp = try_alloc_gfp(gfp);
548549
if (bs->cache && nr_vecs <= BIO_INLINE_VECS) {
549550
/*
550551
* Set REQ_ALLOC_CACHE even if no cached bio is available to
@@ -1048,10 +1049,10 @@ int bio_add_page(struct bio *bio, struct page *page,
10481049
if (bio->bi_vcnt > 0) {
10491050
struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
10501051

1051-
if (!zone_device_pages_have_same_pgmap(bv->bv_page, page))
1052+
if (!zone_device_pages_compatible(bv->bv_page, page))
10521053
return 0;
1053-
1054-
if (bvec_try_merge_page(bv, page, len, offset)) {
1054+
if (zone_device_pages_have_same_pgmap(bv->bv_page, page) &&
1055+
bvec_try_merge_page(bv, page, len, offset)) {
10551056
bio->bi_iter.bi_size += len;
10561057
return len;
10571058
}
@@ -1958,7 +1959,7 @@ int bioset_init(struct bio_set *bs,
19581959

19591960
if (flags & BIOSET_NEED_RESCUER) {
19601961
bs->rescue_workqueue = alloc_workqueue("bioset",
1961-
WQ_MEM_RECLAIM, 0);
1962+
WQ_MEM_RECLAIM | WQ_PERCPU, 0);
19621963
if (!bs->rescue_workqueue)
19631964
goto bad;
19641965
}

block/blk-core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ int __init blk_dev_init(void)
12821282

12831283
/* used for unplugging and affects IO latency/throughput - HIGHPRI */
12841284
kblockd_workqueue = alloc_workqueue("kblockd",
1285-
WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
1285+
WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU, 0);
12861286
if (!kblockd_workqueue)
12871287
panic("Failed to create kblockd\n");
12881288

block/blk-throttle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1839,7 +1839,7 @@ void blk_throtl_exit(struct gendisk *disk)
18391839

18401840
static int __init throtl_init(void)
18411841
{
1842-
kthrotld_workqueue = alloc_workqueue("kthrotld", WQ_MEM_RECLAIM, 0);
1842+
kthrotld_workqueue = alloc_workqueue("kthrotld", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
18431843
if (!kthrotld_workqueue)
18441844
panic("Failed to create kthrotld\n");
18451845

block/blk.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,34 @@ static inline bool biovec_phys_mergeable(struct request_queue *q,
127127

128128
if (addr1 + vec1->bv_len != addr2)
129129
return false;
130+
if (!zone_device_pages_have_same_pgmap(vec1->bv_page, vec2->bv_page))
131+
return false;
130132
if (xen_domain() && !xen_biovec_phys_mergeable(vec1, vec2->bv_page))
131133
return false;
132134
if ((addr1 | mask) != ((addr2 + vec2->bv_len - 1) | mask))
133135
return false;
134136
return true;
135137
}
136138

139+
/*
140+
* Check if two pages from potentially different zone device pgmaps can
141+
* coexist as separate bvec entries in the same bio.
142+
*
143+
* The block DMA iterator (blk_dma_map_iter_start) caches the P2PDMA mapping
144+
* state from the first segment and applies it to all subsequent segments, so
145+
* P2PDMA pages from different pgmaps must not be mixed in the same bio.
146+
*
147+
* Other zone device types (FS_DAX, GENERIC) use the same dma_map_phys() path
148+
* as normal RAM. PRIVATE and COHERENT pages never appear in bios.
149+
*/
150+
static inline bool zone_device_pages_compatible(const struct page *a,
151+
const struct page *b)
152+
{
153+
if (is_pci_p2pdma_page(a) || is_pci_p2pdma_page(b))
154+
return zone_device_pages_have_same_pgmap(a, b);
155+
return true;
156+
}
157+
137158
static inline bool __bvec_gap_to_prev(const struct queue_limits *lim,
138159
struct bio_vec *bprv, unsigned int offset)
139160
{

drivers/block/ublk_drv.c

Lines changed: 80 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,10 +1319,18 @@ static bool ublk_copy_user_bvec(const struct bio_vec *bv, unsigned *offset,
13191319

13201320
len = bv->bv_len - *offset;
13211321
bv_buf = kmap_local_page(bv->bv_page) + bv->bv_offset + *offset;
1322+
/*
1323+
* Bio pages may originate from slab caches without a usercopy region
1324+
* (e.g. jbd2 frozen metadata buffers). This is the same data that
1325+
* the loop driver writes to its backing file — no exposure risk.
1326+
* The bvec length is always trusted, so the size check in
1327+
* check_copy_size() is not needed either. Use the unchecked
1328+
* helpers to avoid false positives on slab pages.
1329+
*/
13221330
if (dir == ITER_DEST)
1323-
copied = copy_to_iter(bv_buf, len, uiter);
1331+
copied = _copy_to_iter(bv_buf, len, uiter);
13241332
else
1325-
copied = copy_from_iter(bv_buf, len, uiter);
1333+
copied = _copy_from_iter(bv_buf, len, uiter);
13261334

13271335
kunmap_local(bv_buf);
13281336

@@ -5413,39 +5421,88 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
54135421
return ret;
54145422
}
54155423

5416-
static int __ublk_ctrl_unreg_buf(struct ublk_device *ub, int buf_index)
5424+
static void ublk_unpin_range_pages(unsigned long base_pfn,
5425+
unsigned long nr_pages)
5426+
{
5427+
#define UBLK_UNPIN_BATCH 32
5428+
struct page *pages[UBLK_UNPIN_BATCH];
5429+
unsigned long off;
5430+
5431+
for (off = 0; off < nr_pages; ) {
5432+
unsigned int batch = min_t(unsigned long,
5433+
nr_pages - off, UBLK_UNPIN_BATCH);
5434+
unsigned int j;
5435+
5436+
for (j = 0; j < batch; j++)
5437+
pages[j] = pfn_to_page(base_pfn + off + j);
5438+
unpin_user_pages(pages, batch);
5439+
off += batch;
5440+
}
5441+
}
5442+
5443+
/*
5444+
* Inner loop: erase up to UBLK_REMOVE_BATCH matching ranges under
5445+
* mas_lock, collecting them into an xarray. Then drop the lock and
5446+
* unpin pages + free ranges outside spinlock context.
5447+
*
5448+
* Returns true if the tree walk completed, false if more ranges remain.
5449+
* Xarray key is the base PFN, value encodes nr_pages via xa_mk_value().
5450+
*/
5451+
#define UBLK_REMOVE_BATCH 64
5452+
5453+
static bool __ublk_shmem_remove_ranges(struct ublk_device *ub,
5454+
int buf_index, int *ret)
54175455
{
54185456
MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX);
54195457
struct ublk_buf_range *range;
5420-
struct page *pages[32];
5421-
int ret = -ENOENT;
5458+
struct xarray to_unpin;
5459+
unsigned long idx;
5460+
unsigned int count = 0;
5461+
bool done = false;
5462+
void *entry;
5463+
5464+
xa_init(&to_unpin);
54225465

54235466
mas_lock(&mas);
54245467
mas_for_each(&mas, range, ULONG_MAX) {
5425-
unsigned long base, nr, off;
5468+
unsigned long nr;
54265469

5427-
if (range->buf_index != buf_index)
5470+
if (buf_index >= 0 && range->buf_index != buf_index)
54285471
continue;
54295472

5430-
ret = 0;
5431-
base = mas.index;
5432-
nr = mas.last - base + 1;
5473+
*ret = 0;
5474+
nr = mas.last - mas.index + 1;
5475+
if (xa_err(xa_store(&to_unpin, mas.index,
5476+
xa_mk_value(nr), GFP_ATOMIC)))
5477+
goto unlock;
54335478
mas_erase(&mas);
5434-
5435-
for (off = 0; off < nr; ) {
5436-
unsigned int batch = min_t(unsigned long,
5437-
nr - off, 32);
5438-
unsigned int j;
5439-
5440-
for (j = 0; j < batch; j++)
5441-
pages[j] = pfn_to_page(base + off + j);
5442-
unpin_user_pages(pages, batch);
5443-
off += batch;
5444-
}
54455479
kfree(range);
5480+
if (++count >= UBLK_REMOVE_BATCH)
5481+
goto unlock;
54465482
}
5483+
done = true;
5484+
unlock:
54475485
mas_unlock(&mas);
54485486

5487+
xa_for_each(&to_unpin, idx, entry)
5488+
ublk_unpin_range_pages(idx, xa_to_value(entry));
5489+
xa_destroy(&to_unpin);
5490+
5491+
return done;
5492+
}
5493+
5494+
/*
5495+
* Remove ranges from the maple tree matching buf_index, unpin pages
5496+
* and free range structs. If buf_index < 0, remove all ranges.
5497+
* Processes ranges in batches to avoid holding the maple tree spinlock
5498+
* across potentially expensive page unpinning.
5499+
*/
5500+
static int ublk_shmem_remove_ranges(struct ublk_device *ub, int buf_index)
5501+
{
5502+
int ret = -ENOENT;
5503+
5504+
while (!__ublk_shmem_remove_ranges(ub, buf_index, &ret))
5505+
cond_resched();
54495506
return ret;
54505507
}
54515508

@@ -5464,7 +5521,7 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54645521

54655522
memflags = ublk_lock_buf_tree(ub);
54665523

5467-
ret = __ublk_ctrl_unreg_buf(ub, index);
5524+
ret = ublk_shmem_remove_ranges(ub, index);
54685525
if (!ret)
54695526
ida_free(&ub->buf_ida, index);
54705527

@@ -5474,27 +5531,7 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54745531

54755532
static void ublk_buf_cleanup(struct ublk_device *ub)
54765533
{
5477-
MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX);
5478-
struct ublk_buf_range *range;
5479-
struct page *pages[32];
5480-
5481-
mas_for_each(&mas, range, ULONG_MAX) {
5482-
unsigned long base = mas.index;
5483-
unsigned long nr = mas.last - base + 1;
5484-
unsigned long off;
5485-
5486-
for (off = 0; off < nr; ) {
5487-
unsigned int batch = min_t(unsigned long,
5488-
nr - off, 32);
5489-
unsigned int j;
5490-
5491-
for (j = 0; j < batch; j++)
5492-
pages[j] = pfn_to_page(base + off + j);
5493-
unpin_user_pages(pages, batch);
5494-
off += batch;
5495-
}
5496-
kfree(range);
5497-
}
5534+
ublk_shmem_remove_ranges(ub, -1);
54985535
mtree_destroy(&ub->buf_tree);
54995536
ida_destroy(&ub->buf_ida);
55005537
}

0 commit comments

Comments
 (0)