Skip to content

Commit 39ae3ed

Browse files
mikechristiemartinkpetersen
authored andcommitted
scsi: target: core: Make completion affinity configurable
It may not always be best to complete the IO on same CPU as it was submitted on. This commit allows userspace to configure it. This has been useful for vhost-scsi where we have a single thread for submissions and completions. If we force the completion on the submission CPU we may be adding conflicts with what the user has setup in the lower levels with settings like the block layer rq_affinity or the driver's IRQ or softirq (the network's rps_cpus value) settings. We may also want to set it up where the vhost thread runs on CPU N and does its submissions/completions there, and then have LIO do its completion booking on CPU M, but can't configure the lower levels due to issues like using dm-multipath with lots of paths (the path selector can throw commands all over the system because it's only taking into account latency/throughput at its level). The new setting is in: /sys/kernel/config/target/$fabric/$target/param/cmd_completion_affinity Writing: -1 -> Gives the current default behavior of completing on the submission CPU. -2 -> Completes the cmd on the CPU the lower layers sent it to us from. > 0 -> Completes on the CPU userspace has specified. Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Himanshu Madhani <[email protected]> Signed-off-by: Mike Christie <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 3d75948 commit 39ae3ed

File tree

4 files changed

+77
-2
lines changed

4 files changed

+77
-2
lines changed

drivers/target/target_core_fabric_configfs.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,7 @@ static void target_fabric_release_wwn(struct config_item *item)
892892
struct target_fabric_configfs *tf = wwn->wwn_tf;
893893

894894
configfs_remove_default_groups(&wwn->fabric_stat_group);
895+
configfs_remove_default_groups(&wwn->param_group);
895896
tf->tf_ops->fabric_drop_wwn(wwn);
896897
}
897898

@@ -918,6 +919,57 @@ TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL);
918919

919920
/* End of tfc_wwn_fabric_stats_cit */
920921

922+
static ssize_t
923+
target_fabric_wwn_cmd_completion_affinity_show(struct config_item *item,
924+
char *page)
925+
{
926+
struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,
927+
param_group);
928+
return sprintf(page, "%d\n",
929+
wwn->cmd_compl_affinity == WORK_CPU_UNBOUND ?
930+
SE_COMPL_AFFINITY_CURR_CPU : wwn->cmd_compl_affinity);
931+
}
932+
933+
static ssize_t
934+
target_fabric_wwn_cmd_completion_affinity_store(struct config_item *item,
935+
const char *page, size_t count)
936+
{
937+
struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,
938+
param_group);
939+
int compl_val;
940+
941+
if (kstrtoint(page, 0, &compl_val))
942+
return -EINVAL;
943+
944+
switch (compl_val) {
945+
case SE_COMPL_AFFINITY_CPUID:
946+
wwn->cmd_compl_affinity = compl_val;
947+
break;
948+
case SE_COMPL_AFFINITY_CURR_CPU:
949+
wwn->cmd_compl_affinity = WORK_CPU_UNBOUND;
950+
break;
951+
default:
952+
if (compl_val < 0 || compl_val >= nr_cpu_ids ||
953+
!cpu_online(compl_val)) {
954+
pr_err("Command completion value must be between %d and %d or an online CPU.\n",
955+
SE_COMPL_AFFINITY_CPUID,
956+
SE_COMPL_AFFINITY_CURR_CPU);
957+
return -EINVAL;
958+
}
959+
wwn->cmd_compl_affinity = compl_val;
960+
}
961+
962+
return count;
963+
}
964+
CONFIGFS_ATTR(target_fabric_wwn_, cmd_completion_affinity);
965+
966+
static struct configfs_attribute *target_fabric_wwn_param_attrs[] = {
967+
&target_fabric_wwn_attr_cmd_completion_affinity,
968+
NULL,
969+
};
970+
971+
TF_CIT_SETUP(wwn_param, NULL, NULL, target_fabric_wwn_param_attrs);
972+
921973
/* Start of tfc_wwn_cit */
922974

923975
static struct config_group *target_fabric_make_wwn(
@@ -937,6 +989,7 @@ static struct config_group *target_fabric_make_wwn(
937989
if (!wwn || IS_ERR(wwn))
938990
return ERR_PTR(-EINVAL);
939991

992+
wwn->cmd_compl_affinity = SE_COMPL_AFFINITY_CPUID;
940993
wwn->wwn_tf = tf;
941994

942995
config_group_init_type_name(&wwn->wwn_group, name, &tf->tf_tpg_cit);
@@ -945,6 +998,10 @@ static struct config_group *target_fabric_make_wwn(
945998
&tf->tf_wwn_fabric_stats_cit);
946999
configfs_add_default_group(&wwn->fabric_stat_group, &wwn->wwn_group);
9471000

1001+
config_group_init_type_name(&wwn->param_group, "param",
1002+
&tf->tf_wwn_param_cit);
1003+
configfs_add_default_group(&wwn->param_group, &wwn->wwn_group);
1004+
9481005
if (tf->tf_ops->add_wwn_groups)
9491006
tf->tf_ops->add_wwn_groups(wwn);
9501007
return &wwn->wwn_group;
@@ -974,6 +1031,7 @@ int target_fabric_setup_cits(struct target_fabric_configfs *tf)
9741031
target_fabric_setup_discovery_cit(tf);
9751032
target_fabric_setup_wwn_cit(tf);
9761033
target_fabric_setup_wwn_fabric_stats_cit(tf);
1034+
target_fabric_setup_wwn_param_cit(tf);
9771035
target_fabric_setup_tpg_cit(tf);
9781036
target_fabric_setup_tpg_base_cit(tf);
9791037
target_fabric_setup_tpg_port_cit(tf);

drivers/target/target_core_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct target_fabric_configfs {
3434
struct config_item_type tf_discovery_cit;
3535
struct config_item_type tf_wwn_cit;
3636
struct config_item_type tf_wwn_fabric_stats_cit;
37+
struct config_item_type tf_wwn_param_cit;
3738
struct config_item_type tf_tpg_cit;
3839
struct config_item_type tf_tpg_base_cit;
3940
struct config_item_type tf_tpg_lun_cit;

drivers/target/target_core_transport.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,8 @@ static bool target_cmd_interrupted(struct se_cmd *cmd)
857857
/* May be called from interrupt context so must not sleep. */
858858
void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
859859
{
860-
int success;
860+
struct se_wwn *wwn = cmd->se_sess->se_tpg->se_tpg_wwn;
861+
int success, cpu;
861862
unsigned long flags;
862863

863864
if (target_cmd_interrupted(cmd))
@@ -884,7 +885,13 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
884885

885886
INIT_WORK(&cmd->work, success ? target_complete_ok_work :
886887
target_complete_failure_work);
887-
queue_work_on(cmd->cpuid, target_completion_wq, &cmd->work);
888+
889+
if (wwn->cmd_compl_affinity == SE_COMPL_AFFINITY_CPUID)
890+
cpu = cmd->cpuid;
891+
else
892+
cpu = wwn->cmd_compl_affinity;
893+
894+
queue_work_on(cpu, target_completion_wq, &cmd->work);
888895
}
889896
EXPORT_SYMBOL(target_complete_cmd);
890897

include/target/target_core_base.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,11 +944,20 @@ static inline struct se_portal_group *param_to_tpg(struct config_item *item)
944944
tpg_param_group);
945945
}
946946

947+
enum {
948+
/* Use se_cmd's cpuid for completion */
949+
SE_COMPL_AFFINITY_CPUID = -1,
950+
/* Complete on current CPU */
951+
SE_COMPL_AFFINITY_CURR_CPU = -2,
952+
};
953+
947954
struct se_wwn {
948955
struct target_fabric_configfs *wwn_tf;
949956
void *priv;
950957
struct config_group wwn_group;
951958
struct config_group fabric_stat_group;
959+
struct config_group param_group;
960+
int cmd_compl_affinity;
952961
};
953962

954963
static inline void atomic_inc_mb(atomic_t *v)

0 commit comments

Comments
 (0)