Commit a2e94e80 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'block-6.17-20250822' of git://git.kernel.dk/linux

Pull block fixes from Jens Axboe:
 "A set of fixes for block that should go into this tree. A bit larger
  than what I usually have at this point in time, a lot of that is the
  continued fixing of the lockdep annotation for queue freezing that we
  recently added, which has highlighted a number of little issues here
  and there. This contains:

   - MD pull request via Yu:

       - Add a legacy_async_del_gendisk mode, to prevent a user tools
         regression. New user tools releases will not use such a mode,
         the old release with a new kernel now will have warning about
         deprecated behavior, and we prepare to remove this legacy mode
         after about a year later

       - The rename in kernel causing user tools build failure, revert
         the rename in mdp_superblock_s

       - Fix a regression that interrupted resync can be shown as
         recover from mdstat or sysfs

   - Improve file size detection for loop, particularly for networked
     file systems, by using getattr to get the size rather than the
     cached inode size.

   - Hotplug CPU lock vs queue freeze fix

   - Lockdep fix while updating the number of hardware queues

   - Fix stacking for PI devices

   - Silence bio_check_eod() for the known case of device removal where
     the size is truncated to 0 sectors"

* tag 'block-6.17-20250822' of git://git.kernel.dk/linux:
  block: avoid cpu_hotplug_lock depedency on freeze_lock
  block: decrement block_rq_qos static key in rq_qos_del()
  block: skip q->rq_qos check in rq_qos_done_bio()
  blk-mq: fix lockdep warning in __blk_mq_update_nr_hw_queues
  block: tone down bio_check_eod
  loop: use vfs_getattr_nosec for accurate file size
  loop: Consolidate size calculation logic into lo_calculate_size()
  block: remove newlines from the warnings in blk_validate_integrity_limits
  block: handle pi_tuple_size in queue_limits_stack_integrity
  selftests: ublk: Use ARRAY_SIZE() macro to improve code
  md: fix sync_action incorrect display during resync
  md: add helper rdev_needs_recovery()
  md: keep recovery_cp in mdp_superblock_s
  md: add legacy_async_del_gendisk mode
parents d28de4fc 370ac285
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -557,7 +557,7 @@ static inline int bio_check_eod(struct bio *bio)
	sector_t maxsector = bdev_nr_sectors(bio->bi_bdev);
	unsigned int nr_sectors = bio_sectors(bio);

	if (nr_sectors &&
	if (nr_sectors && maxsector &&
	    (nr_sectors > maxsector ||
	     bio->bi_iter.bi_sector > maxsector - nr_sectors)) {
		pr_info_ratelimited("%s: attempt to access beyond end of device\n"
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ static const char *const blk_queue_flag_name[] = {
	QUEUE_FLAG_NAME(SQ_SCHED),
	QUEUE_FLAG_NAME(DISABLE_WBT_DEF),
	QUEUE_FLAG_NAME(NO_ELV_SWITCH),
	QUEUE_FLAG_NAME(QOS_ENABLED),
};
#undef QUEUE_FLAG_NAME

+9 −4
Original line number Diff line number Diff line
@@ -5033,6 +5033,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
	unsigned int memflags;
	int i;
	struct xarray elv_tbl, et_tbl;
	bool queues_frozen = false;

	lockdep_assert_held(&set->tag_list_lock);

@@ -5056,9 +5057,6 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
		blk_mq_sysfs_unregister_hctxs(q);
	}

	list_for_each_entry(q, &set->tag_list, tag_set_list)
		blk_mq_freeze_queue_nomemsave(q);

	/*
	 * Switch IO scheduler to 'none', cleaning up the data associated
	 * with the previous scheduler. We will switch back once we are done
@@ -5068,6 +5066,9 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
		if (blk_mq_elv_switch_none(q, &elv_tbl))
			goto switch_back;

	list_for_each_entry(q, &set->tag_list, tag_set_list)
		blk_mq_freeze_queue_nomemsave(q);
	queues_frozen = true;
	if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0)
		goto switch_back;

@@ -5091,8 +5092,12 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
	}
switch_back:
	/* The blk_mq_elv_switch_back unfreezes queue for us. */
	list_for_each_entry(q, &set->tag_list, tag_set_list)
	list_for_each_entry(q, &set->tag_list, tag_set_list) {
		/* switch_back expects queue to be frozen */
		if (!queues_frozen)
			blk_mq_freeze_queue_nomemsave(q);
		blk_mq_elv_switch_back(q, &elv_tbl, &et_tbl);
	}

	list_for_each_entry(q, &set->tag_list, tag_set_list) {
		blk_mq_sysfs_register_hctxs(q);
+4 −4
Original line number Diff line number Diff line
@@ -2,8 +2,6 @@

#include "blk-rq-qos.h"

__read_mostly DEFINE_STATIC_KEY_FALSE(block_rq_qos);

/*
 * Increment 'v', if 'v' is below 'below'. Returns true if we succeeded,
 * false if 'v' + 1 would be bigger than 'below'.
@@ -319,8 +317,8 @@ void rq_qos_exit(struct request_queue *q)
		struct rq_qos *rqos = q->rq_qos;
		q->rq_qos = rqos->next;
		rqos->ops->exit(rqos);
		static_branch_dec(&block_rq_qos);
	}
	blk_queue_flag_clear(QUEUE_FLAG_QOS_ENABLED, q);
	mutex_unlock(&q->rq_qos_mutex);
}

@@ -346,7 +344,7 @@ int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id,
		goto ebusy;
	rqos->next = q->rq_qos;
	q->rq_qos = rqos;
	static_branch_inc(&block_rq_qos);
	blk_queue_flag_set(QUEUE_FLAG_QOS_ENABLED, q);

	blk_mq_unfreeze_queue(q, memflags);

@@ -377,6 +375,8 @@ void rq_qos_del(struct rq_qos *rqos)
			break;
		}
	}
	if (!q->rq_qos)
		blk_queue_flag_clear(QUEUE_FLAG_QOS_ENABLED, q);
	blk_mq_unfreeze_queue(q, memflags);

	mutex_lock(&q->debugfs_mutex);
+31 −17
Original line number Diff line number Diff line
@@ -12,7 +12,6 @@
#include "blk-mq-debugfs.h"

struct blk_mq_debugfs_attr;
extern struct static_key_false block_rq_qos;

enum rq_qos_id {
	RQ_QOS_WBT,
@@ -113,43 +112,55 @@ void __rq_qos_queue_depth_changed(struct rq_qos *rqos);

static inline void rq_qos_cleanup(struct request_queue *q, struct bio *bio)
{
	if (static_branch_unlikely(&block_rq_qos) && q->rq_qos)
	if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) &&
			q->rq_qos)
		__rq_qos_cleanup(q->rq_qos, bio);
}

static inline void rq_qos_done(struct request_queue *q, struct request *rq)
{
	if (static_branch_unlikely(&block_rq_qos) && q->rq_qos &&
	    !blk_rq_is_passthrough(rq))
	if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) &&
			q->rq_qos && !blk_rq_is_passthrough(rq))
		__rq_qos_done(q->rq_qos, rq);
}

static inline void rq_qos_issue(struct request_queue *q, struct request *rq)
{
	if (static_branch_unlikely(&block_rq_qos) && q->rq_qos)
	if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) &&
			q->rq_qos)
		__rq_qos_issue(q->rq_qos, rq);
}

static inline void rq_qos_requeue(struct request_queue *q, struct request *rq)
{
	if (static_branch_unlikely(&block_rq_qos) && q->rq_qos)
	if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) &&
			q->rq_qos)
		__rq_qos_requeue(q->rq_qos, rq);
}

static inline void rq_qos_done_bio(struct bio *bio)
{
	if (static_branch_unlikely(&block_rq_qos) &&
	    bio->bi_bdev && (bio_flagged(bio, BIO_QOS_THROTTLED) ||
			     bio_flagged(bio, BIO_QOS_MERGED))) {
		struct request_queue *q = bdev_get_queue(bio->bi_bdev);
		if (q->rq_qos)
	struct request_queue *q;

	if (!bio->bi_bdev || (!bio_flagged(bio, BIO_QOS_THROTTLED) &&
			     !bio_flagged(bio, BIO_QOS_MERGED)))
		return;

	q = bdev_get_queue(bio->bi_bdev);

	/*
	 * If a bio has BIO_QOS_xxx set, it implicitly implies that
	 * q->rq_qos is present. So, we skip re-checking q->rq_qos
	 * here as an extra optimization and directly call
	 * __rq_qos_done_bio().
	 */
	__rq_qos_done_bio(q->rq_qos, bio);
}
}

static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio)
{
	if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) {
	if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) &&
			q->rq_qos) {
		bio_set_flag(bio, BIO_QOS_THROTTLED);
		__rq_qos_throttle(q->rq_qos, bio);
	}
@@ -158,14 +169,16 @@ static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio)
static inline void rq_qos_track(struct request_queue *q, struct request *rq,
				struct bio *bio)
{
	if (static_branch_unlikely(&block_rq_qos) && q->rq_qos)
	if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) &&
			q->rq_qos)
		__rq_qos_track(q->rq_qos, rq, bio);
}

static inline void rq_qos_merge(struct request_queue *q, struct request *rq,
				struct bio *bio)
{
	if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) {
	if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) &&
			q->rq_qos) {
		bio_set_flag(bio, BIO_QOS_MERGED);
		__rq_qos_merge(q->rq_qos, rq, bio);
	}
@@ -173,7 +186,8 @@ static inline void rq_qos_merge(struct request_queue *q, struct request *rq,

static inline void rq_qos_queue_depth_changed(struct request_queue *q)
{
	if (static_branch_unlikely(&block_rq_qos) && q->rq_qos)
	if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) &&
			q->rq_qos)
		__rq_qos_queue_depth_changed(q->rq_qos);
}

Loading