block-7.2-20260717

-----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmpbBc8QHGF4Ym9lQGtl
 cm5lbC5kawAKCRD301j7KXHgpibUD/9SCYq0YZSH4fgwv6PwouAdw2/0TogbCf2E
 OZ+oq76WYeG8Q95iFXLdjv72EkNi+m1cHesn89lhvZkHWu9TAKAeCoXcnfsLIpmp
 60e6Dnz7GCTRsv2L9nBEEmsyQdYGVbbMes8hSpBXbcO1jczbr8x9nzBzkfR4XL3z
 /Vqy1CK9lA0z1+0sVkUrjKt9li7BGodpUPiNdhMReu8nuwuy1mHJ585+Y6pkwHav
 1TmaSiQ+NQxSLmyOwG1rzmzWCDdeszAa56exJ6L/T16RJ6rNTPcz2TCjsBcmuupo
 UytqdUhKaqxlikfrdus0Cnjsn8ivTiXFfYnvNTAWThRuIq+ePC4nzWzuncJTeVdE
 MIzfND6sTmfOG6Vchrx0CN92nv5gsOprxbLjbM28VSb5Xpad5PYMMGpdkBranI/9
 zUkJi0fiJOp0i/uvpltdPqcgvPKBHBhLyi5GPVb+fjLJW2Gm1s1xcBfpKIj+2+S5
 A3F2ac626DhcGrKQcZPl71RwAeEWRzP3Zr93Eg1oEQd9uqRz1jH2K8DCGh0fd9mP
 FppUw/p4GbBnc8QVraIfAIssg12eFU2ZIHvWuTiB/1UnzMuS3gJ8pwEy0s/9ObUJ
 +8vCI1fZDmbXN7T31rTl/X4npL0AfXtTbG61KcWqvbAhyVmmKNoNPHFj4SA3G0wF
 p5Y7qj2Jmg==
 =qHz/
 -----END PGP SIGNATURE-----

Merge tag 'block-7.2-20260717' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux

Pull block fixes from Jens Axboe:

 - Fixes for the dio bounce buffer helpers: correct the alignment of
   bounced dio read bios to avoid a double unpin, handle huge zero
   folios in bio_free_folios(), and don't warn on the larger-order folio
   attempts in the greedy allocation path.

 - Try a slab allocation in bio_alloc_bioset() before falling back to
   the mempool, restoring the previous behavior for non-sleeping
   allocations from a cache-enabled bioset.

 - Serialize elevator changes for the same queue using the writer lock.

 - Fix a race in blk_time_get_ns() where a task preempted between
   setting PF_BLOCK_TS and the cached-timestamp reload could return 0.

 - blk-cgroup fix for leaks and the online flag on a radix_tree_insert()
   failure in blkg_create().

 - Free the copied pages when blk_rq_map_kern() fails after
   blk_rq_append_bio() rejects the bio.

 - Remove manually added partitions on loop device detach, fixing dead
   partition devices left behind and a subsequent LOOP_CONFIGURE -EBUSY

 - Bound the AIX partition lvd scan to the sector that was actually
   read.

 - Show the block operation in error injection rules (Jackie)

* tag 'block-7.2-20260717' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux:
  block: fix aligning of bounced dio read bios
  block: handle huge zero folios in bio_free_folios
  block: try slab allocation in bio_alloc_bioset() before mempool
  block: show operation in error injection rules
  block: serialize elevator changes for the same queue using a writer lock
  block: free copied pages when blk_rq_map_kern() fails
  block: do not warn when doing greedy allocation in folio_alloc_greedy()
  partitions: aix: bound the lvd scan to one sector
  blk-cgroup: fix leaks and online flag on radix_tree_insert failure
  loop: remove manually added partitions on detach
  block: fix race in blk_time_get_ns() returning 0
This commit is contained in:
Linus Torvalds 2026-07-19 09:29:42 -07:00
commit 980ab36ae5
8 changed files with 91 additions and 56 deletions

View File

@ -555,6 +555,14 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs,
bio = bio_alloc_percpu_cache(bs);
} else {
opf &= ~REQ_ALLOC_CACHE;
}
/*
* For a bioset without a percpu cache, or when the percpu cache was
* empty, try a slab allocation with optimistic GFP_ flags before
* falling back to the mempool.
*/
if (!bio) {
p = kmem_cache_alloc(bs->bio_slab, gfp);
if (p)
bio = p + bs->front_pad;
@ -1191,7 +1199,7 @@ void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter)
* for the next iteration.
*/
static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
unsigned len_align_mask)
struct bio_vec *bv, unsigned len_align_mask)
{
size_t nbytes = bio->bi_iter.bi_size & len_align_mask;
@ -1200,23 +1208,16 @@ static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
iov_iter_revert(iter, nbytes);
bio->bi_iter.bi_size -= nbytes;
do {
struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
if (nbytes < bv->bv_len) {
bv->bv_len -= nbytes;
break;
}
while (nbytes >= bv->bv_len) {
if (bio_flagged(bio, BIO_PAGE_PINNED))
unpin_user_page(bv->bv_page);
bio->bi_vcnt--;
if (!--bio->bi_vcnt)
return -EFAULT;
nbytes -= bv->bv_len;
} while (nbytes);
if (!bio->bi_vcnt)
return -EFAULT;
bv--;
}
bv->bv_len -= nbytes;
return 0;
}
@ -1276,7 +1277,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter,
if (is_pci_p2pdma_page(bio->bi_io_vec->bv_page))
bio->bi_opf |= REQ_NOMERGE;
return bio_iov_iter_align_down(bio, iter, len_align_mask);
return bio_iov_iter_align_down(bio, iter,
&bio->bi_io_vec[bio->bi_vcnt - 1], len_align_mask);
}
static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size,
@ -1285,7 +1287,8 @@ static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size,
struct folio *folio;
while (*size > minsize) {
folio = folio_alloc(gfp | __GFP_NORETRY, get_order(*size));
folio = folio_alloc(gfp | __GFP_NORETRY | __GFP_NOWARN,
get_order(*size));
if (folio)
return folio;
*size = rounddown_pow_of_two(*size - 1);
@ -1302,7 +1305,7 @@ static void bio_free_folios(struct bio *bio)
bio_for_each_bvec_all(bv, bio, i) {
struct folio *folio = bvec_folio(bv);
if (!is_zero_folio(folio))
if (!is_zero_folio(folio) && !is_huge_zero_folio(folio))
folio_put(folio);
}
}
@ -1360,7 +1363,8 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
if (!bio->bi_iter.bi_size)
return -ENOMEM;
return bio_iov_iter_align_down(bio, iter, minsize - 1);
return bio_iov_iter_align_down(bio, iter,
&bio->bi_io_vec[bio->bi_vcnt - 1], minsize - 1);
}
static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
@ -1368,21 +1372,18 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
{
size_t len = min3(iov_iter_count(iter), maxlen, SZ_1M);
struct folio *folio;
ssize_t ret;
folio = folio_alloc_greedy(GFP_KERNEL, &len, minsize);
if (!folio)
return -ENOMEM;
do {
ssize_t ret;
ret = iov_iter_extract_bvecs(iter, bio->bi_io_vec + 1, len,
&bio->bi_vcnt, bio->bi_max_vecs - 1, 0);
if (ret <= 0) {
if (!bio->bi_vcnt) {
folio_put(folio);
return ret;
}
if (!bio->bi_vcnt)
goto out_folio_put;
break;
}
len -= ret;
@ -1398,7 +1399,20 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
bvec_set_folio(&bio->bi_io_vec[0], folio, bio->bi_iter.bi_size, 0);
if (iov_iter_extract_will_pin(iter))
bio_set_flag(bio, BIO_PAGE_PINNED);
return bio_iov_iter_align_down(bio, iter, minsize - 1);
/* The first vec stores the bounce buffer, so do not subtract 1 here. */
ret = bio_iov_iter_align_down(bio, iter,
&bio->bi_io_vec[bio->bi_vcnt], minsize - 1);
if (ret)
goto out_folio_put;
/* Update the bounc buffer bv_len to the aligned down size. */
bio->bi_io_vec[0].bv_len = bio->bi_iter.bi_size;
return 0;
out_folio_put:
folio_put(folio);
return ret;
}
/**

View File

@ -434,15 +434,15 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
blkg->pd[i]->online = true;
}
}
blkg->online = true;
}
blkg->online = true;
spin_unlock(&blkcg->lock);
if (!ret)
return blkg;
/* @blkg failed fully initialized, use the usual release path */
blkg_put(blkg);
percpu_ref_kill(&blkg->refcnt);
return ERR_PTR(ret);
err_free_blkg:

View File

@ -653,6 +653,7 @@ int blk_rq_map_kern(struct request *rq, void *kbuf, unsigned int len,
gfp_t gfp_mask)
{
unsigned long addr = (unsigned long) kbuf;
bool do_copy;
struct bio *bio;
int ret;
@ -661,7 +662,8 @@ int blk_rq_map_kern(struct request *rq, void *kbuf, unsigned int len,
if (!len || !kbuf)
return -EINVAL;
if (!blk_rq_aligned(rq->q, addr, len) || object_is_on_stack(kbuf))
do_copy = !blk_rq_aligned(rq->q, addr, len) || object_is_on_stack(kbuf);
if (do_copy)
bio = bio_copy_kern(rq, kbuf, len, gfp_mask);
else
bio = bio_map_kern(rq, kbuf, len, gfp_mask);
@ -670,8 +672,11 @@ int blk_rq_map_kern(struct request *rq, void *kbuf, unsigned int len,
return PTR_ERR(bio);
ret = blk_rq_append_bio(rq, bio);
if (unlikely(ret))
if (unlikely(ret)) {
if (do_copy)
bio_free_pages(bio);
blk_mq_map_bio_put(bio);
}
return ret;
}
EXPORT_SYMBOL(blk_rq_map_kern);

View File

@ -717,6 +717,7 @@ static inline int req_ref_read(struct request *req)
static inline u64 blk_time_get_ns(void)
{
struct blk_plug *plug = current->plug;
u64 now;
if (!plug || !in_task())
return ktime_get_ns();
@ -725,12 +726,18 @@ static inline u64 blk_time_get_ns(void)
* 0 could very well be a valid time, but rather than flag "this is
* a valid timestamp" separately, just accept that we'll do an extra
* ktime_get_ns() if we just happen to get 0 as the current time.
*
* cur_ktime can be zeroed by pre-emption the moment PF_BLOCK_TS is set.
*/
if (!plug->cur_ktime) {
plug->cur_ktime = ktime_get_ns();
now = READ_ONCE(plug->cur_ktime);
if (!now) {
now = ktime_get_ns();
WRITE_ONCE(plug->cur_ktime, now);
/* Ensure PF_BLOCK_TS is set after cur_ktime. */
barrier();
current->flags |= PF_BLOCK_TS;
}
return plug->cur_ktime;
return now;
}
static inline ktime_t blk_time_get(void)

View File

@ -812,8 +812,13 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
* reference during concurrent disk deletion:
* update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del)
* kn->active -> update_nr_hwq_lock (via this sysfs write path)
*
* Use the writer lock instead of the reader lock of update_nr_hwq_lock
* to serialize the two-stage elevator switch steps in
* elevator_change(): the core switch step under the elevator lock and
* the elevator_change_done() step outside the elevator lock.
*/
if (!down_read_trylock(&set->update_nr_hwq_lock)) {
if (!down_write_trylock(&set->update_nr_hwq_lock)) {
ret = -EBUSY;
goto out;
}
@ -824,7 +829,7 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
} else {
ret = -ENOENT;
}
up_read(&set->update_nr_hwq_lock);
up_write(&set->update_nr_hwq_lock);
out:
if (ctx.type)

View File

@ -276,9 +276,10 @@ static int blk_error_injection_show(struct seq_file *s, void *private)
rcu_read_lock();
list_for_each_entry_rcu(inj, &disk->error_injection_list, entry) {
seq_printf(s, "%llu:%llu status=%s,chance=%u",
inj->start, inj->end,
blk_status_to_tag(inj->status), inj->chance);
seq_printf(s, "%llu:%llu op=%s,status=%s,chance=%u",
inj->start, inj->end,
blk_op_str(inj->op),
blk_status_to_tag(inj->status), inj->chance);
seq_putc(s, '\n');
}
rcu_read_unlock();

View File

@ -208,7 +208,14 @@ int aix_partition(struct parsed_partitions *state)
if (n) {
int foundlvs = 0;
for (i = 0; foundlvs < numlvs && i < state->limit; i += 1) {
/*
* The lvd array was read as a single sector; only the
* struct lvd entries that fit in it are valid. Bound the
* scan so an on-disk numlvs larger than that cannot walk
* the read buffer out of bounds.
*/
for (i = 0; foundlvs < numlvs && i < state->limit &&
i < SECTOR_SIZE / (int)sizeof(struct lvd); i++) {
lvip[i].pps_per_lv = be16_to_cpu(p[i].num_lps);
if (lvip[i].pps_per_lv)
foundlvs += 1;

View File

@ -1113,6 +1113,7 @@ static void __loop_clr_fd(struct loop_device *lo)
struct queue_limits lim;
struct file *filp;
gfp_t gfp = lo->old_gfp_mask;
int err;
spin_lock_irq(&lo->lo_lock);
filp = lo->lo_backing_file;
@ -1146,26 +1147,21 @@ static void __loop_clr_fd(struct loop_device *lo)
disk_force_media_change(lo->lo_disk);
if (lo->lo_flags & LO_FLAGS_PARTSCAN) {
int err;
/*
* open_mutex has been held already in release path, so don't
* acquire it if this function is called in such case.
*
* If the reread partition isn't from release path, lo_refcnt
* must be at least one and it can only become zero when the
* current holder is released.
*/
err = bdev_disk_changed(lo->lo_disk, false);
if (err)
pr_warn("%s: partition scan of loop%d failed (rc=%d)\n",
__func__, lo->lo_number, err);
/* Device is gone, no point in returning error */
}
/*
* Remove all partitions, including partitions added manually with
* BLKPG, which may exist even if LO_FLAGS_PARTSCAN is not set.
*
* open_mutex has been held already in release path, so don't acquire
* it here.
*/
err = bdev_disk_changed(lo->lo_disk, false);
if (err)
pr_warn("%s: partition scan of loop%d failed (rc=%d)\n",
__func__, lo->lo_number, err);
/* Device is gone, no point in returning error */
/*
* lo->lo_state is set to Lo_unbound here after above partscan has
* lo->lo_state is set to Lo_unbound here after removing partitions has
* finished. There cannot be anybody else entering __loop_clr_fd() as
* Lo_rundown state protects us from all the other places trying to
* change the 'lo' device.