mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 07:35:36 -05:00
Merge tag 'block-6.19-20251218' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux
Pull block fixes from Jens Axboe: - ublk selftests for missing coverage - two fixes for the block integrity code - fix for the newly added newly added PR read keys ioctl, limiting the memory that can be allocated - work around for a deadlock that can occur with ublk, where partition scanning ends up recursing back into file closure, which needs the same mutex grabbed. Not the prettiest thing in the world, but an acceptable work-around until we can eliminate the reliance on disk->open_mutex for this - fix for a race between enabling writeback throttling and new IO submissions - move a bit of bio flag handling code. No changes, but needed for a patchset for a future kernel - fix for an init time id leak failure in rnbd - loop/zloop state check fix * tag 'block-6.19-20251218' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux: block: validate interval_exp integrity limit block: validate pi_offset integrity limit block: rnbd-clt: Fix leaked ID in init_dev() ublk: fix deadlock when reading partition table block: add allocation size check in blkdev_pr_read_keys() Documentation: admin-guide: blockdev: replace zone_capacity with zone_capacity_mb when creating devices zloop: use READ_ONCE() to read lo->lo_state in queue_rq path loop: use READ_ONCE() to read lo->lo_state without locking block: fix race between wbt_enable_default and IO submission selftests: ublk: add user copy test cases selftests: ublk: add support for user copy to kublk selftests: ublk: forbid multiple data copy modes selftests: ublk: don't share backing files between ublk servers selftests: ublk: use auto_zc for PER_IO_DAEMON tests in stress_04 selftests: ublk: fix fio arguments in run_io_and_recover() selftests: ublk: remove unused ios map in seq_io.bt selftests: ublk: correct last_rw map type in seq_io.bt selftests: ublk: fix overflow in ublk_queue_auto_zc_fallback() block: move around bio flagging helpers
This commit is contained in:
@@ -134,7 +134,7 @@ MB and a zone capacity of 63 MB::
|
||||
|
||||
$ modprobe zloop
|
||||
$ mkdir -p /var/local/zloop/0
|
||||
$ echo "add capacity_mb=2048,zone_size_mb=64,zone_capacity=63MB" > /dev/zloop-control
|
||||
$ echo "add capacity_mb=2048,zone_size_mb=64,zone_capacity_mb=63" > /dev/zloop-control
|
||||
|
||||
For the device created (/dev/zloop0), the zone backing files are all created
|
||||
under the default base directory (/var/local/zloop)::
|
||||
|
||||
@@ -7181,7 +7181,7 @@ static void bfq_exit_queue(struct elevator_queue *e)
|
||||
|
||||
blk_stat_disable_accounting(bfqd->queue);
|
||||
blk_queue_flag_clear(QUEUE_FLAG_DISABLE_WBT_DEF, bfqd->queue);
|
||||
set_bit(ELEVATOR_FLAG_ENABLE_WBT_ON_EXIT, &e->flags);
|
||||
wbt_enable_default(bfqd->queue->disk);
|
||||
|
||||
kfree(bfqd);
|
||||
}
|
||||
|
||||
@@ -161,10 +161,9 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bi->pi_tuple_size > bi->metadata_size) {
|
||||
pr_warn("pi_tuple_size (%u) exceeds metadata_size (%u)\n",
|
||||
bi->pi_tuple_size,
|
||||
bi->metadata_size);
|
||||
if (bi->pi_offset + bi->pi_tuple_size > bi->metadata_size) {
|
||||
pr_warn("pi_offset (%u) + pi_tuple_size (%u) exceeds metadata_size (%u)\n",
|
||||
bi->pi_offset, bi->pi_tuple_size, bi->metadata_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -194,8 +193,13 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bi->interval_exp)
|
||||
if (!bi->interval_exp) {
|
||||
bi->interval_exp = ilog2(lim->logical_block_size);
|
||||
} else if (bi->interval_exp < SECTOR_SHIFT ||
|
||||
bi->interval_exp > ilog2(lim->logical_block_size)) {
|
||||
pr_warn("invalid interval_exp %u\n", bi->interval_exp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The PI generation / validation helpers do not expect intervals to
|
||||
|
||||
@@ -932,7 +932,7 @@ int blk_register_queue(struct gendisk *disk)
|
||||
elevator_set_default(q);
|
||||
|
||||
blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);
|
||||
wbt_enable_default(disk);
|
||||
wbt_init_enable_default(disk);
|
||||
|
||||
/* Now everything is ready and send out KOBJ_ADD uevent */
|
||||
kobject_uevent(&disk->queue_kobj, KOBJ_ADD);
|
||||
|
||||
@@ -699,7 +699,7 @@ static void wbt_requeue(struct rq_qos *rqos, struct request *rq)
|
||||
/*
|
||||
* Enable wbt if defaults are configured that way
|
||||
*/
|
||||
void wbt_enable_default(struct gendisk *disk)
|
||||
static bool __wbt_enable_default(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct rq_qos *rqos;
|
||||
@@ -716,19 +716,31 @@ void wbt_enable_default(struct gendisk *disk)
|
||||
if (enable && RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
|
||||
RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT;
|
||||
mutex_unlock(&disk->rqos_state_mutex);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
mutex_unlock(&disk->rqos_state_mutex);
|
||||
|
||||
/* Queue not registered? Maybe shutting down... */
|
||||
if (!blk_queue_registered(q))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (queue_is_mq(q) && enable)
|
||||
wbt_init(disk);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void wbt_enable_default(struct gendisk *disk)
|
||||
{
|
||||
__wbt_enable_default(disk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wbt_enable_default);
|
||||
|
||||
void wbt_init_enable_default(struct gendisk *disk)
|
||||
{
|
||||
if (__wbt_enable_default(disk))
|
||||
WARN_ON_ONCE(wbt_init(disk));
|
||||
}
|
||||
|
||||
u64 wbt_default_latency_nsec(struct request_queue *q)
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifdef CONFIG_BLK_WBT
|
||||
|
||||
int wbt_init(struct gendisk *disk);
|
||||
void wbt_init_enable_default(struct gendisk *disk);
|
||||
void wbt_disable_default(struct gendisk *disk);
|
||||
void wbt_enable_default(struct gendisk *disk);
|
||||
|
||||
@@ -16,6 +17,10 @@ u64 wbt_default_latency_nsec(struct request_queue *);
|
||||
|
||||
#else
|
||||
|
||||
static inline void wbt_init_enable_default(struct gendisk *disk)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wbt_disable_default(struct gendisk *disk)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -633,14 +633,10 @@ static int elevator_change_done(struct request_queue *q,
|
||||
.et = ctx->old->et,
|
||||
.data = ctx->old->elevator_data
|
||||
};
|
||||
bool enable_wbt = test_bit(ELEVATOR_FLAG_ENABLE_WBT_ON_EXIT,
|
||||
&ctx->old->flags);
|
||||
|
||||
elv_unregister_queue(q, ctx->old);
|
||||
blk_mq_free_sched_res(&res, ctx->old->type, q->tag_set);
|
||||
kobject_put(&ctx->old->kobj);
|
||||
if (enable_wbt)
|
||||
wbt_enable_default(q->disk);
|
||||
}
|
||||
if (ctx->new) {
|
||||
ret = elv_register_queue(q, ctx->new, !ctx->no_uevent);
|
||||
|
||||
@@ -156,7 +156,6 @@ struct elevator_queue
|
||||
|
||||
#define ELEVATOR_FLAG_REGISTERED 0
|
||||
#define ELEVATOR_FLAG_DYING 1
|
||||
#define ELEVATOR_FLAG_ENABLE_WBT_ON_EXIT 2
|
||||
|
||||
/*
|
||||
* block elevator interface
|
||||
|
||||
@@ -442,11 +442,12 @@ static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode,
|
||||
if (copy_from_user(&read_keys, arg, sizeof(read_keys)))
|
||||
return -EFAULT;
|
||||
|
||||
keys_info_len = struct_size(keys_info, keys, read_keys.num_keys);
|
||||
if (keys_info_len == SIZE_MAX)
|
||||
if (read_keys.num_keys > PR_KEYS_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
keys_info = kzalloc(keys_info_len, GFP_KERNEL);
|
||||
keys_info_len = struct_size(keys_info, keys, read_keys.num_keys);
|
||||
|
||||
keys_info = kvzalloc(keys_info_len, GFP_KERNEL);
|
||||
if (!keys_info)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -473,7 +474,7 @@ static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode,
|
||||
if (copy_to_user(arg, &read_keys, sizeof(read_keys)))
|
||||
ret = -EFAULT;
|
||||
out:
|
||||
kfree(keys_info);
|
||||
kvfree(keys_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1082,7 +1082,7 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
|
||||
/* Order wrt reading lo_state in loop_validate_file(). */
|
||||
wmb();
|
||||
|
||||
lo->lo_state = Lo_bound;
|
||||
WRITE_ONCE(lo->lo_state, Lo_bound);
|
||||
if (part_shift)
|
||||
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
||||
partscan = lo->lo_flags & LO_FLAGS_PARTSCAN;
|
||||
@@ -1179,7 +1179,7 @@ static void __loop_clr_fd(struct loop_device *lo)
|
||||
if (!part_shift)
|
||||
set_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
|
||||
mutex_lock(&lo->lo_mutex);
|
||||
lo->lo_state = Lo_unbound;
|
||||
WRITE_ONCE(lo->lo_state, Lo_unbound);
|
||||
mutex_unlock(&lo->lo_mutex);
|
||||
|
||||
/*
|
||||
@@ -1218,7 +1218,7 @@ static int loop_clr_fd(struct loop_device *lo)
|
||||
|
||||
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
|
||||
if (disk_openers(lo->lo_disk) == 1)
|
||||
lo->lo_state = Lo_rundown;
|
||||
WRITE_ONCE(lo->lo_state, Lo_rundown);
|
||||
loop_global_unlock(lo, true);
|
||||
|
||||
return 0;
|
||||
@@ -1743,7 +1743,7 @@ static void lo_release(struct gendisk *disk)
|
||||
|
||||
mutex_lock(&lo->lo_mutex);
|
||||
if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR))
|
||||
lo->lo_state = Lo_rundown;
|
||||
WRITE_ONCE(lo->lo_state, Lo_rundown);
|
||||
|
||||
need_clear = (lo->lo_state == Lo_rundown);
|
||||
mutex_unlock(&lo->lo_mutex);
|
||||
@@ -1858,7 +1858,7 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
|
||||
blk_mq_start_request(rq);
|
||||
|
||||
if (lo->lo_state != Lo_bound)
|
||||
if (data_race(READ_ONCE(lo->lo_state)) != Lo_bound)
|
||||
return BLK_STS_IOERR;
|
||||
|
||||
switch (req_op(rq)) {
|
||||
@@ -2016,7 +2016,7 @@ static int loop_add(int i)
|
||||
lo->worker_tree = RB_ROOT;
|
||||
INIT_LIST_HEAD(&lo->idle_worker_list);
|
||||
timer_setup(&lo->timer, loop_free_idle_workers_timer, TIMER_DEFERRABLE);
|
||||
lo->lo_state = Lo_unbound;
|
||||
WRITE_ONCE(lo->lo_state, Lo_unbound);
|
||||
|
||||
err = mutex_lock_killable(&loop_ctl_mutex);
|
||||
if (err)
|
||||
@@ -2174,7 +2174,7 @@ static int loop_control_remove(int idx)
|
||||
goto mark_visible;
|
||||
}
|
||||
/* Mark this loop device as no more bound, but not quite unbound yet */
|
||||
lo->lo_state = Lo_deleting;
|
||||
WRITE_ONCE(lo->lo_state, Lo_deleting);
|
||||
mutex_unlock(&lo->lo_mutex);
|
||||
|
||||
loop_remove(lo);
|
||||
@@ -2197,8 +2197,12 @@ static int loop_control_get_free(int idx)
|
||||
if (ret)
|
||||
return ret;
|
||||
idr_for_each_entry(&loop_index_idr, lo, id) {
|
||||
/* Hitting a race results in creating a new loop device which is harmless. */
|
||||
if (lo->idr_visible && data_race(lo->lo_state) == Lo_unbound)
|
||||
/*
|
||||
* Hitting a race results in creating a new loop device
|
||||
* which is harmless.
|
||||
*/
|
||||
if (lo->idr_visible &&
|
||||
data_race(READ_ONCE(lo->lo_state)) == Lo_unbound)
|
||||
goto found;
|
||||
}
|
||||
mutex_unlock(&loop_ctl_mutex);
|
||||
|
||||
@@ -1423,9 +1423,11 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
|
||||
goto out_alloc;
|
||||
}
|
||||
|
||||
ret = ida_alloc_max(&index_ida, (1 << (MINORBITS - RNBD_PART_BITS)) - 1,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
dev->clt_device_id = ida_alloc_max(&index_ida,
|
||||
(1 << (MINORBITS - RNBD_PART_BITS)) - 1,
|
||||
GFP_KERNEL);
|
||||
if (dev->clt_device_id < 0) {
|
||||
ret = dev->clt_device_id;
|
||||
pr_err("Failed to initialize device '%s' from session %s, allocating idr failed, err: %d\n",
|
||||
pathname, sess->sessname, ret);
|
||||
goto out_queues;
|
||||
@@ -1434,10 +1436,9 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
|
||||
dev->pathname = kstrdup(pathname, GFP_KERNEL);
|
||||
if (!dev->pathname) {
|
||||
ret = -ENOMEM;
|
||||
goto out_queues;
|
||||
goto out_ida;
|
||||
}
|
||||
|
||||
dev->clt_device_id = ret;
|
||||
dev->sess = sess;
|
||||
dev->access_mode = access_mode;
|
||||
dev->nr_poll_queues = nr_poll_queues;
|
||||
@@ -1453,6 +1454,8 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
|
||||
|
||||
return dev;
|
||||
|
||||
out_ida:
|
||||
ida_free(&index_ida, dev->clt_device_id);
|
||||
out_queues:
|
||||
kfree(dev->hw_queues);
|
||||
out_alloc:
|
||||
|
||||
@@ -1080,12 +1080,20 @@ static inline struct ublk_uring_cmd_pdu *ublk_get_uring_cmd_pdu(
|
||||
return io_uring_cmd_to_pdu(ioucmd, struct ublk_uring_cmd_pdu);
|
||||
}
|
||||
|
||||
static void ublk_end_request(struct request *req, blk_status_t error)
|
||||
{
|
||||
local_bh_disable();
|
||||
blk_mq_end_request(req, error);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
/* todo: handle partial completion */
|
||||
static inline void __ublk_complete_rq(struct request *req, struct ublk_io *io,
|
||||
bool need_map)
|
||||
{
|
||||
unsigned int unmapped_bytes;
|
||||
blk_status_t res = BLK_STS_OK;
|
||||
bool requeue;
|
||||
|
||||
/* failed read IO if nothing is read */
|
||||
if (!io->res && req_op(req) == REQ_OP_READ)
|
||||
@@ -1117,14 +1125,30 @@ static inline void __ublk_complete_rq(struct request *req, struct ublk_io *io,
|
||||
if (unlikely(unmapped_bytes < io->res))
|
||||
io->res = unmapped_bytes;
|
||||
|
||||
if (blk_update_request(req, BLK_STS_OK, io->res))
|
||||
/*
|
||||
* Run bio->bi_end_io() with softirqs disabled. If the final fput
|
||||
* happens off this path, then that will prevent ublk's blkdev_release()
|
||||
* from being called on current's task work, see fput() implementation.
|
||||
*
|
||||
* Otherwise, ublk server may not provide forward progress in case of
|
||||
* reading the partition table from bdev_open() with disk->open_mutex
|
||||
* held, and causes dead lock as we could already be holding
|
||||
* disk->open_mutex here.
|
||||
*
|
||||
* Preferably we would not be doing IO with a mutex held that is also
|
||||
* used for release, but this work-around will suffice for now.
|
||||
*/
|
||||
local_bh_disable();
|
||||
requeue = blk_update_request(req, BLK_STS_OK, io->res);
|
||||
local_bh_enable();
|
||||
if (requeue)
|
||||
blk_mq_requeue_request(req, true);
|
||||
else if (likely(!blk_should_fake_timeout(req->q)))
|
||||
__blk_mq_end_request(req, BLK_STS_OK);
|
||||
|
||||
return;
|
||||
exit:
|
||||
blk_mq_end_request(req, res);
|
||||
ublk_end_request(req, res);
|
||||
}
|
||||
|
||||
static struct io_uring_cmd *__ublk_prep_compl_io_cmd(struct ublk_io *io,
|
||||
@@ -1164,7 +1188,7 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
|
||||
if (ublk_nosrv_dev_should_queue_io(ubq->dev))
|
||||
blk_mq_requeue_request(rq, false);
|
||||
else
|
||||
blk_mq_end_request(rq, BLK_STS_IOERR);
|
||||
ublk_end_request(rq, BLK_STS_IOERR);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1209,7 +1233,7 @@ __ublk_do_auto_buf_reg(const struct ublk_queue *ubq, struct request *req,
|
||||
ublk_auto_buf_reg_fallback(ubq, req->tag);
|
||||
return AUTO_BUF_REG_FALLBACK;
|
||||
}
|
||||
blk_mq_end_request(req, BLK_STS_IOERR);
|
||||
ublk_end_request(req, BLK_STS_IOERR);
|
||||
return AUTO_BUF_REG_FAIL;
|
||||
}
|
||||
|
||||
|
||||
@@ -697,7 +697,7 @@ 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 (zlo->state == Zlo_deleting)
|
||||
if (data_race(READ_ONCE(zlo->state)) == Zlo_deleting)
|
||||
return BLK_STS_IOERR;
|
||||
|
||||
/*
|
||||
@@ -1002,7 +1002,7 @@ static int zloop_ctl_add(struct zloop_options *opts)
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
zlo->state = Zlo_creating;
|
||||
WRITE_ONCE(zlo->state, Zlo_creating);
|
||||
|
||||
ret = mutex_lock_killable(&zloop_ctl_mutex);
|
||||
if (ret)
|
||||
@@ -1113,7 +1113,7 @@ static int zloop_ctl_add(struct zloop_options *opts)
|
||||
}
|
||||
|
||||
mutex_lock(&zloop_ctl_mutex);
|
||||
zlo->state = Zlo_live;
|
||||
WRITE_ONCE(zlo->state, Zlo_live);
|
||||
mutex_unlock(&zloop_ctl_mutex);
|
||||
|
||||
pr_info("zloop: device %d, %u zones of %llu MiB, %u B block size\n",
|
||||
@@ -1177,7 +1177,7 @@ static int zloop_ctl_remove(struct zloop_options *opts)
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
idr_remove(&zloop_index_idr, zlo->id);
|
||||
zlo->state = Zlo_deleting;
|
||||
WRITE_ONCE(zlo->state, Zlo_deleting);
|
||||
}
|
||||
|
||||
mutex_unlock(&zloop_ctl_mutex);
|
||||
|
||||
@@ -46,6 +46,21 @@ static inline unsigned int bio_max_segs(unsigned int nr_segs)
|
||||
#define bio_data_dir(bio) \
|
||||
(op_is_write(bio_op(bio)) ? WRITE : READ)
|
||||
|
||||
static inline bool bio_flagged(const struct bio *bio, unsigned int bit)
|
||||
{
|
||||
return bio->bi_flags & (1U << bit);
|
||||
}
|
||||
|
||||
static inline void bio_set_flag(struct bio *bio, unsigned int bit)
|
||||
{
|
||||
bio->bi_flags |= (1U << bit);
|
||||
}
|
||||
|
||||
static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
|
||||
{
|
||||
bio->bi_flags &= ~(1U << bit);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether this bio carries any data or not. A NULL bio is allowed.
|
||||
*/
|
||||
@@ -225,21 +240,6 @@ static inline void bio_cnt_set(struct bio *bio, unsigned int count)
|
||||
atomic_set(&bio->__bi_cnt, count);
|
||||
}
|
||||
|
||||
static inline bool bio_flagged(struct bio *bio, unsigned int bit)
|
||||
{
|
||||
return bio->bi_flags & (1U << bit);
|
||||
}
|
||||
|
||||
static inline void bio_set_flag(struct bio *bio, unsigned int bit)
|
||||
{
|
||||
bio->bi_flags |= (1U << bit);
|
||||
}
|
||||
|
||||
static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
|
||||
{
|
||||
bio->bi_flags &= ~(1U << bit);
|
||||
}
|
||||
|
||||
static inline struct bio_vec *bio_first_bvec_all(struct bio *bio)
|
||||
{
|
||||
WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED));
|
||||
|
||||
@@ -79,4 +79,6 @@ struct pr_read_reservation {
|
||||
#define IOC_PR_READ_KEYS _IOWR('p', 206, struct pr_read_keys)
|
||||
#define IOC_PR_READ_RESERVATION _IOR('p', 207, struct pr_read_reservation)
|
||||
|
||||
#define PR_KEYS_MAX (1u << 16)
|
||||
|
||||
#endif /* _UAPI_PR_H */
|
||||
|
||||
@@ -21,24 +21,32 @@ TEST_PROGS += test_generic_10.sh
|
||||
TEST_PROGS += test_generic_11.sh
|
||||
TEST_PROGS += test_generic_12.sh
|
||||
TEST_PROGS += test_generic_13.sh
|
||||
TEST_PROGS += test_generic_14.sh
|
||||
|
||||
TEST_PROGS += test_null_01.sh
|
||||
TEST_PROGS += test_null_02.sh
|
||||
TEST_PROGS += test_null_03.sh
|
||||
TEST_PROGS += test_loop_01.sh
|
||||
TEST_PROGS += test_loop_02.sh
|
||||
TEST_PROGS += test_loop_03.sh
|
||||
TEST_PROGS += test_loop_04.sh
|
||||
TEST_PROGS += test_loop_05.sh
|
||||
TEST_PROGS += test_loop_06.sh
|
||||
TEST_PROGS += test_loop_07.sh
|
||||
TEST_PROGS += test_stripe_01.sh
|
||||
TEST_PROGS += test_stripe_02.sh
|
||||
TEST_PROGS += test_stripe_03.sh
|
||||
TEST_PROGS += test_stripe_04.sh
|
||||
TEST_PROGS += test_stripe_05.sh
|
||||
TEST_PROGS += test_stripe_06.sh
|
||||
|
||||
TEST_PROGS += test_stress_01.sh
|
||||
TEST_PROGS += test_stress_02.sh
|
||||
TEST_PROGS += test_stress_03.sh
|
||||
TEST_PROGS += test_stress_04.sh
|
||||
TEST_PROGS += test_stress_05.sh
|
||||
TEST_PROGS += test_stress_06.sh
|
||||
TEST_PROGS += test_stress_07.sh
|
||||
|
||||
TEST_GEN_PROGS_EXTENDED = kublk
|
||||
|
||||
|
||||
@@ -34,8 +34,9 @@ static int loop_queue_tgt_rw_io(struct ublk_thread *t, struct ublk_queue *q,
|
||||
unsigned zc = ublk_queue_use_zc(q);
|
||||
unsigned auto_zc = ublk_queue_use_auto_zc(q);
|
||||
enum io_uring_op op = ublk_to_uring_op(iod, zc | auto_zc);
|
||||
struct ublk_io *io = ublk_get_io(q, tag);
|
||||
struct io_uring_sqe *sqe[3];
|
||||
void *addr = (zc | auto_zc) ? NULL : (void *)iod->addr;
|
||||
void *addr = io->buf_addr;
|
||||
|
||||
if (!zc || auto_zc) {
|
||||
ublk_io_alloc_sqes(t, sqe, 1);
|
||||
@@ -56,7 +57,7 @@ static int loop_queue_tgt_rw_io(struct ublk_thread *t, struct ublk_queue *q,
|
||||
|
||||
ublk_io_alloc_sqes(t, sqe, 3);
|
||||
|
||||
io_uring_prep_buf_register(sqe[0], q, tag, q->q_id, ublk_get_io(q, tag)->buf_index);
|
||||
io_uring_prep_buf_register(sqe[0], q, tag, q->q_id, io->buf_index);
|
||||
sqe[0]->flags |= IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_HARDLINK;
|
||||
sqe[0]->user_data = build_user_data(tag,
|
||||
ublk_cmd_op_nr(sqe[0]->cmd_op), 0, q->q_id, 1);
|
||||
@@ -68,7 +69,7 @@ static int loop_queue_tgt_rw_io(struct ublk_thread *t, struct ublk_queue *q,
|
||||
sqe[1]->flags |= IOSQE_FIXED_FILE | IOSQE_IO_HARDLINK;
|
||||
sqe[1]->user_data = build_user_data(tag, ublk_op, 0, q->q_id, 1);
|
||||
|
||||
io_uring_prep_buf_unregister(sqe[2], q, tag, q->q_id, ublk_get_io(q, tag)->buf_index);
|
||||
io_uring_prep_buf_unregister(sqe[2], q, tag, q->q_id, io->buf_index);
|
||||
sqe[2]->user_data = build_user_data(tag, ublk_cmd_op_nr(sqe[2]->cmd_op), 0, q->q_id, 1);
|
||||
|
||||
return 2;
|
||||
|
||||
@@ -596,6 +596,38 @@ static void ublk_set_auto_buf_reg(const struct ublk_queue *q,
|
||||
sqe->addr = ublk_auto_buf_reg_to_sqe_addr(&buf);
|
||||
}
|
||||
|
||||
/* Copy in pieces to test the buffer offset logic */
|
||||
#define UBLK_USER_COPY_LEN 2048
|
||||
|
||||
static void ublk_user_copy(const struct ublk_io *io, __u8 match_ublk_op)
|
||||
{
|
||||
const struct ublk_queue *q = ublk_io_to_queue(io);
|
||||
const struct ublksrv_io_desc *iod = ublk_get_iod(q, io->tag);
|
||||
__u64 off = ublk_user_copy_offset(q->q_id, io->tag);
|
||||
__u8 ublk_op = ublksrv_get_op(iod);
|
||||
__u32 len = iod->nr_sectors << 9;
|
||||
void *addr = io->buf_addr;
|
||||
|
||||
if (ublk_op != match_ublk_op)
|
||||
return;
|
||||
|
||||
while (len) {
|
||||
__u32 copy_len = min(len, UBLK_USER_COPY_LEN);
|
||||
ssize_t copied;
|
||||
|
||||
if (ublk_op == UBLK_IO_OP_WRITE)
|
||||
copied = pread(q->ublk_fd, addr, copy_len, off);
|
||||
else if (ublk_op == UBLK_IO_OP_READ)
|
||||
copied = pwrite(q->ublk_fd, addr, copy_len, off);
|
||||
else
|
||||
assert(0);
|
||||
assert(copied == (ssize_t)copy_len);
|
||||
addr += copy_len;
|
||||
off += copy_len;
|
||||
len -= copy_len;
|
||||
}
|
||||
}
|
||||
|
||||
int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
|
||||
{
|
||||
struct ublk_queue *q = ublk_io_to_queue(io);
|
||||
@@ -618,9 +650,12 @@ int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
|
||||
|
||||
if (io->flags & UBLKS_IO_NEED_GET_DATA)
|
||||
cmd_op = UBLK_U_IO_NEED_GET_DATA;
|
||||
else if (io->flags & UBLKS_IO_NEED_COMMIT_RQ_COMP)
|
||||
else if (io->flags & UBLKS_IO_NEED_COMMIT_RQ_COMP) {
|
||||
if (ublk_queue_use_user_copy(q))
|
||||
ublk_user_copy(io, UBLK_IO_OP_READ);
|
||||
|
||||
cmd_op = UBLK_U_IO_COMMIT_AND_FETCH_REQ;
|
||||
else if (io->flags & UBLKS_IO_NEED_FETCH_RQ)
|
||||
} else if (io->flags & UBLKS_IO_NEED_FETCH_RQ)
|
||||
cmd_op = UBLK_U_IO_FETCH_REQ;
|
||||
|
||||
if (io_uring_sq_space_left(&t->ring) < 1)
|
||||
@@ -649,7 +684,7 @@ int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
|
||||
sqe[0]->rw_flags = 0;
|
||||
cmd->tag = io->tag;
|
||||
cmd->q_id = q->q_id;
|
||||
if (!ublk_queue_no_buf(q))
|
||||
if (!ublk_queue_no_buf(q) && !ublk_queue_use_user_copy(q))
|
||||
cmd->addr = (__u64) (uintptr_t) io->buf_addr;
|
||||
else
|
||||
cmd->addr = 0;
|
||||
@@ -751,6 +786,10 @@ static void ublk_handle_uring_cmd(struct ublk_thread *t,
|
||||
|
||||
if (cqe->res == UBLK_IO_RES_OK) {
|
||||
assert(tag < q->q_depth);
|
||||
|
||||
if (ublk_queue_use_user_copy(q))
|
||||
ublk_user_copy(io, UBLK_IO_OP_WRITE);
|
||||
|
||||
if (q->tgt_ops->queue_io)
|
||||
q->tgt_ops->queue_io(t, q, tag);
|
||||
} else if (cqe->res == UBLK_IO_RES_NEED_GET_DATA) {
|
||||
@@ -1507,7 +1546,7 @@ static void __cmd_create_help(char *exe, bool recovery)
|
||||
|
||||
printf("%s %s -t [null|loop|stripe|fault_inject] [-q nr_queues] [-d depth] [-n dev_id]\n",
|
||||
exe, recovery ? "recover" : "add");
|
||||
printf("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1 ] [-g]\n");
|
||||
printf("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1] [-g] [-u]\n");
|
||||
printf("\t[-e 0|1 ] [-i 0|1] [--no_ublk_fixed_fd]\n");
|
||||
printf("\t[--nthreads threads] [--per_io_tasks]\n");
|
||||
printf("\t[target options] [backfile1] [backfile2] ...\n");
|
||||
@@ -1568,6 +1607,7 @@ int main(int argc, char *argv[])
|
||||
{ "get_data", 1, NULL, 'g'},
|
||||
{ "auto_zc", 0, NULL, 0 },
|
||||
{ "auto_zc_fallback", 0, NULL, 0 },
|
||||
{ "user_copy", 0, NULL, 'u'},
|
||||
{ "size", 1, NULL, 's'},
|
||||
{ "nthreads", 1, NULL, 0 },
|
||||
{ "per_io_tasks", 0, NULL, 0 },
|
||||
@@ -1593,7 +1633,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
opterr = 0;
|
||||
optind = 2;
|
||||
while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:s:gaz",
|
||||
while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:s:gazu",
|
||||
longopts, &option_idx)) != -1) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
@@ -1613,7 +1653,7 @@ int main(int argc, char *argv[])
|
||||
ctx.queue_depth = strtol(optarg, NULL, 10);
|
||||
break;
|
||||
case 'z':
|
||||
ctx.flags |= UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_USER_COPY;
|
||||
ctx.flags |= UBLK_F_SUPPORT_ZERO_COPY;
|
||||
break;
|
||||
case 'r':
|
||||
value = strtol(optarg, NULL, 10);
|
||||
@@ -1633,6 +1673,9 @@ int main(int argc, char *argv[])
|
||||
case 'g':
|
||||
ctx.flags |= UBLK_F_NEED_GET_DATA;
|
||||
break;
|
||||
case 'u':
|
||||
ctx.flags |= UBLK_F_USER_COPY;
|
||||
break;
|
||||
case 's':
|
||||
ctx.size = strtoull(optarg, NULL, 10);
|
||||
break;
|
||||
@@ -1686,6 +1729,15 @@ int main(int argc, char *argv[])
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!!(ctx.flags & UBLK_F_NEED_GET_DATA) +
|
||||
!!(ctx.flags & UBLK_F_USER_COPY) +
|
||||
(ctx.flags & UBLK_F_SUPPORT_ZERO_COPY && !ctx.auto_zc_fallback) +
|
||||
(ctx.flags & UBLK_F_AUTO_BUF_REG && !ctx.auto_zc_fallback) +
|
||||
ctx.auto_zc_fallback > 1) {
|
||||
fprintf(stderr, "too many data copy modes specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i = optind;
|
||||
while (i < argc && ctx.nr_files < MAX_BACK_FILES) {
|
||||
ctx.files[ctx.nr_files++] = argv[i++];
|
||||
|
||||
@@ -208,6 +208,12 @@ static inline int ublk_io_auto_zc_fallback(const struct ublksrv_io_desc *iod)
|
||||
return !!(iod->op_flags & UBLK_IO_F_NEED_REG_BUF);
|
||||
}
|
||||
|
||||
static inline __u64 ublk_user_copy_offset(unsigned q_id, unsigned tag)
|
||||
{
|
||||
return UBLKSRV_IO_BUF_OFFSET +
|
||||
((__u64)q_id << UBLK_QID_OFF | (__u64)tag << UBLK_TAG_OFF);
|
||||
}
|
||||
|
||||
static inline int is_target_io(__u64 user_data)
|
||||
{
|
||||
return (user_data & (1ULL << 63)) != 0;
|
||||
@@ -390,19 +396,24 @@ static inline int ublk_completed_tgt_io(struct ublk_thread *t,
|
||||
return --io->tgt_ios == 0;
|
||||
}
|
||||
|
||||
static inline int ublk_queue_use_zc(const struct ublk_queue *q)
|
||||
static inline bool ublk_queue_use_zc(const struct ublk_queue *q)
|
||||
{
|
||||
return q->flags & UBLK_F_SUPPORT_ZERO_COPY;
|
||||
return !!(q->flags & UBLK_F_SUPPORT_ZERO_COPY);
|
||||
}
|
||||
|
||||
static inline int ublk_queue_use_auto_zc(const struct ublk_queue *q)
|
||||
static inline bool ublk_queue_use_auto_zc(const struct ublk_queue *q)
|
||||
{
|
||||
return q->flags & UBLK_F_AUTO_BUF_REG;
|
||||
return !!(q->flags & UBLK_F_AUTO_BUF_REG);
|
||||
}
|
||||
|
||||
static inline int ublk_queue_auto_zc_fallback(const struct ublk_queue *q)
|
||||
static inline bool ublk_queue_auto_zc_fallback(const struct ublk_queue *q)
|
||||
{
|
||||
return q->flags & UBLKS_Q_AUTO_BUF_REG_FALLBACK;
|
||||
return !!(q->flags & UBLKS_Q_AUTO_BUF_REG_FALLBACK);
|
||||
}
|
||||
|
||||
static inline bool ublk_queue_use_user_copy(const struct ublk_queue *q)
|
||||
{
|
||||
return !!(q->flags & UBLK_F_USER_COPY);
|
||||
}
|
||||
|
||||
static inline int ublk_queue_no_buf(const struct ublk_queue *q)
|
||||
|
||||
@@ -134,7 +134,7 @@ static int stripe_queue_tgt_rw_io(struct ublk_thread *t, struct ublk_queue *q,
|
||||
struct stripe_array *s = alloc_stripe_array(conf, iod);
|
||||
struct ublk_io *io = ublk_get_io(q, tag);
|
||||
int i, extra = zc ? 2 : 0;
|
||||
void *base = (zc | auto_zc) ? NULL : (void *)iod->addr;
|
||||
void *base = io->buf_addr;
|
||||
|
||||
io->private_data = s;
|
||||
calculate_stripe_array(conf, iod, s, base);
|
||||
|
||||
@@ -333,11 +333,12 @@ run_io_and_kill_daemon()
|
||||
|
||||
run_io_and_recover()
|
||||
{
|
||||
local action=$1
|
||||
local size=$1
|
||||
local action=$2
|
||||
local state
|
||||
local dev_id
|
||||
|
||||
shift 1
|
||||
shift 2
|
||||
dev_id=$(_add_ublk_dev "$@")
|
||||
_check_add_dev "$TID" $?
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ ERR_CODE=0
|
||||
|
||||
ublk_run_recover_test()
|
||||
{
|
||||
run_io_and_recover "kill_daemon" "$@"
|
||||
run_io_and_recover 256M "kill_daemon" "$@"
|
||||
ERR_CODE=$?
|
||||
if [ ${ERR_CODE} -ne 0 ]; then
|
||||
echo "$TID failure: $*"
|
||||
|
||||
@@ -8,7 +8,7 @@ ERR_CODE=0
|
||||
|
||||
ublk_run_recover_test()
|
||||
{
|
||||
run_io_and_recover "kill_daemon" "$@"
|
||||
run_io_and_recover 256M "kill_daemon" "$@"
|
||||
ERR_CODE=$?
|
||||
if [ ${ERR_CODE} -ne 0 ]; then
|
||||
echo "$TID failure: $*"
|
||||
|
||||
@@ -8,7 +8,7 @@ ERR_CODE=0
|
||||
|
||||
ublk_run_quiesce_recover()
|
||||
{
|
||||
run_io_and_recover "quiesce_dev" "$@"
|
||||
run_io_and_recover 256M "quiesce_dev" "$@"
|
||||
ERR_CODE=$?
|
||||
if [ ${ERR_CODE} -ne 0 ]; then
|
||||
echo "$TID failure: $*"
|
||||
|
||||
40
tools/testing/selftests/ublk/test_generic_14.sh
Executable file
40
tools/testing/selftests/ublk/test_generic_14.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
|
||||
TID="generic_14"
|
||||
ERR_CODE=0
|
||||
|
||||
ublk_run_recover_test()
|
||||
{
|
||||
run_io_and_recover 256M "kill_daemon" "$@"
|
||||
ERR_CODE=$?
|
||||
if [ ${ERR_CODE} -ne 0 ]; then
|
||||
echo "$TID failure: $*"
|
||||
_show_result $TID $ERR_CODE
|
||||
fi
|
||||
}
|
||||
|
||||
if ! _have_program fio; then
|
||||
exit "$UBLK_SKIP_CODE"
|
||||
fi
|
||||
|
||||
_prep_test "recover" "basic recover function verification (user copy)"
|
||||
|
||||
_create_backfile 0 256M
|
||||
_create_backfile 1 128M
|
||||
_create_backfile 2 128M
|
||||
|
||||
ublk_run_recover_test -t null -q 2 -r 1 -u &
|
||||
ublk_run_recover_test -t loop -q 2 -r 1 -u "${UBLK_BACKFILES[0]}" &
|
||||
ublk_run_recover_test -t stripe -q 2 -r 1 -u "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
|
||||
wait
|
||||
|
||||
ublk_run_recover_test -t null -q 2 -r 1 -u -i 1 &
|
||||
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"
|
||||
_show_result $TID $ERR_CODE
|
||||
25
tools/testing/selftests/ublk/test_loop_06.sh
Executable file
25
tools/testing/selftests/ublk/test_loop_06.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
|
||||
TID="loop_06"
|
||||
ERR_CODE=0
|
||||
|
||||
if ! _have_program fio; then
|
||||
exit "$UBLK_SKIP_CODE"
|
||||
fi
|
||||
|
||||
_prep_test "loop" "write and verify over user copy"
|
||||
|
||||
_create_backfile 0 256M
|
||||
dev_id=$(_add_ublk_dev -t loop -u "${UBLK_BACKFILES[0]}")
|
||||
_check_add_dev $TID $?
|
||||
|
||||
# run fio over the ublk disk
|
||||
_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M
|
||||
ERR_CODE=$?
|
||||
|
||||
_cleanup_test "loop"
|
||||
|
||||
_show_result $TID $ERR_CODE
|
||||
21
tools/testing/selftests/ublk/test_loop_07.sh
Executable file
21
tools/testing/selftests/ublk/test_loop_07.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
|
||||
TID="loop_07"
|
||||
ERR_CODE=0
|
||||
|
||||
_prep_test "loop" "mkfs & mount & umount with user copy"
|
||||
|
||||
_create_backfile 0 256M
|
||||
|
||||
dev_id=$(_add_ublk_dev -t loop -u "${UBLK_BACKFILES[0]}")
|
||||
_check_add_dev $TID $?
|
||||
|
||||
_mkfs_mount_test /dev/ublkb"${dev_id}"
|
||||
ERR_CODE=$?
|
||||
|
||||
_cleanup_test "loop"
|
||||
|
||||
_show_result $TID $ERR_CODE
|
||||
24
tools/testing/selftests/ublk/test_null_03.sh
Executable file
24
tools/testing/selftests/ublk/test_null_03.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
|
||||
TID="null_03"
|
||||
ERR_CODE=0
|
||||
|
||||
if ! _have_program fio; then
|
||||
exit "$UBLK_SKIP_CODE"
|
||||
fi
|
||||
|
||||
_prep_test "null" "basic IO test with user copy"
|
||||
|
||||
dev_id=$(_add_ublk_dev -t null -u)
|
||||
_check_add_dev $TID $?
|
||||
|
||||
# run fio over the two disks
|
||||
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"
|
||||
|
||||
_show_result $TID $ERR_CODE
|
||||
@@ -31,21 +31,23 @@ _create_backfile 2 128M
|
||||
ublk_io_and_kill_daemon 8G -t null -q 4 -z --no_ublk_fixed_fd &
|
||||
ublk_io_and_kill_daemon 256M -t loop -q 4 -z --no_ublk_fixed_fd "${UBLK_BACKFILES[0]}" &
|
||||
ublk_io_and_kill_daemon 256M -t stripe -q 4 -z "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
|
||||
wait
|
||||
|
||||
if _have_feature "AUTO_BUF_REG"; then
|
||||
ublk_io_and_kill_daemon 8G -t null -q 4 --auto_zc &
|
||||
ublk_io_and_kill_daemon 256M -t loop -q 4 --auto_zc "${UBLK_BACKFILES[0]}" &
|
||||
ublk_io_and_kill_daemon 256M -t stripe -q 4 --auto_zc --no_ublk_fixed_fd "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
|
||||
ublk_io_and_kill_daemon 8G -t null -q 4 -z --auto_zc --auto_zc_fallback &
|
||||
wait
|
||||
fi
|
||||
|
||||
if _have_feature "PER_IO_DAEMON"; then
|
||||
ublk_io_and_kill_daemon 8G -t null -q 4 --nthreads 8 --per_io_tasks &
|
||||
ublk_io_and_kill_daemon 256M -t loop -q 4 --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
|
||||
ublk_io_and_kill_daemon 256M -t stripe -q 4 --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
|
||||
ublk_io_and_kill_daemon 8G -t null -q 4 --nthreads 8 --per_io_tasks &
|
||||
ublk_io_and_kill_daemon 8G -t null -q 4 --auto_zc --nthreads 8 --per_io_tasks &
|
||||
ublk_io_and_kill_daemon 256M -t loop -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
|
||||
ublk_io_and_kill_daemon 256M -t stripe -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
|
||||
ublk_io_and_kill_daemon 8G -t null -q 4 -z --auto_zc --auto_zc_fallback --nthreads 8 --per_io_tasks &
|
||||
wait
|
||||
fi
|
||||
wait
|
||||
|
||||
_cleanup_test "stress"
|
||||
_show_result $TID $ERR_CODE
|
||||
|
||||
@@ -58,17 +58,17 @@ done
|
||||
|
||||
if _have_feature "ZERO_COPY"; then
|
||||
for reissue in $(seq 0 1); do
|
||||
ublk_io_and_remove 8G -t null -q 4 -g -z -r 1 -i "$reissue" &
|
||||
ublk_io_and_remove 256M -t loop -q 4 -g -z -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
|
||||
ublk_io_and_remove 8G -t null -q 4 -z -r 1 -i "$reissue" &
|
||||
ublk_io_and_remove 256M -t loop -q 4 -z -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
|
||||
wait
|
||||
done
|
||||
fi
|
||||
|
||||
if _have_feature "AUTO_BUF_REG"; then
|
||||
for reissue in $(seq 0 1); do
|
||||
ublk_io_and_remove 8G -t null -q 4 -g --auto_zc -r 1 -i "$reissue" &
|
||||
ublk_io_and_remove 256M -t loop -q 4 -g --auto_zc -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
|
||||
ublk_io_and_remove 8G -t null -q 4 -g -z --auto_zc --auto_zc_fallback -r 1 -i "$reissue" &
|
||||
ublk_io_and_remove 8G -t null -q 4 --auto_zc -r 1 -i "$reissue" &
|
||||
ublk_io_and_remove 256M -t loop -q 4 --auto_zc -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
|
||||
ublk_io_and_remove 8G -t null -q 4 -z --auto_zc --auto_zc_fallback -r 1 -i "$reissue" &
|
||||
wait
|
||||
done
|
||||
fi
|
||||
|
||||
39
tools/testing/selftests/ublk/test_stress_06.sh
Executable file
39
tools/testing/selftests/ublk/test_stress_06.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
TID="stress_06"
|
||||
ERR_CODE=0
|
||||
|
||||
ublk_io_and_remove()
|
||||
{
|
||||
run_io_and_remove "$@"
|
||||
ERR_CODE=$?
|
||||
if [ ${ERR_CODE} -ne 0 ]; then
|
||||
echo "$TID failure: $*"
|
||||
_show_result $TID $ERR_CODE
|
||||
fi
|
||||
}
|
||||
|
||||
if ! _have_program fio; then
|
||||
exit "$UBLK_SKIP_CODE"
|
||||
fi
|
||||
|
||||
_prep_test "stress" "run IO and remove device (user copy)"
|
||||
|
||||
_create_backfile 0 256M
|
||||
_create_backfile 1 128M
|
||||
_create_backfile 2 128M
|
||||
|
||||
ublk_io_and_remove 8G -t null -q 4 -u &
|
||||
ublk_io_and_remove 256M -t loop -q 4 -u "${UBLK_BACKFILES[0]}" &
|
||||
ublk_io_and_remove 256M -t stripe -q 4 -u "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
|
||||
wait
|
||||
|
||||
ublk_io_and_remove 8G -t null -q 4 -u --nthreads 8 --per_io_tasks &
|
||||
ublk_io_and_remove 256M -t loop -q 4 -u --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
|
||||
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"
|
||||
_show_result $TID $ERR_CODE
|
||||
39
tools/testing/selftests/ublk/test_stress_07.sh
Executable file
39
tools/testing/selftests/ublk/test_stress_07.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
TID="stress_07"
|
||||
ERR_CODE=0
|
||||
|
||||
ublk_io_and_kill_daemon()
|
||||
{
|
||||
run_io_and_kill_daemon "$@"
|
||||
ERR_CODE=$?
|
||||
if [ ${ERR_CODE} -ne 0 ]; then
|
||||
echo "$TID failure: $*"
|
||||
_show_result $TID $ERR_CODE
|
||||
fi
|
||||
}
|
||||
|
||||
if ! _have_program fio; then
|
||||
exit "$UBLK_SKIP_CODE"
|
||||
fi
|
||||
|
||||
_prep_test "stress" "run IO and kill ublk server (user copy)"
|
||||
|
||||
_create_backfile 0 256M
|
||||
_create_backfile 1 128M
|
||||
_create_backfile 2 128M
|
||||
|
||||
ublk_io_and_kill_daemon 8G -t null -q 4 -u --no_ublk_fixed_fd &
|
||||
ublk_io_and_kill_daemon 256M -t loop -q 4 -u --no_ublk_fixed_fd "${UBLK_BACKFILES[0]}" &
|
||||
ublk_io_and_kill_daemon 256M -t stripe -q 4 -u "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
|
||||
wait
|
||||
|
||||
ublk_io_and_kill_daemon 8G -t null -q 4 -u --nthreads 8 --per_io_tasks &
|
||||
ublk_io_and_kill_daemon 256M -t loop -q 4 -u --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
|
||||
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"
|
||||
_show_result $TID $ERR_CODE
|
||||
26
tools/testing/selftests/ublk/test_stripe_05.sh
Executable file
26
tools/testing/selftests/ublk/test_stripe_05.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
|
||||
TID="stripe_05"
|
||||
ERR_CODE=0
|
||||
|
||||
if ! _have_program fio; then
|
||||
exit "$UBLK_SKIP_CODE"
|
||||
fi
|
||||
|
||||
_prep_test "stripe" "write and verify test on user copy"
|
||||
|
||||
_create_backfile 0 256M
|
||||
_create_backfile 1 256M
|
||||
|
||||
dev_id=$(_add_ublk_dev -t stripe -q 2 -u "${UBLK_BACKFILES[0]}" "${UBLK_BACKFILES[1]}")
|
||||
_check_add_dev $TID $?
|
||||
|
||||
# run fio over the ublk disk
|
||||
_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=512M
|
||||
ERR_CODE=$?
|
||||
|
||||
_cleanup_test "stripe"
|
||||
_show_result $TID $ERR_CODE
|
||||
21
tools/testing/selftests/ublk/test_stripe_06.sh
Executable file
21
tools/testing/selftests/ublk/test_stripe_06.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
|
||||
TID="stripe_06"
|
||||
ERR_CODE=0
|
||||
|
||||
_prep_test "stripe" "mkfs & mount & umount on user copy"
|
||||
|
||||
_create_backfile 0 256M
|
||||
_create_backfile 1 256M
|
||||
|
||||
dev_id=$(_add_ublk_dev -t stripe -u -q 2 "${UBLK_BACKFILES[0]}" "${UBLK_BACKFILES[1]}")
|
||||
_check_add_dev $TID $?
|
||||
|
||||
_mkfs_mount_test /dev/ublkb"${dev_id}"
|
||||
ERR_CODE=$?
|
||||
|
||||
_cleanup_test "stripe"
|
||||
_show_result $TID $ERR_CODE
|
||||
@@ -4,7 +4,7 @@
|
||||
$3: strlen($2)
|
||||
*/
|
||||
BEGIN {
|
||||
@last_rw[$1, str($2)] = 0;
|
||||
@last_rw[$1, str($2)] = (uint64)0;
|
||||
}
|
||||
tracepoint:block:block_rq_complete
|
||||
{
|
||||
@@ -17,7 +17,6 @@ tracepoint:block:block_rq_complete
|
||||
}
|
||||
@last_rw[$dev, str($2)] = (args.sector + args.nr_sector);
|
||||
}
|
||||
@ios = count();
|
||||
}
|
||||
|
||||
END {
|
||||
|
||||
Reference in New Issue
Block a user