Skip to content

Commit 5f544cf

Browse files
Nicholas BellingerNicholas Bellinger
Nicholas Bellinger
authored and
Nicholas Bellinger
committed
tcm_fc: Convert to per-cpu command map pre-allocation of ft_cmd
This patch converts tcm_fc to use transport_init_session_tags() pre-allocation logic for struct ft_cmd descriptors using per-cpu session tag pooling in order to effectively avoid memory allocation + release for each received I/O. It adds percpu_ida_alloc() in ft_recv_cmd() to obtain an tag and locate ft_cmd from se_sess->sess_cmd_map[], and percpu_ida_free() in ft_free_cmd() to release the tag based upon se_cmd->map_tag id. It also uses a TCM_FC_DEFAULT_TAGS value of 512, that puts the per se_sess->sess_cmd_map allocation at ~360K on 64-bit. v2 changes: - Handle possible tag < 0 failure with GFP_ATOMIC Cc: Mark Rustad <[email protected]> Cc: Robert Love <[email protected]> Cc: Kent Overstreet <[email protected]> Signed-off-by: Nicholas Bellinger <[email protected]>
1 parent 15c03dd commit 5f544cf

File tree

3 files changed

+17
-5
lines changed

3 files changed

+17
-5
lines changed

drivers/target/tcm_fc/tcm_fc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#define FT_NAMELEN 32 /* length of ASCII WWPNs including pad */
2323
#define FT_TPG_NAMELEN 32 /* max length of TPG name */
2424
#define FT_LUN_NAMELEN 32 /* max length of LUN name */
25+
#define TCM_FC_DEFAULT_TAGS 512 /* tags used for per-session preallocation */
2526

2627
struct ft_transport_id {
2728
__u8 format;

drivers/target/tcm_fc/tfc_cmd.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/configfs.h>
2929
#include <linux/ctype.h>
3030
#include <linux/hash.h>
31+
#include <linux/percpu_ida.h>
3132
#include <asm/unaligned.h>
3233
#include <scsi/scsi.h>
3334
#include <scsi/scsi_host.h>
@@ -89,16 +90,18 @@ static void ft_free_cmd(struct ft_cmd *cmd)
8990
{
9091
struct fc_frame *fp;
9192
struct fc_lport *lport;
93+
struct se_session *se_sess;
9294

9395
if (!cmd)
9496
return;
97+
se_sess = cmd->sess->se_sess;
9598
fp = cmd->req_frame;
9699
lport = fr_dev(fp);
97100
if (fr_seq(fp))
98101
lport->tt.seq_release(fr_seq(fp));
99102
fc_frame_free(fp);
103+
percpu_ida_free(&se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
100104
ft_sess_put(cmd->sess); /* undo get from lookup at recv */
101-
kfree(cmd);
102105
}
103106

104107
void ft_release_cmd(struct se_cmd *se_cmd)
@@ -432,14 +435,21 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
432435
{
433436
struct ft_cmd *cmd;
434437
struct fc_lport *lport = sess->tport->lport;
438+
struct se_session *se_sess = sess->se_sess;
439+
int tag;
435440

436-
cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
437-
if (!cmd)
441+
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
442+
if (tag < 0)
438443
goto busy;
444+
445+
cmd = &((struct ft_cmd *)se_sess->sess_cmd_map)[tag];
446+
memset(cmd, 0, sizeof(struct ft_cmd));
447+
448+
cmd->se_cmd.map_tag = tag;
439449
cmd->sess = sess;
440450
cmd->seq = lport->tt.seq_assign(lport, fp);
441451
if (!cmd->seq) {
442-
kfree(cmd);
452+
percpu_ida_free(&se_sess->sess_tag_pool, tag);
443453
goto busy;
444454
}
445455
cmd->req_frame = fp; /* hold frame during cmd */

drivers/target/tcm_fc/tfc_sess.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,8 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
210210
if (!sess)
211211
return NULL;
212212

213-
sess->se_sess = transport_init_session();
213+
sess->se_sess = transport_init_session_tags(TCM_FC_DEFAULT_TAGS,
214+
sizeof(struct ft_cmd));
214215
if (IS_ERR(sess->se_sess)) {
215216
kfree(sess);
216217
return NULL;

0 commit comments

Comments
 (0)