Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/kernel_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: blktests-ci

on:
pull_request:

jobs:
build-kernel:
runs-on: ubuntu-latest
steps:
- name: Configure git
run: |
git config --global --add safe.directory '*'
- name: Checkout git
run: |
sudo apt-get install -y libelf-dev
mkdir -p linux
cd linux
git init
git remote add origin https://github.com/${{ github.repository }}
git fetch origin --depth=5 ${{ github.event.pull_request.head.sha }}
git reset --hard ${{ github.event.pull_request.head.sha }}
git log -1
- name: Build kernel
run: |
cd linux
make defconfig
make -j 8

35 changes: 24 additions & 11 deletions Documentation/block/ublk.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,15 @@ managing and controlling ublk devices with help of several control commands:

- ``UBLK_CMD_START_DEV``

After the server prepares userspace resources (such as creating per-queue
pthread & io_uring for handling ublk IO), this command is sent to the
After the server prepares userspace resources (such as creating I/O handler
threads & io_uring for handling ublk IO), this command is sent to the
driver for allocating & exposing ``/dev/ublkb*``. Parameters set via
``UBLK_CMD_SET_PARAMS`` are applied for creating the device.

- ``UBLK_CMD_STOP_DEV``

Halt IO on ``/dev/ublkb*`` and remove the device. When this command returns,
ublk server will release resources (such as destroying per-queue pthread &
ublk server will release resources (such as destroying I/O handler threads &
io_uring).

- ``UBLK_CMD_DEL_DEV``
Expand Down Expand Up @@ -208,15 +208,15 @@ managing and controlling ublk devices with help of several control commands:
modify how I/O is handled while the ublk server is dying/dead (this is called
the ``nosrv`` case in the driver code).

With just ``UBLK_F_USER_RECOVERY`` set, after one ubq_daemon(ublk server's io
handler) is dying, ublk does not delete ``/dev/ublkb*`` during the whole
With just ``UBLK_F_USER_RECOVERY`` set, after the ublk server exits,
ublk does not delete ``/dev/ublkb*`` during the whole
recovery stage and ublk device ID is kept. It is ublk server's
responsibility to recover the device context by its own knowledge.
Requests which have not been issued to userspace are requeued. Requests
which have been issued to userspace are aborted.

With ``UBLK_F_USER_RECOVERY_REISSUE`` additionally set, after one ubq_daemon
(ublk server's io handler) is dying, contrary to ``UBLK_F_USER_RECOVERY``,
With ``UBLK_F_USER_RECOVERY_REISSUE`` additionally set, after the ublk server
exits, contrary to ``UBLK_F_USER_RECOVERY``,
requests which have been issued to userspace are requeued and will be
re-issued to the new process after handling ``UBLK_CMD_END_USER_RECOVERY``.
``UBLK_F_USER_RECOVERY_REISSUE`` is designed for backends who tolerate
Expand All @@ -241,10 +241,11 @@ can be controlled/accessed just inside this container.
Data plane
----------

ublk server needs to create per-queue IO pthread & io_uring for handling IO
commands via io_uring passthrough. The per-queue IO pthread
focuses on IO handling and shouldn't handle any control & management
tasks.
The ublk server should create dedicated threads for handling I/O. Each
thread should have its own io_uring through which it is notified of new
I/O, and through which it can complete I/O. These dedicated threads
should focus on IO handling and shouldn't handle any control &
management tasks.

The's IO is assigned by a unique tag, which is 1:1 mapping with IO
request of ``/dev/ublkb*``.
Expand All @@ -265,6 +266,18 @@ with specified IO tag in the command data:
destined to ``/dev/ublkb*``. This command is sent only once from the server
IO pthread for ublk driver to setup IO forward environment.

Once a thread issues this command against a given (qid,tag) pair, the thread
registers itself as that I/O's daemon. In the future, only that I/O's daemon
is allowed to issue commands against the I/O. If any other thread attempts
to issue a command against a (qid,tag) pair for which the thread is not the
daemon, the command will fail. Daemons can be reset only be going through
recovery.

The ability for every (qid,tag) pair to have its own independent daemon task
is indicated by the ``UBLK_F_PER_IO_DAEMON`` feature. If this feature is not
supported by the driver, daemons must be per-queue instead - i.e. all I/Os
associated to a single qid must be handled by the same task.

- ``UBLK_IO_COMMIT_AND_FETCH_REQ``

When an IO request is destined to ``/dev/ublkb*``, the driver stores
Expand Down
1 change: 0 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -12604,7 +12604,6 @@ F: include/linux/iosys-map.h

IO_URING
M: Jens Axboe <[email protected]>
M: Pavel Begunkov <[email protected]>
L: [email protected]
S: Maintained
T: git git://git.kernel.dk/linux-block
Expand Down
17 changes: 5 additions & 12 deletions block/bio-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,9 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
EXPORT_SYMBOL(bio_integrity_add_page);

static int bio_integrity_copy_user(struct bio *bio, struct bio_vec *bvec,
int nr_vecs, unsigned int len,
unsigned int direction)
int nr_vecs, unsigned int len)
{
bool write = direction == ITER_SOURCE;
bool write = op_is_write(bio_op(bio));
struct bio_integrity_payload *bip;
struct iov_iter iter;
void *buf;
Expand All @@ -168,7 +167,7 @@ static int bio_integrity_copy_user(struct bio *bio, struct bio_vec *bvec,
return -ENOMEM;

if (write) {
iov_iter_bvec(&iter, direction, bvec, nr_vecs, len);
iov_iter_bvec(&iter, ITER_SOURCE, bvec, nr_vecs, len);
if (!copy_from_iter_full(buf, len, &iter)) {
ret = -EFAULT;
goto free_buf;
Expand Down Expand Up @@ -264,7 +263,7 @@ int bio_integrity_map_user(struct bio *bio, struct iov_iter *iter)
struct page *stack_pages[UIO_FASTIOV], **pages = stack_pages;
struct bio_vec stack_vec[UIO_FASTIOV], *bvec = stack_vec;
size_t offset, bytes = iter->count;
unsigned int direction, nr_bvecs;
unsigned int nr_bvecs;
int ret, nr_vecs;
bool copy;

Expand All @@ -273,11 +272,6 @@ int bio_integrity_map_user(struct bio *bio, struct iov_iter *iter)
if (bytes >> SECTOR_SHIFT > queue_max_hw_sectors(q))
return -E2BIG;

if (bio_data_dir(bio) == READ)
direction = ITER_DEST;
else
direction = ITER_SOURCE;

nr_vecs = iov_iter_npages(iter, BIO_MAX_VECS + 1);
if (nr_vecs > BIO_MAX_VECS)
return -E2BIG;
Expand All @@ -300,8 +294,7 @@ int bio_integrity_map_user(struct bio *bio, struct iov_iter *iter)
copy = true;

if (copy)
ret = bio_integrity_copy_user(bio, bvec, nr_bvecs, bytes,
direction);
ret = bio_integrity_copy_user(bio, bvec, nr_bvecs, bytes);
else
ret = bio_integrity_init_user(bio, bvec, nr_bvecs, bytes);
if (ret)
Expand Down
48 changes: 42 additions & 6 deletions block/blk-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/scatterlist.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/t10-pi.h>

#include "blk.h"

Expand Down Expand Up @@ -54,6 +55,46 @@ int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio)
return segments;
}

int blk_get_pi_cap(struct block_device *bdev, struct fs_pi_cap __user *argp)
{
struct blk_integrity *bi = blk_get_integrity(bdev->bd_disk);
struct fs_pi_cap pi_cap = {};

if (!bi)
goto out;

if (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE)
pi_cap.fpc_flags |= FILE_PI_CAP_INTEGRITY;
if (bi->flags & BLK_INTEGRITY_REF_TAG)
pi_cap.fpc_flags |= FILE_PI_CAP_REFTAG;
pi_cap.fpc_csum_type = bi->csum_type;
pi_cap.fpc_metadata_size = bi->tuple_size;
pi_cap.fpc_tag_size = bi->tag_size;
pi_cap.fpc_interval = 1 << bi->interval_exp;
pi_cap.fpc_pi_offset = bi->pi_offset;
pi_cap.fpc_pi_size = bi->pi_size;
if (bi->flags & BLK_INTEGRITY_REF_TAG) {
switch (bi->csum_type) {
case BLK_INTEGRITY_CSUM_CRC64:
pi_cap.fpc_ref_tag_size =
sizeof_field(struct crc64_pi_tuple, ref_tag);
break;
case BLK_INTEGRITY_CSUM_CRC:
case BLK_INTEGRITY_CSUM_IP:
pi_cap.fpc_ref_tag_size =
sizeof_field(struct t10_pi_tuple, ref_tag);
break;
default:
break;
}
}

out:
if (copy_to_user(argp, &pi_cap, sizeof(struct fs_pi_cap)))
return -EFAULT;
return 0;
}

/**
* blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
* @rq: request to map
Expand Down Expand Up @@ -117,13 +158,8 @@ int blk_rq_integrity_map_user(struct request *rq, void __user *ubuf,
{
int ret;
struct iov_iter iter;
unsigned int direction;

if (op_is_write(req_op(rq)))
direction = ITER_DEST;
else
direction = ITER_SOURCE;
iov_iter_ubuf(&iter, direction, ubuf, bytes);
iov_iter_ubuf(&iter, rq_data_dir(rq), ubuf, bytes);
ret = bio_integrity_map_user(rq->bio, &iter);
if (ret)
return ret;
Expand Down
3 changes: 3 additions & 0 deletions block/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/uaccess.h>
#include <linux/pagemap.h>
#include <linux/io_uring/cmd.h>
#include <linux/blk-integrity.h>
#include <uapi/linux/blkdev.h>
#include "blk.h"
#include "blk-crypto-internal.h"
Expand Down Expand Up @@ -643,6 +644,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
return blkdev_pr_preempt(bdev, mode, argp, true);
case IOC_PR_CLEAR:
return blkdev_pr_clear(bdev, mode, argp);
case FS_IOC_GETPICAP:
return blk_get_pi_cap(bdev, argp);
default:
return -ENOIOCTLCMD;
}
Expand Down
8 changes: 6 additions & 2 deletions drivers/block/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,14 @@ static void lo_complete_rq(struct request *rq)
static void lo_rw_aio_do_completion(struct loop_cmd *cmd)
{
struct request *rq = blk_mq_rq_from_pdu(cmd);
struct loop_device *lo = rq->q->queuedata;

if (!atomic_dec_and_test(&cmd->ref))
return;
kfree(cmd->bvec);
cmd->bvec = NULL;
if (req_op(rq) == REQ_OP_WRITE)
file_end_write(lo->lo_backing_file);
if (likely(!blk_should_fake_timeout(rq->q)))
blk_mq_complete_request(rq);
}
Expand Down Expand Up @@ -387,9 +390,10 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
cmd->iocb.ki_flags = 0;
}

if (rw == ITER_SOURCE)
if (rw == ITER_SOURCE) {
file_start_write(lo->lo_backing_file);
ret = file->f_op->write_iter(&cmd->iocb, &iter);
else
} else
ret = file->f_op->read_iter(&cmd->iocb, &iter);

lo_rw_aio_do_completion(cmd);
Expand Down
Loading