From 32be3c01c3b8e948a4326ab7e76c1c63dd3e27bc Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 14 Apr 2026 10:17:46 +0200 Subject: [PATCH 01/21] zloop: fix write pointer calculation in zloop_forget_cache The write pointer is absolute and in sector units, so we need to convert it to a relative byte address first. Fixes: c505448748f7 ("zloop: forget write cache on force removal") Signed-off-by: Christoph Hellwig Reviewed-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Link: https://patch.msgid.link/20260414081811.549755-2-hch@lst.de Signed-off-by: Jens Axboe --- drivers/block/zloop.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index 8baf642037fd..672948d3653e 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -1401,8 +1401,17 @@ static void zloop_forget_cache(struct zloop_device *zlo) zlo->disk->part0, ret); continue; } - if (old_wp < zone->wp) - zloop_truncate(file, old_wp); + + if (old_wp > zone->wp) + continue; + /* + * This should not happen, if we recored a full zone, it can't + * be active. + */ + if (WARN_ON_ONCE(old_wp == ULLONG_MAX)) + continue; + + zloop_truncate(file, (old_wp - zone->start) << SECTOR_SHIFT); } } From 14e0077911e3d5e11e94417861e700cbb521a107 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 14 Apr 2026 10:17:47 +0200 Subject: [PATCH 02/21] zloop: use vfs_truncate While vfs_truncate does various extra checks that we don't really need, it is always better to use a VFS helper rather than open coding the logic. Signed-off-by: Christoph Hellwig Reviewed-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Link: https://patch.msgid.link/20260414081811.549755-3-hch@lst.de Signed-off-by: Jens Axboe --- drivers/block/zloop.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index 672948d3653e..fc54480ed62d 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -1363,20 +1363,6 @@ static int zloop_ctl_add(struct zloop_options *opts) return ret; } -static void zloop_truncate(struct file *file, loff_t pos) -{ - struct mnt_idmap *idmap = file_mnt_idmap(file); - struct dentry *dentry = file_dentry(file); - struct iattr newattrs; - - newattrs.ia_size = pos; - newattrs.ia_valid = ATTR_SIZE; - - inode_lock(dentry->d_inode); - notify_change(idmap, dentry, &newattrs, NULL); - inode_unlock(dentry->d_inode); -} - static void zloop_forget_cache(struct zloop_device *zlo) { unsigned int i; @@ -1411,7 +1397,8 @@ static void zloop_forget_cache(struct zloop_device *zlo) if (WARN_ON_ONCE(old_wp == ULLONG_MAX)) continue; - zloop_truncate(file, (old_wp - zone->start) << SECTOR_SHIFT); + vfs_truncate(&file->f_path, + (old_wp - zone->start) << SECTOR_SHIFT); } } From 6466b211f797ae88073b5826dd764a6a98b67edb Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 14 Apr 2026 10:17:48 +0200 Subject: [PATCH 03/21] zloop: improve the unaligned write pointer warning Use the IS_ALIGNED helper and avoid extra conversions, and tell the user what the unaligned size is. Signed-off-by: Christoph Hellwig Reviewed-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Link: https://patch.msgid.link/20260414081811.549755-4-hch@lst.de Signed-off-by: Jens Axboe --- drivers/block/zloop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index fc54480ed62d..a738f8629062 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -313,9 +313,9 @@ static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no) return -EINVAL; } - if (file_sectors & ((zlo->block_size >> SECTOR_SHIFT) - 1)) { - pr_err("Zone %u file size not aligned to block size %u\n", - zone_no, zlo->block_size); + if (!IS_ALIGNED(stat.size, zlo->block_size)) { + pr_err("Zone %u file size (%llu) not aligned to block size %u\n", + zone_no, stat.size, zlo->block_size); return -EINVAL; } From 5b680d7afc4a2fefa0b4f584462c7540de56e2e4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 14 Apr 2026 10:17:49 +0200 Subject: [PATCH 04/21] zloop: set RQF_QUIET when completing requests on deleted devices Reduce the dmesg spam for tests that involve device deletion. Signed-off-by: Christoph Hellwig Reviewed-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Link: https://patch.msgid.link/20260414081811.549755-5-hch@lst.de Signed-off-by: Jens Axboe --- drivers/block/zloop.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index a738f8629062..7257188dd3a8 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -891,8 +891,10 @@ static blk_status_t zloop_queue_rq(struct blk_mq_hw_ctx *hctx, struct zloop_cmd *cmd = blk_mq_rq_to_pdu(rq); struct zloop_device *zlo = rq->q->queuedata; - if (data_race(READ_ONCE(zlo->state)) == Zlo_deleting) + if (data_race(READ_ONCE(zlo->state)) == Zlo_deleting) { + rq->rq_flags |= RQF_QUIET; return BLK_STS_IOERR; + } /* * If we need to strongly order zone append operations, set the request From ec5c045f6cc879637cb52c9902d5fb7d419bdf47 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 14 Apr 2026 10:17:50 +0200 Subject: [PATCH 05/21] zloop: factor out zloop_mark_{full,empty} helpers Move a few chunks of duplicated code into helpers. Signed-off-by: Christoph Hellwig Reviewed-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Link: https://patch.msgid.link/20260414081811.549755-6-hch@lst.de Signed-off-by: Jens Axboe --- drivers/block/zloop.c | 48 +++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index 7257188dd3a8..3f69206d674a 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -288,6 +288,24 @@ static bool zloop_do_open_zone(struct zloop_device *zlo, } } +static void zloop_mark_full(struct zloop_device *zlo, struct zloop_zone *zone) +{ + lockdep_assert_held(&zone->wp_lock); + + zloop_lru_remove_open_zone(zlo, zone); + zone->cond = BLK_ZONE_COND_FULL; + zone->wp = ULLONG_MAX; +} + +static void zloop_mark_empty(struct zloop_device *zlo, struct zloop_zone *zone) +{ + lockdep_assert_held(&zone->wp_lock); + + zloop_lru_remove_open_zone(zlo, zone); + zone->cond = BLK_ZONE_COND_EMPTY; + zone->wp = zone->start; +} + static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no) { struct zloop_zone *zone = &zlo->zones[zone_no]; @@ -321,13 +339,9 @@ static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no) spin_lock_irqsave(&zone->wp_lock, flags); if (!file_sectors) { - zloop_lru_remove_open_zone(zlo, zone); - zone->cond = BLK_ZONE_COND_EMPTY; - zone->wp = zone->start; + zloop_mark_empty(zlo, zone); } else if (file_sectors == zlo->zone_capacity) { - zloop_lru_remove_open_zone(zlo, zone); - zone->cond = BLK_ZONE_COND_FULL; - zone->wp = ULLONG_MAX; + zloop_mark_full(zlo, zone); } else { if (zone->cond != BLK_ZONE_COND_IMP_OPEN && zone->cond != BLK_ZONE_COND_EXP_OPEN) @@ -429,9 +443,7 @@ static int zloop_reset_zone(struct zloop_device *zlo, unsigned int zone_no) } spin_lock_irqsave(&zone->wp_lock, flags); - zloop_lru_remove_open_zone(zlo, zone); - zone->cond = BLK_ZONE_COND_EMPTY; - zone->wp = zone->start; + zloop_mark_empty(zlo, zone); clear_bit(ZLOOP_ZONE_SEQ_ERROR, &zone->flags); spin_unlock_irqrestore(&zone->wp_lock, flags); @@ -477,9 +489,7 @@ static int zloop_finish_zone(struct zloop_device *zlo, unsigned int zone_no) } spin_lock_irqsave(&zone->wp_lock, flags); - zloop_lru_remove_open_zone(zlo, zone); - zone->cond = BLK_ZONE_COND_FULL; - zone->wp = ULLONG_MAX; + zloop_mark_full(zlo, zone); clear_bit(ZLOOP_ZONE_SEQ_ERROR, &zone->flags); spin_unlock_irqrestore(&zone->wp_lock, flags); @@ -616,11 +626,8 @@ static int zloop_seq_write_prep(struct zloop_cmd *cmd) */ if (!is_append || !zlo->ordered_zone_append) { zone->wp += nr_sectors; - if (zone->wp == zone_end) { - zloop_lru_remove_open_zone(zlo, zone); - zone->cond = BLK_ZONE_COND_FULL; - zone->wp = ULLONG_MAX; - } + if (zone->wp == zone_end) + zloop_mark_full(zlo, zone); } out_unlock: spin_unlock_irqrestore(&zone->wp_lock, flags); @@ -873,11 +880,8 @@ static bool zloop_set_zone_append_sector(struct request *rq) rq->__sector = zone->wp; zone->wp += blk_rq_sectors(rq); - if (zone->wp >= zone_end) { - zloop_lru_remove_open_zone(zlo, zone); - zone->cond = BLK_ZONE_COND_FULL; - zone->wp = ULLONG_MAX; - } + if (zone->wp >= zone_end) + zloop_mark_full(zlo, zone); spin_unlock_irqrestore(&zone->wp_lock, flags); From 64b437c4a96ae088d46c7d9930c35e77ee1b5b21 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 14 Apr 2026 10:17:51 +0200 Subject: [PATCH 06/21] zloop: remove irq-safe locking All of zloop runs in user context, so drop the irq-safe locking. Signed-off-by: Christoph Hellwig Reviewed-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Link: https://patch.msgid.link/20260414081811.549755-7-hch@lst.de Signed-off-by: Jens Axboe --- drivers/block/zloop.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index 3f69206d674a..55eeb6aac0ea 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -311,7 +311,6 @@ static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no) struct zloop_zone *zone = &zlo->zones[zone_no]; struct kstat stat; sector_t file_sectors; - unsigned long flags; int ret; lockdep_assert_held(&zone->lock); @@ -337,7 +336,7 @@ static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no) return -EINVAL; } - spin_lock_irqsave(&zone->wp_lock, flags); + spin_lock(&zone->wp_lock); if (!file_sectors) { zloop_mark_empty(zlo, zone); } else if (file_sectors == zlo->zone_capacity) { @@ -348,7 +347,7 @@ static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no) zone->cond = BLK_ZONE_COND_CLOSED; zone->wp = zone->start + file_sectors; } - spin_unlock_irqrestore(&zone->wp_lock, flags); + spin_unlock(&zone->wp_lock); return 0; } @@ -381,7 +380,6 @@ static int zloop_open_zone(struct zloop_device *zlo, unsigned int zone_no) static int zloop_close_zone(struct zloop_device *zlo, unsigned int zone_no) { struct zloop_zone *zone = &zlo->zones[zone_no]; - unsigned long flags; int ret = 0; if (test_bit(ZLOOP_ZONE_CONV, &zone->flags)) @@ -400,13 +398,13 @@ static int zloop_close_zone(struct zloop_device *zlo, unsigned int zone_no) break; case BLK_ZONE_COND_IMP_OPEN: case BLK_ZONE_COND_EXP_OPEN: - spin_lock_irqsave(&zone->wp_lock, flags); + spin_lock(&zone->wp_lock); zloop_lru_remove_open_zone(zlo, zone); if (zone->wp == zone->start) zone->cond = BLK_ZONE_COND_EMPTY; else zone->cond = BLK_ZONE_COND_CLOSED; - spin_unlock_irqrestore(&zone->wp_lock, flags); + spin_unlock(&zone->wp_lock); break; case BLK_ZONE_COND_EMPTY: case BLK_ZONE_COND_FULL: @@ -424,7 +422,6 @@ static int zloop_close_zone(struct zloop_device *zlo, unsigned int zone_no) static int zloop_reset_zone(struct zloop_device *zlo, unsigned int zone_no) { struct zloop_zone *zone = &zlo->zones[zone_no]; - unsigned long flags; int ret = 0; if (test_bit(ZLOOP_ZONE_CONV, &zone->flags)) @@ -442,10 +439,10 @@ static int zloop_reset_zone(struct zloop_device *zlo, unsigned int zone_no) goto unlock; } - spin_lock_irqsave(&zone->wp_lock, flags); + spin_lock(&zone->wp_lock); zloop_mark_empty(zlo, zone); clear_bit(ZLOOP_ZONE_SEQ_ERROR, &zone->flags); - spin_unlock_irqrestore(&zone->wp_lock, flags); + spin_unlock(&zone->wp_lock); unlock: mutex_unlock(&zone->lock); @@ -470,7 +467,6 @@ static int zloop_reset_all_zones(struct zloop_device *zlo) static int zloop_finish_zone(struct zloop_device *zlo, unsigned int zone_no) { struct zloop_zone *zone = &zlo->zones[zone_no]; - unsigned long flags; int ret = 0; if (test_bit(ZLOOP_ZONE_CONV, &zone->flags)) @@ -488,10 +484,10 @@ static int zloop_finish_zone(struct zloop_device *zlo, unsigned int zone_no) goto unlock; } - spin_lock_irqsave(&zone->wp_lock, flags); + spin_lock(&zone->wp_lock); zloop_mark_full(zlo, zone); clear_bit(ZLOOP_ZONE_SEQ_ERROR, &zone->flags); - spin_unlock_irqrestore(&zone->wp_lock, flags); + spin_unlock(&zone->wp_lock); unlock: mutex_unlock(&zone->lock); @@ -581,10 +577,9 @@ static int zloop_seq_write_prep(struct zloop_cmd *cmd) bool is_append = req_op(rq) == REQ_OP_ZONE_APPEND; struct zloop_zone *zone = &zlo->zones[zone_no]; sector_t zone_end = zone->start + zlo->zone_capacity; - unsigned long flags; int ret = 0; - spin_lock_irqsave(&zone->wp_lock, flags); + spin_lock(&zone->wp_lock); /* * Zone append operations always go at the current write pointer, but @@ -630,7 +625,7 @@ static int zloop_seq_write_prep(struct zloop_cmd *cmd) zloop_mark_full(zlo, zone); } out_unlock: - spin_unlock_irqrestore(&zone->wp_lock, flags); + spin_unlock(&zone->wp_lock); return ret; } @@ -868,13 +863,12 @@ static bool zloop_set_zone_append_sector(struct request *rq) struct zloop_zone *zone = &zlo->zones[zone_no]; sector_t zone_end = zone->start + zlo->zone_capacity; sector_t nr_sectors = blk_rq_sectors(rq); - unsigned long flags; - spin_lock_irqsave(&zone->wp_lock, flags); + spin_lock(&zone->wp_lock); if (zone->cond == BLK_ZONE_COND_FULL || zone->wp + nr_sectors > zone_end) { - spin_unlock_irqrestore(&zone->wp_lock, flags); + spin_unlock(&zone->wp_lock); return false; } @@ -883,7 +877,7 @@ static bool zloop_set_zone_append_sector(struct request *rq) if (zone->wp >= zone_end) zloop_mark_full(zlo, zone); - spin_unlock_irqrestore(&zone->wp_lock, flags); + spin_unlock(&zone->wp_lock); return true; } @@ -944,7 +938,6 @@ static int zloop_report_zones(struct gendisk *disk, sector_t sector, struct zloop_device *zlo = disk->private_data; struct blk_zone blkz = {}; unsigned int first, i; - unsigned long flags; int ret; first = disk_zone_no(disk, sector); @@ -968,9 +961,9 @@ static int zloop_report_zones(struct gendisk *disk, sector_t sector, blkz.start = zone->start; blkz.len = zlo->zone_size; - spin_lock_irqsave(&zone->wp_lock, flags); + spin_lock(&zone->wp_lock); blkz.wp = zone->wp; - spin_unlock_irqrestore(&zone->wp_lock, flags); + spin_unlock(&zone->wp_lock); blkz.cond = zone->cond; if (test_bit(ZLOOP_ZONE_CONV, &zone->flags)) { blkz.type = BLK_ZONE_TYPE_CONVENTIONAL; From 2f5015461984caa8ebf265a60b22f38c94d9c70a Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Wed, 15 Apr 2026 15:08:47 -0600 Subject: [PATCH 07/21] t10-pi: reduce ref tag code duplication t10_pi_ref_tag() and ext_pi_ref_tag() are identical except for the final truncation of the ref tag to 32 or 48 bits. Factor out a helper full_pi_ref_tag() to return the untruncated ref tag and use it in t10_pi_ref_tag() and ext_pi_ref_tag(). Signed-off-by: Caleb Sander Mateos Reviewed-by: Anuj Gupta Reviewed-by: Christoph Hellwig Link: https://patch.msgid.link/20260415210847.1730016-1-csander@purestorage.com Signed-off-by: Jens Axboe --- include/linux/t10-pi.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/include/linux/t10-pi.h b/include/linux/t10-pi.h index 2c59fe3efcd4..b6c2496866ea 100644 --- a/include/linux/t10-pi.h +++ b/include/linux/t10-pi.h @@ -4,6 +4,7 @@ #include #include +#include /* * A T10 PI-capable target device can be formatted with different @@ -25,6 +26,16 @@ enum t10_dif_type { T10_PI_TYPE3_PROTECTION = 0x3, }; +static inline u64 full_pi_ref_tag(const struct request *rq) +{ + unsigned int shift = ilog2(queue_logical_block_size(rq->q)); + + if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) && + rq->q->limits.integrity.interval_exp) + shift = rq->q->limits.integrity.interval_exp; + return blk_rq_pos(rq) >> (shift - SECTOR_SHIFT); +} + /* * T10 Protection Information tuple. */ @@ -39,12 +50,7 @@ struct t10_pi_tuple { static inline u32 t10_pi_ref_tag(struct request *rq) { - unsigned int shift = ilog2(queue_logical_block_size(rq->q)); - - if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) && - rq->q->limits.integrity.interval_exp) - shift = rq->q->limits.integrity.interval_exp; - return blk_rq_pos(rq) >> (shift - SECTOR_SHIFT) & 0xffffffff; + return lower_32_bits(full_pi_ref_tag(rq)); } struct crc64_pi_tuple { @@ -64,12 +70,7 @@ static inline u64 lower_48_bits(u64 n) static inline u64 ext_pi_ref_tag(struct request *rq) { - unsigned int shift = ilog2(queue_logical_block_size(rq->q)); - - if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) && - rq->q->limits.integrity.interval_exp) - shift = rq->q->limits.integrity.interval_exp; - return lower_48_bits(blk_rq_pos(rq) >> (shift - SECTOR_SHIFT)); + return lower_48_bits(full_pi_ref_tag(rq)); } #endif From a7c9fa7f6601c84d27cdd43bd96e8fcbacfb7479 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 16 Apr 2026 07:02:46 +0800 Subject: [PATCH 08/21] ublk: use unchecked copy helpers for bio page data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bio pages may originate from slab caches that lack a usercopy region (e.g. jbd2 frozen metadata buffers allocated via jbd2_alloc()). When CONFIG_HARDENED_USERCOPY is enabled, copy_to_iter() calls check_copy_size() which rejects these slab pages, triggering a kernel BUG in usercopy_abort(). This is a false positive: the data is ordinary block I/O content — the same data the loop driver writes to its backing file via vfs_iter_write(). The bvec length is always trusted, so the size check in check_copy_size() is not needed either. Switch to _copy_to_iter()/_copy_from_iter() which skip the check_copy_size() wrapper while the underlying copy_to_user() remains unchanged. Acked-by: Caleb Sander Mateos Fixes: 2299ceec364e ("ublk: use copy_{to,from}_iter() for user copy") Signed-off-by: Ming Lei Link: https://patch.msgid.link/20260415230246.808176-1-tom.leiming@gmail.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 603a98a30989..ef8a0705e68b 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -1319,10 +1319,18 @@ static bool ublk_copy_user_bvec(const struct bio_vec *bv, unsigned *offset, len = bv->bv_len - *offset; bv_buf = kmap_local_page(bv->bv_page) + bv->bv_offset + *offset; + /* + * Bio pages may originate from slab caches without a usercopy region + * (e.g. jbd2 frozen metadata buffers). This is the same data that + * the loop driver writes to its backing file — no exposure risk. + * The bvec length is always trusted, so the size check in + * check_copy_size() is not needed either. Use the unchecked + * helpers to avoid false positives on slab pages. + */ if (dir == ITER_DEST) - copied = copy_to_iter(bv_buf, len, uiter); + copied = _copy_to_iter(bv_buf, len, uiter); else - copied = copy_from_iter(bv_buf, len, uiter); + copied = _copy_from_iter(bv_buf, len, uiter); kunmap_local(bv_buf); From e784f2ea0b4fd0e7b70028ff8218f22456c5dcf8 Mon Sep 17 00:00:00 2001 From: Guangshuo Li Date: Wed, 15 Apr 2026 22:57:08 +0800 Subject: [PATCH 09/21] floppy: fix reference leak on platform_device_register() failure When platform_device_register() fails in do_floppy_init(), the embedded struct device in floppy_device[drive] has already been initialized by device_initialize(), but the failure path jumps to out_remove_drives without dropping the device reference for the current drive. Previously registered floppy devices are cleaned up in out_remove_drives, but the device for the drive that fails registration is not, leading to a reference leak. The issue was identified by a static analysis tool I developed and confirmed by manual review. Fix this by calling put_device() for the current floppy device before jumping to the common cleanup path. Fixes: 94fd0db7bfb4a ("[PATCH] Floppy: Add cmos attribute to floppy driver") Cc: stable@vger.kernel.org Signed-off-by: Guangshuo Li Link: https://patch.msgid.link/20260415145708.3331818-1-lgs201920130244@gmail.com Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 0509746f8aed..a028bf6b8ae2 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4722,15 +4722,19 @@ static int __init do_floppy_init(void) floppy_device[drive].dev.groups = floppy_dev_groups; err = platform_device_register(&floppy_device[drive]); - if (err) + if (err) { + platform_device_put(&floppy_device[drive]); goto out_remove_drives; - + } registered[drive] = true; err = device_add_disk(&floppy_device[drive].dev, disks[drive][0], NULL); - if (err) + if (err) { + platform_device_unregister(&floppy_device[drive]); + registered[drive] = false; goto out_remove_drives; + } } return 0; From 13920e4b7b784b40cf4519ff1f0f3e513476a499 Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Fri, 10 Apr 2026 15:34:13 +0000 Subject: [PATCH 10/21] block: add pgmap check to biovec_phys_mergeable biovec_phys_mergeable() is used by the request merge, DMA mapping, and integrity merge paths to decide if two physically contiguous bvec segments can be coalesced into one. It currently has no check for whether the segments belong to different dev_pagemaps. When zone device memory is registered in multiple chunks, each chunk gets its own dev_pagemap. A single bio can legitimately contain bvecs from different pgmaps -- iov_iter_extract_bvecs() breaks at pgmap boundaries but the outer loop in bio_iov_iter_get_pages() continues filling the same bio. If such bvecs are physically contiguous, biovec_phys_mergeable() will coalesce them, making it impossible to recover the correct pgmap for the merged segment via page_pgmap(). Add a zone_device_pages_have_same_pgmap() check to prevent merging bvec segments that span different pgmaps. Fixes: 49580e690755 ("block: add check when merging zone device pages") Cc: stable@vger.kernel.org Reviewed-by: Christoph Hellwig Signed-off-by: Naman Jain Link: https://patch.msgid.link/20260410153414.4159050-2-namjain@linux.microsoft.com Signed-off-by: Jens Axboe --- block/blk.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/blk.h b/block/blk.h index ec4674cdf2ea..50a41db03913 100644 --- a/block/blk.h +++ b/block/blk.h @@ -127,6 +127,8 @@ static inline bool biovec_phys_mergeable(struct request_queue *q, if (addr1 + vec1->bv_len != addr2) return false; + if (!zone_device_pages_have_same_pgmap(vec1->bv_page, vec2->bv_page)) + return false; if (xen_domain() && !xen_biovec_phys_mergeable(vec1, vec2->bv_page)) return false; if ((addr1 | mask) != ((addr2 + vec2->bv_len - 1) | mask)) From 41c665aae2b5dbecddddcc8ace344caf630cc7a4 Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Fri, 10 Apr 2026 15:34:14 +0000 Subject: [PATCH 11/21] block: relax pgmap check in bio_add_page for compatible zone device pages bio_add_page() and bio_integrity_add_page() reject pages from different dev_pagemaps entirely, returning 0 even when those pages have compatible DMA mapping requirements. This forces callers to start a new bio when buffers span pgmap boundaries, even though the pages could safely coexist as separate bvec entries. This matters for guests where memory is registered through devm_memremap_pages() with MEMORY_DEVICE_GENERIC in multiple calls, creating separate dev_pagemaps for each chunk. When a direct I/O buffer spans two such chunks, bio_add_page() rejects the second page, forcing an unnecessary bio split or I/O failure. Introduce zone_device_pages_compatible() in blk.h to check whether two pages can coexist in the same bio as separate bvec entries. The block DMA iterator (blk_dma_map_iter_start) caches the P2PDMA mapping state from the first segment and applies it to all others, so P2PDMA pages from different pgmaps must not be mixed, and neither must P2PDMA and non-P2PDMA pages. All other combinations (MEMORY_DEVICE_GENERIC pages from different pgmaps, or MEMORY_DEVICE_GENERIC with normal RAM) use the same dma_map_phys path and are safe. Replace the blanket zone_device_pages_have_same_pgmap() rejection with zone_device_pages_compatible(), while keeping zone_device_pages_have_same_pgmap() as a merge guard. Pages from different pgmaps can be added as separate bvec entries but must not be coalesced into the same segment, as that would make it impossible to recover the correct pgmap via page_pgmap(). Fixes: 49580e690755 ("block: add check when merging zone device pages") Cc: stable@vger.kernel.org Signed-off-by: Naman Jain Reviewed-by: Christoph Hellwig Link: https://patch.msgid.link/20260410153414.4159050-3-namjain@linux.microsoft.com Signed-off-by: Jens Axboe --- block/bio-integrity.c | 6 +++--- block/bio.c | 6 +++--- block/blk.h | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/block/bio-integrity.c b/block/bio-integrity.c index e79eaf047794..e54c6e06e1cb 100644 --- a/block/bio-integrity.c +++ b/block/bio-integrity.c @@ -231,10 +231,10 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, if (bip->bip_vcnt > 0) { struct bio_vec *bv = &bip->bip_vec[bip->bip_vcnt - 1]; - if (!zone_device_pages_have_same_pgmap(bv->bv_page, page)) + if (!zone_device_pages_compatible(bv->bv_page, page)) return 0; - - if (bvec_try_merge_hw_page(q, bv, page, len, offset)) { + if (zone_device_pages_have_same_pgmap(bv->bv_page, page) && + bvec_try_merge_hw_page(q, bv, page, len, offset)) { bip->bip_iter.bi_size += len; return len; } diff --git a/block/bio.c b/block/bio.c index 641ef0928d73..c52a0bd1e899 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1048,10 +1048,10 @@ int bio_add_page(struct bio *bio, struct page *page, if (bio->bi_vcnt > 0) { struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1]; - if (!zone_device_pages_have_same_pgmap(bv->bv_page, page)) + if (!zone_device_pages_compatible(bv->bv_page, page)) return 0; - - if (bvec_try_merge_page(bv, page, len, offset)) { + if (zone_device_pages_have_same_pgmap(bv->bv_page, page) && + bvec_try_merge_page(bv, page, len, offset)) { bio->bi_iter.bi_size += len; return len; } diff --git a/block/blk.h b/block/blk.h index 50a41db03913..b998a7761faf 100644 --- a/block/blk.h +++ b/block/blk.h @@ -136,6 +136,25 @@ static inline bool biovec_phys_mergeable(struct request_queue *q, return true; } +/* + * Check if two pages from potentially different zone device pgmaps can + * coexist as separate bvec entries in the same bio. + * + * The block DMA iterator (blk_dma_map_iter_start) caches the P2PDMA mapping + * state from the first segment and applies it to all subsequent segments, so + * P2PDMA pages from different pgmaps must not be mixed in the same bio. + * + * Other zone device types (FS_DAX, GENERIC) use the same dma_map_phys() path + * as normal RAM. PRIVATE and COHERENT pages never appear in bios. + */ +static inline bool zone_device_pages_compatible(const struct page *a, + const struct page *b) +{ + if (is_pci_p2pdma_page(a) || is_pci_p2pdma_page(b)) + return zone_device_pages_have_same_pgmap(a, b); + return true; +} + static inline bool __bvec_gap_to_prev(const struct queue_limits *lim, struct bio_vec *bprv, unsigned int offset) { From 98236343bb5dbbf3fcb3260795be2bbb1e3d2001 Mon Sep 17 00:00:00 2001 From: Marco Crivellari Date: Mon, 23 Feb 2026 10:29:19 +0100 Subject: [PATCH 12/21] block: Add WQ_PERCPU to alloc_workqueue users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This continues the effort to refactor workqueue APIs, which began with the introduction of new workqueues and a new alloc_workqueue flag in: commit 128ea9f6ccfb ("workqueue: Add system_percpu_wq and system_dfl_wq") commit 930c2ea566af ("workqueue: Add new WQ_PERCPU flag") The refactoring is going to alter the default behavior of alloc_workqueue() to be unbound by default. With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND), any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND must now use WQ_PERCPU. For more details see the Link tag below. In order to keep alloc_workqueue() behavior identical, explicitly request WQ_PERCPU. Link: https://lore.kernel.org/all/20250221112003.1dSuoGyc@linutronix.de/ Suggested-by: Tejun Heo Signed-off-by: Marco Crivellari Link: https://patch.msgid.link/20260223092920.60424-2-marco.crivellari@suse.com Signed-off-by: Jens Axboe --- block/bio-integrity-auto.c | 2 +- block/bio.c | 2 +- block/blk-core.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/block/bio-integrity-auto.c b/block/bio-integrity-auto.c index ebd17f47e0f9..353eed632fcc 100644 --- a/block/bio-integrity-auto.c +++ b/block/bio-integrity-auto.c @@ -125,7 +125,7 @@ static int __init blk_integrity_auto_init(void) * Make it highpri CPU intensive wq with max concurrency of 1. */ kintegrityd_wq = alloc_workqueue("kintegrityd", WQ_MEM_RECLAIM | - WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1); + WQ_HIGHPRI | WQ_CPU_INTENSIVE | WQ_PERCPU, 1); if (!kintegrityd_wq) panic("Failed to create kintegrityd\n"); return 0; diff --git a/block/bio.c b/block/bio.c index c52a0bd1e899..4d46af0cd256 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1958,7 +1958,7 @@ int bioset_init(struct bio_set *bs, if (flags & BIOSET_NEED_RESCUER) { bs->rescue_workqueue = alloc_workqueue("bioset", - WQ_MEM_RECLAIM, 0); + WQ_MEM_RECLAIM | WQ_PERCPU, 0); if (!bs->rescue_workqueue) goto bad; } diff --git a/block/blk-core.c b/block/blk-core.c index 474700ffaa1c..17450058ea6d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1282,7 +1282,7 @@ int __init blk_dev_init(void) /* used for unplugging and affects IO latency/throughput - HIGHPRI */ kblockd_workqueue = alloc_workqueue("kblockd", - WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); + WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU, 0); if (!kblockd_workqueue) panic("Failed to create kblockd\n"); From 19d32966e1f68623ac9d95fbcf34b1fb1a7be48d Mon Sep 17 00:00:00 2001 From: Marco Crivellari Date: Mon, 23 Feb 2026 10:29:20 +0100 Subject: [PATCH 13/21] block/blk-throttle: Add WQ_PERCPU to alloc_workqueue users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This continues the effort to refactor workqueue APIs, which began with the introduction of new workqueues and a new alloc_workqueue flag in: commit 128ea9f6ccfb ("workqueue: Add system_percpu_wq and system_dfl_wq") commit 930c2ea566af ("workqueue: Add new WQ_PERCPU flag") The refactoring is going to alter the default behavior of alloc_workqueue() to be unbound by default. With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND), any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND must now use WQ_PERCPU. For more details see the Link tag below. In order to keep alloc_workqueue() behavior identical, explicitly request WQ_PERCPU. Cc: Josef Bacik Cc: cgroups@vger.kernel.org Link: https://lore.kernel.org/all/20250221112003.1dSuoGyc@linutronix.de/ Suggested-by: Tejun Heo Signed-off-by: Marco Crivellari Link: https://patch.msgid.link/20260223092920.60424-3-marco.crivellari@suse.com Signed-off-by: Jens Axboe --- block/blk-throttle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 97188a795848..cabf91f0d0dc 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -1839,7 +1839,7 @@ void blk_throtl_exit(struct gendisk *disk) static int __init throtl_init(void) { - kthrotld_workqueue = alloc_workqueue("kthrotld", WQ_MEM_RECLAIM, 0); + kthrotld_workqueue = alloc_workqueue("kthrotld", WQ_MEM_RECLAIM | WQ_PERCPU, 0); if (!kthrotld_workqueue) panic("Failed to create kthrotld\n"); From b5129bda5bbcceea5b2589c8248d39f77660aa19 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 15 Apr 2026 08:08:07 +0200 Subject: [PATCH 14/21] block: only restrict bio allocation gfp mask asked to block If the caller is asking for a non-blocking allocation, we should not further restrict the gfp mask, which just increases the likelihood of failures. Fixes: b520c4eef83d ("block: split bio_alloc_bioset more clearly into a fast and slowpath") Reported-by: Shin'ichiro Kawasaki Signed-off-by: Christoph Hellwig Reviewed-by: Bart Van Assche Reviewed-by: Hannes Reinecke Link: https://patch.msgid.link/20260415060813.807659-3-hch@lst.de Signed-off-by: Jens Axboe --- block/bio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/bio.c b/block/bio.c index 4d46af0cd256..b8972dba68a0 100644 --- a/block/bio.c +++ b/block/bio.c @@ -544,7 +544,8 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs, if (WARN_ON_ONCE(!mempool_initialized(&bs->bvec_pool) && nr_vecs > 0)) return NULL; - gfp = try_alloc_gfp(gfp); + if (saved_gfp & __GFP_DIRECT_RECLAIM) + gfp = try_alloc_gfp(gfp); if (bs->cache && nr_vecs <= BIO_INLINE_VECS) { /* * Set REQ_ALLOC_CACHE even if no cached bio is available to From eac857a12a95de69daae7fb657108d048db9b46d Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Tue, 21 Apr 2026 14:08:59 -0600 Subject: [PATCH 15/21] selftests: ublk: remove unused argument to _cleanup The _cleanup helper function doesn't take any arguments, so drop them from its callers. Signed-off-by: Caleb Sander Mateos Reviewed-by: Ming Lei Link: https://patch.msgid.link/20260421200901.1528842-2-csander@purestorage.com Signed-off-by: Jens Axboe --- tools/testing/selftests/ublk/test_batch_01.sh | 4 ++-- tools/testing/selftests/ublk/test_batch_02.sh | 2 +- tools/testing/selftests/ublk/test_batch_03.sh | 2 +- tools/testing/selftests/ublk/test_generic_02.sh | 4 ++-- tools/testing/selftests/ublk/test_generic_03.sh | 2 +- tools/testing/selftests/ublk/test_generic_06.sh | 2 +- tools/testing/selftests/ublk/test_generic_07.sh | 2 +- tools/testing/selftests/ublk/test_generic_08.sh | 4 ++-- tools/testing/selftests/ublk/test_generic_09.sh | 2 +- tools/testing/selftests/ublk/test_generic_10.sh | 2 +- tools/testing/selftests/ublk/test_generic_12.sh | 4 ++-- tools/testing/selftests/ublk/test_generic_13.sh | 2 +- tools/testing/selftests/ublk/test_generic_16.sh | 4 ++-- tools/testing/selftests/ublk/test_generic_17.sh | 2 +- tools/testing/selftests/ublk/test_loop_01.sh | 2 +- tools/testing/selftests/ublk/test_loop_02.sh | 2 +- tools/testing/selftests/ublk/test_loop_03.sh | 2 +- tools/testing/selftests/ublk/test_loop_04.sh | 2 +- tools/testing/selftests/ublk/test_loop_05.sh | 2 +- tools/testing/selftests/ublk/test_loop_06.sh | 2 +- tools/testing/selftests/ublk/test_loop_07.sh | 2 +- tools/testing/selftests/ublk/test_null_01.sh | 2 +- tools/testing/selftests/ublk/test_null_02.sh | 2 +- tools/testing/selftests/ublk/test_null_03.sh | 2 +- tools/testing/selftests/ublk/test_part_01.sh | 4 ++-- tools/testing/selftests/ublk/test_part_02.sh | 2 +- tools/testing/selftests/ublk/test_recover_01.sh | 2 +- tools/testing/selftests/ublk/test_recover_02.sh | 2 +- tools/testing/selftests/ublk/test_recover_03.sh | 2 +- tools/testing/selftests/ublk/test_recover_04.sh | 2 +- tools/testing/selftests/ublk/test_shmemzc_01.sh | 2 +- tools/testing/selftests/ublk/test_shmemzc_02.sh | 2 +- tools/testing/selftests/ublk/test_shmemzc_03.sh | 2 +- tools/testing/selftests/ublk/test_shmemzc_04.sh | 2 +- tools/testing/selftests/ublk/test_stress_01.sh | 2 +- tools/testing/selftests/ublk/test_stress_02.sh | 2 +- tools/testing/selftests/ublk/test_stress_03.sh | 2 +- tools/testing/selftests/ublk/test_stress_04.sh | 2 +- tools/testing/selftests/ublk/test_stress_05.sh | 2 +- tools/testing/selftests/ublk/test_stress_06.sh | 2 +- tools/testing/selftests/ublk/test_stress_07.sh | 2 +- tools/testing/selftests/ublk/test_stress_08.sh | 2 +- tools/testing/selftests/ublk/test_stress_09.sh | 2 +- tools/testing/selftests/ublk/test_stripe_01.sh | 2 +- tools/testing/selftests/ublk/test_stripe_02.sh | 2 +- tools/testing/selftests/ublk/test_stripe_03.sh | 2 +- tools/testing/selftests/ublk/test_stripe_04.sh | 2 +- tools/testing/selftests/ublk/test_stripe_05.sh | 2 +- tools/testing/selftests/ublk/test_stripe_06.sh | 2 +- 49 files changed, 55 insertions(+), 55 deletions(-) diff --git a/tools/testing/selftests/ublk/test_batch_01.sh b/tools/testing/selftests/ublk/test_batch_01.sh index a18fb39af8be..6e19303706a9 100755 --- a/tools/testing/selftests/ublk/test_batch_01.sh +++ b/tools/testing/selftests/ublk/test_batch_01.sh @@ -18,7 +18,7 @@ dev_id=$(_add_ublk_dev -t loop -q 2 -b "${UBLK_BACKFILES[0]}") _check_add_dev $TID $? if ! _mkfs_mount_test /dev/ublkb"${dev_id}"; then - _cleanup_test "generic" + _cleanup_test _show_result $TID 255 fi @@ -27,5 +27,5 @@ _check_add_dev $TID $? _mkfs_mount_test /dev/ublkb"${dev_id}" ERR_CODE=$? -_cleanup_test "generic" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_batch_02.sh b/tools/testing/selftests/ublk/test_batch_02.sh index 7ca384d11987..7c683f755379 100755 --- a/tools/testing/selftests/ublk/test_batch_02.sh +++ b/tools/testing/selftests/ublk/test_batch_02.sh @@ -25,5 +25,5 @@ fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio --rw=readwrit --iodepth=32 --size=100M --numjobs=4 > /dev/null 2>&1 ERR_CODE=$? -_cleanup_test "generic" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_batch_03.sh b/tools/testing/selftests/ublk/test_batch_03.sh index aca9cf144b55..914ccd6a335d 100755 --- a/tools/testing/selftests/ublk/test_batch_03.sh +++ b/tools/testing/selftests/ublk/test_batch_03.sh @@ -25,5 +25,5 @@ fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio --rw=readwrit --iodepth=32 --size=100M --numjobs=4 > /dev/null 2>&1 ERR_CODE=$? -_cleanup_test "generic" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_02.sh b/tools/testing/selftests/ublk/test_generic_02.sh index 46b657143fd6..2afc8cdbed8f 100755 --- a/tools/testing/selftests/ublk/test_generic_02.sh +++ b/tools/testing/selftests/ublk/test_generic_02.sh @@ -29,7 +29,7 @@ for _ in $(seq 100); do done if ! kill -0 "$btrace_pid" 2>/dev/null; then - _cleanup_test "null" + _cleanup_test exit "$UBLK_SKIP_CODE" fi @@ -51,5 +51,5 @@ if grep -q "^out_of_order:" "$UBLK_TMP"; then grep "^out_of_order:" "$UBLK_TMP" ERR_CODE=255 fi -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_03.sh b/tools/testing/selftests/ublk/test_generic_03.sh index 8934ea926762..8e78be860d34 100755 --- a/tools/testing/selftests/ublk/test_generic_03.sh +++ b/tools/testing/selftests/ublk/test_generic_03.sh @@ -23,5 +23,5 @@ fi if [ "$max_segment_size" != "32768" ]; then ERR_CODE=255 fi -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_06.sh b/tools/testing/selftests/ublk/test_generic_06.sh index 14a05054fcd8..a8b3634b6b4b 100755 --- a/tools/testing/selftests/ublk/test_generic_06.sh +++ b/tools/testing/selftests/ublk/test_generic_06.sh @@ -36,5 +36,5 @@ if [ $ELAPSED -ge 5 ]; then ERR_CODE=255 fi -_cleanup_test "fault_inject" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_07.sh b/tools/testing/selftests/ublk/test_generic_07.sh index 8dcfd8978f50..d2c5e65bd124 100755 --- a/tools/testing/selftests/ublk/test_generic_07.sh +++ b/tools/testing/selftests/ublk/test_generic_07.sh @@ -23,5 +23,5 @@ if [ "$ERR_CODE" -eq 0 ]; then ERR_CODE=$? fi -_cleanup_test "generic" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_08.sh b/tools/testing/selftests/ublk/test_generic_08.sh index ce88c31d6b9c..77a18b313f3d 100755 --- a/tools/testing/selftests/ublk/test_generic_08.sh +++ b/tools/testing/selftests/ublk/test_generic_08.sh @@ -18,7 +18,7 @@ dev_id=$(_add_ublk_dev -t loop -q 2 --auto_zc "${UBLK_BACKFILES[0]}") _check_add_dev $TID $? if ! _mkfs_mount_test /dev/ublkb"${dev_id}"; then - _cleanup_test "generic" + _cleanup_test _show_result $TID 255 fi @@ -27,5 +27,5 @@ _check_add_dev $TID $? _mkfs_mount_test /dev/ublkb"${dev_id}" ERR_CODE=$? -_cleanup_test "generic" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_09.sh b/tools/testing/selftests/ublk/test_generic_09.sh index 744d0cdaa242..6c25242f245f 100755 --- a/tools/testing/selftests/ublk/test_generic_09.sh +++ b/tools/testing/selftests/ublk/test_generic_09.sh @@ -22,6 +22,6 @@ _check_add_dev $TID $? fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio --rw=readwrite --iodepth=32 --size=256M > /dev/null 2>&1 ERR_CODE=$? -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_10.sh b/tools/testing/selftests/ublk/test_generic_10.sh index 4b4293b9081f..fdabc9d9075e 100755 --- a/tools/testing/selftests/ublk/test_generic_10.sh +++ b/tools/testing/selftests/ublk/test_generic_10.sh @@ -25,5 +25,5 @@ if [ "$new_size" != "$size" ]; then ERR_CODE=255 fi -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_12.sh b/tools/testing/selftests/ublk/test_generic_12.sh index 54b81ddfe9f9..435497f8da8d 100755 --- a/tools/testing/selftests/ublk/test_generic_12.sh +++ b/tools/testing/selftests/ublk/test_generic_12.sh @@ -25,7 +25,7 @@ btrace_pid=$! sleep 2 if ! kill -0 "$btrace_pid" > /dev/null 2>&1; then - _cleanup_test "null" + _cleanup_test exit "$UBLK_SKIP_CODE" fi @@ -54,5 +54,5 @@ if [[ $NR_THREADS_THAT_HANDLED_IO -ne $NTHREADS ]]; then ERR_CODE=255 fi -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_13.sh b/tools/testing/selftests/ublk/test_generic_13.sh index 922115aa14f4..2c1be6286db8 100755 --- a/tools/testing/selftests/ublk/test_generic_13.sh +++ b/tools/testing/selftests/ublk/test_generic_13.sh @@ -15,5 +15,5 @@ if ${UBLK_PROG} features | grep -q unknown; then ERR_CODE=255 fi -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_16.sh b/tools/testing/selftests/ublk/test_generic_16.sh index 3ef367836ac5..6a4952146ea1 100755 --- a/tools/testing/selftests/ublk/test_generic_16.sh +++ b/tools/testing/selftests/ublk/test_generic_16.sh @@ -9,7 +9,7 @@ _prep_test "null" "stop --safe command" # Check if SAFE_STOP_DEV feature is supported if ! _have_feature "SAFE_STOP_DEV"; then - _cleanup_test "null" + _cleanup_test exit "$UBLK_SKIP_CODE" fi @@ -52,5 +52,5 @@ wait $dd_pid 2>/dev/null _ublk_del_dev "${dev_id}" udevadm settle -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_generic_17.sh b/tools/testing/selftests/ublk/test_generic_17.sh index 2278b5fc9dba..b483d53a897a 100755 --- a/tools/testing/selftests/ublk/test_generic_17.sh +++ b/tools/testing/selftests/ublk/test_generic_17.sh @@ -31,5 +31,5 @@ fi # time out here _ublk_del_dev "${dev_id}" -_cleanup_test "fault_inject" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_loop_01.sh b/tools/testing/selftests/ublk/test_loop_01.sh index 338a235fd82a..c0f5b619ad6e 100755 --- a/tools/testing/selftests/ublk/test_loop_01.sh +++ b/tools/testing/selftests/ublk/test_loop_01.sh @@ -20,6 +20,6 @@ _check_add_dev $TID $? _run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M ERR_CODE=$? -_cleanup_test "loop" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_loop_02.sh b/tools/testing/selftests/ublk/test_loop_02.sh index 04c52454e2ec..f4191ea71f50 100755 --- a/tools/testing/selftests/ublk/test_loop_02.sh +++ b/tools/testing/selftests/ublk/test_loop_02.sh @@ -14,6 +14,6 @@ _check_add_dev $TID $? _mkfs_mount_test /dev/ublkb"${dev_id}" ERR_CODE=$? -_cleanup_test "loop" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_loop_03.sh b/tools/testing/selftests/ublk/test_loop_03.sh index 6e8f649fe93d..aaac0c59a5ad 100755 --- a/tools/testing/selftests/ublk/test_loop_03.sh +++ b/tools/testing/selftests/ublk/test_loop_03.sh @@ -19,6 +19,6 @@ _check_add_dev $TID $? _run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M ERR_CODE=$? -_cleanup_test "loop" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_loop_04.sh b/tools/testing/selftests/ublk/test_loop_04.sh index 9f6774ec0de6..f584c119f1d2 100755 --- a/tools/testing/selftests/ublk/test_loop_04.sh +++ b/tools/testing/selftests/ublk/test_loop_04.sh @@ -15,6 +15,6 @@ _check_add_dev $TID $? _mkfs_mount_test /dev/ublkb"${dev_id}" ERR_CODE=$? -_cleanup_test "loop" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_loop_05.sh b/tools/testing/selftests/ublk/test_loop_05.sh index 2b8d99e007be..ca1a5df5f9de 100755 --- a/tools/testing/selftests/ublk/test_loop_05.sh +++ b/tools/testing/selftests/ublk/test_loop_05.sh @@ -20,6 +20,6 @@ _check_add_dev $TID $? _run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M ERR_CODE=$? -_cleanup_test "loop" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_loop_06.sh b/tools/testing/selftests/ublk/test_loop_06.sh index e73f6f4844db..26f710ba9db7 100755 --- a/tools/testing/selftests/ublk/test_loop_06.sh +++ b/tools/testing/selftests/ublk/test_loop_06.sh @@ -19,6 +19,6 @@ _check_add_dev $TID $? _run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M ERR_CODE=$? -_cleanup_test "loop" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_loop_07.sh b/tools/testing/selftests/ublk/test_loop_07.sh index 264d20e7c530..a9ab0b671cb2 100755 --- a/tools/testing/selftests/ublk/test_loop_07.sh +++ b/tools/testing/selftests/ublk/test_loop_07.sh @@ -15,6 +15,6 @@ _check_add_dev $TID $? _mkfs_mount_test /dev/ublkb"${dev_id}" ERR_CODE=$? -_cleanup_test "loop" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_null_01.sh b/tools/testing/selftests/ublk/test_null_01.sh index eebce8076530..d2c38cbb2dd5 100755 --- a/tools/testing/selftests/ublk/test_null_01.sh +++ b/tools/testing/selftests/ublk/test_null_01.sh @@ -18,6 +18,6 @@ _check_add_dev $TID $? fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio --rw=readwrite --iodepth=32 --size=256M > /dev/null 2>&1 ERR_CODE=$? -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_null_02.sh b/tools/testing/selftests/ublk/test_null_02.sh index 654bdff39664..7b205ca56367 100755 --- a/tools/testing/selftests/ublk/test_null_02.sh +++ b/tools/testing/selftests/ublk/test_null_02.sh @@ -18,6 +18,6 @@ _check_add_dev $TID $? fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio --rw=readwrite --iodepth=32 --size=256M > /dev/null 2>&1 ERR_CODE=$? -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_null_03.sh b/tools/testing/selftests/ublk/test_null_03.sh index 29cd09f06672..eee7a87a60da 100755 --- a/tools/testing/selftests/ublk/test_null_03.sh +++ b/tools/testing/selftests/ublk/test_null_03.sh @@ -18,6 +18,6 @@ _check_add_dev $TID $? fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio --rw=readwrite --iodepth=32 --size=256M > /dev/null 2>&1 ERR_CODE=$? -_cleanup_test "null" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_part_01.sh b/tools/testing/selftests/ublk/test_part_01.sh index 8028f6e4b3a5..fa3b1a9af894 100755 --- a/tools/testing/selftests/ublk/test_part_01.sh +++ b/tools/testing/selftests/ublk/test_part_01.sh @@ -82,7 +82,7 @@ fi _prep_test "generic" "test UBLK_F_NO_AUTO_PART_SCAN" if ! _have_feature "UBLK_F_NO_AUTO_PART_SCAN"; then - _cleanup_test "generic" + _cleanup_test exit "$UBLK_SKIP_CODE" fi @@ -100,5 +100,5 @@ format_backing_file "${UBLK_BACKFILES[0]}" [ "$ERR_CODE" -eq 0 ] && test_no_auto_part_scan "${UBLK_BACKFILES[0]}" [ $? -ne 0 ] && ERR_CODE=255 -_cleanup_test "generic" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_part_02.sh b/tools/testing/selftests/ublk/test_part_02.sh index 7d42ab4d6e83..d9ec06f36aee 100755 --- a/tools/testing/selftests/ublk/test_part_02.sh +++ b/tools/testing/selftests/ublk/test_part_02.sh @@ -63,5 +63,5 @@ _test_partition_scan_no_hang "no" "DEAD" # Test 2: With recovery support - should transition to QUIESCED _test_partition_scan_no_hang "yes" "QUIESCED" -_cleanup_test "partition_scan" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_recover_01.sh b/tools/testing/selftests/ublk/test_recover_01.sh index 2672f9c40fa8..1cddc2345dab 100755 --- a/tools/testing/selftests/ublk/test_recover_01.sh +++ b/tools/testing/selftests/ublk/test_recover_01.sh @@ -40,5 +40,5 @@ ublk_run_recover_test -t loop -q 2 -r 1 -i 1 "${UBLK_BACKFILES[0]}" & ublk_run_recover_test -t stripe -q 2 -r 1 -i 1 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & wait -_cleanup_test "recover" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_recover_02.sh b/tools/testing/selftests/ublk/test_recover_02.sh index bda5064bc31f..9c3f481880d3 100755 --- a/tools/testing/selftests/ublk/test_recover_02.sh +++ b/tools/testing/selftests/ublk/test_recover_02.sh @@ -44,5 +44,5 @@ ublk_run_recover_test -t loop -q 2 -r 1 -z -i 1 "${UBLK_BACKFILES[0]}" & ublk_run_recover_test -t stripe -q 2 -r 1 -z -i 1 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & wait -_cleanup_test "recover" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_recover_03.sh b/tools/testing/selftests/ublk/test_recover_03.sh index e0dc0b8fe5d6..2554805e5b02 100755 --- a/tools/testing/selftests/ublk/test_recover_03.sh +++ b/tools/testing/selftests/ublk/test_recover_03.sh @@ -39,5 +39,5 @@ ublk_run_quiesce_recover -t loop -q 2 -r 1 -i 1 "${UBLK_BACKFILES[0]}" & ublk_run_quiesce_recover -t stripe -q 2 -r 1 -i 1 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & wait -_cleanup_test "quiesce" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_recover_04.sh b/tools/testing/selftests/ublk/test_recover_04.sh index 178443394ca5..4c83c1840c68 100755 --- a/tools/testing/selftests/ublk/test_recover_04.sh +++ b/tools/testing/selftests/ublk/test_recover_04.sh @@ -35,5 +35,5 @@ ublk_run_recover_test -t loop -q 2 -r 1 -u -i 1 "${UBLK_BACKFILES[0]}" & ublk_run_recover_test -t stripe -q 2 -r 1 -u -i 1 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & wait -_cleanup_test "recover" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_shmemzc_01.sh b/tools/testing/selftests/ublk/test_shmemzc_01.sh index 47210af2aa20..b244ab3479a2 100755 --- a/tools/testing/selftests/ublk/test_shmemzc_01.sh +++ b/tools/testing/selftests/ublk/test_shmemzc_01.sh @@ -67,6 +67,6 @@ umount "$HTLB_MNT" rmdir "$HTLB_MNT" echo "$OLD_NR_HP" > /proc/sys/vm/nr_hugepages -_cleanup_test "shmem_zc" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_shmemzc_02.sh b/tools/testing/selftests/ublk/test_shmemzc_02.sh index aed9262494e9..810dccba6d84 100755 --- a/tools/testing/selftests/ublk/test_shmemzc_02.sh +++ b/tools/testing/selftests/ublk/test_shmemzc_02.sh @@ -63,6 +63,6 @@ umount "$HTLB_MNT" rmdir "$HTLB_MNT" echo "$OLD_NR_HP" > /proc/sys/vm/nr_hugepages -_cleanup_test "shmem_zc" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_shmemzc_03.sh b/tools/testing/selftests/ublk/test_shmemzc_03.sh index db967a9ffe81..606362491a32 100755 --- a/tools/testing/selftests/ublk/test_shmemzc_03.sh +++ b/tools/testing/selftests/ublk/test_shmemzc_03.sh @@ -64,6 +64,6 @@ umount "$HTLB_MNT" rmdir "$HTLB_MNT" echo "$OLD_NR_HP" > /proc/sys/vm/nr_hugepages -_cleanup_test "shmem_zc" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_shmemzc_04.sh b/tools/testing/selftests/ublk/test_shmemzc_04.sh index 899de088ece4..9a2a6c2e8abe 100755 --- a/tools/testing/selftests/ublk/test_shmemzc_04.sh +++ b/tools/testing/selftests/ublk/test_shmemzc_04.sh @@ -67,6 +67,6 @@ umount "$HTLB_MNT" rmdir "$HTLB_MNT" echo "$OLD_NR_HP" > /proc/sys/vm/nr_hugepages -_cleanup_test "shmem_zc" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stress_01.sh b/tools/testing/selftests/ublk/test_stress_01.sh index a9322ce496e9..f91783f27649 100755 --- a/tools/testing/selftests/ublk/test_stress_01.sh +++ b/tools/testing/selftests/ublk/test_stress_01.sh @@ -29,5 +29,5 @@ ublk_io_and_remove 256M -t loop -q 4 "${UBLK_BACKFILES[0]}" & ublk_io_and_remove 256M -t stripe -q 4 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & wait -_cleanup_test "stress" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stress_02.sh b/tools/testing/selftests/ublk/test_stress_02.sh index 6c114194f9c9..b128d11658a8 100755 --- a/tools/testing/selftests/ublk/test_stress_02.sh +++ b/tools/testing/selftests/ublk/test_stress_02.sh @@ -31,5 +31,5 @@ for nr_queue in 1 4; do wait done -_cleanup_test "stress" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stress_03.sh b/tools/testing/selftests/ublk/test_stress_03.sh index 4e81ca0db758..a0f0aba8eebc 100755 --- a/tools/testing/selftests/ublk/test_stress_03.sh +++ b/tools/testing/selftests/ublk/test_stress_03.sh @@ -49,5 +49,5 @@ if _have_feature "PER_IO_DAEMON"; then wait fi -_cleanup_test "stress" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stress_04.sh b/tools/testing/selftests/ublk/test_stress_04.sh index 6c6f44b172bc..896eae68d444 100755 --- a/tools/testing/selftests/ublk/test_stress_04.sh +++ b/tools/testing/selftests/ublk/test_stress_04.sh @@ -48,5 +48,5 @@ if _have_feature "PER_IO_DAEMON"; then wait fi -_cleanup_test "stress" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stress_05.sh b/tools/testing/selftests/ublk/test_stress_05.sh index 7e9324de2030..d6c00c72080d 100755 --- a/tools/testing/selftests/ublk/test_stress_05.sh +++ b/tools/testing/selftests/ublk/test_stress_05.sh @@ -79,5 +79,5 @@ if _have_feature "PER_IO_DAEMON"; then fi wait -_cleanup_test "stress" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stress_06.sh b/tools/testing/selftests/ublk/test_stress_06.sh index c72e5d0b14be..9481a273a4b4 100755 --- a/tools/testing/selftests/ublk/test_stress_06.sh +++ b/tools/testing/selftests/ublk/test_stress_06.sh @@ -34,5 +34,5 @@ ublk_io_and_remove 256M -t loop -q 4 -u --nthreads 8 --per_io_tasks "${UBLK_BACK ublk_io_and_remove 256M -t stripe -q 4 -u --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & wait -_cleanup_test "stress" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stress_07.sh b/tools/testing/selftests/ublk/test_stress_07.sh index 04c2764d5238..3e01c037cffb 100755 --- a/tools/testing/selftests/ublk/test_stress_07.sh +++ b/tools/testing/selftests/ublk/test_stress_07.sh @@ -34,5 +34,5 @@ ublk_io_and_kill_daemon 256M -t loop -q 4 -u --nthreads 8 --per_io_tasks "${UBLK ublk_io_and_kill_daemon 256M -t stripe -q 4 -u --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & wait -_cleanup_test "stress" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stress_08.sh b/tools/testing/selftests/ublk/test_stress_08.sh index 37f7d204879a..5f32424d2892 100755 --- a/tools/testing/selftests/ublk/test_stress_08.sh +++ b/tools/testing/selftests/ublk/test_stress_08.sh @@ -40,5 +40,5 @@ ublk_io_and_remove 256M -t stripe -q 4 --auto_zc -b "${UBLK_BACKFILES[1]}" "${UB ublk_io_and_remove 8G -t null -q 4 -z --auto_zc --auto_zc_fallback -b & wait -_cleanup_test "stress" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stress_09.sh b/tools/testing/selftests/ublk/test_stress_09.sh index 53c1e3b2ab30..64cb8d9b0438 100755 --- a/tools/testing/selftests/ublk/test_stress_09.sh +++ b/tools/testing/selftests/ublk/test_stress_09.sh @@ -39,5 +39,5 @@ ublk_io_and_kill_daemon 256M -t stripe -q 4 -b "${UBLK_BACKFILES[1]}" "${UBLK_BA ublk_io_and_kill_daemon 8G -t null -q 4 -z --auto_zc --auto_zc_fallback -b & wait -_cleanup_test "stress" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stripe_01.sh b/tools/testing/selftests/ublk/test_stripe_01.sh index 3bc821aadad8..9ffce477b461 100755 --- a/tools/testing/selftests/ublk/test_stripe_01.sh +++ b/tools/testing/selftests/ublk/test_stripe_01.sh @@ -21,5 +21,5 @@ _check_add_dev $TID $? _run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=512M ERR_CODE=$? -_cleanup_test "stripe" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stripe_02.sh b/tools/testing/selftests/ublk/test_stripe_02.sh index 4a7d2b21a6bf..4c172950a247 100755 --- a/tools/testing/selftests/ublk/test_stripe_02.sh +++ b/tools/testing/selftests/ublk/test_stripe_02.sh @@ -16,5 +16,5 @@ _check_add_dev $TID $? _mkfs_mount_test /dev/ublkb"${dev_id}" ERR_CODE=$? -_cleanup_test "stripe" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stripe_03.sh b/tools/testing/selftests/ublk/test_stripe_03.sh index a1c159d54e53..2cdf9f958988 100755 --- a/tools/testing/selftests/ublk/test_stripe_03.sh +++ b/tools/testing/selftests/ublk/test_stripe_03.sh @@ -21,5 +21,5 @@ _check_add_dev $TID $? _run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=512M ERR_CODE=$? -_cleanup_test "stripe" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stripe_04.sh b/tools/testing/selftests/ublk/test_stripe_04.sh index 0c30bd6c2b3b..e24120eaca0e 100755 --- a/tools/testing/selftests/ublk/test_stripe_04.sh +++ b/tools/testing/selftests/ublk/test_stripe_04.sh @@ -16,5 +16,5 @@ _check_add_dev $TID $? _mkfs_mount_test /dev/ublkb"${dev_id}" ERR_CODE=$? -_cleanup_test "stripe" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stripe_05.sh b/tools/testing/selftests/ublk/test_stripe_05.sh index 6ddfa88ad226..f3de2d5cdfe4 100755 --- a/tools/testing/selftests/ublk/test_stripe_05.sh +++ b/tools/testing/selftests/ublk/test_stripe_05.sh @@ -21,5 +21,5 @@ _check_add_dev $TID $? _run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=512M ERR_CODE=$? -_cleanup_test "stripe" +_cleanup_test _show_result $TID $ERR_CODE diff --git a/tools/testing/selftests/ublk/test_stripe_06.sh b/tools/testing/selftests/ublk/test_stripe_06.sh index a2c7bf4cc613..3fd5cd902956 100755 --- a/tools/testing/selftests/ublk/test_stripe_06.sh +++ b/tools/testing/selftests/ublk/test_stripe_06.sh @@ -16,5 +16,5 @@ _check_add_dev $TID $? _mkfs_mount_test /dev/ublkb"${dev_id}" ERR_CODE=$? -_cleanup_test "stripe" +_cleanup_test _show_result $TID $ERR_CODE From eb3d1922120605e8934c75fde06b6ab85fc8699d Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Tue, 21 Apr 2026 14:09:00 -0600 Subject: [PATCH 16/21] selftests: ublk: enable test_integrity_02.sh on fio 3.42 fio 3.42 was released with the needed fix for test_integrity_02.sh. Allow 3.42 and newer in the fio version check. Signed-off-by: Caleb Sander Mateos Reviewed-by: Ming Lei Link: https://patch.msgid.link/20260421200901.1528842-3-csander@purestorage.com Signed-off-by: Jens Axboe --- tools/testing/selftests/ublk/test_integrity_02.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/ublk/test_integrity_02.sh b/tools/testing/selftests/ublk/test_integrity_02.sh index aaf1f52da559..2c35fbc8a7cc 100755 --- a/tools/testing/selftests/ublk/test_integrity_02.sh +++ b/tools/testing/selftests/ublk/test_integrity_02.sh @@ -7,9 +7,10 @@ if ! _have_program fio; then exit $UBLK_SKIP_CODE fi +min_fio_version=fio-3.42 fio_version=$(fio --version) -if [[ "$fio_version" =~ fio-[0-9]+\.[0-9]+$ ]]; then - echo "Requires development fio version with https://github.com/axboe/fio/pull/1992" +if ! sort --version-sort --check=quiet <(printf "%s\n%s\n" "$min_fio_version" "$fio_version"); then + echo "Requires fio version with https://github.com/axboe/fio/pull/1992" exit $UBLK_SKIP_CODE fi From 1cdf3b28f46dd82caca39d72e401250ee43130ba Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Tue, 21 Apr 2026 14:09:01 -0600 Subject: [PATCH 17/21] selftests: ublk: add ublk auto integrity test The end-to-end integrity ublk selftest test_integrity_02 requires a relatively recent fio version to support I/O with integrity buffers. Add a version test_integrity_03 that uses the block layer's auto integrity path instead. The auto integrity code doesn't check the application tag, and doesn't indicate the bad guard/ref tag (just returns EILSEQ). But it's a good smoke-test of the ublk integrity code and provides coverage of the auto integrity path as well. Signed-off-by: Caleb Sander Mateos Reviewed-by: Ming Lei Link: https://patch.msgid.link/20260421200901.1528842-4-csander@purestorage.com Signed-off-by: Jens Axboe --- tools/testing/selftests/ublk/Makefile | 1 + .../selftests/ublk/test_integrity_03.sh | 103 ++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100755 tools/testing/selftests/ublk/test_integrity_03.sh diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile index ec6a8ce83d38..6e4fe8d1fed1 100644 --- a/tools/testing/selftests/ublk/Makefile +++ b/tools/testing/selftests/ublk/Makefile @@ -37,6 +37,7 @@ TEST_PROGS += test_loop_07.sh TEST_PROGS += test_integrity_01.sh TEST_PROGS += test_integrity_02.sh +TEST_PROGS += test_integrity_03.sh TEST_PROGS += test_recover_01.sh TEST_PROGS += test_recover_02.sh diff --git a/tools/testing/selftests/ublk/test_integrity_03.sh b/tools/testing/selftests/ublk/test_integrity_03.sh new file mode 100755 index 000000000000..10f02339ea2d --- /dev/null +++ b/tools/testing/selftests/ublk/test_integrity_03.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh + +if ! _have_program fio; then + exit $UBLK_SKIP_CODE +fi + +_test_fill_and_verify() { + fio --name fill --rw randwrite $fio_args > /dev/null + if [ $? != 0 ]; then + echo "fio fill failed" + ERR_CODE=255 + return 1 + fi + + fio --name verify --rw randread $fio_args > /dev/null + if [ $? != 0 ]; then + echo "fio verify failed" + ERR_CODE=255 + return 1 + fi +} + +_test_corrupted_reftag() { + local dd_reftag_args="bs=1 seek=58 count=6 oflag=dsync conv=notrunc status=none" + + # Overwrite 6-byte reftag at offset 48 + 10 = 58 + dd if=/dev/urandom "of=${UBLK_BACKFILES[1]}" $dd_reftag_args + if [ $? != 0 ]; then + echo "dd corrupted_reftag failed" + ERR_CODE=255 + return 1 + fi + + if fio --name corrupted_reftag --rw randread $fio_args > /dev/null 2> "$fio_err"; then + echo "fio corrupted_reftag unexpectedly succeeded" + ERR_CODE=255 + return 1 + fi + + if ! grep -q "$expected_err" "$fio_err"; then + echo "fio corrupted_reftag message not found: $expected_err" + ERR_CODE=255 + return 1 + fi + + # Reset to 0 + dd if=/dev/zero "of=${UBLK_BACKFILES[1]}" $dd_reftag_args + if [ $? != 0 ]; then + echo "dd restore corrupted_reftag failed" + ERR_CODE=255 + return 1 + fi +} + +_test_corrupted_data() { + local dd_data_args="bs=512 count=1 oflag=direct,dsync conv=notrunc status=none" + + dd if=/dev/zero "of=${UBLK_BACKFILES[0]}" $dd_data_args + if [ $? != 0 ]; then + echo "dd corrupted_data failed" + ERR_CODE=255 + return 1 + fi + + if fio --name corrupted_data --rw randread $fio_args > /dev/null 2> "$fio_err"; then + echo "fio corrupted_data unexpectedly succeeded" + ERR_CODE=255 + return 1 + fi + + if ! grep -q "$expected_err" "$fio_err"; then + echo "fio corrupted_data message not found: $expected_err" + ERR_CODE=255 + return 1 + fi +} + +_prep_test "loop" "end-to-end auto integrity" + +_create_backfile 0 256M +_create_backfile 1 32M # 256M * (64 integrity bytes / 512 data bytes) +integrity_params="--integrity_capable --integrity_reftag + --metadata_size 64 --pi_offset 48 --csum_type nvme" +dev_id=$(_add_ublk_dev -t loop -u $integrity_params "${UBLK_BACKFILES[@]}") +_check_add_dev "$TID" $? + +fio_args="--ioengine libaio --direct 1 --bsrange 512-1M --iodepth 32 + --filename /dev/ublkb$dev_id" +fio_err=$(mktemp "${UBLK_TEST_DIR}"/fio_err_XXXXX) +ERR_CODE=0 + +expected_err="Invalid or incomplete multibyte or wide character: read offset=0" +_test_fill_and_verify && \ +_test_corrupted_reftag && \ +_test_corrupted_data + +rm -f "$fio_err" + +_cleanup_test +_show_result "$TID" $ERR_CODE From 47903faa5c6f814f1e79b5d03708e05ca7975f6b Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 23 Apr 2026 11:30:56 +0800 Subject: [PATCH 18/21] ublk: fix maple tree lockdep warning in ublk_buf_cleanup ublk_buf_cleanup() iterates the maple tree with mas_for_each() without holding mas_lock, triggering a lockdep splat on CONFIG_PROVE_RCU kernels since mas_find() internally uses rcu_dereference_check() which requires either RCU or the tree lock. Fix by holding mas_lock around the iteration, and call mas_erase() before freeing each range to avoid dangling pointers in the tree. Fixes: 5e864438e285 ("ublk: replace xarray with IDA for shmem buffer index allocation") Reported-by: Jens Axboe Closes: https://lore.kernel.org/linux-block/0349d72d-dff8-4f9f-b448-919fa5ae96da@kernel.dk/ Signed-off-by: Ming Lei Link: https://patch.msgid.link/20260423033058.2805135-2-tom.leiming@gmail.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index ef8a0705e68b..d5bbade15e65 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -5486,11 +5486,14 @@ static void ublk_buf_cleanup(struct ublk_device *ub) struct ublk_buf_range *range; struct page *pages[32]; + mas_lock(&mas); mas_for_each(&mas, range, ULONG_MAX) { unsigned long base = mas.index; unsigned long nr = mas.last - base + 1; unsigned long off; + mas_erase(&mas); + for (off = 0; off < nr; ) { unsigned int batch = min_t(unsigned long, nr - off, 32); @@ -5503,6 +5506,7 @@ static void ublk_buf_cleanup(struct ublk_device *ub) } kfree(range); } + mas_unlock(&mas); mtree_destroy(&ub->buf_tree); ida_destroy(&ub->buf_ida); } From ea1db795de5fe9ea6844f3152483c4d3a02c0480 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 23 Apr 2026 11:30:57 +0800 Subject: [PATCH 19/21] ublk: refactor common helper ublk_shmem_remove_ranges() Extract the shared walk+erase+unpin+kfree loop into ublk_shmem_remove_ranges(). When buf_index >= 0, only ranges matching that index are removed; when buf_index < 0, all ranges are removed. Also extract ublk_unpin_range_pages() to share the page unpinning loop. Convert both __ublk_ctrl_unreg_buf() and ublk_buf_cleanup() to use the new helper. Signed-off-by: Ming Lei Link: https://patch.msgid.link/20260423033058.2805135-3-tom.leiming@gmail.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 69 +++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index d5bbade15e65..dfdb58d73e81 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -5421,18 +5421,40 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub, return ret; } -static int __ublk_ctrl_unreg_buf(struct ublk_device *ub, int buf_index) +static void ublk_unpin_range_pages(unsigned long base_pfn, + unsigned long nr_pages) +{ +#define UBLK_UNPIN_BATCH 32 + struct page *pages[UBLK_UNPIN_BATCH]; + unsigned long off; + + for (off = 0; off < nr_pages; ) { + unsigned int batch = min_t(unsigned long, + nr_pages - off, UBLK_UNPIN_BATCH); + unsigned int j; + + for (j = 0; j < batch; j++) + pages[j] = pfn_to_page(base_pfn + off + j); + unpin_user_pages(pages, batch); + off += batch; + } +} + +/* + * Remove ranges from the maple tree matching buf_index, unpin pages + * and free range structs. If buf_index < 0, remove all ranges. + */ +static int ublk_shmem_remove_ranges(struct ublk_device *ub, int buf_index) { MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX); struct ublk_buf_range *range; - struct page *pages[32]; int ret = -ENOENT; mas_lock(&mas); mas_for_each(&mas, range, ULONG_MAX) { - unsigned long base, nr, off; + unsigned long base, nr; - if (range->buf_index != buf_index) + if (buf_index >= 0 && range->buf_index != buf_index) continue; ret = 0; @@ -5440,16 +5462,7 @@ static int __ublk_ctrl_unreg_buf(struct ublk_device *ub, int buf_index) nr = mas.last - base + 1; mas_erase(&mas); - for (off = 0; off < nr; ) { - unsigned int batch = min_t(unsigned long, - nr - off, 32); - unsigned int j; - - for (j = 0; j < batch; j++) - pages[j] = pfn_to_page(base + off + j); - unpin_user_pages(pages, batch); - off += batch; - } + ublk_unpin_range_pages(base, nr); kfree(range); } mas_unlock(&mas); @@ -5472,7 +5485,7 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub, memflags = ublk_lock_buf_tree(ub); - ret = __ublk_ctrl_unreg_buf(ub, index); + ret = ublk_shmem_remove_ranges(ub, index); if (!ret) ida_free(&ub->buf_ida, index); @@ -5482,31 +5495,7 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub, static void ublk_buf_cleanup(struct ublk_device *ub) { - MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX); - struct ublk_buf_range *range; - struct page *pages[32]; - - mas_lock(&mas); - mas_for_each(&mas, range, ULONG_MAX) { - unsigned long base = mas.index; - unsigned long nr = mas.last - base + 1; - unsigned long off; - - mas_erase(&mas); - - for (off = 0; off < nr; ) { - unsigned int batch = min_t(unsigned long, - nr - off, 32); - unsigned int j; - - for (j = 0; j < batch; j++) - pages[j] = pfn_to_page(base + off + j); - unpin_user_pages(pages, batch); - off += batch; - } - kfree(range); - } - mas_unlock(&mas); + ublk_shmem_remove_ranges(ub, -1); mtree_destroy(&ub->buf_tree); ida_destroy(&ub->buf_ida); } From 309e02dccf64e1b7bd2067abedc270e33b0aadf3 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 23 Apr 2026 11:30:58 +0800 Subject: [PATCH 20/21] ublk: avoid unpinning pages under maple tree spinlock ublk_shmem_remove_ranges() calls unpin_user_pages() while holding the maple tree spinlock (mas_lock). Although unpin_user_pages() is safe in atomic context, holding the spinlock across potentially many page unpinning operations is not ideal. Split into __ublk_shmem_remove_ranges() which erases up to 64 ranges under mas_lock, collecting base_pfn and nr_pages into a temporary xarray. Then drop the lock and unpin pages outside spinlock context. ublk_shmem_remove_ranges() loops until all matching ranges are processed. Signed-off-by: Ming Lei Link: https://patch.msgid.link/20260423033058.2805135-4-tom.leiming@gmail.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 56 +++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index dfdb58d73e81..8e5f3738c203 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -5441,32 +5441,68 @@ static void ublk_unpin_range_pages(unsigned long base_pfn, } /* - * Remove ranges from the maple tree matching buf_index, unpin pages - * and free range structs. If buf_index < 0, remove all ranges. + * Inner loop: erase up to UBLK_REMOVE_BATCH matching ranges under + * mas_lock, collecting them into an xarray. Then drop the lock and + * unpin pages + free ranges outside spinlock context. + * + * Returns true if the tree walk completed, false if more ranges remain. + * Xarray key is the base PFN, value encodes nr_pages via xa_mk_value(). */ -static int ublk_shmem_remove_ranges(struct ublk_device *ub, int buf_index) +#define UBLK_REMOVE_BATCH 64 + +static bool __ublk_shmem_remove_ranges(struct ublk_device *ub, + int buf_index, int *ret) { MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX); struct ublk_buf_range *range; - int ret = -ENOENT; + struct xarray to_unpin; + unsigned long idx; + unsigned int count = 0; + bool done = false; + void *entry; + + xa_init(&to_unpin); mas_lock(&mas); mas_for_each(&mas, range, ULONG_MAX) { - unsigned long base, nr; + unsigned long nr; if (buf_index >= 0 && range->buf_index != buf_index) continue; - ret = 0; - base = mas.index; - nr = mas.last - base + 1; + *ret = 0; + nr = mas.last - mas.index + 1; + if (xa_err(xa_store(&to_unpin, mas.index, + xa_mk_value(nr), GFP_ATOMIC))) + goto unlock; mas_erase(&mas); - - ublk_unpin_range_pages(base, nr); kfree(range); + if (++count >= UBLK_REMOVE_BATCH) + goto unlock; } + done = true; +unlock: mas_unlock(&mas); + xa_for_each(&to_unpin, idx, entry) + ublk_unpin_range_pages(idx, xa_to_value(entry)); + xa_destroy(&to_unpin); + + return done; +} + +/* + * Remove ranges from the maple tree matching buf_index, unpin pages + * and free range structs. If buf_index < 0, remove all ranges. + * Processes ranges in batches to avoid holding the maple tree spinlock + * across potentially expensive page unpinning. + */ +static int ublk_shmem_remove_ranges(struct ublk_device *ub, int buf_index) +{ + int ret = -ENOENT; + + while (!__ublk_shmem_remove_ranges(ub, buf_index, &ret)) + cond_resched(); return ret; } From 895a9b37917d2718ef2240a7ead7458c22f1f011 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 23 Apr 2026 05:06:43 -0600 Subject: [PATCH 21/21] Revert "floppy: fix reference leak on platform_device_register() failure" This reverts commit e784f2ea0b4fd0e7b70028ff8218f22456c5dcf8. Jiri says the patch is buggy, and it looks like he is right revert it for now. Link: https://lore.kernel.org/linux-block/897f442d-4e04-4b70-b716-38fd10b8af36@kernel.org/ Reported-by: Jiri Slaby Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index a028bf6b8ae2..0509746f8aed 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4722,19 +4722,15 @@ static int __init do_floppy_init(void) floppy_device[drive].dev.groups = floppy_dev_groups; err = platform_device_register(&floppy_device[drive]); - if (err) { - platform_device_put(&floppy_device[drive]); + if (err) goto out_remove_drives; - } + registered[drive] = true; err = device_add_disk(&floppy_device[drive].dev, disks[drive][0], NULL); - if (err) { - platform_device_unregister(&floppy_device[drive]); - registered[drive] = false; + if (err) goto out_remove_drives; - } } return 0;