target: Eliminate usage of struct se_mem

Both backstores and fabrics use arrays of struct scatterlist to describe
data buffers. However TCM used struct se_mems, basically a linked list
of scatterlist entries. We are able to simplify the code by eliminating
this intermediate data structure and just using struct scatterlist[]
throughout.

Also, moved attachment of task to cmd out of transport_generic_get_task
and into allocate_control_task and allocate_data_tasks. The reasoning
is that it's nonintuitive that get_task should automatically add it to
the cmd's task list -- it should just return an allocated, initialized
task. That's all it should do, based on the function's name, so either the
function shouldn't do it, or the name should change to encapsulate the
entire essence of what it does.

(nab: Fix compile warnings in tcm_fc, and make transport_kmap_first_data_page
 honor sg->offset for SGLs from contigious memory with TCM_Loop, and
 fix control se_cmd descriptor memory leak)

Signed-off-by: Andy Grover <agrover@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Andy Grover 2011-07-20 19:28:46 +00:00 committed by Nicholas Bellinger
parent 3a86720567
commit ec98f7825c
7 changed files with 322 additions and 793 deletions

View File

@ -175,10 +175,7 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
sgl_bidi_count = sdb->table.nents;
}
/*
* Map the SG memory into struct se_mem->page linked list using the same
* physical memory at sg->page_link.
*/
/* Tell the core about our preallocated memory */
ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
scsi_sg_count(sc), sgl_bidi, sgl_bidi_count);
if (ret < 0)

View File

@ -634,7 +634,7 @@ static int iblock_map_task_SG(struct se_task *task)
hbio = tbio = bio;
/*
* Use fs/bio.c:bio_add_pages() to setup the bio_vec maplist
* from TCM struct se_mem -> task->task_sg -> struct scatterlist memory.
* from task->task_sg -> struct scatterlist memory.
*/
for_each_sg(task->task_sg, sg, task->task_sg_num, i) {
DEBUG_IBLOCK("task: %p bio: %p Calling bio_add_page(): page:"

View File

@ -1097,7 +1097,7 @@ static int __pscsi_map_task_SG(
return 0;
/*
* For SCF_SCSI_DATA_SG_IO_CDB, Use fs/bio.c:bio_add_page() to setup
* the bio_vec maplist from TC< struct se_mem -> task->task_sg ->
* the bio_vec maplist from task->task_sg ->
* struct scatterlist memory. The struct se_task->task_sg[] currently needs
* to be attached to struct bios for submission to Linux/SCSI using
* struct request to struct scsi_device->request_queue.

File diff suppressed because it is too large Load Diff

View File

@ -59,7 +59,8 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
struct fc_exch *ep;
struct fc_seq *sp;
struct se_cmd *se_cmd;
struct se_mem *mem;
struct scatterlist *sg;
int count;
if (!(ft_debug_logging & FT_DEBUG_IO))
return;
@ -71,15 +72,16 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
caller, cmd, cmd->cdb);
printk(KERN_INFO "%s: cmd %p lun %d\n", caller, cmd, cmd->lun);
printk(KERN_INFO "%s: cmd %p se_num %u len %u se_cmd_flags <0x%x>\n",
caller, cmd, se_cmd->t_tasks_se_num,
printk(KERN_INFO "%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n",
caller, cmd, se_cmd->t_data_nents,
se_cmd->data_length, se_cmd->se_cmd_flags);
list_for_each_entry(mem, &se_cmd->t_mem_list, se_list)
printk(KERN_INFO "%s: cmd %p mem %p page %p "
"len 0x%x off 0x%x\n",
caller, cmd, mem,
mem->se_page, mem->se_len, mem->se_off);
for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, count)
printk(KERN_INFO "%s: cmd %p sg %p page %p "
"len 0x%x off 0x%x\n",
caller, cmd, sg,
sg_page(sg), sg->length, sg->offset);
sp = cmd->seq;
if (sp) {
ep = fc_seq_exch(sp);
@ -256,10 +258,9 @@ int ft_write_pending(struct se_cmd *se_cmd)
(fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) {
if (se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
/*
* Map se_mem list to scatterlist, so that
* DDP can be setup. DDP setup function require
* scatterlist. se_mem_list is internal to
* TCM/LIO target
* cmd may have been broken up into multiple
* tasks. Link their sgs together so we can
* operate on them all at once.
*/
transport_do_task_sg_chain(se_cmd);
cmd->sg = se_cmd->t_tasks_sg_chained;

View File

@ -68,17 +68,17 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
struct fc_frame *fp = NULL;
struct fc_exch *ep;
struct fc_lport *lport;
struct se_mem *mem;
struct scatterlist *sg = NULL;
size_t remaining;
u32 f_ctl = FC_FC_EX_CTX | FC_FC_REL_OFF;
u32 mem_off;
u32 mem_off = 0;
u32 fh_off = 0;
u32 frame_off = 0;
size_t frame_len = 0;
size_t mem_len;
size_t mem_len = 0;
size_t tlen;
size_t off_in_page;
struct page *page;
struct page *page = NULL;
int use_sg;
int error;
void *page_addr;
@ -94,13 +94,12 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
/*
* Setup to use first mem list entry, unless no data.
*/
BUG_ON(remaining && list_empty(&se_cmd->t_mem_list));
BUG_ON(remaining && !se_cmd->t_data_sg);
if (remaining) {
mem = list_first_entry(&se_cmd->t_mem_list,
struct se_mem, se_list);
mem_len = mem->se_len;
mem_off = mem->se_off;
page = mem->se_page;
sg = se_cmd->t_data_sg;
mem_len = sg->length;
mem_off = sg->offset;
page = sg_page(sg);
}
/* no scatter/gather in skb for odd word length due to fc_seq_send() */
@ -108,12 +107,10 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
while (remaining) {
if (!mem_len) {
BUG_ON(!mem);
mem = list_entry(mem->se_list.next,
struct se_mem, se_list);
mem_len = min((size_t)mem->se_len, remaining);
mem_off = mem->se_off;
page = mem->se_page;
sg = sg_next(sg);
mem_len = min((size_t)sg->length, remaining);
mem_off = sg->offset;
page = sg_page(sg);
}
if (!frame_len) {
/*
@ -200,13 +197,13 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
struct fc_exch *ep;
struct fc_lport *lport;
struct fc_frame_header *fh;
struct se_mem *mem;
u32 mem_off;
struct scatterlist *sg = NULL;
u32 mem_off = 0;
u32 rel_off;
size_t frame_len;
size_t mem_len;
size_t mem_len = 0;
size_t tlen;
struct page *page;
struct page *page = NULL;
void *page_addr;
void *from;
void *to;
@ -288,23 +285,20 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
/*
* Setup to use first mem list entry, unless no data.
*/
BUG_ON(frame_len && list_empty(&se_cmd->t_mem_list));
BUG_ON(frame_len && !se_cmd->t_data_sg);
if (frame_len) {
mem = list_first_entry(&se_cmd->t_mem_list,
struct se_mem, se_list);
mem_len = mem->se_len;
mem_off = mem->se_off;
page = mem->se_page;
sg = se_cmd->t_data_sg;
mem_len = sg->length;
mem_off = sg->offset;
page = sg_page(sg);
}
while (frame_len) {
if (!mem_len) {
BUG_ON(!mem);
mem = list_entry(mem->se_list.next,
struct se_mem, se_list);
mem_len = mem->se_len;
mem_off = mem->se_off;
page = mem->se_page;
sg = sg_next(sg);
mem_len = sg->length;
mem_off = sg->offset;
page = sg_page(sg);
}
if (rel_off >= mem_len) {
rel_off -= mem_len;

View File

@ -490,8 +490,6 @@ struct se_cmd {
int t_tasks_failed;
int t_tasks_fua;
bool t_tasks_bidi;
u32 t_tasks_se_num;
u32 t_tasks_se_bidi_num;
u32 t_tasks_sg_chained_no;
atomic_t t_fe_count;
atomic_t t_se_count;
@ -523,9 +521,13 @@ struct se_cmd {
*/
struct scatterlist *t_task_pt_sgl;
u32 t_task_pt_sgl_num;
struct list_head t_mem_list;
struct scatterlist *t_data_sg;
unsigned int t_data_nents;
struct scatterlist *t_bidi_data_sg;
unsigned int t_bidi_data_nents;
/* Used for BIDI READ */
struct list_head t_mem_bidi_list;
struct list_head t_task_list;
u32 t_task_list_num;