diff --git a/src/common/plugrack.h b/src/common/plugrack.h
index 285bca14e306cb44a39c34721868f910025aff61..b0ed3f78a868d34d87744cfb788b18d27902906f 100644
--- a/src/common/plugrack.h
+++ b/src/common/plugrack.h
@@ -1,5 +1,5 @@
 /*****************************************************************************\
- * plugrack.h - an intelligent container for plugins
+ *  plugrack.h - an intelligent container for plugins
  *****************************************************************************
  *  Copyright (C) 2002 The Regents of the University of California.
  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
diff --git a/src/common/xmalloc.h b/src/common/xmalloc.h
index 588f648e26af291c9a52d438478f95e3b0449c1a..2db328a20615cfa4884a604b1d70f10cae59731b 100644
--- a/src/common/xmalloc.h
+++ b/src/common/xmalloc.h
@@ -57,7 +57,7 @@
  * when there is an error allocating the memory.
  *
  * xrealloc(p, newsize) changes the size of the block pointed to by p to the
- * value of newsize. Newly allocated memory is not zeroed. If p is NULL,
+ * value of newsize. Newly allocated memory is zeroed. If p is NULL,
  * xrealloc() performs the same function as  `p = xmalloc(newsize)'. If p
  * is not NULL, it is required to have been initialized with a call to
  * [try_]xmalloc() or [try_]xrealloc().
diff --git a/src/plugins/job_submit/defaults/job_submit_defaults.c b/src/plugins/job_submit/defaults/job_submit_defaults.c
index ffe8daa39f72b5634df94e9f3737f68f4291d661..0fe982a7f8ca537518e82b313103ccdd925c6cdb 100644
--- a/src/plugins/job_submit/defaults/job_submit_defaults.c
+++ b/src/plugins/job_submit/defaults/job_submit_defaults.c
@@ -98,7 +98,15 @@ const char plugin_type[]       	= "job_submit/defaults";
 const uint32_t plugin_version   = 100;
 const uint32_t min_plug_version = 100;
 
-extern int submit_job_p(struct job_record *job_ptr)
+extern int job_submit(struct job_descriptor *job_desc)
 {
+	info("in job_submit/defaults, job_submit");
+	return SLURM_SUCCESS;
+}
+
+extern int job_modify(struct job_descriptor *job_desc, 
+		      struct job_record *job_ptr)
+{
+	info("in job_submit/defaults, job_modify");
 	return SLURM_SUCCESS;
 }
diff --git a/src/plugins/job_submit/logging/job_submit_logging.c b/src/plugins/job_submit/logging/job_submit_logging.c
index c641ee8b5749b1bcbdf74f37f8ab9aa7016f56f8..537faeaca1c757bcb18bbab7642b1534418487a9 100644
--- a/src/plugins/job_submit/logging/job_submit_logging.c
+++ b/src/plugins/job_submit/logging/job_submit_logging.c
@@ -63,6 +63,7 @@
 
 #include <stdio.h>
 
+#include <slurm/slurm.h>
 #include <slurm/slurm_errno.h>
 #include "src/common/slurm_xlator.h"
 #include "src/slurmctld/slurmctld.h"
@@ -98,7 +99,15 @@ const char plugin_type[]       	= "job_submit/logging";
 const uint32_t plugin_version   = 100;
 const uint32_t min_plug_version = 100;
 
-extern int submit_job_p(struct job_record *job_ptr)
+extern int job_submit(struct job_descriptor *job_desc)
 {
+	info("in job_submit/logging, job_submit");
+	return SLURM_SUCCESS;
+}
+
+extern int job_modify(struct job_descriptor *job_desc, 
+		      struct job_record *job_ptr)
+{
+	info("in job_submit/logging, job_modify");
 	return SLURM_SUCCESS;
 }
diff --git a/src/plugins/job_submit/partition/job_submit_partition.c b/src/plugins/job_submit/partition/job_submit_partition.c
index 3900ddfca5977794344bcbbc1fc5d9b74eb1336b..f7beb196a2256d94aaea5aed8361854c881c03ef 100644
--- a/src/plugins/job_submit/partition/job_submit_partition.c
+++ b/src/plugins/job_submit/partition/job_submit_partition.c
@@ -99,7 +99,15 @@ const char plugin_type[]       	= "job_submit/partition";
 const uint32_t plugin_version   = 100;
 const uint32_t min_plug_version = 100;
 
-extern int submit_job_p(struct job_record *job_ptr)
+extern int job_submit(struct job_descriptor *job_desc)
 {
+	info("in job_submit/partition, job_submit");
+	return SLURM_SUCCESS;
+}
+
+extern int job_modify(struct job_descriptor *job_desc, 
+		      struct job_record *job_ptr)
+{
+	info("in job_submit/partition, job_modify");
 	return SLURM_SUCCESS;
 }
diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c
index 511ced7dcc8bcc6f2e7f953041c82d3fdf76a1c4..174beee528e6672af11fe33518fc4229926d6308 100644
--- a/src/slurmctld/controller.c
+++ b/src/slurmctld/controller.c
@@ -86,6 +86,7 @@
 #include "src/slurmctld/agent.h"
 #include "src/slurmctld/basil_interface.h"
 #include "src/slurmctld/job_scheduler.h"
+#include "src/slurmctld/job_submit.h"
 #include "src/slurmctld/licenses.h"
 #include "src/slurmctld/locks.h"
 #include "src/slurmctld/ping_nodes.h"
@@ -412,6 +413,8 @@ int main(int argc, char *argv[])
 		fatal( "failed to initialize accounting_storage plugin");
 	if (slurm_jobacct_gather_init() != SLURM_SUCCESS )
 		fatal( "failed to initialize jobacct_gather plugin");
+	if (job_submit_plugin_init() != SLURM_SUCCESS )
+		fatal( "failed to initialize job_submit plugin");
 
 	while (1) {
 		/* initialization for each primary<->backup switch */
@@ -610,6 +613,7 @@ int main(int argc, char *argv[])
 
 	/* Some plugins are needed to purge job/node data structures,
 	 * unplug after other data structures are purged */
+	job_submit_plugin_fini();
 	slurm_preempt_fini();
 	g_slurm_jobcomp_fini();
 	slurm_acct_storage_fini();
diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c
index 10686e62ce1823765c1c323eee8895f40f90986c..317892f6317480ae1bd538eb0e6a421df6405c85 100644
--- a/src/slurmctld/job_mgr.c
+++ b/src/slurmctld/job_mgr.c
@@ -75,6 +75,7 @@
 #include "src/slurmctld/acct_policy.h"
 #include "src/slurmctld/agent.h"
 #include "src/slurmctld/job_scheduler.h"
+#include "src/slurmctld/job_submit.h"
 #include "src/slurmctld/licenses.h"
 #include "src/slurmctld/locks.h"
 #include "src/slurmctld/node_scheduler.h"
@@ -2629,6 +2630,10 @@ static int _job_create(job_desc_msg_t * job_desc, int allocate, int will_run,
 #endif
 
 	*job_pptr = (struct job_record *) NULL;
+	error_code = job_submit_plugin_submit(job_desc);
+	if (error_code != SLURM_SUCCESS)
+		return error_code;
+
 	/* find selected partition */
 	if (job_desc->partition) {
 		part_ptr = list_find_first(part_list, &list_find_part,
@@ -5339,6 +5344,11 @@ int update_job(job_desc_msg_t * job_specs, uid_t uid)
 		      job_specs->job_id);
 		return ESLURM_INVALID_JOB_ID;
 	}
+
+	error_code = job_submit_plugin_modify(job_specs, job_ptr);
+	if (error_code != SLURM_SUCCESS)
+		return error_code;
+
 	if ((uid == 0) || (uid == slurmctld_conf.slurm_user_id))
 		super_user = 1;
 	if ((job_ptr->user_id != uid) && (super_user == 0)) {
diff --git a/src/slurmctld/job_submit.c b/src/slurmctld/job_submit.c
index 7a00a4d897bcdfb92e7e6bd8374c0ef952ccb673..3b738b8b631b42da65298fcda878937e48b051a6 100644
--- a/src/slurmctld/job_submit.c
+++ b/src/slurmctld/job_submit.c
@@ -62,6 +62,252 @@
 #endif /* HAVE_CONFIG_H */
 
 #include <stdio.h>
+#include <slurm/slurm.h>
 #include <slurm/slurm_errno.h>
 
-#include "src/slurmctld/slurmctld.h"
+#include "src/common/macros.h"
+#include "src/common/plugin.h"
+#include "src/common/plugrack.h"
+#include "src/common/slurm_protocol_api.h"
+#include "src/common/xmalloc.h"
+#include "src/common/xstring.h"
+
+typedef struct slurm_submit_ops {
+	int		(*submit)	( struct job_descriptor *job_desc );
+	int		(*modify)	( struct job_descriptor *job_desc,
+					  struct job_record *job_ptr);
+} slurm_submit_ops_t;
+
+typedef struct slurm_submit_context {
+	char	       	*sched_type;
+	plugrack_t     	plugin_list;
+	plugin_handle_t	cur_plugin;
+	int		sched_errno;
+	slurm_submit_ops_t ops;
+} slurm_submit_context_t;
+
+static int submit_context_cnt = -1;
+static slurm_submit_context_t *submit_context = NULL;
+static char *submit_plugin_list = NULL;
+static pthread_mutex_t submit_context_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int _load_submit_plugin(char *plugin_name, 
+			       slurm_submit_context_t *plugin_context)
+{
+	/*
+	 * Must be synchronized with slurm_submit_ops_t above.
+	 */
+	static const char *syms[] = {
+		"job_submit",
+		"job_modify"
+	};
+	int n_syms = sizeof(syms) / sizeof(char *);
+
+	/* Find the correct plugin */
+	plugin_context->sched_type	= xstrdup("job_submit/");
+	xstrcat(plugin_context->sched_type, plugin_name);
+	plugin_context->plugin_list	= NULL;
+	plugin_context->cur_plugin	= PLUGIN_INVALID_HANDLE;
+	plugin_context->sched_errno 	= SLURM_SUCCESS;
+
+        plugin_context->cur_plugin = plugin_load_and_link(
+					plugin_context->sched_type, 
+					n_syms, syms,
+					(void **) &plugin_context->ops);
+        if (plugin_context->cur_plugin != PLUGIN_INVALID_HANDLE)
+        	return SLURM_SUCCESS;
+
+	error("job_submit: Couldn't find the specified plugin name for %s "
+	      "looking at all files",
+	      plugin_context->sched_type);
+
+	/* Get plugin list */
+	if (plugin_context->plugin_list == NULL) {
+		char *plugin_dir;
+		plugin_context->plugin_list = plugrack_create();
+		if (plugin_context->plugin_list == NULL) {
+			error("job_submit: cannot create plugin manager");
+			return SLURM_ERROR;
+		}
+		plugrack_set_major_type(plugin_context->plugin_list,
+					"job_submit");
+		plugrack_set_paranoia(plugin_context->plugin_list,
+				      PLUGRACK_PARANOIA_NONE, 0);
+		plugin_dir = slurm_get_plugin_dir();
+		plugrack_read_dir(plugin_context->plugin_list, plugin_dir);
+		xfree(plugin_dir);
+	}
+
+	plugin_context->cur_plugin = plugrack_use_by_type(
+					plugin_context->plugin_list,
+					plugin_context->sched_type );
+	if (plugin_context->cur_plugin == PLUGIN_INVALID_HANDLE) {
+		error("job_submit: cannot find scheduler plugin for %s", 
+		       plugin_context->sched_type);
+		return SLURM_ERROR;
+	}
+
+	/* Dereference the API. */
+	if (plugin_get_syms(plugin_context->cur_plugin,
+			    n_syms, syms,
+			    (void **) &plugin_context->ops ) < n_syms ) {
+		error("job_submit: incomplete plugin detected");
+		return SLURM_ERROR;
+	}
+	return SLURM_SUCCESS;
+}
+
+static int _unload_submit_plugin(slurm_submit_context_t *plugin_context)
+{
+	int rc;
+
+	/*
+	 * Must check return code here because plugins might still
+	 * be loaded and active.
+	 */
+	if (plugin_context->plugin_list)
+		rc = plugrack_destroy(plugin_context->plugin_list);
+	else {
+		rc = SLURM_SUCCESS;
+		plugin_unload(plugin_context->cur_plugin);
+	}
+	xfree(plugin_context->sched_type);
+
+	return rc;
+}
+
+/*
+ * Initialize the job submit plugin.
+ *
+ * Returns a SLURM errno.
+ */
+extern int job_submit_plugin_init(void)
+{
+	int rc = SLURM_SUCCESS;
+	char *last, *names, *one_name;
+
+	slurm_mutex_lock(&submit_context_lock);
+	if (submit_context_cnt >= 0)
+		goto fini;
+
+	submit_plugin_list = slurm_get_job_submit_plugins();
+	submit_context_cnt = 0;
+	if ((submit_plugin_list == NULL) || (submit_plugin_list[0] == '\0'))
+		goto fini;
+
+	submit_context_cnt = 0;
+	names = xstrdup(submit_plugin_list);
+	one_name = strtok_r(names, ",", &last);
+	while (one_name) {
+		xrealloc(submit_context, (sizeof(slurm_submit_context_t) * 
+			 (submit_context_cnt + 1)));
+		rc = _load_submit_plugin(one_name, 
+					 submit_context + submit_context_cnt);
+		if (rc != SLURM_SUCCESS)
+			break;
+		submit_context_cnt++;
+		one_name = strtok_r(NULL, ",", &last);
+	}
+	xfree(names);
+
+fini:	slurm_mutex_unlock(&submit_context_lock);
+	return rc;
+}
+
+/*
+ * Terminate the job submit plugin. Free memory.
+ *
+ * Returns a SLURM errno.
+ */
+extern int job_submit_plugin_fini(void)
+{
+	int i, j, rc = SLURM_SUCCESS;
+
+	slurm_mutex_lock(&submit_context_lock);
+	if (submit_context_cnt < 0)
+		goto fini;
+
+	for (i=0; i<submit_context_cnt; i++) {
+		j = _unload_submit_plugin(submit_context + i);
+		if (j != SLURM_SUCCESS)
+			rc = j;
+	}
+	xfree(submit_context);
+	xfree(submit_plugin_list);
+	submit_context_cnt = -1;
+
+fini:	slurm_mutex_unlock(&submit_context_lock);
+	return rc;
+}
+
+/*
+ **************************************************************************
+ *                          P L U G I N   C A L L S                       *
+ **************************************************************************
+ */
+
+/*
+ * Perform reconfig, re-read any configuration files
+ */
+extern int job_submit_plugin_reconfig(void)
+{
+	int rc = SLURM_SUCCESS;
+	char *plugin_names = slurm_get_job_submit_plugins();
+	bool plugin_change;
+
+	if (!plugin_names && !submit_plugin_list)
+		return rc;
+
+	slurm_mutex_lock(&submit_context_lock);
+	if (plugin_names && submit_plugin_list &&
+	    strcmp(plugin_names, submit_plugin_list))
+		plugin_change = true;
+	else
+		plugin_change = false;
+	slurm_mutex_unlock(&submit_context_lock);
+
+	if (plugin_change) {
+		info("JobSubmitPlugins changed to %s", plugin_names);
+		rc = job_submit_plugin_fini();
+		if (rc == SLURM_SUCCESS)
+			rc = job_submit_plugin_init();
+	}
+	xfree(plugin_names);
+
+	return rc;
+}
+
+/*
+ * Execute the job_submit() function in each job submit plugin.
+ * If any plugin function returns anything other than SLURM_SUCCESS
+ * then stop and forward it's return value.
+ */
+extern int job_submit_plugin_submit(struct job_descriptor *job_desc)
+{
+	int i, rc;
+
+	rc = job_submit_plugin_init();
+	slurm_mutex_lock(&submit_context_lock);
+	for (i=0; ((i < submit_context_cnt) && (rc == SLURM_SUCCESS)); i++)
+		rc = (*(submit_context[i].ops.submit))(job_desc);
+	slurm_mutex_unlock(&submit_context_lock);
+	return rc;
+}
+
+/*
+ * Execute the job_modify() function in each job submit plugin.
+ * If any plugin function returns anything other than SLURM_SUCCESS
+ * then stop and forward it's return value.
+ */
+extern int job_submit_plugin_modify(struct job_descriptor *job_desc,
+				    struct job_record *job_ptr)
+{
+	int i, rc;
+
+	rc = job_submit_plugin_init();
+	slurm_mutex_lock(&submit_context_lock);
+	for (i=0; ((i < submit_context_cnt) && (rc == SLURM_SUCCESS)); i++)
+		rc = (*(submit_context[i].ops.modify))(job_desc, job_ptr);
+	slurm_mutex_unlock(&submit_context_lock);
+	return rc;
+}
diff --git a/src/slurmctld/job_submit.h b/src/slurmctld/job_submit.h
index ee5126313e87b2e3563da75053454fb2e759a304..c263b7026c2336ffc80450e577277916610c0be2 100644
--- a/src/slurmctld/job_submit.h
+++ b/src/slurmctld/job_submit.h
@@ -39,6 +39,47 @@
 #ifndef _JOB_SUBMIT_H
 #define _JOB_SUBMIT_H
 
-#include "src/slurmctld/slurmctld.h"
+#include <slurm/slurm.h>
+
+/*
+ * Initialize the job submit plugin.
+ *
+ * Returns a SLURM errno.
+ */
+extern int job_submit_plugin_init(void);
+
+/*
+ * Terminate the job submit plugin. Free memory.
+ *
+ * Returns a SLURM errno.
+ */
+extern int job_submit_plugin_fini(void);
+
+/*
+ **************************************************************************
+ *                          P L U G I N   C A L L S                       *
+ **************************************************************************
+ */
+
+/*
+ * Perform reconfig, re-read any configuration files
+ */
+extern int job_submit_plugin_reconfig(void);
+
+/*
+ * Execute the job_submit() function in each job submit plugin.
+ * If any plugin function returns anything other than SLURM_SUCCESS
+ * then stop and forward it's return value.
+ */
+extern int job_submit_plugin_submit(struct job_descriptor *job_desc);
+
+/*
+ * Execute the job_modify() function in each job submit plugin.
+ * This should be called 
+ * If any plugin function returns anything other than SLURM_SUCCESS
+ * then stop and forward it's return value.
+ */
+extern int job_submit_plugin_modify(struct job_descriptor *job_desc,
+				    struct job_record *job_ptr);
 
 #endif /* !_JOB_SUBMIT_H */
diff --git a/src/slurmctld/read_config.c b/src/slurmctld/read_config.c
index df46a227e0b07025badbd987bb7fc688cc552720..49bbd44480f3e73aa0f629a2e8325e3659cb13db 100644
--- a/src/slurmctld/read_config.c
+++ b/src/slurmctld/read_config.c
@@ -74,6 +74,7 @@
 #include "src/slurmctld/basil_interface.h"
 #include "src/slurmctld/gang.h"
 #include "src/slurmctld/job_scheduler.h"
+#include "src/slurmctld/job_submit.h"
 #include "src/slurmctld/licenses.h"
 #include "src/slurmctld/locks.h"
 #include "src/slurmctld/node_scheduler.h"
@@ -789,6 +790,8 @@ int read_slurm_conf(int recover, bool reconfig)
 	error_code = MAX(error_code, rc);	/* not fatal */
 
 	/* Update plugin parameters as possible */
+	rc = job_submit_plugin_reconfig();
+	error_code = MAX(error_code, rc);	/* not fatal */
 	rc = _preserve_select_type_param(&slurmctld_conf, old_select_type_p);
 	error_code = MAX(error_code, rc);	/* not fatal */