mirror of
https://github.com/SCST-project/scst.git
synced 2026-06-09 23:22:33 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+2
-2
@@ -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);
|
||||
/**
|
||||
|
||||
+140
-141
@@ -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:
|
||||
|
||||
+28
-18
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user