scst, iscsi-scst: Use struct kvec instead of struct iovec for kernel data

This patch does not change any functionality but removes multiple __force
__user casts.


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@9197 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2020-11-27 03:45:16 +00:00
parent 02f350c8a7
commit a673470ce3
6 changed files with 177 additions and 168 deletions

View File

@@ -2912,7 +2912,7 @@ void cmnd_tx_start(struct iscsi_cmnd *cmnd)
set_cork(conn->sock, 1);
conn->write_iop = conn->write_iov;
conn->write_iop->iov_base = (void __force __user *)(&cmnd->pdu.bhs);
conn->write_iop->iov_base = &cmnd->pdu.bhs;
conn->write_iop->iov_len = sizeof(cmnd->pdu.bhs);
conn->write_iop_used = 1;
conn->write_size = sizeof(cmnd->pdu.bhs) + cmnd->pdu.datasize;

View File

@@ -184,7 +184,7 @@ struct iscsi_session {
u64 sid;
};
#define ISCSI_CONN_IOV_MAX (PAGE_SIZE/sizeof(struct iovec))
#define ISCSI_CONN_IOV_MAX (PAGE_SIZE/sizeof(struct kvec))
#define ISCSI_CONN_RD_STATE_IDLE 0
#define ISCSI_CONN_RD_STATE_IN_LIST 1
@@ -243,9 +243,9 @@ struct iscsi_conn {
* thread.
*/
struct iscsi_cmnd *write_cmnd;
struct iovec *write_iop;
struct kvec *write_iop;
int write_iop_used;
struct iovec write_iov[2];
struct kvec write_iov[2];
u32 write_size;
u32 write_offset;
int write_state;

View File

@@ -1097,7 +1097,7 @@ out:
static int write_data(struct iscsi_conn *conn)
{
struct file *file;
struct iovec *iop;
struct kvec *iop;
struct socket *sock;
ssize_t (*sock_sendpage)(struct socket *, struct page *, int, size_t,
int);
@@ -1381,7 +1381,7 @@ static int tx_ddigest(struct iscsi_cmnd *cmnd, int state)
static void init_tx_hdigest(struct iscsi_cmnd *cmnd)
{
struct iscsi_conn *conn = cmnd->conn;
struct iovec *iop;
struct kvec *iop;
iscsi_extracheck_is_wr_thread(conn);
@@ -1391,7 +1391,7 @@ static void init_tx_hdigest(struct iscsi_cmnd *cmnd)
iop = &conn->write_iop[conn->write_iop_used];
conn->write_iop_used++;
iop->iov_base = (void __force __user *)&(cmnd->hdigest);
iop->iov_base = &cmnd->hdigest;
iop->iov_len = sizeof(u32);
conn->write_size += sizeof(u32);

View File

@@ -5543,9 +5543,9 @@ struct scst_data_descriptor {
uint64_t sdd_blocks;
};
ssize_t scst_readv(struct file *file, const struct iovec *vec,
ssize_t scst_readv(struct file *file, const struct kvec *vec,
unsigned long vlen, loff_t *pos);
ssize_t scst_writev(struct file *file, const struct iovec *vec,
ssize_t scst_writev(struct file *file, const struct kvec *vec,
unsigned long vlen, loff_t *pos);
void scst_write_same(struct scst_cmd *cmd, struct scst_data_descriptor *where);
/**

View File

@@ -257,9 +257,9 @@ struct scst_vdisk_dev {
struct vdisk_cmd_params {
union {
struct {
struct iovec *iv;
int iv_count;
struct iovec small_iv[4];
struct kvec *kvec;
int kvec_segs;
struct kvec small_kvec[4];
} sync;
struct {
struct kiocb iocb;
@@ -1689,9 +1689,9 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba,
loff_t err = 0;
ssize_t full_len;
struct file *fd = virt_dev->dif_fd;
struct iovec *iv;
int max_iv_count, iv_count, i;
struct page *iv_page, *data_page;
struct kvec *kvec;
int max_kvec_segs, kvec_segs, i;
struct page *kvec_page, *data_page;
uint8_t *data_buf;
int64_t left, done;
@@ -1702,9 +1702,9 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba,
EXTRACHECKS_BUG_ON(!(dev->dev_dif_mode & SCST_DIF_MODE_DEV_STORE));
iv_page = alloc_page(GFP_KERNEL);
if (iv_page == NULL) {
PRINT_ERROR("Unable to allocate iv page");
kvec_page = alloc_page(GFP_KERNEL);
if (kvec_page == NULL) {
PRINT_ERROR("Unable to allocate kvec page");
scst_set_busy(cmd);
res = -ENOMEM;
goto out;
@@ -1715,23 +1715,23 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba,
PRINT_ERROR("Unable to allocate tags data page");
scst_set_busy(cmd);
res = -ENOMEM;
goto out_free_iv;
goto out_free_kvec;
}
data_buf = page_address(data_page);
memset(data_buf, 0xFF, PAGE_SIZE);
iv = page_address(iv_page);
max_iv_count = min_t(int, UIO_MAXIOV, (int)PAGE_SIZE/sizeof(*iv));
kvec = page_address(kvec_page);
max_kvec_segs = min_t(int, UIO_MAXIOV, (int)PAGE_SIZE/sizeof(*kvec));
for (i = 0; i < max_iv_count; i++)
iv[i].iov_base = (uint8_t __force __user *)data_buf;
for (i = 0; i < max_kvec_segs; i++)
kvec[i].iov_base = data_buf;
loff = start_lba << SCST_DIF_TAG_SHIFT;
left = blocks << SCST_DIF_TAG_SHIFT;
done = 0;
while (left > 0) {
iv_count = 0;
kvec_segs = 0;
full_len = 0;
i = -1;
while (1) {
@@ -1739,12 +1739,12 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba,
full_len += len;
i++;
iv_count++;
iv[i].iov_len = len;
kvec_segs++;
kvec[i].iov_len = len;
left -= len;
done += len;
EXTRACHECKS_BUG_ON(left < 0);
if ((iv_count == max_iv_count) || (left == 0))
if (kvec_segs == max_kvec_segs || left == 0)
break;
}
@@ -1752,7 +1752,7 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba,
full_len, (long long)loff);
/* WRITE */
err = scst_writev(fd, iv, iv_count, &loff);
err = scst_writev(fd, kvec, kvec_segs, &loff);
if (err < 0) {
PRINT_ERROR("Formatting DIF write() returned %lld from "
"%zd", err, full_len);
@@ -1781,8 +1781,8 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba,
out_free_data_page:
__free_page(data_page);
out_free_iv:
__free_page(iv_page);
out_free_kvec:
__free_page(kvec_page);
out:
TRACE_EXIT_RES(res);
@@ -3162,7 +3162,8 @@ static bool do_fileio_async(const struct vdisk_cmd_params *p)
}
}
static bool vdisk_alloc_async_kvec(struct scst_cmd *cmd, struct vdisk_cmd_params *p)
static bool vdisk_alloc_async_kvec(struct scst_cmd *cmd,
struct vdisk_cmd_params *p)
{
int n;
@@ -3175,7 +3176,7 @@ static bool vdisk_alloc_async_kvec(struct scst_cmd *cmd, struct vdisk_cmd_params
p->async.kvec = kmalloc_array(n, sizeof(*p->async.kvec),
cmd->cmd_gfp_mask);
if (p->async.kvec == NULL) {
PRINT_ERROR("Unable to allocate kvecv (%d)", n);
PRINT_ERROR("Unable to allocate kvec (%d)", n);
return false;
}
@@ -3308,8 +3309,8 @@ static enum compl_status_e fileio_exec_async(struct vdisk_cmd_params *p)
static void vdisk_on_free_cmd_params(const struct vdisk_cmd_params *p)
{
if (!p->execute_async) {
if (p->sync.iv != p->sync.small_iv)
kfree(p->sync.iv);
if (p->sync.kvec != p->sync.small_kvec)
kfree(p->sync.kvec);
}
}
@@ -5195,30 +5196,30 @@ static enum compl_status_e vdisk_exec_prevent_allow_medium_removal(struct vdisk_
return CMD_SUCCEEDED;
}
static struct iovec *vdisk_alloc_sync_kvec(struct scst_cmd *cmd,
struct vdisk_cmd_params *p)
static struct kvec *vdisk_alloc_sync_kvec(struct scst_cmd *cmd,
struct vdisk_cmd_params *p)
{
int iv_count;
int kvec_segs;
iv_count = min_t(int, scst_get_buf_count(cmd), UIO_MAXIOV);
if (iv_count > p->sync.iv_count) {
if (p->sync.iv != p->sync.small_iv)
kfree(p->sync.iv);
p->sync.iv_count = 0;
kvec_segs = min_t(int, scst_get_buf_count(cmd), UIO_MAXIOV);
if (kvec_segs > p->sync.kvec_segs) {
if (p->sync.kvec != p->sync.small_kvec)
kfree(p->sync.kvec);
p->sync.kvec_segs = 0;
/* It can't be called in atomic context */
p->sync.iv = iv_count <= ARRAY_SIZE(p->sync.small_iv) ?
p->sync.small_iv :
kmalloc_array(iv_count, sizeof(*p->sync.iv),
p->sync.kvec = kvec_segs <= ARRAY_SIZE(p->sync.small_kvec) ?
p->sync.small_kvec :
kmalloc_array(kvec_segs, sizeof(*p->sync.kvec),
cmd->cmd_gfp_mask);
if (p->sync.iv == NULL) {
PRINT_ERROR("Unable to allocate iv (%d)", iv_count);
if (p->sync.kvec == NULL) {
PRINT_ERROR("Unable to allocate kvec (%d)", kvec_segs);
goto out;
}
p->sync.iv_count = iv_count;
p->sync.kvec_segs = kvec_segs;
}
out:
return p->sync.iv;
return p->sync.kvec;
}
static enum compl_status_e nullio_exec_read(struct vdisk_cmd_params *p)
@@ -5262,8 +5263,8 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p)
uint8_t *address;
struct scst_vdisk_dev *virt_dev = cmd->dev->dh_priv;
struct file *fd = virt_dev->dif_fd;
struct iovec *iv;
int iv_count, max_iv_count, i;
struct kvec *kvec;
int kvec_segs, max_kvec_segs, i;
bool finished = false;
int tags_num, l;
struct scatterlist *tags_sg;
@@ -5283,10 +5284,10 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p)
if (unlikely(tags_num == 0))
goto out;
iv = p->sync.iv;
if (iv == NULL) {
iv = vdisk_alloc_sync_kvec(cmd, p);
if (iv == NULL) {
kvec = p->sync.kvec;
if (kvec == NULL) {
kvec = vdisk_alloc_sync_kvec(cmd, p);
if (kvec == NULL) {
unsigned long flags;
/* To protect sense setting against blockio data reads */
@@ -5297,12 +5298,12 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p)
goto out;
}
}
max_iv_count = p->sync.iv_count;
max_kvec_segs = p->sync.kvec_segs;
tags_sg = NULL;
loff = (p->loff >> cmd->dev->block_shift) << SCST_DIF_TAG_SHIFT;
while (1) {
iv_count = 0;
kvec_segs = 0;
full_len = 0;
i = -1;
address = scst_get_dif_buf(cmd, &tags_sg, &l);
@@ -5311,12 +5312,12 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p)
while (1) {
full_len += length;
i++;
iv_count++;
iv[i].iov_base = (uint8_t __force __user *)address;
iv[i].iov_len = length;
kvec_segs++;
kvec[i].iov_base = address;
kvec[i].iov_len = length;
tags_num -= length >> SCST_DIF_TAG_SHIFT;
EXTRACHECKS_BUG_ON(tags_num < 0);
if ((iv_count == max_iv_count) || (tags_num == 0))
if (kvec_segs == max_kvec_segs || tags_num == 0)
break;
address = scst_get_dif_buf(cmd, &tags_sg, &l);
length = l;
@@ -5325,11 +5326,11 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p)
if (tags_num == 0)
finished = true;
TRACE_DBG("Reading DIF iv_count %d, full_len %zd, loff %lld",
iv_count, full_len, (long long)loff);
TRACE_DBG("Reading DIF kvec_segs %d, full_len %zd, loff %lld",
kvec_segs, full_len, (long long)loff);
/* READ */
err = scst_readv(fd, iv, iv_count, &loff);
err = scst_readv(fd, kvec, kvec_segs, &loff);
if ((err < 0) || (err < full_len)) {
unsigned long flags;
@@ -5349,8 +5350,8 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p)
goto out_put_dif_buf;
}
for (i = 0; i < iv_count; i++)
scst_put_dif_buf(cmd, (void __force *)(iv[i].iov_base));
for (i = 0; i < kvec_segs; i++)
scst_put_dif_buf(cmd, kvec[i].iov_base);
if (finished)
break;
@@ -5361,8 +5362,8 @@ out:
return res;
out_put_dif_buf:
for (i = 0; i < iv_count; i++)
scst_put_dif_buf(cmd, (void __force *)(iv[i].iov_base));
for (i = 0; i < kvec_segs; i++)
scst_put_dif_buf(cmd, kvec[i].iov_base);
goto out;
}
@@ -5376,8 +5377,8 @@ static int vdev_write_dif_tags(struct vdisk_cmd_params *p)
uint8_t *address;
struct scst_vdisk_dev *virt_dev = cmd->dev->dh_priv;
struct file *fd = virt_dev->dif_fd;
struct iovec *iv, *eiv;
int iv_count, eiv_count, max_iv_count, i;
struct kvec *kvec, *ekvec;
int kvec_segs, ekvec_segs, max_kvec_segs, i;
bool finished = false;
int tags_num, l;
struct scatterlist *tags_sg;
@@ -5397,10 +5398,10 @@ static int vdev_write_dif_tags(struct vdisk_cmd_params *p)
if (unlikely(tags_num == 0))
goto out;
iv = p->sync.iv;
if (iv == NULL) {
iv = vdisk_alloc_sync_kvec(cmd, p);
if (iv == NULL) {
kvec = p->sync.kvec;
if (kvec == NULL) {
kvec = vdisk_alloc_sync_kvec(cmd, p);
if (kvec == NULL) {
unsigned long flags;
/* To protect sense setting against blockio data writes */
@@ -5411,12 +5412,12 @@ static int vdev_write_dif_tags(struct vdisk_cmd_params *p)
goto out;
}
}
max_iv_count = p->sync.iv_count;
max_kvec_segs = p->sync.kvec_segs;
tags_sg = NULL;
loff = (p->loff >> cmd->dev->block_shift) << SCST_DIF_TAG_SHIFT;
while (1) {
iv_count = 0;
kvec_segs = 0;
full_len = 0;
i = -1;
address = scst_get_dif_buf(cmd, &tags_sg, &l);
@@ -5425,12 +5426,12 @@ static int vdev_write_dif_tags(struct vdisk_cmd_params *p)
while (1) {
full_len += length;
i++;
iv_count++;
iv[i].iov_base = (uint8_t __force __user *)address;
iv[i].iov_len = length;
kvec_segs++;
kvec[i].iov_base = address;
kvec[i].iov_len = length;
tags_num -= length >> SCST_DIF_TAG_SHIFT;
EXTRACHECKS_BUG_ON(tags_num < 0);
if ((iv_count == max_iv_count) || (tags_num == 0))
if (kvec_segs == max_kvec_segs || tags_num == 0)
break;
address = scst_get_dif_buf(cmd, &tags_sg, &l);
length = l;
@@ -5439,13 +5440,13 @@ static int vdev_write_dif_tags(struct vdisk_cmd_params *p)
if (tags_num == 0)
finished = true;
eiv = iv;
eiv_count = iv_count;
ekvec = kvec;
ekvec_segs = kvec_segs;
restart:
TRACE_DBG("Writing DIF: eiv_count %d, full_len %zd", eiv_count, full_len);
TRACE_DBG("Writing DIF: ekvec_segs %d, full_len %zd", ekvec_segs, full_len);
/* WRITE */
err = scst_writev(fd, eiv, eiv_count, &loff);
err = scst_writev(fd, ekvec, ekvec_segs, &loff);
if (err < 0) {
unsigned long flags;
@@ -5467,33 +5468,32 @@ restart:
* Probably that's wrong, but sometimes write() returns
* value less, than requested. Let's restart.
*/
int e = eiv_count;
int e = ekvec_segs;
TRACE_MGMT_DBG("DIF write() returned %d from %zd "
"(iv_count=%d)", (int)err, full_len,
eiv_count);
"(kvec_segs=%d)", (int)err, full_len,
ekvec_segs);
if (err == 0) {
PRINT_INFO("Suspicious: DIF write() returned 0 from "
"%zd (iv_count=%d)", full_len, eiv_count);
"%zd (kvec_segs=%d)", full_len, ekvec_segs);
}
full_len -= err;
for (i = 0; i < e; i++) {
if ((long long)eiv->iov_len < err) {
err -= eiv->iov_len;
eiv++;
eiv_count--;
if ((long long)ekvec->iov_len < err) {
err -= ekvec->iov_len;
ekvec++;
ekvec_segs--;
} else {
eiv->iov_base =
(uint8_t __force __user *)eiv->iov_base + err;
eiv->iov_len -= err;
ekvec->iov_base = ekvec->iov_base + err;
ekvec->iov_len -= err;
break;
}
}
goto restart;
}
for (i = 0; i < iv_count; i++)
scst_put_dif_buf(cmd, (void __force *)(iv[i].iov_base));
for (i = 0; i < kvec_segs; i++)
scst_put_dif_buf(cmd, kvec[i].iov_base);
if (finished)
break;
@@ -5504,8 +5504,8 @@ out:
return res;
out_put_dif_buf:
for (i = 0; i < iv_count; i++)
scst_put_dif_buf(cmd, (void __force *)(iv[i].iov_base));
for (i = 0; i < kvec_segs; i++)
scst_put_dif_buf(cmd, kvec[i].iov_base);
goto out;
}
@@ -5563,8 +5563,8 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p)
uint8_t *address;
struct scst_vdisk_dev *virt_dev = cmd->dev->dh_priv;
struct file *fd = virt_dev->fd;
struct iovec *iv, *eiv;
int rc, i, iv_count, eiv_count, max_iv_count;
struct kvec *kvec, *ekvec;
int rc, i, kvec_segs, ekvec_segs, max_kvec_segs;
bool finished = false;
TRACE_ENTRY();
@@ -5578,11 +5578,11 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p)
if (unlikely(rc != 0))
goto out;
iv = vdisk_alloc_sync_kvec(cmd, p);
if (iv == NULL)
kvec = vdisk_alloc_sync_kvec(cmd, p);
if (kvec == NULL)
goto out_nomem;
max_iv_count = p->sync.iv_count;
max_kvec_segs = p->sync.kvec_segs;
length = scst_get_buf_first(cmd, &address);
if (unlikely(length < 0)) {
@@ -5593,22 +5593,22 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p)
}
while (1) {
iv_count = 0;
kvec_segs = 0;
full_len = 0;
i = -1;
while (length > 0) {
full_len += length;
i++;
iv_count++;
iv[i].iov_base = (uint8_t __force __user *)address;
iv[i].iov_len = length;
if (iv_count == max_iv_count)
kvec_segs++;
kvec[i].iov_base = address;
kvec[i].iov_len = length;
if (kvec_segs == max_kvec_segs)
break;
length = scst_get_buf_next(cmd, &address);
}
if (length == 0) {
finished = true;
if (unlikely(iv_count == 0))
if (unlikely(kvec_segs == 0))
break;
} else if (unlikely(length < 0)) {
PRINT_ERROR("scst_get_buf_next() failed: %zd", length);
@@ -5617,13 +5617,13 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p)
goto out_put_buf;
}
eiv = iv;
eiv_count = iv_count;
ekvec = kvec;
ekvec_segs = kvec_segs;
restart:
TRACE_DBG("Writing: eiv_count %d, full_len %zd", eiv_count, full_len);
TRACE_DBG("Writing: ekvec_segs %d, full_len %zd", ekvec_segs, full_len);
/* WRITE */
err = scst_writev(fd, eiv, eiv_count, &loff);
err = scst_writev(fd, ekvec, ekvec_segs, &loff);
if (err < 0) {
PRINT_ERROR("write() returned %lld from %zd",
(unsigned long long)err,
@@ -5643,32 +5643,32 @@ restart:
* Probably that's wrong, but sometimes write() returns
* value less, than requested. Let's restart.
*/
int e = eiv_count;
int e = ekvec_segs;
TRACE_MGMT_DBG("write() returned %d from %zd "
"(iv_count=%d)", (int)err, full_len,
eiv_count);
"(kvec_segs=%d)", (int)err, full_len,
ekvec_segs);
if (err == 0) {
PRINT_INFO("Suspicious: write() returned 0 from "
"%zd (iv_count=%d)", full_len, eiv_count);
"%zd (kvec_segs=%d)", full_len, ekvec_segs);
}
full_len -= err;
for (i = 0; i < e; i++) {
if ((long long)eiv->iov_len < err) {
err -= eiv->iov_len;
eiv++;
eiv_count--;
if ((long long)ekvec->iov_len < err) {
err -= ekvec->iov_len;
ekvec++;
ekvec_segs--;
} else {
eiv->iov_base += err;
eiv->iov_len -= err;
ekvec->iov_base += err;
ekvec->iov_len -= err;
break;
}
}
goto restart;
}
for (i = 0; i < iv_count; i++)
scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
for (i = 0; i < kvec_segs; i++)
scst_put_buf(cmd, kvec[i].iov_base);
if (finished)
break;
@@ -5693,8 +5693,8 @@ out:
return CMD_SUCCEEDED;
out_put_buf:
for (i = 0; i < iv_count; i++)
scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
for (i = 0; i < kvec_segs; i++)
scst_put_buf(cmd, kvec[i].iov_base);
goto out_sync;
out_nomem:
@@ -6270,12 +6270,12 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p)
loff_t loff = p->loff;
loff_t err = 0;
ssize_t length, full_len;
uint8_t __user *address;
uint8_t *address;
struct scst_device *dev = cmd->dev;
struct scst_vdisk_dev *virt_dev = dev->dh_priv;
struct file *fd = virt_dev->fd;
struct iovec *iv;
int iv_count, i, max_iv_count;
struct kvec *kvec;
int kvec_segs, i, max_kvec_segs;
bool finished = false;
TRACE_ENTRY();
@@ -6285,13 +6285,13 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p)
if (do_fileio_async(p))
return fileio_exec_async(p);
iv = vdisk_alloc_sync_kvec(cmd, p);
if (iv == NULL)
kvec = vdisk_alloc_sync_kvec(cmd, p);
if (kvec == NULL)
goto out_nomem;
max_iv_count = p->sync.iv_count;
max_kvec_segs = p->sync.kvec_segs;
length = scst_get_buf_first(cmd, (uint8_t __force **)&address);
length = scst_get_buf_first(cmd, &address);
if (unlikely(length < 0)) {
PRINT_ERROR("scst_get_buf_first() failed: %zd", length);
scst_set_cmd_error(cmd,
@@ -6300,23 +6300,22 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p)
}
while (1) {
iv_count = 0;
kvec_segs = 0;
full_len = 0;
i = -1;
while (length > 0) {
full_len += length;
i++;
iv_count++;
iv[i].iov_base = address;
iv[i].iov_len = length;
if (iv_count == max_iv_count)
kvec_segs++;
kvec[i].iov_base = address;
kvec[i].iov_len = length;
if (kvec_segs == max_kvec_segs)
break;
length = scst_get_buf_next(cmd,
(uint8_t __force **)&address);
length = scst_get_buf_next(cmd, &address);
}
if (length == 0) {
finished = true;
if (unlikely(iv_count == 0))
if (unlikely(kvec_segs == 0))
break;
} else if (unlikely(length < 0)) {
PRINT_ERROR("scst_get_buf_next() failed: %zd", length);
@@ -6325,10 +6324,10 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p)
goto out_put_buf;
}
TRACE_DBG("Reading iv_count %d, full_len %zd", iv_count, full_len);
TRACE_DBG("Reading kvec_segs %d, full_len %zd", kvec_segs, full_len);
/* READ */
err = scst_readv(fd, iv, iv_count, &loff);
err = scst_readv(fd, kvec, kvec_segs, &loff);
if ((err < 0) || (err < full_len)) {
PRINT_ERROR("readv() returned %lld from %zd",
(unsigned long long)err,
@@ -6342,13 +6341,13 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p)
goto out_put_buf;
}
for (i = 0; i < iv_count; i++)
scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
for (i = 0; i < kvec_segs; i++)
scst_put_buf(cmd, kvec[i].iov_base);
if (finished)
break;
length = scst_get_buf_next(cmd, (uint8_t __force **)&address);
length = scst_get_buf_next(cmd, &address);
}
if ((dev->dev_dif_mode & SCST_DIF_MODE_DEV_STORE) &&
@@ -6365,8 +6364,8 @@ out:
return CMD_SUCCEEDED;
out_put_buf:
for (i = 0; i < iv_count; i++)
scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
for (i = 0; i < kvec_segs; i++)
scst_put_buf(cmd, kvec[i].iov_base);
goto out;
out_nomem:

View File

@@ -6002,8 +6002,8 @@ static int scst_cmp_fs_ds(void)
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
loff_t *pos)
{
struct iovec iov = {
.iov_base = (void __force __user *)buf,
struct kvec iov = {
.iov_base = buf,
.iov_len = count
};
@@ -6012,7 +6012,14 @@ ssize_t kernel_write(struct file *file, const void *buf, size_t count,
EXPORT_SYMBOL(kernel_write);
#endif
ssize_t scst_readv(struct file *file, const struct iovec *vec,
/**
* scst_writev - read data from a file into a kernel buffer
* @file: File to read from.
* @vec: Pointer to first element of struct kvec array.
* @vlen: Number of elements of the kvec array.
* @pos: Position in @file where to start reading.
*/
ssize_t scst_readv(struct file *file, const struct kvec *vec,
unsigned long vlen, loff_t *pos)
{
ssize_t result;
@@ -6022,25 +6029,25 @@ ssize_t scst_readv(struct file *file, const struct iovec *vec,
size_t count = 0;
int i;
BUILD_BUG_ON(sizeof(struct kvec) != sizeof(struct iovec));
BUILD_BUG_ON(offsetof(struct kvec, iov_base) !=
offsetof(struct iovec, iov_base));
BUILD_BUG_ON(offsetof(struct kvec, iov_len) !=
offsetof(struct iovec, iov_len));
init_sync_kiocb(&kiocb, file);
kiocb.ki_pos = *pos;
for (i = 0; i < vlen; i++)
count += vec[i].iov_len;
iov_iter_kvec(&iter, READ, (struct kvec *)vec, vlen, count);
iov_iter_kvec(&iter, READ, vec, vlen, count);
result = call_read_iter(file, &kiocb, &iter);
sBUG_ON(result == -EIOCBQUEUED);
if (result > 0)
*pos += result;
#else
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
WARN_ON_ONCE(scst_cmp_fs_ds() != 0);
BUILD_BUG_ON(sizeof(struct kvec) != sizeof(struct iovec));
BUILD_BUG_ON(offsetof(struct kvec, iov_base) !=
offsetof(struct iovec, iov_base));
BUILD_BUG_ON(offsetof(struct kvec, iov_len) !=
offsetof(struct iovec, iov_len));
result = vfs_readv(file, (const struct iovec __user *)vec, vlen, pos);
set_fs(old_fs);
#endif
@@ -6050,16 +6057,13 @@ ssize_t scst_readv(struct file *file, const struct iovec *vec,
EXPORT_SYMBOL(scst_readv);
/**
* scst_writev - write a buffer to a file
* scst_writev - write kernel data to a file
* @file: File to write to.
* @vec: Pointer to first element of struct iovec array.
* @vlen: Number of elements of the iovec array.
* @vec: Pointer to first element of struct kvec array.
* @vlen: Number of elements of the kvec array.
* @pos: Position in @file where to start writing.
*
* Note: although @vec->iov_base has type void __user*, it points at kernel
* data and not at data in user space.
*/
ssize_t scst_writev(struct file *file, const struct iovec *vec,
ssize_t scst_writev(struct file *file, const struct kvec *vec,
unsigned long vlen, loff_t *pos)
{
ssize_t result;
@@ -6073,7 +6077,7 @@ ssize_t scst_writev(struct file *file, const struct iovec *vec,
kiocb.ki_pos = *pos;
for (i = 0; i < vlen; i++)
count += vec[i].iov_len;
iov_iter_kvec(&iter, WRITE, (struct kvec *)vec, vlen, count);
iov_iter_kvec(&iter, WRITE, vec, vlen, count);
file_start_write(file);
result = call_write_iter(file, &kiocb, &iter);
file_end_write(file);
@@ -6082,8 +6086,14 @@ ssize_t scst_writev(struct file *file, const struct iovec *vec,
*pos += result;
#else
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
WARN_ON_ONCE(scst_cmp_fs_ds() != 0);
BUILD_BUG_ON(sizeof(struct kvec) != sizeof(struct iovec));
BUILD_BUG_ON(offsetof(struct kvec, iov_base) !=
offsetof(struct iovec, iov_base));
BUILD_BUG_ON(offsetof(struct kvec, iov_len) !=
offsetof(struct iovec, iov_len));
result = vfs_writev(file, (const struct iovec __user *)vec, vlen, pos);
set_fs(old_fs);
#endif