mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-17 18:51:27 +00:00
Small improvement: scst_get_sg_page_first()/scst_get_sg_page_next() added to avoid page_address()/virt_to_page() pair for cases, where only pages are needed.
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2131 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -3401,10 +3401,10 @@ static inline int __scst_get_buf(struct scst_cmd *cmd, int sg_cnt,
|
||||
int res = 0;
|
||||
struct scatterlist *sg = cmd->get_sg_buf_cur_sg_entry;
|
||||
|
||||
*buf = NULL;
|
||||
|
||||
if (cmd->get_sg_buf_entry_num >= sg_cnt)
|
||||
if (cmd->get_sg_buf_entry_num >= sg_cnt) {
|
||||
*buf = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely(sg_is_chain(sg)))
|
||||
sg = sg_chain_ptr(sg);
|
||||
@@ -3490,6 +3490,94 @@ static inline void scst_put_sg_buf(struct scst_cmd *cmd, void *buf,
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions for access to the commands data (SG) page. Should be used
|
||||
* instead of direct access. Returns the buffer length for success, 0 for EOD,
|
||||
* negative error code otherwise.
|
||||
*
|
||||
* "Page" argument returns the starting page, "offset" - offset in it.
|
||||
*
|
||||
* The "put" function "puts" the buffer. It should be always be used, because
|
||||
* in future may need to do some additional operations.
|
||||
*/
|
||||
static inline int __scst_get_sg_page(struct scst_cmd *cmd, int sg_cnt,
|
||||
struct page **page, int *offset)
|
||||
{
|
||||
int res = 0;
|
||||
struct scatterlist *sg = cmd->get_sg_buf_cur_sg_entry;
|
||||
|
||||
if (cmd->get_sg_buf_entry_num >= sg_cnt) {
|
||||
*page = NULL;
|
||||
*offset = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely(sg_is_chain(sg)))
|
||||
sg = sg_chain_ptr(sg);
|
||||
|
||||
*page = sg_page(sg);
|
||||
*offset = sg->offset;
|
||||
res = sg->length;
|
||||
|
||||
cmd->get_sg_buf_entry_num++;
|
||||
cmd->get_sg_buf_cur_sg_entry = ++sg;
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int scst_get_sg_page_first(struct scst_cmd *cmd,
|
||||
struct page **page, int *offset)
|
||||
{
|
||||
if (unlikely(cmd->sg == NULL)) {
|
||||
*page = NULL;
|
||||
*offset = 0;
|
||||
return 0;
|
||||
}
|
||||
cmd->get_sg_buf_entry_num = 0;
|
||||
cmd->get_sg_buf_cur_sg_entry = cmd->sg;
|
||||
cmd->may_need_dma_sync = 1;
|
||||
return __scst_get_sg_page(cmd, cmd->sg_cnt, page, offset);
|
||||
}
|
||||
|
||||
static inline int scst_get_sg_page_next(struct scst_cmd *cmd,
|
||||
struct page **page, int *offset)
|
||||
{
|
||||
return __scst_get_sg_page(cmd, cmd->sg_cnt, page, offset);
|
||||
}
|
||||
|
||||
static inline void scst_put_sg_page(struct scst_cmd *cmd,
|
||||
struct page *page, int offset)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
static inline int scst_get_out_sg_page_first(struct scst_cmd *cmd,
|
||||
struct page **page, int *offset)
|
||||
{
|
||||
if (unlikely(cmd->out_sg == NULL)) {
|
||||
*page = NULL;
|
||||
*offset = 0;
|
||||
return 0;
|
||||
}
|
||||
cmd->get_sg_buf_entry_num = 0;
|
||||
cmd->get_sg_buf_cur_sg_entry = cmd->out_sg;
|
||||
cmd->may_need_dma_sync = 1;
|
||||
return __scst_get_sg_page(cmd, cmd->out_sg_cnt, page, offset);
|
||||
}
|
||||
|
||||
static inline int scst_get_out_sg_page_next(struct scst_cmd *cmd,
|
||||
struct page **page, int *offset)
|
||||
{
|
||||
return __scst_get_sg_page(cmd, cmd->out_sg_cnt, page, offset);
|
||||
}
|
||||
|
||||
static inline void scst_put_out_sg_page(struct scst_cmd *cmd,
|
||||
struct page *page, int offset)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns approximate higher rounded buffers count that
|
||||
* scst_get_buf_[first|next]() return.
|
||||
|
||||
@@ -2641,8 +2641,8 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
|
||||
(struct scst_vdisk_dev *)cmd->dev->dh_priv;
|
||||
struct block_device *bdev = thr->bdev;
|
||||
struct request_queue *q = bdev_get_queue(bdev);
|
||||
int length, max_nr_vecs = 0;
|
||||
uint8_t *address;
|
||||
int length, max_nr_vecs = 0, offset;
|
||||
struct page *page;
|
||||
struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
|
||||
int need_new_bio;
|
||||
struct scst_blockio_work *blockio_work;
|
||||
@@ -2667,21 +2667,20 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
|
||||
|
||||
need_new_bio = 1;
|
||||
|
||||
length = scst_get_buf_first(cmd, &address);
|
||||
length = scst_get_sg_page_first(cmd, &page, &offset);
|
||||
while (length > 0) {
|
||||
int len, bytes, off, thislen;
|
||||
uint8_t *addr;
|
||||
struct page *pg;
|
||||
u64 lba_start0;
|
||||
|
||||
addr = address;
|
||||
off = offset_in_page(addr);
|
||||
pg = page;
|
||||
len = length;
|
||||
off = offset;
|
||||
thislen = 0;
|
||||
lba_start0 = lba_start;
|
||||
|
||||
while (len > 0) {
|
||||
int rc;
|
||||
struct page *page = virt_to_page(addr);
|
||||
|
||||
if (need_new_bio) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
@@ -2725,7 +2724,7 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
|
||||
|
||||
bytes = min_t(unsigned int, len, PAGE_SIZE - off);
|
||||
|
||||
rc = bio_add_page(bio, page, bytes, off);
|
||||
rc = bio_add_page(bio, pg, bytes, off);
|
||||
if (rc < bytes) {
|
||||
sBUG_ON(rc != 0);
|
||||
need_new_bio = 1;
|
||||
@@ -2734,7 +2733,7 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
|
||||
continue;
|
||||
}
|
||||
|
||||
addr += PAGE_SIZE;
|
||||
pg++;
|
||||
thislen += bytes;
|
||||
len -= bytes;
|
||||
off = 0;
|
||||
@@ -2742,8 +2741,8 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
|
||||
|
||||
lba_start += length >> virt_dev->block_shift;
|
||||
|
||||
scst_put_buf(cmd, address);
|
||||
length = scst_get_buf_next(cmd, &address);
|
||||
scst_put_sg_page(cmd, page, offset);
|
||||
length = scst_get_sg_page_next(cmd, &page, &offset);
|
||||
}
|
||||
|
||||
/* +1 to prevent erroneous too early command completion */
|
||||
|
||||
Reference in New Issue
Block a user