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:
Vladislav Bolkhovitin
2010-09-15 19:18:47 +00:00
parent f725c61c7b
commit 53d2c612b7
2 changed files with 101 additions and 14 deletions

View File

@@ -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.

View File

@@ -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 */