mirror of
https://github.com/torvalds/linux.git
synced 2026-05-21 05:18:45 +02:00
Merge branch 'block-6.15' into for-6.16/block
Merge 6.15 block fixes in, once again, to resolve conflicts with the fixes for ublk that went into mainline and the 6.16 ublk updates. * block-6.15: nvmet-auth: always free derived key data nvmet-tcp: don't restore null sk_state_change nvmet-tcp: select CONFIG_TLS from CONFIG_NVME_TARGET_TCP_TLS nvme-tcp: select CONFIG_TLS from CONFIG_NVME_TCP_TLS nvme-tcp: fix premature queue removal and I/O failover nvme-pci: add quirks for WDC Blue SN550 15b7:5009 nvme-pci: add quirks for device 126f:1001 nvme-pci: fix queue unquiesce check on slot_reset ublk: remove the check of ublk_need_req_ref() from __ublk_check_and_get_req ublk: enhance check for register/unregister io buffer command ublk: decouple zero copy from user copy selftests: ublk: fix UBLK_F_NEED_GET_DATA Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
commit
c595b5402f
|
|
@ -208,7 +208,7 @@ struct ublk_params_header {
|
|||
static void ublk_stop_dev_unlocked(struct ublk_device *ub);
|
||||
static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq);
|
||||
static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
|
||||
struct ublk_queue *ubq, int tag, size_t offset);
|
||||
const struct ublk_queue *ubq, int tag, size_t offset);
|
||||
static inline unsigned int ublk_req_build_flags(struct request *req);
|
||||
|
||||
static inline struct ublksrv_io_desc *
|
||||
|
|
@ -217,11 +217,6 @@ ublk_get_iod(const struct ublk_queue *ubq, unsigned tag)
|
|||
return &ubq->io_cmd_buf[tag];
|
||||
}
|
||||
|
||||
static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)
|
||||
{
|
||||
return ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
|
||||
}
|
||||
|
||||
static inline bool ublk_dev_is_zoned(const struct ublk_device *ub)
|
||||
{
|
||||
return ub->dev_info.flags & UBLK_F_ZONED;
|
||||
|
|
@ -621,14 +616,19 @@ static void ublk_apply_params(struct ublk_device *ub)
|
|||
ublk_dev_param_zoned_apply(ub);
|
||||
}
|
||||
|
||||
static inline bool ublk_support_zero_copy(const struct ublk_queue *ubq)
|
||||
{
|
||||
return ubq->flags & UBLK_F_SUPPORT_ZERO_COPY;
|
||||
}
|
||||
|
||||
static inline bool ublk_support_user_copy(const struct ublk_queue *ubq)
|
||||
{
|
||||
return ubq->flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
|
||||
return ubq->flags & UBLK_F_USER_COPY;
|
||||
}
|
||||
|
||||
static inline bool ublk_need_map_io(const struct ublk_queue *ubq)
|
||||
{
|
||||
return !ublk_support_user_copy(ubq);
|
||||
return !ublk_support_user_copy(ubq) && !ublk_support_zero_copy(ubq);
|
||||
}
|
||||
|
||||
static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
|
||||
|
|
@ -636,8 +636,11 @@ static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
|
|||
/*
|
||||
* read()/write() is involved in user copy, so request reference
|
||||
* has to be grabbed
|
||||
*
|
||||
* for zero copy, request buffer need to be registered to io_uring
|
||||
* buffer table, so reference is needed
|
||||
*/
|
||||
return ublk_support_user_copy(ubq);
|
||||
return ublk_support_user_copy(ubq) || ublk_support_zero_copy(ubq);
|
||||
}
|
||||
|
||||
static inline void ublk_init_req_ref(const struct ublk_queue *ubq,
|
||||
|
|
@ -1919,13 +1922,20 @@ static void ublk_io_release(void *priv)
|
|||
}
|
||||
|
||||
static int ublk_register_io_buf(struct io_uring_cmd *cmd,
|
||||
struct ublk_queue *ubq, unsigned int tag,
|
||||
const struct ublk_queue *ubq, unsigned int tag,
|
||||
unsigned int index, unsigned int issue_flags)
|
||||
{
|
||||
struct ublk_device *ub = cmd->file->private_data;
|
||||
const struct ublk_io *io = &ubq->ios[tag];
|
||||
struct request *req;
|
||||
int ret;
|
||||
|
||||
if (!ublk_support_zero_copy(ubq))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
|
||||
return -EINVAL;
|
||||
|
||||
req = __ublk_check_and_get_req(ub, ubq, tag, 0);
|
||||
if (!req)
|
||||
return -EINVAL;
|
||||
|
|
@ -1941,8 +1951,17 @@ static int ublk_register_io_buf(struct io_uring_cmd *cmd,
|
|||
}
|
||||
|
||||
static int ublk_unregister_io_buf(struct io_uring_cmd *cmd,
|
||||
const struct ublk_queue *ubq, unsigned int tag,
|
||||
unsigned int index, unsigned int issue_flags)
|
||||
{
|
||||
const struct ublk_io *io = &ubq->ios[tag];
|
||||
|
||||
if (!ublk_support_zero_copy(ubq))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
|
||||
return -EINVAL;
|
||||
|
||||
return io_buffer_unregister_bvec(cmd, index, issue_flags);
|
||||
}
|
||||
|
||||
|
|
@ -2102,7 +2121,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
|
|||
case UBLK_IO_REGISTER_IO_BUF:
|
||||
return ublk_register_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
|
||||
case UBLK_IO_UNREGISTER_IO_BUF:
|
||||
return ublk_unregister_io_buf(cmd, ub_cmd->addr, issue_flags);
|
||||
return ublk_unregister_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
|
||||
case UBLK_IO_FETCH_REQ:
|
||||
ret = ublk_fetch(cmd, ubq, io, ub_cmd->addr);
|
||||
if (ret)
|
||||
|
|
@ -2134,13 +2153,10 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
|
|||
}
|
||||
|
||||
static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
|
||||
struct ublk_queue *ubq, int tag, size_t offset)
|
||||
const struct ublk_queue *ubq, int tag, size_t offset)
|
||||
{
|
||||
struct request *req;
|
||||
|
||||
if (!ublk_need_req_ref(ubq))
|
||||
return NULL;
|
||||
|
||||
req = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], tag);
|
||||
if (!req)
|
||||
return NULL;
|
||||
|
|
@ -2254,6 +2270,9 @@ static struct request *ublk_check_and_get_req(struct kiocb *iocb,
|
|||
if (!ubq)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!ublk_support_user_copy(ubq))
|
||||
return ERR_PTR(-EACCES);
|
||||
|
||||
if (tag >= ubq->q_depth)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
|
@ -2792,13 +2811,18 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
|
|||
ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE |
|
||||
UBLK_F_URING_CMD_COMP_IN_TASK;
|
||||
|
||||
/* GET_DATA isn't needed any more with USER_COPY */
|
||||
if (ublk_dev_is_user_copy(ub))
|
||||
/* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */
|
||||
if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY))
|
||||
ub->dev_info.flags &= ~UBLK_F_NEED_GET_DATA;
|
||||
|
||||
/* Zoned storage support requires user copy feature */
|
||||
/*
|
||||
* Zoned storage support requires reuse `ublksrv_io_cmd->addr` for
|
||||
* returning write_append_lba, which is only allowed in case of
|
||||
* user copy or zero copy
|
||||
*/
|
||||
if (ublk_dev_is_zoned(ub) &&
|
||||
(!IS_ENABLED(CONFIG_BLK_DEV_ZONED) || !ublk_dev_is_user_copy(ub))) {
|
||||
(!IS_ENABLED(CONFIG_BLK_DEV_ZONED) || !(ub->dev_info.flags &
|
||||
(UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY)))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free_dev_number;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ config NVME_TCP_TLS
|
|||
depends on NVME_TCP
|
||||
select NET_HANDSHAKE
|
||||
select KEYS
|
||||
select TLS
|
||||
help
|
||||
Enables TLS encryption for NVMe TCP using the netlink handshake API.
|
||||
|
||||
|
|
|
|||
|
|
@ -3575,7 +3575,7 @@ static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev)
|
|||
|
||||
dev_info(dev->ctrl.device, "restart after slot reset\n");
|
||||
pci_restore_state(pdev);
|
||||
if (!nvme_try_sched_reset(&dev->ctrl))
|
||||
if (nvme_try_sched_reset(&dev->ctrl))
|
||||
nvme_unquiesce_io_queues(&dev->ctrl);
|
||||
return PCI_ERS_RESULT_RECOVERED;
|
||||
}
|
||||
|
|
@ -3623,6 +3623,9 @@ static const struct pci_device_id nvme_id_table[] = {
|
|||
.driver_data = NVME_QUIRK_BOGUS_NID, },
|
||||
{ PCI_DEVICE(0x1217, 0x8760), /* O2 Micro 64GB Steam Deck */
|
||||
.driver_data = NVME_QUIRK_DMAPOOL_ALIGN_512, },
|
||||
{ PCI_DEVICE(0x126f, 0x1001), /* Silicon Motion generic */
|
||||
.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
|
||||
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
|
||||
{ PCI_DEVICE(0x126f, 0x2262), /* Silicon Motion generic */
|
||||
.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
|
||||
NVME_QUIRK_BOGUS_NID, },
|
||||
|
|
@ -3646,6 +3649,9 @@ static const struct pci_device_id nvme_id_table[] = {
|
|||
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
|
||||
{ PCI_DEVICE(0x15b7, 0x5008), /* Sandisk SN530 */
|
||||
.driver_data = NVME_QUIRK_BROKEN_MSI },
|
||||
{ PCI_DEVICE(0x15b7, 0x5009), /* Sandisk SN550 */
|
||||
.driver_data = NVME_QUIRK_BROKEN_MSI |
|
||||
NVME_QUIRK_NO_DEEPEST_PS },
|
||||
{ PCI_DEVICE(0x1987, 0x5012), /* Phison E12 */
|
||||
.driver_data = NVME_QUIRK_BOGUS_NID, },
|
||||
{ PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */
|
||||
|
|
|
|||
|
|
@ -1946,7 +1946,7 @@ static void __nvme_tcp_stop_queue(struct nvme_tcp_queue *queue)
|
|||
cancel_work_sync(&queue->io_work);
|
||||
}
|
||||
|
||||
static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid)
|
||||
static void nvme_tcp_stop_queue_nowait(struct nvme_ctrl *nctrl, int qid)
|
||||
{
|
||||
struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
|
||||
struct nvme_tcp_queue *queue = &ctrl->queues[qid];
|
||||
|
|
@ -1965,6 +1965,31 @@ static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid)
|
|||
mutex_unlock(&queue->queue_lock);
|
||||
}
|
||||
|
||||
static void nvme_tcp_wait_queue(struct nvme_ctrl *nctrl, int qid)
|
||||
{
|
||||
struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
|
||||
struct nvme_tcp_queue *queue = &ctrl->queues[qid];
|
||||
int timeout = 100;
|
||||
|
||||
while (timeout > 0) {
|
||||
if (!test_bit(NVME_TCP_Q_ALLOCATED, &queue->flags) ||
|
||||
!sk_wmem_alloc_get(queue->sock->sk))
|
||||
return;
|
||||
msleep(2);
|
||||
timeout -= 2;
|
||||
}
|
||||
dev_warn(nctrl->device,
|
||||
"qid %d: timeout draining sock wmem allocation expired\n",
|
||||
qid);
|
||||
}
|
||||
|
||||
static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid)
|
||||
{
|
||||
nvme_tcp_stop_queue_nowait(nctrl, qid);
|
||||
nvme_tcp_wait_queue(nctrl, qid);
|
||||
}
|
||||
|
||||
|
||||
static void nvme_tcp_setup_sock_ops(struct nvme_tcp_queue *queue)
|
||||
{
|
||||
write_lock_bh(&queue->sock->sk->sk_callback_lock);
|
||||
|
|
@ -2032,7 +2057,9 @@ static void nvme_tcp_stop_io_queues(struct nvme_ctrl *ctrl)
|
|||
int i;
|
||||
|
||||
for (i = 1; i < ctrl->queue_count; i++)
|
||||
nvme_tcp_stop_queue(ctrl, i);
|
||||
nvme_tcp_stop_queue_nowait(ctrl, i);
|
||||
for (i = 1; i < ctrl->queue_count; i++)
|
||||
nvme_tcp_wait_queue(ctrl, i);
|
||||
}
|
||||
|
||||
static int nvme_tcp_start_io_queues(struct nvme_ctrl *ctrl,
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ config NVME_TARGET_TCP_TLS
|
|||
bool "NVMe over Fabrics TCP target TLS encryption support"
|
||||
depends on NVME_TARGET_TCP
|
||||
select NET_HANDSHAKE
|
||||
select TLS
|
||||
help
|
||||
Enables TLS encryption for the NVMe TCP target using the netlink handshake API.
|
||||
|
||||
|
|
|
|||
|
|
@ -600,13 +600,12 @@ void nvmet_auth_insert_psk(struct nvmet_sq *sq)
|
|||
pr_warn("%s: ctrl %d qid %d failed to refresh key, error %ld\n",
|
||||
__func__, sq->ctrl->cntlid, sq->qid, PTR_ERR(tls_key));
|
||||
tls_key = NULL;
|
||||
kfree_sensitive(tls_psk);
|
||||
}
|
||||
if (sq->ctrl->tls_key)
|
||||
key_put(sq->ctrl->tls_key);
|
||||
sq->ctrl->tls_key = tls_key;
|
||||
#endif
|
||||
|
||||
kfree_sensitive(tls_psk);
|
||||
out_free_digest:
|
||||
kfree_sensitive(digest);
|
||||
out_free_psk:
|
||||
|
|
|
|||
|
|
@ -1560,6 +1560,9 @@ static void nvmet_tcp_restore_socket_callbacks(struct nvmet_tcp_queue *queue)
|
|||
{
|
||||
struct socket *sock = queue->sock;
|
||||
|
||||
if (!queue->state_change)
|
||||
return;
|
||||
|
||||
write_lock_bh(&sock->sk->sk_callback_lock);
|
||||
sock->sk->sk_data_ready = queue->data_ready;
|
||||
sock->sk->sk_state_change = queue->state_change;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ TEST_PROGS += test_generic_03.sh
|
|||
TEST_PROGS += test_generic_04.sh
|
||||
TEST_PROGS += test_generic_05.sh
|
||||
TEST_PROGS += test_generic_06.sh
|
||||
TEST_PROGS += test_generic_07.sh
|
||||
|
||||
TEST_PROGS += test_null_01.sh
|
||||
TEST_PROGS += test_null_02.sh
|
||||
|
|
|
|||
|
|
@ -536,12 +536,17 @@ int ublk_queue_io_cmd(struct ublk_queue *q, struct ublk_io *io, unsigned tag)
|
|||
if (!(io->flags & UBLKSRV_IO_FREE))
|
||||
return 0;
|
||||
|
||||
/* we issue because we need either fetching or committing */
|
||||
/*
|
||||
* we issue because we need either fetching or committing or
|
||||
* getting data
|
||||
*/
|
||||
if (!(io->flags &
|
||||
(UBLKSRV_NEED_FETCH_RQ | UBLKSRV_NEED_COMMIT_RQ_COMP)))
|
||||
(UBLKSRV_NEED_FETCH_RQ | UBLKSRV_NEED_COMMIT_RQ_COMP | UBLKSRV_NEED_GET_DATA)))
|
||||
return 0;
|
||||
|
||||
if (io->flags & UBLKSRV_NEED_COMMIT_RQ_COMP)
|
||||
if (io->flags & UBLKSRV_NEED_GET_DATA)
|
||||
cmd_op = UBLK_U_IO_NEED_GET_DATA;
|
||||
else if (io->flags & UBLKSRV_NEED_COMMIT_RQ_COMP)
|
||||
cmd_op = UBLK_U_IO_COMMIT_AND_FETCH_REQ;
|
||||
else if (io->flags & UBLKSRV_NEED_FETCH_RQ)
|
||||
cmd_op = UBLK_U_IO_FETCH_REQ;
|
||||
|
|
@ -658,6 +663,9 @@ static void ublk_handle_cqe(struct io_uring *r,
|
|||
assert(tag < q->q_depth);
|
||||
if (q->tgt_ops->queue_io)
|
||||
q->tgt_ops->queue_io(q, tag);
|
||||
} else if (cqe->res == UBLK_IO_RES_NEED_GET_DATA) {
|
||||
io->flags |= UBLKSRV_NEED_GET_DATA | UBLKSRV_IO_FREE;
|
||||
ublk_queue_io_cmd(q, io, tag);
|
||||
} else {
|
||||
/*
|
||||
* COMMIT_REQ will be completed immediately since no fetching
|
||||
|
|
@ -1237,7 +1245,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] [--debug_mask mask] [-r 0|1 ] [-g 0|1]\n");
|
||||
printf("\t[--foreground] [--quiet] [-z] [--debug_mask mask] [-r 0|1 ] [-g]\n");
|
||||
printf("\t[-e 0|1 ] [-i 0|1]\n");
|
||||
printf("\t[target options] [backfile1] [backfile2] ...\n");
|
||||
printf("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n");
|
||||
|
|
@ -1313,7 +1321,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
opterr = 0;
|
||||
optind = 2;
|
||||
while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:az",
|
||||
while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:gaz",
|
||||
longopts, &option_idx)) != -1) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
|
|
@ -1351,9 +1359,7 @@ int main(int argc, char *argv[])
|
|||
ctx.flags |= UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_REISSUE;
|
||||
break;
|
||||
case 'g':
|
||||
value = strtol(optarg, NULL, 10);
|
||||
if (value)
|
||||
ctx.flags |= UBLK_F_NEED_GET_DATA;
|
||||
ctx.flags |= UBLK_F_NEED_GET_DATA;
|
||||
break;
|
||||
case 0:
|
||||
if (!strcmp(longopts[option_idx].name, "debug_mask"))
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ struct ublk_io {
|
|||
#define UBLKSRV_NEED_FETCH_RQ (1UL << 0)
|
||||
#define UBLKSRV_NEED_COMMIT_RQ_COMP (1UL << 1)
|
||||
#define UBLKSRV_IO_FREE (1UL << 2)
|
||||
#define UBLKSRV_NEED_GET_DATA (1UL << 3)
|
||||
unsigned short flags;
|
||||
unsigned short refs; /* used by target code only */
|
||||
|
||||
|
|
|
|||
28
tools/testing/selftests/ublk/test_generic_07.sh
Executable file
28
tools/testing/selftests/ublk/test_generic_07.sh
Executable file
|
|
@ -0,0 +1,28 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
|
||||
TID="generic_07"
|
||||
ERR_CODE=0
|
||||
|
||||
if ! _have_program fio; then
|
||||
exit "$UBLK_SKIP_CODE"
|
||||
fi
|
||||
|
||||
_prep_test "generic" "test UBLK_F_NEED_GET_DATA"
|
||||
|
||||
_create_backfile 0 256M
|
||||
dev_id=$(_add_ublk_dev -t loop -q 2 -g "${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=$?
|
||||
if [ "$ERR_CODE" -eq 0 ]; then
|
||||
_mkfs_mount_test /dev/ublkb"${dev_id}"
|
||||
ERR_CODE=$?
|
||||
fi
|
||||
|
||||
_cleanup_test "generic"
|
||||
_show_result $TID $ERR_CODE
|
||||
|
|
@ -47,15 +47,15 @@ _create_backfile 0 256M
|
|||
_create_backfile 1 256M
|
||||
|
||||
for reissue in $(seq 0 1); do
|
||||
ublk_io_and_remove 8G -t null -q 4 -g 1 -r 1 -i "$reissue" &
|
||||
ublk_io_and_remove 256M -t loop -q 4 -g 1 -r 1 -i "$reissue" "${UBLK_BACKFILES[0]}" &
|
||||
ublk_io_and_remove 8G -t null -q 4 -g -r 1 -i "$reissue" &
|
||||
ublk_io_and_remove 256M -t loop -q 4 -g -r 1 -i "$reissue" "${UBLK_BACKFILES[0]}" &
|
||||
wait
|
||||
done
|
||||
|
||||
if _have_feature "ZERO_COPY"; then
|
||||
for reissue in $(seq 0 1); do
|
||||
ublk_io_and_remove 8G -t null -q 4 -g 1 -z -r 1 -i "$reissue" &
|
||||
ublk_io_and_remove 256M -t loop -q 4 -g 1 -z -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
|
||||
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]}" &
|
||||
wait
|
||||
done
|
||||
fi
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user