code:
#!/usr/bin/env python
# The TCM v4 multi-protocol fabric module generation script for drivers/target/$NEW_MOD
#
# Copyright (c) 2010 Rising Tide Systems
# Copyright (c) 2010 Linux-iSCSI.org
#
# Author: nab@kernel.org
#
import os, sys
import subprocess as sub
import string
import re
import optparse

tcm_dir = ""

fabric_ops = []
fabric_mod_dir = ""
fabric_mod_port = ""
fabric_mod_init_port = ""

def tcm_mod_err(msg):
	print msg
	sys.exit(1)

def tcm_mod_create_module_subdir(fabric_mod_dir_var):

	if os.path.isdir(fabric_mod_dir_var) == True:
		return 1

	print "Creating fabric_mod_dir: " + fabric_mod_dir_var
	ret = os.mkdir(fabric_mod_dir_var)
	if ret:
		tcm_mod_err("Unable to mkdir " + fabric_mod_dir_var)

	return

def tcm_mod_build_FC_include(fabric_mod_dir_var, fabric_mod_name):
	global fabric_mod_port
	global fabric_mod_init_port
	buf = ""

	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_base.h"
	print "Writing file: " + f

	p = open(f, 'w');
	if not p:
		tcm_mod_err("Unable to open file: " + f)

	buf = "#define " + fabric_mod_name.upper() + "_VERSION	\"v0.1\"\n"
	buf += "#define " + fabric_mod_name.upper() + "_NAMELEN	32\n"
	buf += "\n"
	buf += "struct " + fabric_mod_name + "_tpg {\n"
	buf += "	/* FC lport target portal group tag for TCM */\n"
	buf += "	u16 lport_tpgt;\n"
	buf += "	/* Pointer back to " + fabric_mod_name + "_lport */\n"
	buf += "	struct " + fabric_mod_name + "_lport *lport;\n"
	buf += "	/* Returned by " + fabric_mod_name + "_make_tpg() */\n"
	buf += "	struct se_portal_group se_tpg;\n"
	buf += "};\n"
	buf += "\n"
	buf += "struct " + fabric_mod_name + "_lport {\n"
	buf += "	/* Binary World Wide unique Port Name for FC Target Lport */\n"
	buf += "	u64 lport_wwpn;\n"
	buf += "	/* ASCII formatted WWPN for FC Target Lport */\n"
	buf += "	char lport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
	buf += "	/* Returned by " + fabric_mod_name + "_make_lport() */\n"
	buf += "	struct se_wwn lport_wwn;\n"
	buf += "};\n"

	ret = p.write(buf)
	if ret:
		tcm_mod_err("Unable to write f: " + f)

	p.close()

	fabric_mod_port = "lport"
	fabric_mod_init_port = "nport"

	return

def tcm_mod_build_SAS_include(fabric_mod_dir_var, fabric_mod_name):
	global fabric_mod_port
	global fabric_mod_init_port
	buf = ""

	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_base.h"
	print "Writing file: " + f

	p = open(f, 'w');
	if not p:
		tcm_mod_err("Unable to open file: " + f)

	buf = "#define " + fabric_mod_name.upper() + "_VERSION  \"v0.1\"\n"
	buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n"
	buf += "\n"
	buf += "struct " + fabric_mod_name + "_tpg {\n"
	buf += "	/* SAS port target portal group tag for TCM */\n"
	buf += "	u16 tport_tpgt;\n"
	buf += "	/* Pointer back to " + fabric_mod_name + "_tport */\n"
	buf += "	struct " + fabric_mod_name + "_tport *tport;\n"
	buf += "	/* Returned by " + fabric_mod_name + "_make_tpg() */\n"
	buf += "	struct se_portal_group se_tpg;\n"
	buf += "};\n\n"
	buf += "struct " + fabric_mod_name + "_tport {\n"
	buf += "	/* Binary World Wide unique Port Name for SAS Target port */\n"
	buf += "	u64 tport_wwpn;\n"
	buf += "	/* ASCII formatted WWPN for SAS Target port */\n"
	buf += "	char tport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
	buf += "	/* Returned by " + fabric_mod_name + "_make_tport() */\n"
	buf += "	struct se_wwn tport_wwn;\n"
	buf += "};\n"

	ret = p.write(buf)
	if ret:
		tcm_mod_err("Unable to write f: " + f)

	p.close()

	fabric_mod_port = "tport"
	fabric_mod_init_port = "iport"

	return

def tcm_mod_build_iSCSI_include(fabric_mod_dir_var, fabric_mod_name):
	global fabric_mod_port
	global fabric_mod_init_port
	buf = ""

	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_base.h"
	print "Writing file: " + f

	p = open(f, 'w');
	if not p:
		tcm_mod_err("Unable to open file: " + f)

	buf = "#define " + fabric_mod_name.upper() + "_VERSION  \"v0.1\"\n"
	buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n"
	buf += "\n"
	buf += "struct " + fabric_mod_name + "_tpg {\n"
	buf += "	/* iSCSI target portal group tag for TCM */\n"
	buf += "	u16 tport_tpgt;\n"
	buf += "	/* Pointer back to " + fabric_mod_name + "_tport */\n"
	buf += "	struct " + fabric_mod_name + "_tport *tport;\n"
	buf += "	/* Returned by " + fabric_mod_name + "_make_tpg() */\n"
	buf += "	struct se_portal_group se_tpg;\n"
	buf += "};\n\n"
	buf += "struct " + fabric_mod_name + "_tport {\n"
	buf += "	/* ASCII formatted TargetName for IQN */\n"
	buf += "	char tport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
	buf += "	/* Returned by " + fabric_mod_name + "_make_tport() */\n"
	buf += "	struct se_wwn tport_wwn;\n"
	buf += "};\n"

	ret = p.write(buf)
	if ret:
		tcm_mod_err("Unable to write f: " + f)

	p.close()

	fabric_mod_port = "tport"
	fabric_mod_init_port = "iport"

	return

def tcm_mod_build_base_includes(proto_ident, fabric_mod_dir_val, fabric_mod_name):

	if proto_ident == "FC":
		tcm_mod_build_FC_include(fabric_mod_dir_val, fabric_mod_name)
	elif proto_ident == "SAS":
		tcm_mod_build_SAS_include(fabric_mod_dir_val, fabric_mod_name)
	elif proto_ident == "iSCSI":
		tcm_mod_build_iSCSI_include(fabric_mod_dir_val, fabric_mod_name)
	else:
		print "Unsupported proto_ident: " + proto_ident
		sys.exit(1)

	return

def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
	buf = ""

	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_configfs.c"
	print "Writing file: " + f

        p = open(f, 'w');
        if not p:
                tcm_mod_err("Unable to open file: " + f)

	buf = "#include <linux/module.h>\n"
	buf += "#include <linux/moduleparam.h>\n"
	buf += "#include <linux/version.h>\n"
	buf += "#include <generated/utsrelease.h>\n"
	buf += "#include <linux/utsname.h>\n"
	buf += "#include <linux/init.h>\n"
	buf += "#include <linux/slab.h>\n"
	buf += "#include <linux/kthread.h>\n"
	buf += "#include <linux/types.h>\n"
	buf += "#include <linux/string.h>\n"
	buf += "#include <linux/configfs.h>\n"
	buf += "#include <linux/ctype.h>\n"
	buf += "#include <asm/unaligned.h>\n"
	buf += "#include <scsi/scsi_proto.h>\n\n"
	buf += "#include <target/target_core_base.h>\n"
	buf += "#include <target/target_core_fabric.h>\n"
	buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
	buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"

	buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops;\n\n"

	buf += "static struct se_portal_group *" + fabric_mod_name + "_make_tpg(\n"
	buf += "	struct se_wwn *wwn,\n"
	buf += "	struct config_group *group,\n"
	buf += "	const char *name)\n"
	buf += "{\n"
	buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + "*" + fabric_mod_port + " = container_of(wwn,\n"
	buf += "			struct " + fabric_mod_name + "_" + fabric_mod_port + ", " + fabric_mod_port + "_wwn);\n\n"
	buf += "	struct " + fabric_mod_name + "_tpg *tpg;\n"
	buf += "	unsigned long tpgt;\n"
	buf += "	int ret;\n\n"
	buf += "	if (strstr(name, \"tpgt_\") != name)\n"
	buf += "		return ERR_PTR(-EINVAL);\n"
	buf += "	if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX)\n"
	buf += "		return ERR_PTR(-EINVAL);\n\n"
	buf += "	tpg = kzalloc(sizeof(struct " + fabric_mod_name + "_tpg), GFP_KERNEL);\n"
	buf += "	if (!tpg) {\n"
	buf += "		printk(KERN_ERR \"Unable to allocate struct " + fabric_mod_name + "_tpg\");\n"
	buf += "		return ERR_PTR(-ENOMEM);\n"
	buf += "	}\n"
	buf += "	tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
	buf += "	tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"

	if proto_ident == "FC":
		buf += "	ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);\n"
	elif proto_ident == "SAS":
		buf += "	ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n"
	elif proto_ident == "iSCSI":
		buf += "	ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_ISCSI);\n"

	buf += "	if (ret < 0) {\n"
	buf += "		kfree(tpg);\n"
	buf += "		return NULL;\n"
	buf += "	}\n"
	buf += "	return &tpg->se_tpg;\n"
	buf += "}\n\n"
	buf += "static void " + fabric_mod_name + "_drop_tpg(struct se_portal_group *se_tpg)\n"
	buf += "{\n"
	buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
	buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n\n"
	buf += "	core_tpg_deregister(se_tpg);\n"
	buf += "	kfree(tpg);\n"
	buf += "}\n\n"

	buf += "static struct se_wwn *" + fabric_mod_name + "_make_" + fabric_mod_port + "(\n"
	buf += "	struct target_fabric_configfs *tf,\n"
	buf += "	struct config_group *group,\n"
	buf += "	const char *name)\n"
	buf += "{\n"
	buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + ";\n"

	if proto_ident == "FC" or proto_ident == "SAS":
		buf += "	u64 wwpn = 0;\n\n"

	buf += "	/* if (" + fabric_mod_name + "_parse_wwn(name, &wwpn, 1) < 0)\n"
	buf += "		return ERR_PTR(-EINVAL); */\n\n"
	buf += "	" + fabric_mod_port + " = kzalloc(sizeof(struct " + fabric_mod_name + "_" + fabric_mod_port + "), GFP_KERNEL);\n"
	buf += "	if (!" + fabric_mod_port + ") {\n"
	buf += "		printk(KERN_ERR \"Unable to allocate struct " + fabric_mod_name + "_" + fabric_mod_port + "\");\n"
	buf += "		return ERR_PTR(-ENOMEM);\n"
	buf += "	}\n"

	if proto_ident == "FC" or proto_ident == "SAS":
		buf += "	" + fabric_mod_port + "->" + fabric_mod_port + "_wwpn = wwpn;\n"

	buf += "	/* " + fabric_mod_name + "_format_wwn(&" + fabric_mod_port + "->" + fabric_mod_port + "_name[0], " + fabric_mod_name.upper() + "_NAMELEN, wwpn); */\n\n"
	buf += "	return &" + fabric_mod_port + "->" + fabric_mod_port + "_wwn;\n"
	buf += "}\n\n"
	buf += "static void " + fabric_mod_name + "_drop_" + fabric_mod_port + "(struct se_wwn *wwn)\n"
	buf += "{\n"
	buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = container_of(wwn,\n"
	buf += "				struct " + fabric_mod_name + "_" + fabric_mod_port + ", " + fabric_mod_port + "_wwn);\n"
	buf += "	kfree(" + fabric_mod_port + ");\n"
	buf += "}\n\n"

	buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
	buf += "	.module				= THIS_MODULE,\n"
	buf += "	.name				= \"" + fabric_mod_name + "\",\n"
	buf += "	.get_fabric_name		= " + fabric_mod_name + "_get_fabric_name,\n"
	buf += "	.tpg_get_wwn			= " + fabric_mod_name + "_get_fabric_wwn,\n"
	buf += "	.tpg_get_tag			= " + fabric_mod_name + "_get_tag,\n"
	buf += "	.tpg_check_demo_mode		= " + fabric_mod_name + "_check_false,\n"
	buf += "	.tpg_check_demo_mode_cache	= " + fabric_mod_name + "_check_true,\n"
	buf += "	.tpg_check_demo_mode_write_protect = " + fabric_mod_name + "_check_true,\n"
	buf += "	.tpg_check_prod_mode_write_protect = " + fabric_mod_name + "_check_false,\n"
	buf += "	.tpg_get_inst_index		= " + fabric_mod_name + "_tpg_get_inst_index,\n"
	buf += "	.release_cmd			= " + fabric_mod_name + "_release_cmd,\n"
	buf += "	.sess_get_index			= " + fabric_mod_name + "_sess_get_index,\n"
	buf += "	.sess_get_initiator_sid		= NULL,\n"
	buf += "	.write_pending			= " + fabric_mod_name + "_write_pending,\n"
	buf += "	.set_default_node_attributes	= " + fabric_mod_name + "_set_default_node_attrs,\n"
	buf += "	.get_cmd_state			= " + fabric_mod_name + "_get_cmd_state,\n"
	buf += "	.queue_data_in			= " + fabric_mod_name + "_queue_data_in,\n"
	buf += "	.queue_status			= " + fabric_mod_name + "_queue_status,\n"
	buf += "	.queue_tm_rsp			= " + fabric_mod_name + "_queue_tm_rsp,\n"
	buf += "	.aborted_task			= " + fabric_mod_name + "_aborted_task,\n"
	buf += "	/*\n"
	buf += "	 * Setup function pointers for generic logic in target_core_fabric_configfs.c\n"
	buf += "	 */\n"
	buf += "	.fabric_make_wwn		= " + fabric_mod_name + "_make_" + fabric_mod_port + ",\n"
	buf += "	.fabric_drop_wwn		= " + fabric_mod_name + "_drop_" + fabric_mod_port + ",\n"
	buf += "	.fabric_make_tpg		= " + fabric_mod_name + "_make_tpg,\n"
	buf += "	.fabric_drop_tpg		= " + fabric_mod_name + "_drop_tpg,\n"
	buf += "};\n\n"

	buf += "static int __init " + fabric_mod_name + "_init(void)\n"
	buf += "{\n"
	buf += "	return target_register_template(&" + fabric_mod_name + "_ops);\n"
	buf += "};\n\n"

	buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
	buf += "{\n"
	buf += "	target_unregister_template(&" + fabric_mod_name + "_ops);\n"
	buf += "};\n\n"

	buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
	buf += "MODULE_LICENSE(\"GPL\");\n"
	buf += "module_init(" + fabric_mod_name + "_init);\n"
	buf += "module_exit(" + fabric_mod_name + "_exit);\n"

	ret = p.write(buf)
	if ret:
		tcm_mod_err("Unable to write f: " + f)

	p.close()

	return

def tcm_mod_scan_fabric_ops(tcm_dir):

	fabric_ops_api = tcm_dir + "include/target/target_core_fabric.h"

	print "Using tcm_mod_scan_fabric_ops: " + fabric_ops_api
	process_fo = 0;

	p = open(fabric_ops_api, 'r')

	line = p.readline()
	while line:
		if process_fo == 0 and re.search('struct target_core_fabric_ops {', line):
			line = p.readline()
			continue

		if process_fo == 0:
			process_fo = 1;
			line = p.readline()
			# Search for function pointer
			if not re.search('\(\*', line):
				continue

			fabric_ops.append(line.rstrip())
			continue

		line = p.readline()
		# Search for function pointer
		if not re.search('\(\*', line):
			continue

		fabric_ops.append(line.rstrip())

	p.close()
	return

def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
	buf = ""
	bufi = ""

	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_fabric.c"
	print "Writing file: " + f

	p = open(f, 'w')
	if not p:
		tcm_mod_err("Unable to open file: " + f)

	fi = fabric_mod_dir_var + "/" + fabric_mod_name + "_fabric.h"
	print "Writing file: " + fi

	pi = open(fi, 'w')
	if not pi:
		tcm_mod_err("Unable to open file: " + fi)

	buf = "#include <linux/slab.h>\n"
	buf += "#include <linux/kthread.h>\n"
	buf += "#include <linux/types.h>\n"
	buf += "#include <linux/list.h>\n"
	buf += "#include <linux/types.h>\n"
	buf += "#include <linux/string.h>\n"
	buf += "#include <linux/ctype.h>\n"
	buf += "#include <asm/unaligned.h>\n"
	buf += "#include <scsi/scsi_common.h>\n"
	buf += "#include <scsi/scsi_proto.h>\n"
	buf += "#include <target/target_core_base.h>\n"
	buf += "#include <target/target_core_fabric.h>\n"
	buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
	buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"

	buf += "int " + fabric_mod_name + "_check_true(struct se_portal_group *se_tpg)\n"
	buf += "{\n"
	buf += "	return 1;\n"
	buf += "}\n\n"
	bufi += "int " + fabric_mod_name + "_check_true(struct se_portal_group *);\n"

	buf += "int " + fabric_mod_name + "_check_false(struct se_portal_group *se_tpg)\n"
	buf += "{\n"
	buf += "	return 0;\n"
	buf += "}\n\n"
	bufi += "int " + fabric_mod_name + "_check_false(struct se_portal_group *);\n"

	total_fabric_ops = len(fabric_ops)
	i = 0

	while i < total_fabric_ops:
		fo = fabric_ops[i]
		i += 1
#		print "fabric_ops: " + fo

		if re.search('get_fabric_name', fo):
			buf += "char *" + fabric_mod_name + "_get_fabric_name(void)\n"
			buf += "{\n"
			buf += "	return \"" + fabric_mod_name + "\";\n"
			buf += "}\n\n"
			bufi += "char *" + fabric_mod_name + "_get_fabric_name(void);\n"
			continue

		if re.search('get_wwn', fo):
			buf += "char *" + fabric_mod_name + "_get_fabric_wwn(struct se_portal_group *se_tpg)\n"
			buf += "{\n"
			buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
			buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n"
			buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n\n"
			buf += "	return &" + fabric_mod_port + "->" + fabric_mod_port + "_name[0];\n"
			buf += "}\n\n"
			bufi += "char *" + fabric_mod_name + "_get_fabric_wwn(struct se_portal_group *);\n"

		if re.search('get_tag', fo):
			buf += "u16 " + fabric_mod_name + "_get_tag(struct se_portal_group *se_tpg)\n"
			buf += "{\n"
			buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
			buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n"
			buf += "	return tpg->" + fabric_mod_port + "_tpgt;\n"
			buf += "}\n\n"
			bufi += "u16 " + fabric_mod_name + "_get_tag(struct se_portal_group *);\n"

		if re.search('tpg_get_inst_index\)\(', fo):
			buf += "u32 " + fabric_mod_name + "_tpg_get_inst_index(struct se_portal_group *se_tpg)\n"
			buf += "{\n"
			buf += "	return 1;\n"
			buf += "}\n\n"
			bufi += "u32 " + fabric_mod_name + "_tpg_get_inst_index(struct se_portal_group *);\n"

		if re.search('\*release_cmd\)\(', fo):
			buf += "void " + fabric_mod_name + "_release_cmd(struct se_cmd *se_cmd)\n"
			buf += "{\n"
			buf += "	return;\n"
			buf += "}\n\n"
			bufi += "void " + fabric_mod_name + "_release_cmd(struct se_cmd *);\n"

		if re.search('sess_get_index\)\(', fo):
			buf += "u32 " + fabric_mod_name + "_sess_get_index(struct se_session *se_sess)\n"
			buf += "{\n"
			buf += "	return 0;\n"
			buf += "}\n\n"
			bufi += "u32 " + fabric_mod_name + "_sess_get_index(struct se_session *);\n"

		if re.search('write_pending\)\(', fo):
			buf += "int " + fabric_mod_name + "_write_pending(struct se_cmd *se_cmd)\n"
			buf += "{\n"
			buf += "	return 0;\n"
			buf += "}\n\n"
			bufi += "int " + fabric_mod_name + "_write_pending(struct se_cmd *);\n"

		if re.search('set_default_node_attributes\)\(', fo):
			buf += "void " + fabric_mod_name + "_set_default_node_attrs(struct se_node_acl *nacl)\n"
			buf += "{\n"
			buf += "	return;\n"
			buf += "}\n\n"
			bufi += "void " + fabric_mod_name + "_set_default_node_attrs(struct se_node_acl *);\n"

		if re.search('get_cmd_state\)\(', fo):
			buf += "int " + fabric_mod_name + "_get_cmd_state(struct se_cmd *se_cmd)\n"
			buf += "{\n"
			buf += "	return 0;\n"
			buf += "}\n\n"
			bufi += "int " + fabric_mod_name + "_get_cmd_state(struct se_cmd *);\n"

		if re.search('queue_data_in\)\(', fo):
			buf += "int " + fabric_mod_name + "_queue_data_in(struct se_cmd *se_cmd)\n"
			buf += "{\n"
			buf += "	return 0;\n"
			buf += "}\n\n"
			bufi += "int " + fabric_mod_name + "_queue_data_in(struct se_cmd *);\n"

		if re.search('queue_status\)\(', fo):
			buf += "int " + fabric_mod_name + "_queue_status(struct se_cmd *se_cmd)\n"
			buf += "{\n"
			buf += "	return 0;\n"
			buf += "}\n\n"
			bufi += "int " + fabric_mod_name + "_queue_status(struct se_cmd *);\n"

		if re.search('queue_tm_rsp\)\(', fo):
			buf += "void " + fabric_mod_name + "_queue_tm_rsp(struct se_cmd *se_cmd)\n"
			buf += "{\n"
			buf += "	return;\n"
			buf += "}\n\n"
			bufi += "void " + fabric_mod_name + "_queue_tm_rsp(struct se_cmd *);\n"

		if re.search('aborted_task\)\(', fo):
			buf += "void " + fabric_mod_name + "_aborted_task(struct se_cmd *se_cmd)\n"
			buf += "{\n"
			buf += "	return;\n"
			buf += "}\n\n"
			bufi += "void " + fabric_mod_name + "_aborted_task(struct se_cmd *);\n"

	ret = p.write(buf)
	if ret:
		tcm_mod_err("Unable to write f: " + f)

	p.close()

	ret = pi.write(bufi)
	if ret:
		tcm_mod_err("Unable to write fi: " + fi)

	pi.close()
	return

def tcm_mod_build_kbuild(fabric_mod_dir_var, fabric_mod_name):

	buf = ""
	f = fabric_mod_dir_var + "/Makefile"
	print "Writing file: " + f

	p = open(f, 'w')
	if not p:
		tcm_mod_err("Unable to open file: " + f)

	buf += fabric_mod_name + "-objs			:= " + fabric_mod_name + "_fabric.o \\\n"
	buf += "					   " + fabric_mod_name + "_configfs.o\n"
	buf += "obj-$(CONFIG_" + fabric_mod_name.upper() + ")		+= " + fabric_mod_name + ".o\n"

	ret = p.write(buf)
	if ret:
		tcm_mod_err("Unable to write f: " + f)

	p.close()
	return

def tcm_mod_build_kconfig(fabric_mod_dir_var, fabric_mod_name):

	buf = ""
	f = fabric_mod_dir_var + "/Kconfig"
	print "Writing file: " + f

	p = open(f, 'w')
	if not p:
		tcm_mod_err("Unable to open file: " + f)

	buf = "config " + fabric_mod_name.upper() + "\n"
	buf += "	tristate \"" + fabric_mod_name.upper() + " fabric module\"\n"
	buf += "	depends on TARGET_CORE && CONFIGFS_FS\n"
	buf += "	default n\n"
	buf += "	help\n"
	buf += "	  Say Y here to enable the " + fabric_mod_name.upper() + " fabric module\n"

	ret = p.write(buf)
	if ret:
		tcm_mod_err("Unable to write f: " + f)

	p.close()
	return

def tcm_mod_add_kbuild(tcm_dir, fabric_mod_name):
	buf = "obj-$(CONFIG_" + fabric_mod_name.upper() + ")	+= " + fabric_mod_name.lower() + "/\n"
	kbuild = tcm_dir + "/drivers/target/Makefile"

	f = open(kbuild, 'a')
	f.write(buf)
	f.close()
	return

def tcm_mod_add_kconfig(tcm_dir, fabric_mod_name):
	buf = "source \"drivers/target/" + fabric_mod_name.lower() + "/Kconfig\"\n"
	kconfig = tcm_dir + "/drivers/target/Kconfig"

	f = open(kconfig, 'a')
	f.write(buf)
	f.close()
	return

def main(modname, proto_ident):
#	proto_ident = "FC"
#	proto_ident = "SAS"
#	proto_ident = "iSCSI"

	tcm_dir = os.getcwd();
	tcm_dir += "/../../"
	print "tcm_dir: " + tcm_dir
	fabric_mod_name = modname
	fabric_mod_dir = tcm_dir + "drivers/target/" + fabric_mod_name
	print "Set fabric_mod_name: " + fabric_mod_name
	print "Set fabric_mod_dir: " + fabric_mod_dir
	print "Using proto_ident: " + proto_ident

	if proto_ident != "FC" and proto_ident != "SAS" and proto_ident != "iSCSI":
		print "Unsupported proto_ident: " + proto_ident
		sys.exit(1)

	ret = tcm_mod_create_module_subdir(fabric_mod_dir)
	if ret:
		print "tcm_mod_create_module_subdir() failed because module already exists!"
		sys.exit(1)

	tcm_mod_build_base_includes(proto_ident, fabric_mod_dir, fabric_mod_name)
	tcm_mod_scan_fabric_ops(tcm_dir)
	tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir, fabric_mod_name)
	tcm_mod_build_configfs(proto_ident, fabric_mod_dir, fabric_mod_name)
	tcm_mod_build_kbuild(fabric_mod_dir, fabric_mod_name)
	tcm_mod_build_kconfig(fabric_mod_dir, fabric_mod_name)

	input = raw_input("Would you like to add " + fabric_mod_name + " to drivers/target/Makefile..? [yes,no]: ")
	if input == "yes" or input == "y":
		tcm_mod_add_kbuild(tcm_dir, fabric_mod_name)

	input = raw_input("Would you like to add " + fabric_mod_name + " to drivers/target/Kconfig..? [yes,no]: ")
	if input == "yes" or input == "y":
		tcm_mod_add_kconfig(tcm_dir, fabric_mod_name)

	return

parser = optparse.OptionParser()
parser.add_option('-m', '--modulename', help='Module name', dest='modname',
		action='store', nargs=1, type='string')
parser.add_option('-p', '--protoident', help='Protocol Ident', dest='protoident',
		action='store', nargs=1, type='string')

(opts, args) = parser.parse_args()

mandatories = ['modname', 'protoident']
for m in mandatories:
	if not opts.__dict__[m]:
		print "mandatory option is missing\n"
		parser.print_help()
		exit(-1)

if __name__ == "__main__":

	main(str(opts.modname), opts.protoident)


code:
=========================================
The TCM v4 fabric module script generator
=========================================

Greetings all,

This document is intended to be a mini-HOWTO for using the tcm_mod_builder.py
script to generate a brand new functional TCM v4 fabric .ko module of your very own,
that once built can be immediately be loaded to start access the new TCM/ConfigFS
fabric skeleton, by simply using::

	modprobe $TCM_NEW_MOD
	mkdir -p /sys/kernel/config/target/$TCM_NEW_MOD

This script will create a new drivers/target/$TCM_NEW_MOD/, and will do the following

	1) Generate new API callers for drivers/target/target_core_fabric_configs.c logic
	   ->make_tpg(), ->drop_tpg(), ->make_wwn(), ->drop_wwn().  These are created
	   into $TCM_NEW_MOD/$TCM_NEW_MOD_configfs.c
	2) Generate basic infrastructure for loading/unloading LKMs and TCM/ConfigFS fabric module
	   using a skeleton struct target_core_fabric_ops API template.
	3) Based on user defined T10 Proto_Ident for the new fabric module being built,
	   the TransportID / Initiator and Target WWPN related handlers for
	   SPC-3 persistent reservation are automatically generated in $TCM_NEW_MOD/$TCM_NEW_MOD_fabric.c
	   using drivers/target/target_core_fabric_lib.c logic.
	4) NOP API calls for all other Data I/O path and fabric dependent attribute logic
	   in $TCM_NEW_MOD/$TCM_NEW_MOD_fabric.c

tcm_mod_builder.py depends upon the mandatory '-p $PROTO_IDENT' and '-m
$FABRIC_MOD_name' parameters, and actually running the script looks like::

  target:/mnt/sdb/lio-core-2.6.git/Documentation/target# python tcm_mod_builder.py -p iSCSI -m tcm_nab5000
  tcm_dir: /mnt/sdb/lio-core-2.6.git/Documentation/target/../../
  Set fabric_mod_name: tcm_nab5000
  Set fabric_mod_dir:
  /mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000
  Using proto_ident: iSCSI
  Creating fabric_mod_dir:
  /mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000
  Writing file:
  /mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_base.h
  Using tcm_mod_scan_fabric_ops:
  /mnt/sdb/lio-core-2.6.git/Documentation/target/../../include/target/target_core_fabric_ops.h
  Writing file:
  /mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_fabric.c
  Writing file:
  /mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_fabric.h
  Writing file:
  /mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_configfs.c
  Writing file:
  /mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/Kbuild
  Writing file:
  /mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/Kconfig
  Would you like to add tcm_nab5000to drivers/target/Kbuild..? [yes,no]: yes
  Would you like to add tcm_nab5000to drivers/target/Kconfig..? [yes,no]: yes

At the end of tcm_mod_builder.py. the script will ask to add the following
line to drivers/target/Kbuild::

	obj-$(CONFIG_TCM_NAB5000)       += tcm_nab5000/

and the same for drivers/target/Kconfig::

	source "drivers/target/tcm_nab5000/Kconfig"

#) Run 'make menuconfig' and select the new CONFIG_TCM_NAB5000 item::

	<M>   TCM_NAB5000 fabric module

#) Build using 'make modules', once completed you will have::

    target:/mnt/sdb/lio-core-2.6.git# ls -la drivers/target/tcm_nab5000/
    total 1348
    drwxr-xr-x 2 root root   4096 2010-10-05 03:23 .
    drwxr-xr-x 9 root root   4096 2010-10-05 03:22 ..
    -rw-r--r-- 1 root root    282 2010-10-05 03:22 Kbuild
    -rw-r--r-- 1 root root    171 2010-10-05 03:22 Kconfig
    -rw-r--r-- 1 root root     49 2010-10-05 03:23 modules.order
    -rw-r--r-- 1 root root    738 2010-10-05 03:22 tcm_nab5000_base.h
    -rw-r--r-- 1 root root   9096 2010-10-05 03:22 tcm_nab5000_configfs.c
    -rw-r--r-- 1 root root 191200 2010-10-05 03:23 tcm_nab5000_configfs.o
    -rw-r--r-- 1 root root  40504 2010-10-05 03:23 .tcm_nab5000_configfs.o.cmd
    -rw-r--r-- 1 root root   5414 2010-10-05 03:22 tcm_nab5000_fabric.c
    -rw-r--r-- 1 root root   2016 2010-10-05 03:22 tcm_nab5000_fabric.h
    -rw-r--r-- 1 root root 190932 2010-10-05 03:23 tcm_nab5000_fabric.o
    -rw-r--r-- 1 root root  40713 2010-10-05 03:23 .tcm_nab5000_fabric.o.cmd
    -rw-r--r-- 1 root root 401861 2010-10-05 03:23 tcm_nab5000.ko
    -rw-r--r-- 1 root root    265 2010-10-05 03:23 .tcm_nab5000.ko.cmd
    -rw-r--r-- 1 root root    459 2010-10-05 03:23 tcm_nab5000.mod.c
    -rw-r--r-- 1 root root  23896 2010-10-05 03:23 tcm_nab5000.mod.o
    -rw-r--r-- 1 root root  22655 2010-10-05 03:23 .tcm_nab5000.mod.o.cmd
    -rw-r--r-- 1 root root 379022 2010-10-05 03:23 tcm_nab5000.o
    -rw-r--r-- 1 root root    211 2010-10-05 03:23 .tcm_nab5000.o.cmd

#) Load the new module, create a lun_0 configfs group, and add new TCM Core
   IBLOCK backstore symlink to port::

    target:/mnt/sdb/lio-core-2.6.git# insmod drivers/target/tcm_nab5000.ko
    target:/mnt/sdb/lio-core-2.6.git# mkdir -p /sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0
    target:/mnt/sdb/lio-core-2.6.git# cd /sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0/
    target:/sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0# ln -s /sys/kernel/config/target/core/iblock_0/lvm_test0 nab5000_port

    target:/sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0# cd -
    target:/mnt/sdb/lio-core-2.6.git# tree /sys/kernel/config/target/nab5000/
    /sys/kernel/config/target/nab5000/
    |-- discovery_auth
    |-- iqn.foo
    |   `-- tpgt_1
    |       |-- acls
    |       |-- attrib
    |       |-- lun
    |       |   `-- lun_0
    |       |       |-- alua_tg_pt_gp
    |       |       |-- alua_tg_pt_offline
    |       |       |-- alua_tg_pt_status
    |       |       |-- alua_tg_pt_write_md
    |	|	`-- nab5000_port -> ../../../../../../target/core/iblock_0/lvm_test0
    |       |-- np
    |       `-- param
    `-- version

    target:/mnt/sdb/lio-core-2.6.git# lsmod
    Module                  Size  Used by
    tcm_nab5000             3935  4
    iscsi_target_mod      193211  0
    target_core_stgt        8090  0
    target_core_pscsi      11122  1
    target_core_file        9172  2
    target_core_iblock      9280  1
    target_core_mod       228575  31
    tcm_nab5000,iscsi_target_mod,target_core_stgt,target_core_pscsi,target_core_file,target_core_iblock
    libfc                  73681  0
    scsi_debug             56265  0
    scsi_tgt                8666  1 target_core_stgt
    configfs               20644  2 target_core_mod

----------------------------------------------------------------------

Future TODO items
=================

	1) Add more T10 proto_idents
	2) Make tcm_mod_dump_fabric_ops() smarter and generate function pointer
	   defs directly from include/target/target_core_fabric_ops.h:struct target_core_fabric_ops
	   structure members.

October 5th, 2010

Nicholas A. Bellinger <nab@linux-iscsi.org>

repo_name: angery/linux


code:
====================
TCM Userspace Design
====================

.. Contents:

   1) Design
     a) Background
     b) Benefits
     c) Design constraints
     d) Implementation overview
        i. Mailbox
        ii. Command ring
        iii. Data Area
     e) Device discovery
     f) Device events
     g) Other contingencies
   2) Writing a user pass-through handler
     a) Discovering and configuring TCMU uio devices
     b) Waiting for events on the device(s)
     c) Managing the command ring
   3) A final note

Design
======

TCM is another name for LIO, an in-kernel iSCSI target (server).
Existing TCM targets run in the kernel.  TCMU (TCM in Userspace)
allows userspace programs to be written which act as iSCSI targets.
This document describes the design.

The existing kernel provides modules for different SCSI transport
protocols.  TCM also modularizes the data storage.  There are existing
modules for file, block device, RAM or using another SCSI device as
storage.  These are called "backstores" or "storage engines".  These
built-in modules are implemented entirely as kernel code.

Background
----------

In addition to modularizing the transport protocol used for carrying
SCSI commands ("fabrics"), the Linux kernel target, LIO, also modularizes
the actual data storage as well. These are referred to as "backstores"
or "storage engines". The target comes with backstores that allow a
file, a block device, RAM, or another SCSI device to be used for the
local storage needed for the exported SCSI LUN. Like the rest of LIO,
these are implemented entirely as kernel code.

These backstores cover the most common use cases, but not all. One new
use case that other non-kernel target solutions, such as tgt, are able
to support is using Gluster's GLFS or Ceph's RBD as a backstore. The
target then serves as a translator, allowing initiators to store data
in these non-traditional networked storage systems, while still only
using standard protocols themselves.

If the target is a userspace process, supporting these is easy. tgt,
for example, needs only a small adapter module for each, because the
modules just use the available userspace libraries for RBD and GLFS.

Adding support for these backstores in LIO is considerably more
difficult, because LIO is entirely kernel code. Instead of undertaking
the significant work to port the GLFS or RBD APIs and protocols to the
kernel, another approach is to create a userspace pass-through
backstore for LIO, "TCMU".

Benefits
--------

In addition to allowing relatively easy support for RBD and GLFS, TCMU
will also allow easier development of new backstores. TCMU combines
with the LIO loopback fabric to become something similar to FUSE
(Filesystem in Userspace), but at the SCSI layer instead of the
filesystem layer. A SUSE, if you will.

The disadvantage is there are more distinct components to configure, and
potentially to malfunction. This is unavoidable, but hopefully not
fatal if we're careful to keep things as simple as possible.

Design constraints
------------------

- Good performance: high throughput, low latency
- Cleanly handle if userspace:

   1) never attaches
   2) hangs
   3) dies
   4) misbehaves

- Allow future flexibility in user & kernel implementations
- Be reasonably memory-efficient
- Simple to configure & run
- Simple to write a userspace backend

Implementation overview
-----------------------

The core of the TCMU interface is a memory region that is shared
between kernel and userspace. Within this region is: a control area
(mailbox); a lockless producer/consumer circular buffer for commands
to be passed up, and status returned; and an in/out data buffer area.

TCMU uses the pre-existing UIO subsystem. UIO allows device driver
development in userspace, and this is conceptually very close to the
TCMU use case, except instead of a physical device, TCMU implements a
memory-mapped layout designed for SCSI commands. Using UIO also
benefits TCMU by handling device introspection (e.g. a way for
userspace to determine how large the shared region is) and signaling
mechanisms in both directions.

There are no embedded pointers in the memory region. Everything is
expressed as an offset from the region's starting address. This allows
the ring to still work if the user process dies and is restarted with
the region mapped at a different virtual address.

See target_core_user.h for the struct definitions.

The Mailbox
-----------

The mailbox is always at the start of the shared memory region, and
contains a version, details about the starting offset and size of the
command ring, and head and tail pointers to be used by the kernel and
userspace (respectively) to put commands on the ring, and indicate
when the commands are completed.

version - 1 (userspace should abort if otherwise)

flags:
    - TCMU_MAILBOX_FLAG_CAP_OOOC:
	indicates out-of-order completion is supported.
	See "The Command Ring" for details.

cmdr_off
	The offset of the start of the command ring from the start
	of the memory region, to account for the mailbox size.
cmdr_size
	The size of the command ring. This does *not* need to be a
	power of two.
cmd_head
	Modified by the kernel to indicate when a command has been
	placed on the ring.
cmd_tail
	Modified by userspace to indicate when it has completed
	processing of a command.

The Command Ring
----------------

Commands are placed on the ring by the kernel incrementing
mailbox.cmd_head by the size of the command, modulo cmdr_size, and
then signaling userspace via uio_event_notify(). Once the command is
completed, userspace updates mailbox.cmd_tail in the same way and
signals the kernel via a 4-byte write(). When cmd_head equals
cmd_tail, the ring is empty -- no commands are currently waiting to be
processed by userspace.

TCMU commands are 8-byte aligned. They start with a common header
containing "len_op", a 32-bit value that stores the length, as well as
the opcode in the lowest unused bits. It also contains cmd_id and
flags fields for setting by the kernel (kflags) and userspace
(uflags).

Currently only two opcodes are defined, TCMU_OP_CMD and TCMU_OP_PAD.

When the opcode is CMD, the entry in the command ring is a struct
tcmu_cmd_entry. Userspace finds the SCSI CDB (Command Data Block) via
tcmu_cmd_entry.req.cdb_off. This is an offset from the start of the
overall shared memory region, not the entry. The data in/out buffers
are accessible via tht req.iov[] array. iov_cnt contains the number of
entries in iov[] needed to describe either the Data-In or Data-Out
buffers. For bidirectional commands, iov_cnt specifies how many iovec
entries cover the Data-Out area, and iov_bidi_cnt specifies how many
iovec entries immediately after that in iov[] cover the Data-In
area. Just like other fields, iov.iov_base is an offset from the start
of the region.

When completing a command, userspace sets rsp.scsi_status, and
rsp.sense_buffer if necessary. Userspace then increments
mailbox.cmd_tail by entry.hdr.length (mod cmdr_size) and signals the
kernel via the UIO method, a 4-byte write to the file descriptor.

If TCMU_MAILBOX_FLAG_CAP_OOOC is set for mailbox->flags, kernel is
capable of handling out-of-order completions. In this case, userspace can
handle command in different order other than original. Since kernel would
still process the commands in the same order it appeared in the command
ring, userspace need to update the cmd->id when completing the
command(a.k.a steal the original command's entry).

When the opcode is PAD, userspace only updates cmd_tail as above --
it's a no-op. (The kernel inserts PAD entries to ensure each CMD entry
is contiguous within the command ring.)

More opcodes may be added in the future. If userspace encounters an
opcode it does not handle, it must set UNKNOWN_OP bit (bit 0) in
hdr.uflags, update cmd_tail, and proceed with processing additional
commands, if any.

The Data Area
-------------

This is shared-memory space after the command ring. The organization
of this area is not defined in the TCMU interface, and userspace
should access only the parts referenced by pending iovs.

Device Discovery
----------------

Other devices may be using UIO besides TCMU. Unrelated user processes
may also be handling different sets of TCMU devices. TCMU userspace
processes must find their devices by scanning sysfs
class/uio/uio*/name. For TCMU devices, these names will be of the
format::

	tcm-user/<hba_num>/<device_name>/<subtype>/<path>

where "tcm-user" is common for all TCMU-backed UIO devices. <hba_num>
and <device_name> allow userspace to find the device's path in the
kernel target's configfs tree. Assuming the usual mount point, it is
found at::

	/sys/kernel/config/target/core/user_<hba_num>/<device_name>

This location contains attributes such as "hw_block_size", that
userspace needs to know for correct operation.

<subtype> will be a userspace-process-unique string to identify the
TCMU device as expecting to be backed by a certain handler, and <path>
will be an additional handler-specific string for the user process to
configure the device, if needed. The name cannot contain ':', due to
LIO limitations.

For all devices so discovered, the user handler opens /dev/uioX and
calls mmap()::

	mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)

where size must be equal to the value read from
/sys/class/uio/uioX/maps/map0/size.

Device Events
-------------

If a new device is added or removed, a notification will be broadcast
over netlink, using a generic netlink family name of "TCM-USER" and a
multicast group named "config". This will include the UIO name as
described in the previous section, as well as the UIO minor
number. This should allow userspace to identify both the UIO device and
the LIO device, so that after determining the device is supported
(based on subtype) it can take the appropriate action.

Other contingencies
-------------------

Userspace handler process never attaches:

- TCMU will post commands, and then abort them after a timeout period
  (30 seconds.)

Userspace handler process is killed:

- It is still possible to restart and re-connect to TCMU
  devices. Command ring is preserved. However, after the timeout period,
  the kernel will abort pending tasks.

Userspace handler process hangs:

- The kernel will abort pending tasks after a timeout period.

Userspace handler process is malicious:

- The process can trivially break the handling of devices it controls,
  but should not be able to access kernel memory outside its shared
  memory areas.

Writing a user pass-through handler (with example code)
=======================================================

A user process handing a TCMU device must support the following:

a) Discovering and configuring TCMU uio devices
b) Waiting for events on the device(s)
c) Managing the command ring: Parsing operations and commands,
   performing work as needed, setting response fields (scsi_status and
   possibly sense_buffer), updating cmd_tail, and notifying the kernel
   that work has been finished

First, consider instead writing a plugin for tcmu-runner. tcmu-runner
implements all of this, and provides a higher-level API for plugin
authors.

TCMU is designed so that multiple unrelated processes can manage TCMU
devices separately. All handlers should make sure to only open their
devices, based opon a known subtype string.

a) Discovering and configuring TCMU UIO devices::

      /* error checking omitted for brevity */

      int fd, dev_fd;
      char buf[256];
      unsigned long long map_len;
      void *map;

      fd = open("/sys/class/uio/uio0/name", O_RDONLY);
      ret = read(fd, buf, sizeof(buf));
      close(fd);
      buf[ret-1] = '\0'; /* null-terminate and chop off the \n */

      /* we only want uio devices whose name is a format we expect */
      if (strncmp(buf, "tcm-user", 8))
	exit(-1);

      /* Further checking for subtype also needed here */

      fd = open(/sys/class/uio/%s/maps/map0/size, O_RDONLY);
      ret = read(fd, buf, sizeof(buf));
      close(fd);
      str_buf[ret-1] = '\0'; /* null-terminate and chop off the \n */

      map_len = strtoull(buf, NULL, 0);

      dev_fd = open("/dev/uio0", O_RDWR);
      map = mmap(NULL, map_len, PROT_READ|PROT_WRITE, MAP_SHARED, dev_fd, 0);

      b) Waiting for events on the device(s)

      while (1) {
        char buf[4];

        int ret = read(dev_fd, buf, 4); /* will block */

        handle_device_events(dev_fd, map);
      }

c) Managing the command ring::

      #include <linux/target_core_user.h>

      int handle_device_events(int fd, void *map)
      {
        struct tcmu_mailbox *mb = map;
        struct tcmu_cmd_entry *ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
        int did_some_work = 0;

        /* Process events from cmd ring until we catch up with cmd_head */
        while (ent != (void *)mb + mb->cmdr_off + mb->cmd_head) {

          if (tcmu_hdr_get_op(ent->hdr.len_op) == TCMU_OP_CMD) {
            uint8_t *cdb = (void *)mb + ent->req.cdb_off;
            bool success = true;

            /* Handle command here. */
            printf("SCSI opcode: 0x%x\n", cdb[0]);

            /* Set response fields */
            if (success)
              ent->rsp.scsi_status = SCSI_NO_SENSE;
            else {
              /* Also fill in rsp->sense_buffer here */
              ent->rsp.scsi_status = SCSI_CHECK_CONDITION;
            }
          }
          else if (tcmu_hdr_get_op(ent->hdr.len_op) != TCMU_OP_PAD) {
            /* Tell the kernel we didn't handle unknown opcodes */
            ent->hdr.uflags |= TCMU_UFLAG_UNKNOWN_OP;
          }
          else {
            /* Do nothing for PAD entries except update cmd_tail */
          }

          /* update cmd_tail */
          mb->cmd_tail = (mb->cmd_tail + tcmu_hdr_get_len(&ent->hdr)) % mb->cmdr_size;
          ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
          did_some_work = 1;
        }

        /* Notify the kernel that work has been finished */
        if (did_some_work) {
          uint32_t buf = 0;

          write(fd, &buf, 4);
        }

        return 0;
      }

A final note
============

Please be careful to return codes as defined by the SCSI
specifications. These are different than some values defined in the
scsi/scsi.h include file. For example, CHECK CONDITION's status code
is 2, not 1.


code:
=====================================================
High resolution timers and dynamic ticks design notes
=====================================================

Further information can be found in the paper of the OLS 2006 talk "hrtimers
and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can
be found on the OLS website:
https://www.kernel.org/doc/ols/2006/ols2006v1-pages-333-346.pdf

The slides to this talk are available from:
http://www.cs.columbia.edu/~nahum/w6998/papers/ols2006-hrtimers-slides.pdf

The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the
changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the
design of the Linux time(r) system before hrtimers and other building blocks
got merged into mainline.

Note: the paper and the slides are talking about "clock event source", while we
switched to the name "clock event devices" in meantime.

The design contains the following basic building blocks:

- hrtimer base infrastructure
- timeofday and clock source management
- clock event management
- high resolution timer functionality
- dynamic ticks

hrtimer base infrastructure
---------------------------

The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
the base implementation are covered in Documentation/timers/hrtimers.rst. See
also figure #2 (OLS slides p. 15)

The main differences to the timer wheel, which holds the armed timer_list type
timers are:

       - time ordered enqueueing into a rb-tree
       - independent of ticks (the processing is based on nanoseconds)

timeofday and clock source management
-------------------------------------

John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of
code out of the architecture-specific areas into a generic management
framework, as illustrated in figure #3 (OLS slides p. 18). The architecture
specific portion is reduced to the low level hardware details of the clock
sources, which are registered in the framework and selected on a quality based
decision. The low level code provides hardware setup and readout routines and
initializes data structures, which are used by the generic time keeping code to
convert the clock ticks to nanosecond based time values. All other time keeping
related functionality is moved into the generic code. The GTOD base patch got
merged into the 2.6.18 kernel.

Further information about the Generic Time Of Day framework is available in the
OLS 2005 Proceedings Volume 1:

	http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf

The paper "We Are Not Getting Any Younger: A New Approach to Time and
Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan.

Figure #3 (OLS slides p.18) illustrates the transformation.

clock event management
----------------------

While clock sources provide read access to the monotonically increasing time
value, clock event devices are used to schedule the next event
interrupt(s). The next event is currently defined to be periodic, with its
period defined at compile time. The setup and selection of the event device
for various event driven functionalities is hardwired into the architecture
dependent code. This results in duplicated code across all architectures and
makes it extremely difficult to change the configuration of the system to use
event interrupt devices other than those already built into the
architecture. Another implication of the current design is that it is necessary
to touch all the architecture-specific implementations in order to provide new
functionality like high resolution timers or dynamic ticks.

The clock events subsystem tries to address this problem by providing a generic
solution to manage clock event devices and their usage for the various clock
event driven kernel functionalities. The goal of the clock event subsystem is
to minimize the clock event related architecture dependent code to the pure
hardware related handling and to allow easy addition and utilization of new
clock event devices. It also minimizes the duplicated code across the
architectures as it provides generic functionality down to the interrupt
service handler, which is almost inherently hardware dependent.

Clock event devices are registered either by the architecture dependent boot
code or at module insertion time. Each clock event device fills a data
structure with clock-specific property parameters and callback functions. The
clock event management decides, by using the specified property parameters, the
set of system functions a clock event device will be used to support. This
includes the distinction of per-CPU and per-system global event devices.

System-level global event devices are used for the Linux periodic tick. Per-CPU
event devices are used to provide local CPU functionality such as process
accounting, profiling, and high resolution timers.

The management layer assigns one or more of the following functions to a clock
event device:

      - system global periodic tick (jiffies update)
      - cpu local update_process_times
      - cpu local profiling
      - cpu local next event interrupt (non periodic mode)

The clock event device delegates the selection of those timer interrupt related
functions completely to the management layer. The clock management layer stores
a function pointer in the device description structure, which has to be called
from the hardware level handler. This removes a lot of duplicated code from the
architecture specific timer interrupt handlers and hands the control over the
clock event devices and the assignment of timer interrupt related functionality
to the core code.

The clock event layer API is rather small. Aside from the clock event device
registration interface it provides functions to schedule the next event
interrupt, clock event device notification service and support for suspend and
resume.

The framework adds about 700 lines of code which results in a 2KB increase of
the kernel binary size. The conversion of i386 removes about 100 lines of
code. The binary size decrease is in the range of 400 byte. We believe that the
increase of flexibility and the avoidance of duplicated code across
architectures justifies the slight increase of the binary size.

The conversion of an architecture has no functional impact, but allows to
utilize the high resolution and dynamic tick functionalities without any change
to the clock event device and timer interrupt code. After the conversion the
enabling of high resolution timers and dynamic ticks is simply provided by
adding the kernel/time/Kconfig file to the architecture specific Kconfig and
adding the dynamic tick specific calls to the idle routine (a total of 3 lines
added to the idle function and the Kconfig file)

Figure #4 (OLS slides p.20) illustrates the transformation.

high resolution timer functionality
-----------------------------------

During system boot it is not possible to use the high resolution timer
functionality, while making it possible would be difficult and would serve no
useful function. The initialization of the clock event device framework, the
clock source framework (GTOD) and hrtimers itself has to be done and
appropriate clock sources and clock event devices have to be registered before
the high resolution functionality can work. Up to the point where hrtimers are
initialized, the system works in the usual low resolution periodic mode. The
clock source and the clock event device layers provide notification functions
which inform hrtimers about availability of new hardware. hrtimers validates
the usability of the registered clock sources and clock event devices before
switching to high resolution mode. This ensures also that a kernel which is
configured for high resolution timers can run on a system which lacks the
necessary hardware support.

The high resolution timer code does not support SMP machines which have only
global clock event devices. The support of such hardware would involve IPI
calls when an interrupt happens. The overhead would be much larger than the
benefit. This is the reason why we currently disable high resolution and
dynamic ticks on i386 SMP systems which stop the local APIC in C3 power
state. A workaround is available as an idea, but the problem has not been
tackled yet.

The time ordered insertion of timers provides all the infrastructure to decide
whether the event device has to be reprogrammed when a timer is added. The
decision is made per timer base and synchronized across per-cpu timer bases in
a support function. The design allows the system to utilize separate per-CPU
clock event devices for the per-CPU timer bases, but currently only one
reprogrammable clock event device per-CPU is utilized.

When the timer interrupt happens, the next event interrupt handler is called
from the clock event distribution code and moves expired timers from the
red-black tree to a separate double linked list and invokes the softirq
handler. An additional mode field in the hrtimer structure allows the system to
execute callback functions directly from the next event interrupt handler. This
is restricted to code which can safely be executed in the hard interrupt
context. This applies, for example, to the common case of a wakeup function as
used by nanosleep. The advantage of executing the handler in the interrupt
context is the avoidance of up to two context switches - from the interrupted
context to the softirq and to the task which is woken up by the expired
timer.

Once a system has switched to high resolution mode, the periodic tick is
switched off. This disables the per system global periodic clock event device -
e.g. the PIT on i386 SMP systems.

The periodic tick functionality is provided by an per-cpu hrtimer. The callback
function is executed in the next event interrupt context and updates jiffies
and calls update_process_times and profiling. The implementation of the hrtimer
based periodic tick is designed to be extended with dynamic tick functionality.
This allows to use a single clock event device to schedule high resolution
timer and periodic events (jiffies tick, profiling, process accounting) on UP
systems. This has been proved to work with the PIT on i386 and the Incrementer
on PPC.

The softirq for running the hrtimer queues and executing the callbacks has been
separated from the tick bound timer softirq to allow accurate delivery of high
resolution timer signals which are used by itimer and POSIX interval
timers. The execution of this softirq can still be delayed by other softirqs,
but the overall latencies have been significantly improved by this separation.

Figure #5 (OLS slides p.22) illustrates the transformation.

dynamic ticks
-------------

Dynamic ticks are the logical consequence of the hrtimer based periodic tick
replacement (sched_tick). The functionality of the sched_tick hrtimer is
extended by three functions:

- hrtimer_stop_sched_tick
- hrtimer_restart_sched_tick
- hrtimer_update_jiffies

hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code
evaluates the next scheduled timer event (from both hrtimers and the timer
wheel) and in case that the next event is further away than the next tick it
reprograms the sched_tick to this future event, to allow longer idle sleeps
without worthless interruption by the periodic tick. The function is also
called when an interrupt happens during the idle period, which does not cause a
reschedule. The call is necessary as the interrupt handler might have armed a
new timer whose expiry time is before the time which was identified as the
nearest event in the previous call to hrtimer_stop_sched_tick.

hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before
it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick,
which is kept active until the next call to hrtimer_stop_sched_tick().

hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens
in the idle period to make sure that jiffies are up to date and the interrupt
handler has not to deal with an eventually stale jiffy value.

The dynamic tick feature provides statistical values which are exported to
userspace via /proc/stat and can be made available for enhanced power
management control.

The implementation leaves room for further development like full tickless
systems, where the time slice is controlled by the scheduler, variable
frequency profiling, and a complete removal of jiffies in the future.

Aside the current initial submission of i386 support, the patchset has been
extended to x86_64 and ARM already. Initial (work in progress) support is also
available for MIPS and PowerPC.

	  Thomas, Ingo


code:
===========================================
High Precision Event Timer Driver for Linux
===========================================

The High Precision Event Timer (HPET) hardware follows a specification
by Intel and Microsoft, revision 1.

Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision")
and up to 32 comparators.  Normally three or more comparators are provided,
each of which can generate oneshot interrupts and at least one of which has
additional hardware to support periodic interrupts.  The comparators are
also called "timers", which can be misleading since usually timers are
independent of each other ... these share a counter, complicating resets.

HPET devices can support two interrupt routing modes.  In one mode, the
comparators are additional interrupt sources with no particular system
role.  Many x86 BIOS writers don't route HPET interrupts at all, which
prevents use of that mode.  They support the other "legacy replacement"
mode where the first two comparators block interrupts from 8254 timers
and from the RTC.

The driver supports detection of HPET driver allocation and initialization
of the HPET before the driver module_init routine is called.  This enables
platform code which uses timer 0 or 1 as the main timer to intercept HPET
initialization.  An example of this initialization can be found in
arch/x86/kernel/hpet.c.

The driver provides a userspace API which resembles the API found in the
RTC driver framework.  An example user space program is provided in
file:samples/timers/hpet_example.c


code:
======================================================
hrtimers - subsystem for high-resolution kernel timers
======================================================

This patch introduces a new subsystem for high-resolution kernel timers.

One might ask the question: we already have a timer subsystem
(kernel/timers.c), why do we need two timer subsystems? After a lot of
back and forth trying to integrate high-resolution and high-precision
features into the existing timer framework, and after testing various
such high-resolution timer implementations in practice, we came to the
conclusion that the timer wheel code is fundamentally not suitable for
such an approach. We initially didn't believe this ('there must be a way
to solve this'), and spent a considerable effort trying to integrate
things into the timer wheel, but we failed. In hindsight, there are
several reasons why such integration is hard/impossible:

- the forced handling of low-resolution and high-resolution timers in
  the same way leads to a lot of compromises, macro magic and #ifdef
  mess. The timers.c code is very "tightly coded" around jiffies and
  32-bitness assumptions, and has been honed and micro-optimized for a
  relatively narrow use case (jiffies in a relatively narrow HZ range)
  for many years - and thus even small extensions to it easily break
  the wheel concept, leading to even worse compromises. The timer wheel
  code is very good and tight code, there's zero problems with it in its
  current usage - but it is simply not suitable to be extended for
  high-res timers.

- the unpredictable [O(N)] overhead of cascading leads to delays which
  necessitate a more complex handling of high resolution timers, which
  in turn decreases robustness. Such a design still leads to rather large
  timing inaccuracies. Cascading is a fundamental property of the timer
  wheel concept, it cannot be 'designed out' without inevitably
  degrading other portions of the timers.c code in an unacceptable way.

- the implementation of the current posix-timer subsystem on top of
  the timer wheel has already introduced a quite complex handling of
  the required readjusting of absolute CLOCK_REALTIME timers at
  settimeofday or NTP time - further underlying our experience by
  example: that the timer wheel data structure is too rigid for high-res
  timers.

- the timer wheel code is most optimal for use cases which can be
  identified as "timeouts". Such timeouts are usually set up to cover
  error conditions in various I/O paths, such as networking and block
  I/O. The vast majority of those timers never expire and are rarely
  recascaded because the expected correct event arrives in time so they
  can be removed from the timer wheel before any further processing of
  them becomes necessary. Thus the users of these timeouts can accept
  the granularity and precision tradeoffs of the timer wheel, and
  largely expect the timer subsystem to have near-zero overhead.
  Accurate timing for them is not a core purpose - in fact most of the
  timeout values used are ad-hoc. For them it is at most a necessary
  evil to guarantee the processing of actual timeout completions
  (because most of the timeouts are deleted before completion), which
  should thus be as cheap and unintrusive as possible.

The primary users of precision timers are user-space applications that
utilize nanosleep, posix-timers and itimer interfaces. Also, in-kernel
users like drivers and subsystems which require precise timed events
(e.g. multimedia) can benefit from the availability of a separate
high-resolution timer subsystem as well.

While this subsystem does not offer high-resolution clock sources just
yet, the hrtimer subsystem can be easily extended with high-resolution
clock capabilities, and patches for that exist and are maturing quickly.
The increasing demand for realtime and multimedia applications along
with other potential users for precise timers gives another reason to
separate the "timeout" and "precise timer" subsystems.

Another potential benefit is that such a separation allows even more
special-purpose optimization of the existing timer wheel for the low
resolution and low precision use cases - once the precision-sensitive
APIs are separated from the timer wheel and are migrated over to
hrtimers. E.g. we could decrease the frequency of the timeout subsystem
from 250 Hz to 100 HZ (or even smaller).

hrtimer subsystem implementation details
----------------------------------------

the basic design considerations were:

- simplicity

- data structure not bound to jiffies or any other granularity. All the
  kernel logic works at 64-bit nanoseconds resolution - no compromises.

- simplification of existing, timing related kernel code

another basic requirement was the immediate enqueueing and ordering of
timers at activation time. After looking at several possible solutions
such as radix trees and hashes, we chose the red black tree as the basic
data structure. Rbtrees are available as a library in the kernel and are
used in various performance-critical areas of e.g. memory management and
file systems. The rbtree is solely used for time sorted ordering, while
a separate list is used to give the expiry code fast access to the
queued timers, without having to walk the rbtree.

(This separate list is also useful for later when we'll introduce
high-resolution clocks, where we need separate pending and expired
queues while keeping the time-order intact.)

Time-ordered enqueueing is not purely for the purposes of
high-resolution clocks though, it also simplifies the handling of
absolute timers based on a low-resolution CLOCK_REALTIME. The existing
implementation needed to keep an extra list of all armed absolute
CLOCK_REALTIME timers along with complex locking. In case of
settimeofday and NTP, all the timers (!) had to be dequeued, the
time-changing code had to fix them up one by one, and all of them had to
be enqueued again. The time-ordered enqueueing and the storage of the
expiry time in absolute time units removes all this complex and poorly
scaling code from the posix-timer implementation - the clock can simply
be set without having to touch the rbtree. This also makes the handling
of posix-timers simpler in general.

The locking and per-CPU behavior of hrtimers was mostly taken from the
existing timer wheel code, as it is mature and well suited. Sharing code
was not really a win, due to the different data structures. Also, the
hrtimer functions now have clearer behavior and clearer names - such as
hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
equivalent to timer_delete() and timer_delete_sync()] - so there's no direct
1:1 mapping between them on the algorithmic level, and thus no real
potential for code sharing either.

Basic data types: every time value, absolute or relative, is in a
special nanosecond-resolution type: ktime_t. The kernel-internal
representation of ktime_t values and operations is implemented via
macros and inline functions, and can be switched between a "hybrid
union" type and a plain "scalar" 64bit nanoseconds representation (at
compile time). The hybrid union type optimizes time conversions on 32bit
CPUs. This build-time-selectable ktime_t storage format was implemented
to avoid the performance impact of 64-bit multiplications and divisions
on 32bit CPUs. Such operations are frequently necessary to convert
between the storage formats provided by kernel and userspace interfaces
and the internal time format. (See include/linux/ktime.h for further
details.)

hrtimers - rounding of timer values
-----------------------------------

the hrtimer code will round timer events to lower-resolution clocks
because it has to. Otherwise it will do no artificial rounding at all.

one question is, what resolution value should be returned to the user by
the clock_getres() interface. This will return whatever real resolution
a given clock has - be it low-res, high-res, or artificially-low-res.

hrtimers - testing and verification
-----------------------------------

We used the high-resolution clock subsystem ontop of hrtimers to verify
the hrtimer implementation details in praxis, and we also ran the posix
timer tests in order to ensure specification compliance. We also ran
tests on low-resolution clocks.

The hrtimer patch converts the following kernel functionality to use
hrtimers:

 - nanosleep
 - itimers
 - posix-timers

The conversion of nanosleep and posix-timers enabled the unification of
nanosleep and clock_nanosleep.

The code was successfully compiled for the following platforms:

 i386, x86_64, ARM, PPC, PPC64, IA64

The code was run-tested on the following platforms:

 i386(UP/SMP), x86_64(UP/SMP), ARM, PPC

hrtimers were also integrated into the -rt tree, along with a
hrtimers-based high-resolution clock implementation, so the hrtimers
code got a healthy amount of testing and use in practice.

	Thomas Gleixner, Ingo Molnar


code:
.. SPDX-License-Identifier: GPL-2.0

======
timers
======

.. toctree::
    :maxdepth: 1

    highres
    hpet
    hrtimers
    no_hz
    timekeeping
    timers-howto

.. only::  subproject and html

   Indices
   =======

   * :ref:`genindex`


code:
======================================
NO_HZ: Reducing Scheduling-Clock Ticks
======================================

This document describes Kconfig options and boot parameters that can
reduce the number of scheduling-clock interrupts, thereby improving energy
efficiency and reducing OS jitter.  Reducing OS jitter is important for
some types of computationally intensive high-performance computing (HPC)
applications and for real-time applications.

There are three main ways of managing scheduling-clock interrupts
(also known as "scheduling-clock ticks" or simply "ticks"):

1.	Never omit scheduling-clock ticks (CONFIG_HZ_PERIODIC=y or
	CONFIG_NO_HZ=n for older kernels).  You normally will -not-
	want to choose this option.

2.	Omit scheduling-clock ticks on idle CPUs (CONFIG_NO_HZ_IDLE=y or
	CONFIG_NO_HZ=y for older kernels).  This is the most common
	approach, and should be the default.

3.	Omit scheduling-clock ticks on CPUs that are either idle or that
	have only one runnable task (CONFIG_NO_HZ_FULL=y).  Unless you
	are running realtime applications or certain types of HPC
	workloads, you will normally -not- want this option.

These three cases are described in the following three sections, followed
by a third section on RCU-specific considerations, a fourth section
discussing testing, and a fifth and final section listing known issues.

Never Omit Scheduling-Clock Ticks
=================================

Very old versions of Linux from the 1990s and the very early 2000s
are incapable of omitting scheduling-clock ticks.  It turns out that
there are some situations where this old-school approach is still the
right approach, for example, in heavy workloads with lots of tasks
that use short bursts of CPU, where there are very frequent idle
periods, but where these idle periods are also quite short (tens or
hundreds of microseconds).  For these types of workloads, scheduling
clock interrupts will normally be delivered any way because there
will frequently be multiple runnable tasks per CPU.  In these cases,
attempting to turn off the scheduling clock interrupt will have no effect
other than increasing the overhead of switching to and from idle and
transitioning between user and kernel execution.

This mode of operation can be selected using CONFIG_HZ_PERIODIC=y (or
CONFIG_NO_HZ=n for older kernels).

However, if you are instead running a light workload with long idle
periods, failing to omit scheduling-clock interrupts will result in
excessive power consumption.  This is especially bad on battery-powered
devices, where it results in extremely short battery lifetimes.  If you
are running light workloads, you should therefore read the following
section.

In addition, if you are running either a real-time workload or an HPC
workload with short iterations, the scheduling-clock interrupts can
degrade your applications performance.  If this describes your workload,
you should read the following two sections.

Omit Scheduling-Clock Ticks For Idle CPUs
=========================================

If a CPU is idle, there is little point in sending it a scheduling-clock
interrupt.  After all, the primary purpose of a scheduling-clock interrupt
is to force a busy CPU to shift its attention among multiple duties,
and an idle CPU has no duties to shift its attention among.

An idle CPU that is not receiving scheduling-clock interrupts is said to
be "dyntick-idle", "in dyntick-idle mode", "in nohz mode", or "running
tickless".  The remainder of this document will use "dyntick-idle mode".

The CONFIG_NO_HZ_IDLE=y Kconfig option causes the kernel to avoid sending
scheduling-clock interrupts to idle CPUs, which is critically important
both to battery-powered devices and to highly virtualized mainframes.
A battery-powered device running a CONFIG_HZ_PERIODIC=y kernel would
drain its battery very quickly, easily 2-3 times as fast as would the
same device running a CONFIG_NO_HZ_IDLE=y kernel.  A mainframe running
1,500 OS instances might find that half of its CPU time was consumed by
unnecessary scheduling-clock interrupts.  In these situations, there
is strong motivation to avoid sending scheduling-clock interrupts to
idle CPUs.  That said, dyntick-idle mode is not free:

1.	It increases the number of instructions executed on the path
	to and from the idle loop.

2.	On many architectures, dyntick-idle mode also increases the
	number of expensive clock-reprogramming operations.

Therefore, systems with aggressive real-time response constraints often
run CONFIG_HZ_PERIODIC=y kernels (or CONFIG_NO_HZ=n for older kernels)
in order to avoid degrading from-idle transition latencies.

There is also a boot parameter "nohz=" that can be used to disable
dyntick-idle mode in CONFIG_NO_HZ_IDLE=y kernels by specifying "nohz=off".
By default, CONFIG_NO_HZ_IDLE=y kernels boot with "nohz=on", enabling
dyntick-idle mode.

Omit Scheduling-Clock Ticks For CPUs With Only One Runnable Task
================================================================

If a CPU has only one runnable task, there is little point in sending it
a scheduling-clock interrupt because there is no other task to switch to.
Note that omitting scheduling-clock ticks for CPUs with only one runnable
task implies also omitting them for idle CPUs.

The CONFIG_NO_HZ_FULL=y Kconfig option causes the kernel to avoid
sending scheduling-clock interrupts to CPUs with a single runnable task,
and such CPUs are said to be "adaptive-ticks CPUs".  This is important
for applications with aggressive real-time response constraints because
it allows them to improve their worst-case response times by the maximum
duration of a scheduling-clock interrupt.  It is also important for
computationally intensive short-iteration workloads:  If any CPU is
delayed during a given iteration, all the other CPUs will be forced to
wait idle while the delayed CPU finishes.  Thus, the delay is multiplied
by one less than the number of CPUs.  In these situations, there is
again strong motivation to avoid sending scheduling-clock interrupts.

By default, no CPU will be an adaptive-ticks CPU.  The "nohz_full="
boot parameter specifies the adaptive-ticks CPUs.  For example,
"nohz_full=1,6-8" says that CPUs 1, 6, 7, and 8 are to be adaptive-ticks
CPUs.  Note that you are prohibited from marking all of the CPUs as
adaptive-tick CPUs:  At least one non-adaptive-tick CPU must remain
online to handle timekeeping tasks in order to ensure that system
calls like gettimeofday() returns accurate values on adaptive-tick CPUs.
(This is not an issue for CONFIG_NO_HZ_IDLE=y because there are no running
user processes to observe slight drifts in clock rate.)  Therefore, the
boot CPU is prohibited from entering adaptive-ticks mode.  Specifying a
"nohz_full=" mask that includes the boot CPU will result in a boot-time
error message, and the boot CPU will be removed from the mask.  Note that
this means that your system must have at least two CPUs in order for
CONFIG_NO_HZ_FULL=y to do anything for you.

Finally, adaptive-ticks CPUs must have their RCU callbacks offloaded.
This is covered in the "RCU IMPLICATIONS" section below.

Normally, a CPU remains in adaptive-ticks mode as long as possible.
In particular, transitioning to kernel mode does not automatically change
the mode.  Instead, the CPU will exit adaptive-ticks mode only if needed,
for example, if that CPU enqueues an RCU callback.

Just as with dyntick-idle mode, the benefits of adaptive-tick mode do
not come for free:

1.	CONFIG_NO_HZ_FULL selects CONFIG_NO_HZ_COMMON, so you cannot run
	adaptive ticks without also running dyntick idle.  This dependency
	extends down into the implementation, so that all of the costs
	of CONFIG_NO_HZ_IDLE are also incurred by CONFIG_NO_HZ_FULL.

2.	The user/kernel transitions are slightly more expensive due
	to the need to inform kernel subsystems (such as RCU) about
	the change in mode.

3.	POSIX CPU timers prevent CPUs from entering adaptive-tick mode.
	Real-time applications needing to take actions based on CPU time
	consumption need to use other means of doing so.

4.	If there are more perf events pending than the hardware can
	accommodate, they are normally round-robined so as to collect
	all of them over time.  Adaptive-tick mode may prevent this
	round-robining from happening.  This will likely be fixed by
	preventing CPUs with large numbers of perf events pending from
	entering adaptive-tick mode.

5.	Scheduler statistics for adaptive-tick CPUs may be computed
	slightly differently than those for non-adaptive-tick CPUs.
	This might in turn perturb load-balancing of real-time tasks.

Although improvements are expected over time, adaptive ticks is quite
useful for many types of real-time and compute-intensive applications.
However, the drawbacks listed above mean that adaptive ticks should not
(yet) be enabled by default.

RCU Implications
================

There are situations in which idle CPUs cannot be permitted to
enter either dyntick-idle mode or adaptive-tick mode, the most
common being when that CPU has RCU callbacks pending.

Avoid this by offloading RCU callback processing to "rcuo" kthreads
using the CONFIG_RCU_NOCB_CPU=y Kconfig option.  The specific CPUs to
offload may be selected using The "rcu_nocbs=" kernel boot parameter,
which takes a comma-separated list of CPUs and CPU ranges, for example,
"1,3-5" selects CPUs 1, 3, 4, and 5.  Note that CPUs specified by
the "nohz_full" kernel boot parameter are also offloaded.

The offloaded CPUs will never queue RCU callbacks, and therefore RCU
never prevents offloaded CPUs from entering either dyntick-idle mode
or adaptive-tick mode.  That said, note that it is up to userspace to
pin the "rcuo" kthreads to specific CPUs if desired.  Otherwise, the
scheduler will decide where to run them, which might or might not be
where you want them to run.

Testing
=======

So you enable all the OS-jitter features described in this document,
but do not see any change in your workload's behavior.  Is this because
your workload isn't affected that much by OS jitter, or is it because
something else is in the way?  This section helps answer this question
by providing a simple OS-jitter test suite, which is available on branch
master of the following git archive:

git://git.kernel.org/pub/scm/linux/kernel/git/frederic/dynticks-testing.git

Clone this archive and follow the instructions in the README file.
This test procedure will produce a trace that will allow you to evaluate
whether or not you have succeeded in removing OS jitter from your system.
If this trace shows that you have removed OS jitter as much as is
possible, then you can conclude that your workload is not all that
sensitive to OS jitter.

Note: this test requires that your system have at least two CPUs.
We do not currently have a good way to remove OS jitter from single-CPU
systems.

Known Issues
============

*	Dyntick-idle slows transitions to and from idle slightly.
	In practice, this has not been a problem except for the most
	aggressive real-time workloads, which have the option of disabling
	dyntick-idle mode, an option that most of them take.  However,
	some workloads will no doubt want to use adaptive ticks to
	eliminate scheduling-clock interrupt latencies.  Here are some
	options for these workloads:

	a.	Use PMQOS from userspace to inform the kernel of your
		latency requirements (preferred).

	b.	On x86 systems, use the "idle=mwait" boot parameter.

	c.	On x86 systems, use the "intel_idle.max_cstate=" to limit
	`	the maximum C-state depth.

	d.	On x86 systems, use the "idle=poll" boot parameter.
		However, please note that use of this parameter can cause
		your CPU to overheat, which may cause thermal throttling
		to degrade your latencies -- and that this degradation can
		be even worse than that of dyntick-idle.  Furthermore,
		this parameter effectively disables Turbo Mode on Intel
		CPUs, which can significantly reduce maximum performance.

*	Adaptive-ticks slows user/kernel transitions slightly.
	This is not expected to be a problem for computationally intensive
	workloads, which have few such transitions.  Careful benchmarking
	will be required to determine whether or not other workloads
	are significantly affected by this effect.

*	Adaptive-ticks does not do anything unless there is only one
	runnable task for a given CPU, even though there are a number
	of other situations where the scheduling-clock tick is not
	needed.  To give but one example, consider a CPU that has one
	runnable high-priority SCHED_FIFO task and an arbitrary number
	of low-priority SCHED_OTHER tasks.  In this case, the CPU is
	required to run the SCHED_FIFO task until it either blocks or
	some other higher-priority task awakens on (or is assigned to)
	this CPU, so there is no point in sending a scheduling-clock
	interrupt to this CPU.	However, the current implementation
	nevertheless sends scheduling-clock interrupts to CPUs having a
	single runnable SCHED_FIFO task and multiple runnable SCHED_OTHER
	tasks, even though these interrupts are unnecessary.

	And even when there are multiple runnable tasks on a given CPU,
	there is little point in interrupting that CPU until the current
	running task's timeslice expires, which is almost always way
	longer than the time of the next scheduling-clock interrupt.

	Better handling of these sorts of situations is future work.

*	A reboot is required to reconfigure both adaptive idle and RCU
	callback offloading.  Runtime reconfiguration could be provided
	if needed, however, due to the complexity of reconfiguring RCU at
	runtime, there would need to be an earthshakingly good reason.
	Especially given that you have the straightforward option of
	simply offloading RCU callbacks from all CPUs and pinning them
	where you want them whenever you want them pinned.

*	Additional configuration is required to deal with other sources
	of OS jitter, including interrupts and system-utility tasks
	and processes.  This configuration normally involves binding
	interrupts and tasks to particular CPUs.

*	Some sources of OS jitter can currently be eliminated only by
	constraining the workload.  For example, the only way to eliminate
	OS jitter due to global TLB shootdowns is to avoid the unmapping
	operations (such as kernel module unload operations) that
	result in these shootdowns.  For another example, page faults
	and TLB misses can be reduced (and in some cases eliminated) by
	using huge pages and by constraining the amount of memory used
	by the application.  Pre-faulting the working set can also be
	helpful, especially when combined with the mlock() and mlockall()
	system calls.

*	Unless all CPUs are idle, at least one CPU must keep the
	scheduling-clock interrupt going in order to support accurate
	timekeeping.

*	If there might potentially be some adaptive-ticks CPUs, there
	will be at least one CPU keeping the scheduling-clock interrupt
	going, even if all CPUs are otherwise idle.

	Better handling of this situation is ongoing work.

*	Some process-handling operations still require the occasional
	scheduling-clock tick.	These operations include calculating CPU
	load, maintaining sched average, computing CFS entity vruntime,
	computing avenrun, and carrying out load balancing.  They are
	currently accommodated by scheduling-clock tick every second
	or so.	On-going work will eliminate the need even for these
	infrequent scheduling-clock ticks.


code:
===========================================================
Clock sources, Clock events, sched_clock() and delay timers
===========================================================

This document tries to briefly explain some basic kernel timekeeping
abstractions. It partly pertains to the drivers usually found in
drivers/clocksource in the kernel tree, but the code may be spread out
across the kernel.

If you grep through the kernel source you will find a number of architecture-
specific implementations of clock sources, clockevents and several likewise
architecture-specific overrides of the sched_clock() function and some
delay timers.

To provide timekeeping for your platform, the clock source provides
the basic timeline, whereas clock events shoot interrupts on certain points
on this timeline, providing facilities such as high-resolution timers.
sched_clock() is used for scheduling and timestamping, and delay timers
provide an accurate delay source using hardware counters.

Clock sources
-------------

The purpose of the clock source is to provide a timeline for the system that
tells you where you are in time. For example issuing the command 'date' on
a Linux system will eventually read the clock source to determine exactly
what time it is.

Typically the clock source is a monotonic, atomic counter which will provide
n bits which count from 0 to (2^n)-1 and then wraps around to 0 and start over.
It will ideally NEVER stop ticking as long as the system is running. It
may stop during system suspend.

The clock source shall have as high resolution as possible, and the frequency
shall be as stable and correct as possible as compared to a real-world wall
clock. It should not move unpredictably back and forth in time or miss a few
cycles here and there.

It must be immune to the kind of effects that occur in hardware where e.g.
the counter register is read in two phases on the bus lowest 16 bits first
and the higher 16 bits in a second bus cycle with the counter bits
potentially being updated in between leading to the risk of very strange
values from the counter.

When the wall-clock accuracy of the clock source isn't satisfactory, there
are various quirks and layers in the timekeeping code for e.g. synchronizing
the user-visible time to RTC clocks in the system or against networked time
servers using NTP, but all they do basically is update an offset against
the clock source, which provides the fundamental timeline for the system.
These measures does not affect the clock source per se, they only adapt the
system to the shortcomings of it.

The clock source struct shall provide means to translate the provided counter
into a nanosecond value as an unsigned long long (unsigned 64 bit) number.
Since this operation may be invoked very often, doing this in a strict
mathematical sense is not desirable: instead the number is taken as close as
possible to a nanosecond value using only the arithmetic operations
multiply and shift, so in clocksource_cyc2ns() you find:

  ns ~= (clocksource * mult) >> shift

You will find a number of helper functions in the clock source code intended
to aid in providing these mult and shift values, such as
clocksource_khz2mult(), clocksource_hz2mult() that help determine the
mult factor from a fixed shift, and clocksource_register_hz() and
clocksource_register_khz() which will help out assigning both shift and mult
factors using the frequency of the clock source as the only input.

For real simple clock sources accessed from a single I/O memory location
there is nowadays even clocksource_mmio_init() which will take a memory
location, bit width, a parameter telling whether the counter in the
register counts up or down, and the timer clock rate, and then conjure all
necessary parameters.

Since a 32-bit counter at say 100 MHz will wrap around to zero after some 43
seconds, the code handling the clock source will have to compensate for this.
That is the reason why the clock source struct also contains a 'mask'
member telling how many bits of the source are valid. This way the timekeeping
code knows when the counter will wrap around and can insert the necessary
compensation code on both sides of the wrap point so that the system timeline
remains monotonic.

Clock events
------------

Clock events are the conceptual reverse of clock sources: they take a
desired time specification value and calculate the values to poke into
hardware timer registers.

Clock events are orthogonal to clock sources. The same hardware
and register range may be used for the clock event, but it is essentially
a different thing. The hardware driving clock events has to be able to
fire interrupts, so as to trigger events on the system timeline. On an SMP
system, it is ideal (and customary) to have one such event driving timer per
CPU core, so that each core can trigger events independently of any other
core.

You will notice that the clock event device code is based on the same basic
idea about translating counters to nanoseconds using mult and shift
arithmetic, and you find the same family of helper functions again for
assigning these values. The clock event driver does not need a 'mask'
attribute however: the system will not try to plan events beyond the time
horizon of the clock event.

sched_clock()
-------------

In addition to the clock sources and clock events there is a special weak
function in the kernel called sched_clock(). This function shall return the
number of nanoseconds since the system was started. An architecture may or
may not provide an implementation of sched_clock() on its own. If a local
implementation is not provided, the system jiffy counter will be used as
sched_clock().

As the name suggests, sched_clock() is used for scheduling the system,
determining the absolute timeslice for a certain process in the CFS scheduler
for example. It is also used for printk timestamps when you have selected to
include time information in printk for things like bootcharts.

Compared to clock sources, sched_clock() has to be very fast: it is called
much more often, especially by the scheduler. If you have to do trade-offs
between accuracy compared to the clock source, you may sacrifice accuracy
for speed in sched_clock(). It however requires some of the same basic
characteristics as the clock source, i.e. it should be monotonic.

The sched_clock() function may wrap only on unsigned long long boundaries,
i.e. after 64 bits. Since this is a nanosecond value this will mean it wraps
after circa 585 years. (For most practical systems this means "never".)

If an architecture does not provide its own implementation of this function,
it will fall back to using jiffies, making its maximum resolution 1/HZ of the
jiffy frequency for the architecture. This will affect scheduling accuracy
and will likely show up in system benchmarks.

The clock driving sched_clock() may stop or reset to zero during system
suspend/sleep. This does not matter to the function it serves of scheduling
events on the system. However it may result in interesting timestamps in
printk().

The sched_clock() function should be callable in any context, IRQ- and
NMI-safe and return a sane value in any context.

Some architectures may have a limited set of time sources and lack a nice
counter to derive a 64-bit nanosecond value, so for example on the ARM
architecture, special helper functions have been created to provide a
sched_clock() nanosecond base from a 16- or 32-bit counter. Sometimes the
same counter that is also used as clock source is used for this purpose.

On SMP systems, it is crucial for performance that sched_clock() can be called
independently on each CPU without any synchronization performance hits.
Some hardware (such as the x86 TSC) will cause the sched_clock() function to
drift between the CPUs on the system. The kernel can work around this by
enabling the CONFIG_HAVE_UNSTABLE_SCHED_CLOCK option. This is another aspect
that makes sched_clock() different from the ordinary clock source.

Delay timers (some architectures only)
--------------------------------------

On systems with variable CPU frequency, the various kernel delay() functions
will sometimes behave strangely. Basically these delays usually use a hard
loop to delay a certain number of jiffy fractions using a "lpj" (loops per
jiffy) value, calibrated on boot.

Let's hope that your system is running on maximum frequency when this value
is calibrated: as an effect when the frequency is geared down to half the
full frequency, any delay() will be twice as long. Usually this does not
hurt, as you're commonly requesting that amount of delay *or more*. But
basically the semantics are quite unpredictable on such systems.

Enter timer-based delays. Using these, a timer read may be used instead of
a hard-coded loop for providing the desired delay.

This is done by declaring a struct delay_timer and assigning the appropriate
function pointers and rate settings for this delay timer.

This is available on some architectures like OpenRISC or ARM.


code:
===================================================================
delays - Information on the various kernel delay / sleep mechanisms
===================================================================

This document seeks to answer the common question: "What is the
RightWay (TM) to insert a delay?"

This question is most often faced by driver writers who have to
deal with hardware delays and who may not be the most intimately
familiar with the inner workings of the Linux Kernel.

Inserting Delays
----------------

The first, and most important, question you need to ask is "Is my
code in an atomic context?"  This should be followed closely by "Does
it really need to delay in atomic context?" If so...

ATOMIC CONTEXT:
	You must use the `*delay` family of functions. These
	functions use the jiffie estimation of clock speed
	and will busy wait for enough loop cycles to achieve
	the desired delay:

	ndelay(unsigned long nsecs)
	udelay(unsigned long usecs)
	mdelay(unsigned long msecs)

	udelay is the generally preferred API; ndelay-level
	precision may not actually exist on many non-PC devices.

	mdelay is macro wrapper around udelay, to account for
	possible overflow when passing large arguments to udelay.
	In general, use of mdelay is discouraged and code should
	be refactored to allow for the use of msleep.

NON-ATOMIC CONTEXT:
	You should use the `*sleep[_range]` family of functions.
	There are a few more options here, while any of them may
	work correctly, using the "right" sleep function will
	help the scheduler, power management, and just make your
	driver better :)

	-- Backed by busy-wait loop:

		udelay(unsigned long usecs)

	-- Backed by hrtimers:

		usleep_range(unsigned long min, unsigned long max)

	-- Backed by jiffies / legacy_timers

		msleep(unsigned long msecs)
		msleep_interruptible(unsigned long msecs)

	Unlike the `*delay` family, the underlying mechanism
	driving each of these calls varies, thus there are
	quirks you should be aware of.

	SLEEPING FOR "A FEW" USECS ( < ~10us? ):
		* Use udelay

		- Why not usleep?
			On slower systems, (embedded, OR perhaps a speed-
			stepped PC!) the overhead of setting up the hrtimers
			for usleep *may* not be worth it. Such an evaluation
			will obviously depend on your specific situation, but
			it is something to be aware of.

	SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms):
		* Use usleep_range

		- Why not msleep for (1ms - 20ms)?
			Explained originally here:
				https://lore.kernel.org/r/15327.1186166232@lwn.net

			msleep(1~20) may not do what the caller intends, and
			will often sleep longer (~20 ms actual sleep for any
			value given in the 1~20ms range). In many cases this
			is not the desired behavior.

		- Why is there no "usleep" / What is a good range?
			Since usleep_range is built on top of hrtimers, the
			wakeup will be very precise (ish), thus a simple
			usleep function would likely introduce a large number
			of undesired interrupts.

			With the introduction of a range, the scheduler is
			free to coalesce your wakeup with any other wakeup
			that may have happened for other reasons, or at the
			worst case, fire an interrupt for your upper bound.

			The larger a range you supply, the greater a chance
			that you will not trigger an interrupt; this should
			be balanced with what is an acceptable upper bound on
			delay / performance for your specific code path. Exact
			tolerances here are very situation specific, thus it
			is left to the caller to determine a reasonable range.

	SLEEPING FOR LARGER MSECS ( 10ms+ )
		* Use msleep or possibly msleep_interruptible

		- What's the difference?
			msleep sets the current task to TASK_UNINTERRUPTIBLE
			whereas msleep_interruptible sets the current task to
			TASK_INTERRUPTIBLE before scheduling the sleep. In
			short, the difference is whether the sleep can be ended
			early by a signal. In general, just use msleep unless
			you know you have a need for the interruptible variant.

	FLEXIBLE SLEEPING (any delay, uninterruptible)
		* Use fsleep


code:
.. SPDX-License-Identifier: GPL-2.0

============
Kernel tools
============

This book covers user-space tools that are shipped with the kernel source;
more additions are needed here:

.. toctree::
   :maxdepth: 1

   rtla/index
   rv/index

.. only::  subproject and html

   Indices
   =======

   * :ref:`genindex`


code:
# SPDX-License-Identifier: GPL-2.0-only
# Based on bpftool's Documentation Makefile

INSTALL		?= install
RM		?= rm -f
RMDIR		?= rmdir --ignore-fail-on-non-empty

PREFIX		?= /usr/share
MANDIR		?= $(PREFIX)/man
MAN1DIR		= $(MANDIR)/man1

MAN1_RST	= $(wildcard rtla*.rst)

_DOC_MAN1	= $(patsubst %.rst,%.1,$(MAN1_RST))
DOC_MAN1	= $(addprefix $(OUTPUT),$(_DOC_MAN1))

RST2MAN_DEP	:= $(shell command -v rst2man 2>/dev/null)
RST2MAN_OPTS	+= --verbose

TEST_RST2MAN = $(shell sh -c "rst2man --version > /dev/null 2>&1 || echo n")

$(OUTPUT)%.1: %.rst
ifndef RST2MAN_DEP
	$(info ********************************************)
	$(info ** NOTICE: rst2man not found)
	$(info **)
	$(info ** Consider installing the latest rst2man from your)
	$(info ** distribution, e.g., 'dnf install python3-docutils' on Fedora,)
	$(info ** or from source:)
	$(info **)
	$(info **  https://docutils.sourceforge.io/docs/dev/repository.html )
	$(info **)
	$(info ********************************************)
	$(error NOTICE: rst2man required to generate man pages)
endif
	rst2man $(RST2MAN_OPTS) $< > $@

man1: $(DOC_MAN1)
man: man1

clean:
	$(RM) $(DOC_MAN1)

install: man
	$(INSTALL) -d -m 755 $(DESTDIR)$(MAN1DIR)
	$(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(MAN1DIR)

uninstall:
	$(RM) $(addprefix $(DESTDIR)$(MAN1DIR)/,$(_DOC_MAN1))
	$(RMDIR) $(DESTDIR)$(MAN1DIR)

.PHONY: man man1 clean install uninstall
.DEFAULT_GOAL := man

path: Documentation/tools/rtla/Makefile


code:
REPORTING BUGS
==============
Report bugs to <linux-kernel@vger.kernel.org>
and <linux-trace-devel@vger.kernel.org>

LICENSE
=======
**rtla** is Free Software licensed under the GNU GPLv2

COPYING
=======
Copyright \(C) 2021 Red Hat, Inc. Free use of this software is granted under
the terms of the GNU Public License (GPL).


code:
**-b**, **--bucket-size** *N*

        Set the histogram bucket size (default *1*).

**-E**, **--entries** *N*

        Set the number of entries of the histogram (default 256).

**--no-header**

        Do not print header.

**--no-summary**

        Do not print summary.

**--no-index**

        Do not print index.

**--with-zeros**

        Print zero only entries.