Commit 00d20db2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull block fixes from Jens Axboe:

 - A set of selftest fixes for ublk

 - Fix for a pid mismatch in ublk, comparing PIDs in different
   namespaces if run inside a namespace

 - Fix for a regression added in this release with polling, where the
   nvme tcp connect code would spin forever

 - Zoned device error path fix

 - Tweak the blkzoned uapi additions from this kernel release, making
   them more easily discoverable

 - Fix for a regression in bcache with bio endio handling added in this
   release

* tag 'block-6.19-20260122' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux:
  bcache: use bio cloning for detached device requests
  blk-mq: use BLK_POLL_ONESHOT for synchronous poll completion
  selftests/ublk: fix garbage output in foreground mode
  selftests/ublk: fix error handling for starting device
  selftests/ublk: fix IO thread idle check
  block: make the new blkzoned UAPI constants discoverable
  ublk: fix ublksrv pid handling for pid namespaces
  block: Fix an error path in disk_update_zone_resources()
parents 7907f673 3ef825df
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1480,7 +1480,7 @@ EXPORT_SYMBOL_GPL(blk_rq_is_poll);
static void blk_rq_poll_completion(struct request *rq, struct completion *wait)
{
	do {
		blk_hctx_poll(rq->q, rq->mq_hctx, NULL, 0);
		blk_hctx_poll(rq->q, rq->mq_hctx, NULL, BLK_POLL_ONESHOT);
		cond_resched();
	} while (!completion_done(wait));
}
+1 −0
Original line number Diff line number Diff line
@@ -1957,6 +1957,7 @@ static int disk_update_zone_resources(struct gendisk *disk,

	disk->nr_zones = args->nr_zones;
	if (args->nr_conv_zones >= disk->nr_zones) {
		queue_limits_cancel_update(q);
		pr_warn("%s: Invalid number of conventional zones %u / %u\n",
			disk->disk_name, args->nr_conv_zones, disk->nr_zones);
		ret = -ENODEV;
+34 −5
Original line number Diff line number Diff line
@@ -2885,6 +2885,15 @@ static struct ublk_device *ublk_get_device_from_id(int idx)
	return ub;
}

static bool ublk_validate_user_pid(struct ublk_device *ub, pid_t ublksrv_pid)
{
	rcu_read_lock();
	ublksrv_pid = pid_nr(find_vpid(ublksrv_pid));
	rcu_read_unlock();

	return ub->ublksrv_tgid == ublksrv_pid;
}

static int ublk_ctrl_start_dev(struct ublk_device *ub,
		const struct ublksrv_ctrl_cmd *header)
{
@@ -2953,7 +2962,7 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
	if (wait_for_completion_interruptible(&ub->completion) != 0)
		return -EINTR;

	if (ub->ublksrv_tgid != ublksrv_pid)
	if (!ublk_validate_user_pid(ub, ublksrv_pid))
		return -EINVAL;

	mutex_lock(&ub->mutex);
@@ -2972,7 +2981,7 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
	disk->fops = &ub_fops;
	disk->private_data = ub;

	ub->dev_info.ublksrv_pid = ublksrv_pid;
	ub->dev_info.ublksrv_pid = ub->ublksrv_tgid;
	ub->ub_disk = disk;

	ublk_apply_params(ub);
@@ -3320,12 +3329,32 @@ static int ublk_ctrl_stop_dev(struct ublk_device *ub)
static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
		const struct ublksrv_ctrl_cmd *header)
{
	struct task_struct *p;
	struct pid *pid;
	struct ublksrv_ctrl_dev_info dev_info;
	pid_t init_ublksrv_tgid = ub->dev_info.ublksrv_pid;
	void __user *argp = (void __user *)(unsigned long)header->addr;

	if (header->len < sizeof(struct ublksrv_ctrl_dev_info) || !header->addr)
		return -EINVAL;

	if (copy_to_user(argp, &ub->dev_info, sizeof(ub->dev_info)))
	memcpy(&dev_info, &ub->dev_info, sizeof(dev_info));
	dev_info.ublksrv_pid = -1;

	if (init_ublksrv_tgid > 0) {
		rcu_read_lock();
		pid = find_pid_ns(init_ublksrv_tgid, &init_pid_ns);
		p = pid_task(pid, PIDTYPE_TGID);
		if (p) {
			int vnr = task_tgid_vnr(p);

			if (vnr)
				dev_info.ublksrv_pid = vnr;
		}
		rcu_read_unlock();
	}

	if (copy_to_user(argp, &dev_info, sizeof(dev_info)))
		return -EFAULT;

	return 0;
@@ -3470,7 +3499,7 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
	pr_devel("%s: All FETCH_REQs received, dev id %d\n", __func__,
		 header->dev_id);

	if (ub->ublksrv_tgid != ublksrv_pid)
	if (!ublk_validate_user_pid(ub, ublksrv_pid))
		return -EINVAL;

	mutex_lock(&ub->mutex);
@@ -3481,7 +3510,7 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
		ret = -EBUSY;
		goto out_unlock;
	}
	ub->dev_info.ublksrv_pid = ublksrv_pid;
	ub->dev_info.ublksrv_pid = ub->ublksrv_tgid;
	ub->dev_info.state = UBLK_S_DEV_LIVE;
	pr_devel("%s: new ublksrv_pid %d, dev id %d\n",
			__func__, ublksrv_pid, header->dev_id);
+9 −0
Original line number Diff line number Diff line
@@ -273,6 +273,8 @@ struct bcache_device {

	struct bio_set		bio_split;

	struct bio_set		bio_detached;

	unsigned int		data_csum:1;

	int (*cache_miss)(struct btree *b, struct search *s,
@@ -753,6 +755,13 @@ struct bbio {
	struct bio		bio;
};

struct detached_dev_io_private {
	struct bcache_device	*d;
	unsigned long		start_time;
	struct bio		*orig_bio;
	struct bio              bio;
};

#define BTREE_PRIO		USHRT_MAX
#define INITIAL_PRIO		32768U

+35 −44
Original line number Diff line number Diff line
@@ -1077,68 +1077,58 @@ static CLOSURE_CALLBACK(cached_dev_nodata)
	continue_at(cl, cached_dev_bio_complete, NULL);
}

struct detached_dev_io_private {
	struct bcache_device	*d;
	unsigned long		start_time;
	bio_end_io_t		*bi_end_io;
	void			*bi_private;
	struct block_device	*orig_bdev;
};

static void detached_dev_end_io(struct bio *bio)
{
	struct detached_dev_io_private *ddip;

	ddip = bio->bi_private;
	bio->bi_end_io = ddip->bi_end_io;
	bio->bi_private = ddip->bi_private;
	struct detached_dev_io_private *ddip =
		container_of(bio, struct detached_dev_io_private, bio);
	struct bio *orig_bio = ddip->orig_bio;

	/* Count on the bcache device */
	bio_end_io_acct_remapped(bio, ddip->start_time, ddip->orig_bdev);
	bio_end_io_acct(orig_bio, ddip->start_time);

	if (bio->bi_status) {
		struct cached_dev *dc = container_of(ddip->d,
						     struct cached_dev, disk);
		struct cached_dev *dc = bio->bi_private;

		/* should count I/O error for backing device here */
		bch_count_backing_io_errors(dc, bio);
		orig_bio->bi_status = bio->bi_status;
	}

	kfree(ddip);
	bio_endio(bio);
	bio_put(bio);
	bio_endio(orig_bio);
}

static void detached_dev_do_request(struct bcache_device *d, struct bio *bio,
		struct block_device *orig_bdev, unsigned long start_time)
static void detached_dev_do_request(struct bcache_device *d,
		struct bio *orig_bio, unsigned long start_time)
{
	struct detached_dev_io_private *ddip;
	struct cached_dev *dc = container_of(d, struct cached_dev, disk);
	struct bio *clone_bio;

	/*
	 * no need to call closure_get(&dc->disk.cl),
	 * because upper layer had already opened bcache device,
	 * which would call closure_get(&dc->disk.cl)
	 */
	ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO);
	if (!ddip) {
		bio->bi_status = BLK_STS_RESOURCE;
		bio_endio(bio);
	if (bio_op(orig_bio) == REQ_OP_DISCARD &&
	    !bdev_max_discard_sectors(dc->bdev)) {
		bio_endio(orig_bio);
		return;
	}

	ddip->d = d;
	clone_bio = bio_alloc_clone(dc->bdev, orig_bio, GFP_NOIO,
				    &d->bio_detached);
	if (!clone_bio) {
		orig_bio->bi_status = BLK_STS_RESOURCE;
		bio_endio(orig_bio);
		return;
	}

	ddip = container_of(clone_bio, struct detached_dev_io_private, bio);
	/* Count on the bcache device */
	ddip->orig_bdev = orig_bdev;
	ddip->d = d;
	ddip->start_time = start_time;
	ddip->bi_end_io = bio->bi_end_io;
	ddip->bi_private = bio->bi_private;
	bio->bi_end_io = detached_dev_end_io;
	bio->bi_private = ddip;
	ddip->orig_bio = orig_bio;

	if ((bio_op(bio) == REQ_OP_DISCARD) &&
	    !bdev_max_discard_sectors(dc->bdev))
		detached_dev_end_io(bio);
	else
		submit_bio_noacct(bio);
	clone_bio->bi_end_io = detached_dev_end_io;
	clone_bio->bi_private = dc;

	submit_bio_noacct(clone_bio);
}

static void quit_max_writeback_rate(struct cache_set *c,
@@ -1214,10 +1204,10 @@ void cached_dev_submit_bio(struct bio *bio)

	start_time = bio_start_io_acct(bio);

	bio_set_dev(bio, dc->bdev);
	bio->bi_iter.bi_sector += dc->sb.data_offset;

	if (cached_dev_get(dc)) {
		bio_set_dev(bio, dc->bdev);
		s = search_alloc(bio, d, orig_bdev, start_time);
		trace_bcache_request_start(s->d, bio);

@@ -1237,9 +1227,10 @@ void cached_dev_submit_bio(struct bio *bio)
			else
				cached_dev_read(dc, s);
		}
	} else
	} else {
		/* I/O request sent to backing device */
		detached_dev_do_request(d, bio, orig_bdev, start_time);
		detached_dev_do_request(d, bio, start_time);
	}
}

static int cached_dev_ioctl(struct bcache_device *d, blk_mode_t mode,
Loading