Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
lnocturno committed Apr 22, 2024
1 parent 659c7a7 commit a6bb9c3
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 55 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*.orig
*.sdtinfo.c
*.sdtstub.S
*.out
*~
.cache.mk
.cache/
Expand Down
9 changes: 9 additions & 0 deletions scst/include/scst.h
Original file line number Diff line number Diff line change
Expand Up @@ -5675,6 +5675,15 @@ int scst_scsi_exec_async(struct scst_cmd *cmd, void *data,
int scst_get_file_mode(const char *path);
bool scst_parent_dir_exists(const char *path);

struct scst_bdev_descriptor {
struct block_device *bdev;
void *priv;
};

int scst_open_bdev_by_path(struct scst_bdev_descriptor *bdev_descriptor, const char *path,
blk_mode_t mode, void *holder, const struct blk_holder_ops *hops);
void scst_release_bdev(struct scst_bdev_descriptor *bdev_descriptor);

struct scst_data_descriptor {
uint64_t sdd_lba;
uint64_t sdd_blocks;
Expand Down
92 changes: 43 additions & 49 deletions scst/src/dev_handlers/scst_vdisk.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ struct scst_vdisk_dev {

struct file *fd;
struct file *dif_fd;
struct bdev_handle *bdev_handle;
struct scst_bdev_descriptor bdev_descriptor;
struct bio_set *vdisk_bioset;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
struct bio_set vdisk_bioset_struct;
Expand Down Expand Up @@ -494,34 +494,35 @@ static int vdisk_blockio_flush(struct block_device *bdev, gfp_t gfp_mask,

static void vdisk_blockio_check_flush_support(struct scst_vdisk_dev *virt_dev)
{
struct bdev_handle *bdev_handle;
struct scst_bdev_descriptor bdev_descriptor;
int rc;

TRACE_ENTRY();

if (!virt_dev->blockio || virt_dev->rd_only || virt_dev->nv_cache ||
virt_dev->wt_flag || !virt_dev->dev_active)
goto out;

bdev_handle = bdev_open_by_path(virt_dev->filename, BLK_OPEN_READ, NULL, NULL);
if (IS_ERR(bdev_handle)) {
if (PTR_ERR(bdev_handle) == -EMEDIUMTYPE)
rc = scst_open_bdev_by_path(&bdev_descriptor, virt_dev->filename, BLK_OPEN_READ, NULL, NULL);
if (rc) {
if (rc == -EMEDIUMTYPE)
TRACE(TRACE_MINOR,
"Unable to open %s with EMEDIUMTYPE, DRBD passive?",
virt_dev->filename);
else
PRINT_ERROR("bdev_open_by_path(%s) failed: %ld",
virt_dev->filename, PTR_ERR(bdev_handle));
PRINT_ERROR("bdev_open_by_path(%s) failed: %d",
virt_dev->filename, rc);
goto out;
}

if (vdisk_blockio_flush(bdev_handle->bdev, GFP_KERNEL, false, NULL, false) != 0) {
if (vdisk_blockio_flush(bdev_descriptor.bdev, GFP_KERNEL, false, NULL, false) != 0) {
PRINT_WARNING(
"Device %s doesn't support barriers, switching to NV_CACHE mode. Read README for more details.",
virt_dev->filename);
virt_dev->nv_cache = 1;
}

bdev_release(bdev_handle);
scst_release_bdev(&bdev_descriptor);

out:
TRACE_EXIT();
Expand All @@ -536,7 +537,7 @@ static bool vdisk_supports_active(const struct scst_vdisk_dev *virt_dev)

static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev)
{
struct bdev_handle *bdev_handle = NULL;
struct scst_bdev_descriptor bdev_descriptor;
struct file *fd = NULL;
bool fd_open = false;
int res;
Expand All @@ -549,8 +550,7 @@ static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev)
goto check;

if (virt_dev->blockio) {
bdev_handle = bdev_open_by_path(virt_dev->filename, BLK_OPEN_READ, NULL, NULL);
res = PTR_ERR_OR_ZERO(bdev_handle);
res = scst_open_bdev_by_path(&bdev_descriptor, virt_dev->filename, BLK_OPEN_READ, NULL, NULL);
} else {
fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600);
res = PTR_ERR_OR_ZERO(fd);
Expand All @@ -573,10 +573,10 @@ static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev)
(!defined(RHEL_RELEASE_CODE) || \
RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(9, 1))
virt_dev->dev_thin_provisioned =
blk_queue_discard(bdev_get_queue(bdev_handle->bdev));
blk_queue_discard(bdev_get_queue(bdev_descriptor.bdev));
#else
virt_dev->dev_thin_provisioned =
!!bdev_max_discard_sectors(bdev_handle->bdev);
!!bdev_max_discard_sectors(bdev_descriptor.bdev);
#endif
} else {
virt_dev->dev_thin_provisioned = (fd->f_op->fallocate != NULL);
Expand Down Expand Up @@ -613,7 +613,7 @@ static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev)
struct request_queue *q;

sBUG_ON(!fd_open);
q = bdev_get_queue(bdev_handle->bdev);
q = bdev_get_queue(bdev_descriptor.bdev);
virt_dev->unmap_opt_gran = q->limits.discard_granularity >> block_shift;
virt_dev->unmap_align = q->limits.discard_alignment >> block_shift;
if (virt_dev->unmap_opt_gran == virt_dev->unmap_align)
Expand Down Expand Up @@ -645,7 +645,7 @@ static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev)

if (fd_open) {
if (virt_dev->blockio)
bdev_release(bdev_handle);
scst_release_bdev(&bdev_descriptor);
else
filp_close(fd, NULL);
}
Expand Down Expand Up @@ -962,21 +962,19 @@ static int vdev_load_mode_pages(struct scst_vdisk_dev *virt_dev)
#if defined(CONFIG_BLK_DEV_INTEGRITY)
static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev)
{
int res;
struct scst_device *dev = virt_dev->dev;
struct bdev_handle *bdev_handle;
struct scst_bdev_descriptor bdev_descriptor;
struct blk_integrity *bi;
const char *bi_profile_name;
int res;

TRACE_ENTRY();

bdev_handle = bdev_open_by_path(virt_dev->filename, BLK_OPEN_READ, NULL, NULL);
if (IS_ERR(bdev_handle)) {
res = PTR_ERR(bdev_handle);
res = scst_open_bdev_by_path(&bdev_descriptor, virt_dev->filename, BLK_OPEN_READ, NULL, NULL);
if (res)
goto out;
}

bi = bdev_get_integrity(bdev_handle->bdev);
bi = bdev_get_integrity(bdev_descriptor.bdev);
if (bi == NULL) {
TRACE_DBG("Block integrity not supported");
goto out_no_bi;
Expand Down Expand Up @@ -1048,7 +1046,7 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev)
res = 0;

out_close:
bdev_release(bdev_handle);
scst_release_bdev(&bdev_descriptor);

out:
TRACE_EXIT_RES(res);
Expand Down Expand Up @@ -1297,7 +1295,7 @@ static void vdisk_detach(struct scst_device *dev)

static bool vdisk_is_open(const struct scst_vdisk_dev *virt_dev)
{
return virt_dev->fd || virt_dev->bdev_handle;
return virt_dev->fd || virt_dev->bdev_descriptor.bdev;
}

static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only)
Expand All @@ -1317,16 +1315,15 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only)
if (!read_only)
bdev_mode |= BLK_OPEN_WRITE;

virt_dev->bdev_handle = bdev_open_by_path(virt_dev->filename, bdev_mode, virt_dev,
NULL);
res = PTR_ERR_OR_ZERO(virt_dev->bdev_handle);
res = scst_open_bdev_by_path(&virt_dev->bdev_descriptor, virt_dev->filename,
bdev_mode, virt_dev, NULL);
} else {
virt_dev->fd = vdev_open_fd(virt_dev, virt_dev->filename,
read_only);
res = PTR_ERR_OR_ZERO(virt_dev->fd);
}
if (res) {
virt_dev->bdev_handle = NULL;
scst_release_bdev(&virt_dev->bdev_descriptor);
virt_dev->fd = NULL;
goto out;
}
Expand All @@ -1336,7 +1333,7 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only)
* characteristics.
*/
if (virt_dev->blockio && !virt_dev->opt_trans_len_set)
virt_dev->opt_trans_len = bdev_io_opt(virt_dev->bdev_handle->bdev) ? :
virt_dev->opt_trans_len = bdev_io_opt(virt_dev->bdev_descriptor.bdev) ? :
virt_dev->opt_trans_len;

if (virt_dev->dif_filename != NULL) {
Expand All @@ -1350,15 +1347,14 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only)
}

TRACE_DBG("virt_dev %s: fd %p %p open (dif_fd %p)", virt_dev->name,
virt_dev->fd, virt_dev->bdev_handle, virt_dev->dif_fd);
virt_dev->fd, virt_dev->bdev_descriptor.bdev, virt_dev->dif_fd);

out:
return res;

out_close_fd:
if (virt_dev->blockio) {
bdev_release(virt_dev->bdev_handle);
virt_dev->bdev_handle = NULL;
scst_release_bdev(&virt_dev->bdev_descriptor);
} else {
filp_close(virt_dev->fd, NULL);
virt_dev->fd = NULL;
Expand All @@ -1369,11 +1365,10 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only)
static void vdisk_close_fd(struct scst_vdisk_dev *virt_dev)
{
TRACE_DBG("virt_dev %s: closing fd %p %p (dif_fd %p)", virt_dev->name,
virt_dev->fd, virt_dev->bdev_handle, virt_dev->dif_fd);
virt_dev->fd, virt_dev->bdev_descriptor.bdev, virt_dev->dif_fd);

if (virt_dev->bdev_handle) {
bdev_release(virt_dev->bdev_handle);
virt_dev->bdev_handle = NULL;
if (virt_dev->bdev_descriptor.bdev) {
scst_release_bdev(&virt_dev->bdev_descriptor);
} else if (virt_dev->fd) {
filp_close(virt_dev->fd, NULL);
virt_dev->fd = NULL;
Expand Down Expand Up @@ -1459,7 +1454,7 @@ static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev)
}
} else {
virt_dev->fd = NULL;
virt_dev->bdev_handle = NULL;
scst_release_bdev(&virt_dev->bdev_descriptor); /* TODO: GLEB ??? */
virt_dev->dif_fd = NULL;
}

Expand Down Expand Up @@ -1545,8 +1540,7 @@ static int vdisk_fsync_blockio(loff_t loff,
goto out;
}

res = vdisk_blockio_flush(virt_dev->bdev_handle->bdev, gfp_flags, true,
cmd, async);
res = vdisk_blockio_flush(virt_dev->bdev_descriptor.bdev, gfp_flags, true, cmd, async);

out:
TRACE_EXIT_RES(res);
Expand Down Expand Up @@ -1857,7 +1851,7 @@ static int vdisk_unmap_range(struct scst_cmd *cmd,
(unsigned long long)start_lba, blocks);

if (virt_dev->blockio) {
struct block_device *bdev = virt_dev->bdev_handle->bdev;
struct block_device *bdev = virt_dev->bdev_descriptor.bdev;
sector_t start_sector = start_lba << (cmd->dev->block_shift - 9);
sector_t nr_sects = blocks << (cmd->dev->block_shift - 9);
gfp_t gfp = cmd->cmd_gfp_mask;
Expand Down Expand Up @@ -2871,7 +2865,7 @@ static ssize_t blockio_read_sync(struct scst_vdisk_dev *virt_dev, void *buf,
struct bio_priv_sync s = {
COMPLETION_INITIALIZER_ONSTACK(s.c), 0,
};
struct block_device *bdev = virt_dev->bdev_handle->bdev;
struct block_device *bdev = virt_dev->bdev_descriptor.bdev;
const bool is_vmalloc = is_vmalloc_addr(buf);
struct bio *bio;
void *p;
Expand Down Expand Up @@ -3407,7 +3401,7 @@ static enum scst_exec_res blockio_exec(struct scst_cmd *cmd)
if (unlikely(!vdisk_parse_offset(&p, cmd)))
goto err;

if (unlikely(virt_dev->bdev_handle == NULL)) {
if (unlikely(virt_dev->bdev_descriptor.bdev == NULL)) {
if (!vdisk_no_fd_allowed_commands(cmd)) {
/*
* We should not get here, unless the user space
Expand Down Expand Up @@ -4996,8 +4990,8 @@ static enum compl_status_e vdisk_exec_read_capacity16(struct vdisk_cmd_params *p

/* LOGICAL BLOCKS PER PHYSICAL BLOCK EXPONENT */
if (virt_dev->lb_per_pb_exp) {
struct request_queue *q = virt_dev->bdev_handle ?
bdev_get_queue(virt_dev->bdev_handle->bdev) : NULL;
struct request_queue *q = virt_dev->bdev_descriptor.bdev ?
bdev_get_queue(virt_dev->bdev_descriptor.bdev) : NULL;
uint32_t physical_blocksize = q ? queue_physical_block_size(q) : 4096;
buffer[13] = max(ilog2(physical_blocksize) - ilog2(blocksize), 0);
}
Expand Down Expand Up @@ -5926,7 +5920,7 @@ static void blockio_exec_rw(struct vdisk_cmd_params *p, bool write, bool fua)
struct scst_device *dev = cmd->dev;
struct scst_vdisk_dev *virt_dev = dev->dh_priv;
int block_shift = dev->block_shift;
struct block_device *bdev = virt_dev->bdev_handle->bdev;
struct block_device *bdev = virt_dev->bdev_descriptor.bdev;
struct bio_set *bs = virt_dev->vdisk_bioset;
struct request_queue *q = bdev_get_queue(bdev);
int length, max_nr_vecs = 0, offset;
Expand Down Expand Up @@ -6597,7 +6591,7 @@ static int vdisk_resync_size(struct scst_vdisk_dev *virt_dev)
sBUG_ON(virt_dev->nullio);
sBUG_ON(!virt_dev->filename);

if ((!virt_dev->fd && !virt_dev->bdev_handle) || !virt_dev->dev_active) {
if ((!virt_dev->fd && !virt_dev->bdev_descriptor.bdev) || !virt_dev->dev_active) {
res = -EMEDIUMTYPE;
goto out;
}
Expand Down Expand Up @@ -7645,7 +7639,7 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev, char *buffer)
err = 0;
virt_dev->filename = NULL;
virt_dev->fd = NULL;
virt_dev->bdev_handle = NULL;
scst_release_bdev(&virt_dev->bdev_descriptor); /* TODO: GLEB ??? */
}

virt_dev->file_size = err;
Expand Down Expand Up @@ -7705,7 +7699,7 @@ static ssize_t vdisk_sysfs_sync_store(struct kobject *kobj,
if (virt_dev->nullio)
res = 0;
else if (virt_dev->blockio)
res = vdisk_blockio_flush(virt_dev->bdev_handle->bdev, GFP_KERNEL, false,
res = vdisk_blockio_flush(virt_dev->bdev_descriptor.bdev, GFP_KERNEL, false,
NULL, false);
else
res = __vdisk_fsync_fileio(0, i_size_read(file_inode(virt_dev->fd)),
Expand Down
Loading

0 comments on commit a6bb9c3

Please sign in to comment.