diff --git a/NEWS b/NEWS
index 01ed04d9ef7fc9526f581e7087bd49bf558d598a..73bbc3cbe087376bccff1e5bd6ac0b0d091874b3 100644
--- a/NEWS
+++ b/NEWS
@@ -52,6 +52,10 @@ documents those changes that are of interest to users and admins.
  -- Add support for job time limit specification formats: min, min:sec, 
     hour:min:sec, and days-hour:min:sec (formerly only supported minutes).
     Applies to salloc, sbatch, and srun commands.
+ -- Improve scheduling support for exclusive constraint list, nodes can 
+    now be in more than one constraint specific exclusively for a job
+    (e.g. "srun -C [rack1|rack2|rack3|rowB] srun")
+ -- Create separate MPICH/MX plugin (split out from MPICH/GM plugin)
 
 * Changes in SLURM 1.2.12
 =========================
diff --git a/configure b/configure
index 39ed9e6f1e47311d3b82716cf6b30782ffd88e5b..a74ad03255ece9fcb6ce7c938f5fc33543e40b87 100755
--- a/configure
+++ b/configure
@@ -26612,7 +26612,7 @@ _ACEOF
 
 
 
-ac_config_files="$ac_config_files Makefile config.xml auxdir/Makefile contribs/Makefile contribs/perlapi/Makefile contribs/perlapi/libslurm-perl/Makefile.PL contribs/torque/Makefile src/Makefile src/api/Makefile src/common/Makefile src/sacct/Makefile src/salloc/Makefile src/sbatch/Makefile src/sattach/Makefile src/srun/Makefile src/slaunch/Makefile src/slurmd/Makefile src/slurmd/slurmd/Makefile src/slurmd/slurmstepd/Makefile src/slurmctld/Makefile src/sbcast/Makefile src/scontrol/Makefile src/scancel/Makefile src/squeue/Makefile src/sinfo/Makefile src/smap/Makefile src/strigger/Makefile src/sview/Makefile src/plugins/Makefile src/plugins/auth/Makefile src/plugins/auth/authd/Makefile src/plugins/auth/munge/Makefile src/plugins/auth/none/Makefile src/plugins/checkpoint/Makefile src/plugins/checkpoint/aix/Makefile src/plugins/checkpoint/none/Makefile src/plugins/crypto/Makefile src/plugins/crypto/munge/Makefile src/plugins/crypto/openssl/Makefile src/plugins/jobacct/Makefile src/plugins/jobacct/linux/Makefile src/plugins/jobacct/aix/Makefile src/plugins/jobacct/none/Makefile src/plugins/jobcomp/Makefile src/plugins/jobcomp/filetxt/Makefile src/plugins/jobcomp/none/Makefile src/plugins/jobcomp/script/Makefile src/plugins/jobcomp/database/Makefile src/plugins/proctrack/Makefile src/plugins/proctrack/aix/Makefile src/plugins/proctrack/pgid/Makefile src/plugins/proctrack/linuxproc/Makefile src/plugins/proctrack/rms/Makefile src/plugins/proctrack/sgi_job/Makefile src/plugins/sched/Makefile src/plugins/sched/backfill/Makefile src/plugins/sched/builtin/Makefile src/plugins/sched/gang/Makefile src/plugins/sched/hold/Makefile src/plugins/sched/wiki/Makefile src/plugins/sched/wiki2/Makefile src/plugins/select/Makefile src/plugins/select/bluegene/Makefile src/plugins/select/bluegene/block_allocator/Makefile src/plugins/select/bluegene/plugin/Makefile src/plugins/select/linear/Makefile src/plugins/select/cons_res/Makefile src/plugins/switch/Makefile src/plugins/switch/elan/Makefile src/plugins/switch/none/Makefile src/plugins/switch/federation/Makefile src/plugins/mpi/Makefile src/plugins/mpi/mpich1_p4/Makefile src/plugins/mpi/mpich1_shmem/Makefile src/plugins/mpi/mpichgm/Makefile src/plugins/mpi/mvapich/Makefile src/plugins/mpi/lam/Makefile src/plugins/mpi/none/Makefile src/plugins/mpi/openmpi/Makefile src/plugins/task/Makefile src/plugins/task/affinity/Makefile src/plugins/task/none/Makefile src/plugins/database/Makefile src/plugins/database/flatfile/Makefile src/plugins/database/mysql/Makefile src/plugins/database/pgsql/Makefile doc/Makefile doc/man/Makefile doc/html/Makefile doc/html/configurator.html testsuite/Makefile testsuite/expect/Makefile testsuite/slurm_unit/Makefile testsuite/slurm_unit/common/Makefile testsuite/slurm_unit/slurmctld/Makefile testsuite/slurm_unit/slurmd/Makefile testsuite/slurm_unit/api/Makefile testsuite/slurm_unit/api/manual/Makefile"
+ac_config_files="$ac_config_files Makefile config.xml auxdir/Makefile contribs/Makefile contribs/perlapi/Makefile contribs/perlapi/libslurm-perl/Makefile.PL contribs/torque/Makefile src/Makefile src/api/Makefile src/common/Makefile src/sacct/Makefile src/salloc/Makefile src/sbatch/Makefile src/sattach/Makefile src/srun/Makefile src/slaunch/Makefile src/slurmd/Makefile src/slurmd/slurmd/Makefile src/slurmd/slurmstepd/Makefile src/slurmctld/Makefile src/sbcast/Makefile src/scontrol/Makefile src/scancel/Makefile src/squeue/Makefile src/sinfo/Makefile src/smap/Makefile src/strigger/Makefile src/sview/Makefile src/plugins/Makefile src/plugins/auth/Makefile src/plugins/auth/authd/Makefile src/plugins/auth/munge/Makefile src/plugins/auth/none/Makefile src/plugins/checkpoint/Makefile src/plugins/checkpoint/aix/Makefile src/plugins/checkpoint/none/Makefile src/plugins/crypto/Makefile src/plugins/crypto/munge/Makefile src/plugins/crypto/openssl/Makefile src/plugins/jobacct/Makefile src/plugins/jobacct/linux/Makefile src/plugins/jobacct/aix/Makefile src/plugins/jobacct/none/Makefile src/plugins/jobcomp/Makefile src/plugins/jobcomp/filetxt/Makefile src/plugins/jobcomp/none/Makefile src/plugins/jobcomp/script/Makefile src/plugins/jobcomp/database/Makefile src/plugins/proctrack/Makefile src/plugins/proctrack/aix/Makefile src/plugins/proctrack/pgid/Makefile src/plugins/proctrack/linuxproc/Makefile src/plugins/proctrack/rms/Makefile src/plugins/proctrack/sgi_job/Makefile src/plugins/sched/Makefile src/plugins/sched/backfill/Makefile src/plugins/sched/builtin/Makefile src/plugins/sched/gang/Makefile src/plugins/sched/hold/Makefile src/plugins/sched/wiki/Makefile src/plugins/sched/wiki2/Makefile src/plugins/select/Makefile src/plugins/select/bluegene/Makefile src/plugins/select/bluegene/block_allocator/Makefile src/plugins/select/bluegene/plugin/Makefile src/plugins/select/linear/Makefile src/plugins/select/cons_res/Makefile src/plugins/switch/Makefile src/plugins/switch/elan/Makefile src/plugins/switch/none/Makefile src/plugins/switch/federation/Makefile src/plugins/mpi/Makefile src/plugins/mpi/mpich1_p4/Makefile src/plugins/mpi/mpich1_shmem/Makefile src/plugins/mpi/mpichgm/Makefile src/plugins/mpi/mpichmx/Makefile src/plugins/mpi/mvapich/Makefile src/plugins/mpi/lam/Makefile src/plugins/mpi/none/Makefile src/plugins/mpi/openmpi/Makefile src/plugins/task/Makefile src/plugins/task/affinity/Makefile src/plugins/task/none/Makefile src/plugins/database/Makefile src/plugins/database/flatfile/Makefile src/plugins/database/mysql/Makefile src/plugins/database/pgsql/Makefile doc/Makefile doc/man/Makefile doc/html/Makefile doc/html/configurator.html testsuite/Makefile testsuite/expect/Makefile testsuite/slurm_unit/Makefile testsuite/slurm_unit/common/Makefile testsuite/slurm_unit/slurmctld/Makefile testsuite/slurm_unit/slurmd/Makefile testsuite/slurm_unit/api/Makefile testsuite/slurm_unit/api/manual/Makefile"
 
 
 cat >confcache <<\_ACEOF
@@ -27403,6 +27403,7 @@ do
     "src/plugins/mpi/mpich1_p4/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/mpi/mpich1_p4/Makefile" ;;
     "src/plugins/mpi/mpich1_shmem/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/mpi/mpich1_shmem/Makefile" ;;
     "src/plugins/mpi/mpichgm/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/mpi/mpichgm/Makefile" ;;
+    "src/plugins/mpi/mpichmx/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/mpi/mpichmx/Makefile" ;;
     "src/plugins/mpi/mvapich/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/mpi/mvapich/Makefile" ;;
     "src/plugins/mpi/lam/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/mpi/lam/Makefile" ;;
     "src/plugins/mpi/none/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/mpi/none/Makefile" ;;
diff --git a/configure.ac b/configure.ac
index 761eaa4c1dd1d7c92423b5a4b4b4c317a3b9eec7..cecb74a6dd2df6a90e4505585e90e334cd469511 100644
--- a/configure.ac
+++ b/configure.ac
@@ -318,6 +318,7 @@ AC_CONFIG_FILES([Makefile
 		 src/plugins/mpi/mpich1_p4/Makefile
 		 src/plugins/mpi/mpich1_shmem/Makefile
 		 src/plugins/mpi/mpichgm/Makefile
+		 src/plugins/mpi/mpichmx/Makefile
 		 src/plugins/mpi/mvapich/Makefile
 		 src/plugins/mpi/lam/Makefile
 		 src/plugins/mpi/none/Makefile
diff --git a/contribs/perlapi/libslurm-perl/Makefile.PL.in b/contribs/perlapi/libslurm-perl/Makefile.PL.in
index 1afcc798c8e220ffd3d2a651446e22065a304c68..260b29eb52fcf9d5cb1b4b36cd67bf625a0d7744 100644
--- a/contribs/perlapi/libslurm-perl/Makefile.PL.in
+++ b/contribs/perlapi/libslurm-perl/Makefile.PL.in
@@ -11,6 +11,69 @@ following link(s):
    @prefix@/lib/libslurm.so\n");
 }
 
+# Most all the extra code is to deal with MakeMaker < 6.11 not working
+# correctly to build rpms
+ 
+my(
+   $mm_version,
+   $mm_knows_destdir,
+   $mm_has_destdir,
+   $mm_has_good_destdir,
+   $mm_needs_destdir,
+   );
+
+# Gather some information about what EU::MM offers and/or needs
+
+# Store the version for later use
+$mm_version          = $ExtUtils::MakeMaker::VERSION;
+
+# MakeMaker prior to 6.11 doesn't support DESTDIR which is needed for
+# packaging with builddir!=destdir. See bug 2388.
+$mm_knows_destdir    = $ExtUtils::MakeMaker::Recognized_Att_Keys{DESTDIR};
+$mm_has_good_destdir = $mm_version >= 6.11;
+# Add DESTDIR hack only if it's requested (and necessary)
+$mm_needs_destdir    = !$mm_has_good_destdir;
+$mm_has_destdir      = $mm_knows_destdir || $mm_needs_destdir;
+$ExtUtils::MakeMaker::Recognized_Att_Keys{"DESTDIR"} = 1 if $mm_needs_destdir;
+
+if ($mm_needs_destdir) {
+	my $error = <<DESTDIR_HACK;
+
+    ***********************************************************************
+    ExtUtils::MakeMaker ${mm_version} does not include support for DESTDIR,
+    so if you want to be on the safe side, you might want to upgrade your
+    ExtUtils::MakeMaker to version 6.11 or later. It is available via CPAN.
+
+    You can use either the CPAN shell or go to
+      <http://search.cpan.org/search?module=ExtUtils::MakeMaker>
+    to get an up-to-date version.
+
+    This should only be necessary if you are creating binary packages.
+    ***********************************************************************
+
+DESTDIR_HACK
+       $error =~ s/^ {4}//gm;
+       warn $error;
+} elsif (!$mm_has_good_destdir) {
+	my $error = <<DESTDIR_BUG;
+	
+    ***********************************************************************
+    ExtUtils::MakeMaker ${mm_version} contains bugs that may cause problems
+    in the \"make\" process.  It is recommended that you upgrade
+    ExtUtils::MakeMaker to version 6.11 or later. It is available via CPAN.
+
+    You can use either the CPAN shell or go to
+      <http://search.cpan.org/search?module=ExtUtils::MakeMaker>
+    to get an up-to-date version.
+
+    This should only be necessary if you are creating binary packages.
+    ***********************************************************************
+
+DESTDIR_BUG
+       $error =~ s/^ {4}//gm;
+       warn $error;
+}
+
 WriteMakefile(
 	NAME              => 'Slurm',
 	VERSION_FROM      => 'Slurm.pm', # finds $VERSION
@@ -187,3 +250,203 @@ else {
 	die "Error creating constant files: $!";
 }
 
+# Override the install routine to add our additional install dirs and
+# hack DESTDIR support into old EU::MMs.
+sub MY::install {
+	package MY;
+	my $self = shift;
+	my @code = split(/\n/, $self->SUPER::install(@_));
+	init_MY_globals($self);
+
+	foreach (@code) {
+		# Write the correct path to perllocal.pod
+		next if /installed into/;
+	
+		# Replace all other $(INSTALL*) vars (except $(INSTALLDIRS) of course)
+		# with their $(DESTINSTALL*) counterparts
+		s/\Q$(\E(INSTALL(?!DIRS)${MACRO_RE})\Q)\E/\$(DEST$1)/g;	
+         }
+
+         clean_MY_globals($self);
+         return join("\n", @code);
+}
+
+# Now override the constants routine to add our own macros.
+sub MY::constants {
+	package MY;
+	my $self = shift;
+	my @code = split(/\n/, $self->SUPER::constants(@_));
+	init_MY_globals($self);
+
+	foreach my $line (@code) {
+		# Skip comments
+		next if $line =~ /^\s*\#/;
+		# Skip everything which isn't a var assignment.
+		next unless line_has_macro_def($line);
+
+		#tore the assignment string if necessary.
+		set_EQ_from_line($line);
+		
+		# Add some "dummy" (PERL|SITE|VENDOR)PREFIX macros for later use (only if
+		# necessary for old EU::MMs of course)
+		if (line_has_macro_def($line, 'PREFIX')) {
+			foreach my $r (@REPOSITORIES) {
+				my $rprefix = "${r}PREFIX";
+				
+				if (!defined(get_macro($rprefix))) {
+					set_macro($rprefix, macro_ref('PREFIX'));
+					$line .= "\n" . macro_def($rprefix);
+				}
+			}
+		}
+
+ 		# fix problem with /usr(/local) being used as a prefix
+		# instead of the real thing.
+		
+		if ($line =~ 'INSTALL') {
+			$line =~ s/= \/usr\/local/= \$(PREFIX)/;
+			$line =~ s/= \/usr/= \$(PREFIX)/;
+		}
+		
+		# Add DESTDIR support if necessary
+		if (line_has_macro_def($line, 'INSTALLDIRS')) {
+			if(!get_macro('DESTDIR')) {
+				$line .= "\n" . macro_def('DESTDIR');
+			}
+		} elsif (line_has_macro_def($line,
+					    qr/INSTALL${MACRO_RE}/)) {
+			my $macro = get_macro_name_from_line($line);
+			if(!get_macro('DEST' . $macro,
+				      macro_ref('DESTDIR') 
+				      . macro_ref($macro))) {
+				$line .= "\n"
+					. macro_def('DEST' . $macro,
+						    macro_ref('DESTDIR') 
+						    . macro_ref($macro));
+			}
+		}
+	}
+	push(@code, qq{});
+	
+	clean_MY_globals($self);
+	return join("\n", @code);
+}
+
+
+package MY;
+
+use vars qw(
+  @REPOSITORIES
+
+  $MY_GLOBALS_ARE_SANE
+
+  $MACRO_RE
+  $EQ_RE
+  $EQ
+
+  $SELF
+);
+
+
+sub line_has_macro_def {
+	my($line, $name) = (@_, undef);
+	$name = $MACRO_RE unless defined $name;
+
+	return $line =~ /^($name)${EQ_RE}/;
+}
+
+
+sub macro_def {
+	my($name, $val) = (@_, undef);
+	my $error_message = "Problems building report error.";
+
+	die $error_message  unless defined $name;
+	die $error_message  unless defined $EQ;
+	$val = $SELF->{$name} unless defined $val;
+
+	return $name . $EQ . $val;
+}
+
+sub set_EQ_from_line {
+	my($line) = (@_);
+	
+	return if defined($EQ);
+	
+	$line =~ /\S(${EQ_RE})/;
+	$EQ = $1;
+}
+
+# Reads the name of the macro defined on the given line.
+#
+# The first parameter must be the line to be expected. If the line doesn't
+# contain a macro definition, weird things may happen. So check with
+# line_has_macro_def() before!
+sub get_macro_name_from_line {
+	my($line) = (@_);
+
+	$line =~ /^(${MACRO_RE})${EQ_RE}/;
+	return $1;
+}
+
+sub macro_ref {
+	my($name) = (@_);
+
+	return sprintf('$(%s)', $name);
+}
+
+# Reads the value of the given macro from the current instance of EU::MM.
+#
+# The first parameter must be the name of a macro.
+sub get_macro {
+	my($name) = (@_);
+
+	return $SELF->{$name};
+}
+
+# Sets the value of the macro with the given name to the given value in the
+# current instance of EU::MM. Just sets, doesn't write to the Makefile!
+#
+# The first parameter must be the macro's name, the second the value.
+sub set_macro {
+	my($name, $val) = (@_);
+
+	$SELF->{$name} = $val;
+}
+
+# For some reason initializing the vars on the global scope doesn't work;
+# guess its some weird Perl behaviour in combination with bless().
+sub init_MY_globals {
+	my $self = shift;
+
+	# Keep a reference to ourselves so we don't have to feed it to the helper
+	# scripts.
+	$SELF = $self;
+
+	return if $MY_GLOBALS_ARE_SANE;
+
+	$MY_GLOBALS_ARE_SANE = 1;
+	
+	@REPOSITORIES = qw(
+			   PERL
+			   SITE
+			   VENDOR
+			   );
+
+	# Macro names follow this RE -- at least stricly enough for our purposes.
+	$MACRO_RE = qr/[A-Z0-9_]+/;
+	# Normally macros are assigned via FOO = bar. But the part with the equal
+	# sign might differ from platform to platform. So we use this RE:
+	$EQ_RE = qr/\s*:?=\s*/;
+	# To assign or own macros we'll follow the first assignment string we find;
+	# normally " = ".
+	$EQ = undef;
+	
+}
+
+# Unset $SELF to avoid any leaking memory.
+sub clean_MY_globals {
+	my $self = shift;
+
+	$SELF = undef;
+}
+
diff --git a/contribs/perlapi/libslurm-perl/alloc.c b/contribs/perlapi/libslurm-perl/alloc.c
index 0910813b3eb1c7dec45ba03fdb4301439af25945..e98ed7f8e36befe79f9637c28847b06a25b038c7 100644
--- a/contribs/perlapi/libslurm-perl/alloc.c
+++ b/contribs/perlapi/libslurm-perl/alloc.c
@@ -131,15 +131,15 @@ hv_to_job_desc_msg(HV* hv, job_desc_msg_t* job_desc_msg)
 	/* geometry */
 #if SYSTEM_DIMENSIONS
 	if((svp = hv_fetch(hv, "geometry", 8, FALSE))) {
-		SV *avp;
+		AV *avp;
 		if (!SvROK(*svp) || SvTYPE(SvRV(*svp)) != SVt_PVAV) {
 			Perl_warn(aTHX_ "`geometry' is not an array reference in job descriptor");
 			free_job_desc_msg_memory(job_desc_msg);
 			return -1;
 		}
-		avp = SvRV(*svp);
+		avp = (AV*)SvRV(*svp);
 		for(i = 0; i < SYSTEM_DIMENSIONS; i ++) {
-			if(! (svp = av_fetch(avp, i, 0))) {
+			if(! (svp = av_fetch(avp, i, FALSE))) {
 				Perl_warn(aTHX_ "geometry of dimension %s missing in job descriptor", i);
 				free_job_desc_msg_memory(job_desc_msg);
 				return -1;
diff --git a/doc/html/quickstart.shtml b/doc/html/quickstart.shtml
index d37aa790e6e015b73b10f259b702a6ce70b0b114..f5c8ba5499f3779e11b5326f521d8588d6ae5ec1 100644
--- a/doc/html/quickstart.shtml
+++ b/doc/html/quickstart.shtml
@@ -309,7 +309,6 @@ of 1 or higher for the PMI libary to print debugging information</li>
 </ul></p>
 
 <p><a href="http://www.myri.com/scs/download-mpichgm.html"><b>MPICH-GM</b></a>
-and <a href="http://www.myri.com/scs/download-mpichmx.html"><b>MPICH-MX</b></a>
 jobs can be launched directly by <b>srun</b> command.
 SLURM's <i>mpichgm</i> MPI plugin must be used to establish communications 
 between the laucnhed tasks. This can be accomplished either using the SLURM 
@@ -320,6 +319,17 @@ $ mpicc ...
 $ srun -n16 --mpi=mpichgm a.out
 </pre>
 
+<p><a href="http://www.myri.com/scs/download-mpichmx.html"><b>MPICH-MX</b></a>
+jobs can be launched directly by <b>srun</b> command.
+SLURM's <i>mpichmx</i> MPI plugin must be used to establish communications
+between the laucnhed tasks. This can be accomplished either using the SLURM
+configuration parameter <i>MpiDefault=mpichmx</i> in <b>slurm.conf</b>
+or srun's <i>--mpi=mpichmx</i> option.
+<pre>
+$ mpicc ...
+$ srun -n16 --mpi=mpichmx a.out
+</pre>
+
 <p><a href="http://nowlab.cse.ohio-state.edu/projects/mpi-iba"><b>MVAPICH</b></a>
 jobs can be launched directly by <b>srun</b> command.
 SLURM's <i>mvapich</i> MPI plugin must be used to establish communications 
@@ -419,6 +429,6 @@ sbatch: Submitted batch job 1234
 tasks. These tasks are not managed by SLURM since they are launched 
 outside of its control.</p>
  
-<p style="text-align:center;">Last modified 1 August 2007</p>
+<p style="text-align:center;">Last modified 14 August 2007</p>
 
 <!--#include virtual="footer.txt"-->
diff --git a/doc/html/team.shtml b/doc/html/team.shtml
index ab90d33f1b9ebd3259448d7336e90998f0be0e67..1ec2f00d6c4e1417eba5614314d0516953427447 100644
--- a/doc/html/team.shtml
+++ b/doc/html/team.shtml
@@ -40,6 +40,7 @@
 <li>Puenlap Lee (Bull)</li>
 <li>Bernard Li (Genome Sciences Centre, Canada)</li>
 <li>Donna Mecozzi (LLNL)</li>
+<li>Pere Munt (Barcelona Supercomputer Center, Spain)<li>
 <li>Bryan O'Sullivan (Pathscale)</li>
 <li>Gennaro Oliva (Institute of High Performance Computing and 
 Networking, Italy)</li>
@@ -56,6 +57,6 @@ Networking, Italy)</li>
 <li>Anne-Marie Wunderlin (Bull)</li>
 </ul>
 
-<p style="text-align:center;">Last modified 26 July 2007</p>
+<p style="text-align:center;">Last modified 14 August 2007</p>
 
 <!--#include virtual="footer.txt"-->
diff --git a/doc/man/man1/salloc.1 b/doc/man/man1/salloc.1
index 6518e5ed082e308fef0ceac678fdc74176a88819..e888e4b5d70b42b4cc2b8a54a8ff91a7f64f7d39 100644
--- a/doc/man/man1/salloc.1
+++ b/doc/man/man1/salloc.1
@@ -38,9 +38,10 @@ The value may be changed after job submission using the
 
 .TP 
 \fB\-\-bell\fR
-Force salloc to ring the terminal bell when the job allocation is granted.
-By default, salloc only rings the bell if the allocation is pending for more
-than ten seconds. Also see the option \fB\-\-no\-bell\fR.
+Force salloc to ring the terminal bell when the job allocation is granted
+(and only if stdout is a tty).  By default, salloc only rings the bell
+if the allocation is pending for more than ten seconds (and only if stdout
+is a tty). Also see the option \fB\-\-no\-bell\fR.
 
 .TP
 \fB\-C\fR, \fB\-\-constraint\fR[=]<\fIlist\fR>
@@ -51,6 +52,11 @@ The \fIlist\fR of constraints may include multiple features separated
 by ampersand (AND) and/or vertical bar (OR) operators.
 For example: \fB\-\-constraint="opteron&video"\fR or 
 \fB\-\-constraint="fast|faster"\fR.
+If only one of a set of possible options should be used for all allocated 
+nodes, then use the OR operator and enclose the options within square brackets. 
+For example: "\fB\-\-constraint="[rack1|rack2|rack3|rack4]"\fR might 
+be used to specify that all nodes must be allocated on a single rack of 
+the cluster, but any of those four racks can be used.
 If no nodes have the requested features, then the job will be rejected 
 by the slurm job manager.
 
@@ -77,11 +83,6 @@ the \-\-cpus\-per\-task=3 options, the controller knows that each task requires
 3 processors on the same node, and the controller will grant an allocation
 of 4 nodes, one for each of the 4 tasks.
 
-.TP 
-\fB\-D\fR, \fB\-\-workdir\fR[=]<\fIdirectory\fR>
-Set the working directory of the batch script to \fIdirectory\fR before
-it it executed.
-
 .TP 
 \fB\-d\fR, \fB\-\-dependency\fR[=]<\fIjobid\fR>
 Defer the start of this job until the specified \fIjobid\fR has completed.
diff --git a/doc/man/man1/sbatch.1 b/doc/man/man1/sbatch.1
index 31592e406b15b635b729be2e54b6fd07a59f3bde..7adc20b75441609cd125a0753b668af483aa9a34 100644
--- a/doc/man/man1/sbatch.1
+++ b/doc/man/man1/sbatch.1
@@ -55,6 +55,11 @@ The \fIlist\fR of constraints may include multiple features separated
 by ampersand (AND) and/or vertical bar (OR) operators.
 For example: \fB\-\-constraint="opteron&video"\fR or 
 \fB\-\-constraint="fast|faster"\fR.
+If only one of a set of possible options should be used for all allocated 
+nodes, then use the OR operator and enclose the options within square brackets. 
+For example: "\fB\-\-constraint="[rack1|rack2|rack3|rack4]"\fR might 
+be used to specify that all nodes must be allocated on a single rack of 
+the cluster, but any of those four racks can be used.
 If no nodes have the requested features, then the job will be rejected 
 by the slurm job manager.
 
diff --git a/doc/man/man1/srun.1 b/doc/man/man1/srun.1
index 6879c4239c418438e173febe5ead3b307b7b783b..c557acea76de9f2a3fe3cc8de1d9008582f3cd7c 100644
--- a/doc/man/man1/srun.1
+++ b/doc/man/man1/srun.1
@@ -72,7 +72,7 @@ For example:
 .fi
 
 .TP
-\fB\-C\fR, \fB\-\-constraint\fR=\fIlist\fR
+\fB\-C\fR, \fB\-\-constraint\fR[=]<\fIlist\fR>
 Specify a list of constraints. 
 The constraints are features that have been assigned to the nodes by 
 the slurm administrator. 
@@ -80,6 +80,11 @@ The \fIlist\fR of constraints may include multiple features separated
 by ampersand (AND) and/or vertical bar (OR) operators.
 For example: \fB\-\-constraint="opteron&video"\fR or 
 \fB\-\-constraint="fast|faster"\fR.
+If only one of a set of possible options should be used for all allocated 
+nodes, then use the OR operator and enclose the options within square brackets. 
+For example: "\fB\-\-constraint="[rack1|rack2|rack3|rack4]"\fR might 
+be used to specify that all nodes must be allocated on a single rack of 
+the cluster, but any of those four racks can be used.
 If no nodes have the requested features, then the job will be rejected 
 by the slurm job manager.
 
diff --git a/slurm.spec b/slurm.spec
index 21723047ac096dd2526343713fc5364d68e4df46..060b9e2893ba922ae1ab921399d8bf5ddd15f5de 100644
--- a/slurm.spec
+++ b/slurm.spec
@@ -320,6 +320,7 @@ rm -rf $RPM_BUILD_ROOT
 %{_libdir}/slurm/mpi_mpich1_p4.so
 %{_libdir}/slurm/mpi_mpich1_shmem.so
 %{_libdir}/slurm/mpi_mpichgm.so
+%{_libdir}/slurm/mpi_mpichmx.so
 %{_libdir}/slurm/mpi_mvapich.so
 %{_libdir}/slurm/mpi_lam.so
 %{_libdir}/slurm/task_none.so
diff --git a/src/plugins/mpi/Makefile.am b/src/plugins/mpi/Makefile.am
index 9db6b883a187eab4513ad253899f12943fde0b6c..c69678ac76d1d59201ceec04a92eb188a27843b3 100644
--- a/src/plugins/mpi/Makefile.am
+++ b/src/plugins/mpi/Makefile.am
@@ -1,3 +1,3 @@
 # Makefile for mpi plugins
 
-SUBDIRS = mpich1_p4 mpich1_shmem mpichgm mvapich none lam openmpi
+SUBDIRS = mpich1_p4 mpich1_shmem mpichgm mpichmx mvapich none lam openmpi
diff --git a/src/plugins/mpi/Makefile.in b/src/plugins/mpi/Makefile.in
index 7bd4680240cf8303ff74d294e8c46205224f12b1..1221af5b4c9c313da0321cab3f4ea01ee85e26a4 100644
--- a/src/plugins/mpi/Makefile.in
+++ b/src/plugins/mpi/Makefile.in
@@ -240,7 +240,7 @@ target_os = @target_os@
 target_vendor = @target_vendor@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-SUBDIRS = mpich1_p4 mpich1_shmem mpichgm mvapich none lam openmpi
+SUBDIRS = mpich1_p4 mpich1_shmem mpichgm mpichmx mvapich none lam openmpi
 all: all-recursive
 
 .SUFFIXES:
diff --git a/src/plugins/mpi/mpichmx/Makefile.am b/src/plugins/mpi/mpichmx/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..c0bbfaf2bf02d6f843dfaf419c05b047033e8384
--- /dev/null
+++ b/src/plugins/mpi/mpichmx/Makefile.am
@@ -0,0 +1,14 @@
+# Makefile for mpi/mx plugin
+
+AUTOMAKE_OPTIONS = foreign
+
+PLUGIN_FLAGS = -module -avoid-version --export-dynamic 
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src/common
+
+pkglib_LTLIBRARIES = mpi_mpichmx.la
+
+# Null switch plugin.
+mpi_mpichmx_la_SOURCES = mpi_mpichmx.c mpichmx.c mpichmx.h\
+			  $(top_srcdir)/src/common/mpi.h
+mpi_mpichmx_la_LDFLAGS = $(SO_LDFLAGS) $(PLUGIN_FLAGS)
diff --git a/src/plugins/mpi/mpichmx/Makefile.in b/src/plugins/mpi/mpichmx/Makefile.in
new file mode 100644
index 0000000000000000000000000000000000000000..4b0feba9c103e3aa209579d345a1012a08cd819a
--- /dev/null
+++ b/src/plugins/mpi/mpichmx/Makefile.in
@@ -0,0 +1,545 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile for mpi/mx plugin
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = src/plugins/mpi/mpichmx
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/auxdir/acx_pthread.m4 \
+	$(top_srcdir)/auxdir/slurm.m4 \
+	$(top_srcdir)/auxdir/x_ac__system_configuration.m4 \
+	$(top_srcdir)/auxdir/x_ac_affinity.m4 \
+	$(top_srcdir)/auxdir/x_ac_aix.m4 \
+	$(top_srcdir)/auxdir/x_ac_bluegene.m4 \
+	$(top_srcdir)/auxdir/x_ac_debug.m4 \
+	$(top_srcdir)/auxdir/x_ac_elan.m4 \
+	$(top_srcdir)/auxdir/x_ac_federation.m4 \
+	$(top_srcdir)/auxdir/x_ac_gpl_licensed.m4 \
+	$(top_srcdir)/auxdir/x_ac_gtk.m4 \
+	$(top_srcdir)/auxdir/x_ac_munge.m4 \
+	$(top_srcdir)/auxdir/x_ac_ncurses.m4 \
+	$(top_srcdir)/auxdir/x_ac_pam.m4 \
+	$(top_srcdir)/auxdir/x_ac_ptrace.m4 \
+	$(top_srcdir)/auxdir/x_ac_readline.m4 \
+	$(top_srcdir)/auxdir/x_ac_setpgrp.m4 \
+	$(top_srcdir)/auxdir/x_ac_setproctitle.m4 \
+	$(top_srcdir)/auxdir/x_ac_sgi_job.m4 \
+	$(top_srcdir)/auxdir/x_ac_slurm_ssl.m4 \
+	$(top_srcdir)/auxdir/x_ac_xcpu.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/slurm/slurm.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(pkglibdir)"
+pkglibLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mpi_mpichmx_la_LIBADD =
+am_mpi_mpichmx_la_OBJECTS = mpi_mpichmx.lo mpichmx.lo
+mpi_mpichmx_la_OBJECTS = $(am_mpi_mpichmx_la_OBJECTS)
+mpi_mpichmx_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(mpi_mpichmx_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir) -I$(top_builddir)/slurm@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/auxdir/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(mpi_mpichmx_la_SOURCES)
+DIST_SOURCES = $(mpi_mpichmx_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTHD_CFLAGS = @AUTHD_CFLAGS@
+AUTHD_LIBS = @AUTHD_LIBS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BG_INCLUDES = @BG_INCLUDES@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CMD_LDFLAGS = @CMD_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ELAN_LIBS = @ELAN_LIBS@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FEDERATION_LDFLAGS = @FEDERATION_LDFLAGS@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+GTK2_CFLAGS = @GTK2_CFLAGS@
+GTK2_LIBS = @GTK2_LIBS@
+HAVEPKGCONFIG = @HAVEPKGCONFIG@
+HAVE_AIX = @HAVE_AIX@
+HAVE_ELAN = @HAVE_ELAN@
+HAVE_FEDERATION = @HAVE_FEDERATION@
+HAVE_SOME_CURSES = @HAVE_SOME_CURSES@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_LDFLAGS = @LIB_LDFLAGS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUNGE_CPPFLAGS = @MUNGE_CPPFLAGS@
+MUNGE_LDFLAGS = @MUNGE_LDFLAGS@
+MUNGE_LIBS = @MUNGE_LIBS@
+NCURSES = @NCURSES@
+NUMA_LIBS = @NUMA_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PAM_LIBS = @PAM_LIBS@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PLPA_LIBS = @PLPA_LIBS@
+PROCTRACKDIR = @PROCTRACKDIR@
+PROJECT = @PROJECT@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE = @RELEASE@
+SEMAPHORE_LIBS = @SEMAPHORE_LIBS@
+SEMAPHORE_SOURCES = @SEMAPHORE_SOURCES@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SLURMCTLD_PORT = @SLURMCTLD_PORT@
+SLURMD_PORT = @SLURMD_PORT@
+SLURM_API_AGE = @SLURM_API_AGE@
+SLURM_API_CURRENT = @SLURM_API_CURRENT@
+SLURM_API_MAJOR = @SLURM_API_MAJOR@
+SLURM_API_REVISION = @SLURM_API_REVISION@
+SLURM_API_VERSION = @SLURM_API_VERSION@
+SLURM_MAJOR = @SLURM_MAJOR@
+SLURM_MICRO = @SLURM_MICRO@
+SLURM_MINOR = @SLURM_MINOR@
+SLURM_VERSION = @SLURM_VERSION@
+SO_LDFLAGS = @SO_LDFLAGS@
+SSL_CPPFLAGS = @SSL_CPPFLAGS@
+SSL_LDFLAGS = @SSL_LDFLAGS@
+SSL_LIBS = @SSL_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign
+PLUGIN_FLAGS = -module -avoid-version --export-dynamic 
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src/common
+pkglib_LTLIBRARIES = mpi_mpichmx.la
+
+# Null switch plugin.
+mpi_mpichmx_la_SOURCES = mpi_mpichmx.c mpichmx.c mpichmx.h\
+			  $(top_srcdir)/src/common/mpi.h
+
+mpi_mpichmx_la_LDFLAGS = $(SO_LDFLAGS) $(PLUGIN_FLAGS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/plugins/mpi/mpichmx/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  src/plugins/mpi/mpichmx/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)"
+	@list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(pkglibdir)/$$f'"; \
+	    $(LIBTOOL) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(pkglibdir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-pkglibLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$p'"; \
+	  $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
+	done
+
+clean-pkglibLTLIBRARIES:
+	-test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+	@list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+mpi_mpichmx.la: $(mpi_mpichmx_la_OBJECTS) $(mpi_mpichmx_la_DEPENDENCIES) 
+	$(mpi_mpichmx_la_LINK) -rpath $(pkglibdir) $(mpi_mpichmx_la_OBJECTS) $(mpi_mpichmx_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi_mpichmx.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpichmx.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+	for dir in "$(DESTDIR)$(pkglibdir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-pkglibLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-pkglibLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-pkglibLTLIBRARIES \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-pkglibLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/plugins/mpi/mpichmx/mpi_mpichmx.c b/src/plugins/mpi/mpichmx/mpi_mpichmx.c
new file mode 100644
index 0000000000000000000000000000000000000000..c8fd562f116f0022619de74c17e0ec0b70e141f2
--- /dev/null
+++ b/src/plugins/mpi/mpichmx/mpi_mpichmx.c
@@ -0,0 +1,119 @@
+/*****************************************************************************\
+ **  mpi_mpichmx.c - Library routines for initiating jobs with MPICH-MX
+ *****************************************************************************
+ *  Copyright (C) 2004 The Regents of the University of California.
+ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ *  Written by Danny Auble <da@llnl.gov>
+ *  UCRL-CODE-226842.
+ *  
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://www.llnl.gov/linux/slurm/>.
+ *  
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  In addition, as a special exception, the copyright holders give permission 
+ *  to link the code of portions of this program with the OpenSSL library under 
+ *  certain conditions as described in each individual source file, and 
+ *  distribute linked combinations including the two. You must obey the GNU 
+ *  General Public License in all respects for all of the code used other than 
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this 
+ *  exception to your version of the file(s), but you are not obligated to do 
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in 
+ *  the program, then also delete it here.
+ *  
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *  
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+
+#if     HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+
+#include <slurm/slurm_errno.h>
+#include "src/common/slurm_xlator.h"
+#include "src/plugins/mpi/mpichmx/mpichmx.h"
+
+/*
+ * These variables are required by the generic plugin interface.  If they
+ * are not found in the plugin, the plugin loader will ignore it.
+ *
+ * plugin_name - a string giving a human-readable description of the
+ * plugin.  There is no maximum length, but the symbol must refer to
+ * a valid string.
+ *
+ * plugin_type - a string suggesting the type of the plugin or its
+ * applicability to a particular form of data or method of data handling.
+ * If the low-level plugin API is used, the contents of this string are
+ * unimportant and may be anything.  SLURM uses the higher-level plugin
+ * interface which requires this string to be of the form
+ *
+ *      <application>/<method>
+ *
+ * where <application> is a description of the intended application of
+ * the plugin (e.g., "switch" for SLURM switch) and <method> is a description 
+ * of how this plugin satisfies that application.  SLURM will only load
+ * a switch plugin if the plugin_type string has a prefix of "switch/".
+ *
+ * plugin_version - an unsigned 32-bit integer giving the version number
+ * of the plugin.  If major and minor revisions are desired, the major
+ * version number may be multiplied by a suitable magnitude constant such
+ * as 100 or 1000.  Various SLURM versions will likely require a certain
+ * minimum versions for their plugins as this API matures.
+ */
+const char plugin_name[]        = "mpi MPICH-GM plugin";
+const char plugin_type[]        = "mpi/mpichgm";
+const uint32_t plugin_version   = 100;
+
+int p_mpi_hook_slurmstepd_task(const mpi_plugin_task_info_t *job,
+			       char ***env)
+{
+	char addrbuf[1024];
+	char *p;
+	char *addr = getenvp(*env, "SLURM_LAUNCH_NODE_IPADDR");
+	
+	debug("Using mpi/mpich-gm");
+	slurm_print_slurm_addr (job->self, addrbuf, sizeof(addrbuf));
+	
+	if ((p = strchr (addrbuf, ':')) != NULL)
+		*p = '\0';
+		
+	env_array_overwrite_fmt(env, "GMPI_MASTER", "%s", addr);
+	env_array_overwrite_fmt(env, "GMPI_SLAVE",  "%s", addrbuf);
+	env_array_overwrite_fmt(env, "GMPI_ID",  "%u", job->gtaskid);
+	env_array_overwrite_fmt(env, "MXMPI_MASTER", "%s", addr);
+	env_array_overwrite_fmt(env, "MXMPI_ID", "%u", job->gtaskid);
+	debug2("init for mpi rank %u\n", job->gtaskid);
+	
+	return SLURM_SUCCESS;
+}
+
+mpi_plugin_client_state_t *
+p_mpi_hook_client_prelaunch(mpi_plugin_client_info_t *job, char ***env)
+{
+	debug("Using mpi/mpich-gm");
+	return (mpi_plugin_client_state_t *)gmpi_thr_create(job, env);
+}
+
+int p_mpi_hook_client_single_task_per_node()
+{
+	return false;
+}
+
+int p_mpi_hook_client_fini(mpi_plugin_client_state_t *state)
+{
+	return gmpi_thr_destroy((gmpi_state_t *)state);
+}
diff --git a/src/plugins/mpi/mpichmx/mpichmx.c b/src/plugins/mpi/mpichmx/mpichmx.c
new file mode 100644
index 0000000000000000000000000000000000000000..b1d48fffd8f00b48d055073fd5a624b50c3fe7e9
--- /dev/null
+++ b/src/plugins/mpi/mpichmx/mpichmx.c
@@ -0,0 +1,409 @@
+/*****************************************************************************\
+ ** mpichmx.c - srun support for MPICH-MX (based upon MPICH-GM code)
+ *****************************************************************************
+ *  Copyright (C) 2004 The Regents of the University of California.
+ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ *  Written by Takao Hatazaki <takao.hatazaki@hp.com>
+ *  UCRL-CODE-226842.
+ *  
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://www.llnl.gov/linux/slurm/>.
+ *  
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  In addition, as a special exception, the copyright holders give permission 
+ *  to link the code of portions of this program with the OpenSSL library under
+ *  certain conditions as described in each individual source file, and 
+ *  distribute linked combinations including the two. You must obey the GNU 
+ *  General Public License in all respects for all of the code used other than 
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this 
+ *  exception to your version of the file(s), but you are not obligated to do 
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in 
+ *  the program, then also delete it here.
+ *  
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *  
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#ifdef WITH_PTHREADS
+#  include <pthread.h>
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <strings.h>
+
+#include "src/common/slurm_xlator.h"
+#include "src/common/xmalloc.h"
+#include "src/common/xstring.h"
+#include "src/common/net.h"
+#include "src/common/mpi.h"
+
+#include "src/plugins/mpi/mpichmx/mpichmx.h"
+
+typedef struct {
+	int defined;
+	unsigned int port_board_id;
+	unsigned int unique_high_id;
+	unsigned int unique_low_id;
+	unsigned int numanode;
+	unsigned int remote_pid;
+	unsigned int remote_port;
+} gm_slave_t;
+
+#define GMPI_RECV_BUF_LEN 65536
+
+struct gmpi_state {
+	pthread_t tid;
+	int fd; /* = -1 */
+	mpi_plugin_client_info_t *job;
+};
+
+static int _gmpi_parse_init_recv_msg(mpi_plugin_client_info_t *job, char *rbuf,
+				     gm_slave_t *slave_data, int *ii)
+{
+	unsigned int magic, id, port_board_id, unique_high_id,
+		unique_low_id, numanode, remote_pid, remote_port;
+	int got;
+	gm_slave_t *dp;
+
+	got = sscanf(rbuf, "<<<%u:%u:%u:%u:%u:%u:%u::%u>>>",
+		     &magic, &id, &port_board_id, &unique_high_id,
+		     &unique_low_id, &numanode, &remote_pid, &remote_port);
+	*ii = id;
+	if (got != 8) {
+		error("GMPI master received invalid init message");
+		return -1;
+	}
+	if (magic != job->jobid) {
+		error("GMPI master received invalid magic number");
+		return -1;
+	}
+	if (id >= job->step_layout->task_cnt)
+		fatal("GMPI id is out of range");
+#if 0
+	/* Unlike GM ports, MX endpoints can be 0,
+	 * Pere Munt, BSC-CMS */ 
+	if (port_board_id == 0)
+		fatal("MPI id=%d was unable to open a GM port", id);
+#endif
+
+	dp = &slave_data[id];
+	if (dp->defined) {
+		error("Ignoring the message from MPI id=%d", id);
+		return -1;
+	}
+	dp->defined = 1;
+	dp->port_board_id = port_board_id;
+	dp->unique_high_id = unique_high_id;
+	dp->unique_low_id = unique_low_id;
+	dp->numanode = numanode;
+	dp->remote_pid = remote_pid;
+	dp->remote_port = remote_port;
+
+	debug3("slave_data[%d]: <<<%u:%u:%u:%u:%u:%u:%u::%u>>>",
+	       id, magic, id, port_board_id,
+	       dp->unique_high_id, dp->unique_low_id, dp->numanode,
+	       dp->remote_pid, dp->remote_port);
+	return 0;
+}
+
+
+static int _gmpi_establish_map(gmpi_state_t *st)
+{
+	mpi_plugin_client_info_t *job = st->job;
+	struct sockaddr_in addr;
+	in_addr_t *iaddrs;
+	socklen_t addrlen;
+	int accfd, newfd, rlen, nprocs, i, j, id;
+	size_t gmaplen, lmaplen, maplen;
+	char *p, *rbuf = NULL, *gmap = NULL, *lmap = NULL, *map = NULL;
+	char tmp[128];
+	gm_slave_t *slave_data = NULL, *dp;
+	
+	/*
+	 * Collect info from slaves.
+	 * Will never finish unless slaves are GMPI processes.
+	 */
+	accfd = st->fd;
+	addrlen = sizeof(addr);
+	nprocs = job->step_layout->task_cnt;
+	iaddrs = (in_addr_t *)xmalloc(sizeof(*iaddrs)*nprocs);
+	slave_data = (gm_slave_t *)xmalloc(sizeof(*slave_data)*nprocs);
+	for (i=0; i<nprocs; i++)
+		slave_data[i].defined = 0;
+	i = 0;
+	rbuf = (char *)xmalloc(GMPI_RECV_BUF_LEN);
+	
+	while (i < nprocs) {
+		newfd = accept(accfd, (struct sockaddr *)&addr, &addrlen);
+		if (newfd == -1) {
+			error("accept(2) in GMPI master thread: %m");
+			continue;
+		}
+		rlen = recv(newfd, rbuf, GMPI_RECV_BUF_LEN, 0);
+		if (rlen <= 0) {
+			error("GMPI master recv returned %d", rlen);
+			close(newfd);
+			continue;
+		} else {
+			rbuf[rlen] = 0;
+		}
+		if (_gmpi_parse_init_recv_msg(job, rbuf, slave_data,
+					      &id) == 0) {
+			i++;
+			iaddrs[id] = ntohl(addr.sin_addr.s_addr);
+		}
+		close(newfd);
+	}
+	xfree(rbuf);
+	debug2("Received data from all of %d GMPI processes.", i);
+
+	/*
+	 * Compose the global map string.
+	 */
+	gmap = (char *)xmalloc(128*nprocs);
+	p = gmap;
+	strcpy(p, "[[[");
+	p += 3;
+	for (i=0; i<nprocs; i++) {
+		dp = &slave_data[i];
+		sprintf(tmp, "<%u:%u:%u:%u>", dp->port_board_id,
+			dp->unique_high_id, dp->unique_low_id, dp->numanode);
+		strcpy(p, tmp);
+		p += strlen(tmp);
+	}
+	strcpy(p, "|||");
+	p += 3;
+	gmaplen = (size_t)(p - gmap);
+
+	/*
+	 * Respond to slaves.
+	 */
+	lmap = (char *)xmalloc(128*nprocs);
+	for (i=0; i<nprocs; i++) {
+		/*
+		 * Compose the string to send.
+		 */
+		dp = &slave_data[i];
+		p = lmap;
+		for (j=0; j<nprocs; j++) {
+			if (iaddrs[i] == iaddrs[j] &&
+			    (dp->numanode == slave_data[j].numanode)) {
+				sprintf(tmp, "<%u>", j);
+				strcpy(p, tmp);
+				p += strlen(tmp);
+			}
+		}
+		lmaplen = (size_t)(p - lmap);
+		map = (char *)xmalloc(gmaplen+lmaplen+4);
+		strcpy(map, gmap);
+		strcpy(map+gmaplen, lmap);
+		strcpy(map+gmaplen+lmaplen, "]]]");
+		maplen = gmaplen + lmaplen + 3;
+
+		/*
+		 * Send it.
+		 */
+		if ((newfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+			fatal("GMPI master failed to respond");
+		}
+		j = 1;
+		if (setsockopt(newfd, SOL_SOCKET, SO_REUSEADDR,
+			       (void *)&j, sizeof(j)))
+			error("setsockopt in GMPI master: %m");
+		bzero(&addr, sizeof(addr));
+		addr.sin_family = AF_INET;
+		addr.sin_addr.s_addr = htonl(iaddrs[i]);
+		addr.sin_port = htons(dp->remote_port);
+		if (connect(newfd, (struct sockaddr *)&addr, sizeof(addr)))
+			fatal("GMPI master failed to connect");
+		send(newfd, map, maplen, 0);
+		close(newfd);
+		xfree(map);
+	}
+	xfree(slave_data);
+	xfree(lmap);
+	xfree(gmap);
+	xfree(iaddrs);
+
+	debug2("GMPI master responded to all GMPI processes");
+	return 0;
+}
+
+static void _gmpi_wait_abort(gmpi_state_t *st)
+{
+	mpi_plugin_client_info_t *job = st->job;
+	struct sockaddr_in addr;
+	socklen_t addrlen;
+	int newfd, rlen;
+	unsigned int magic;
+	char *rbuf;
+
+	rbuf = (char *)xmalloc(GMPI_RECV_BUF_LEN);
+	addrlen = sizeof(addr);
+	while (1) {
+		newfd = accept(st->fd, (struct sockaddr *)&addr,
+			       &addrlen);
+		if (newfd == -1) {
+			fatal("GMPI master failed to accept (abort-wait)");
+		}
+		rlen = recv(newfd, rbuf, GMPI_RECV_BUF_LEN, 0);
+		if (rlen <= 0) {
+			error("GMPI recv (abort-wait) returned %d", rlen);
+			close(newfd);
+			continue;
+		} else {
+			rbuf[rlen] = 0;
+		}
+		if (sscanf(rbuf, "<<<ABORT_%u_ABORT>>>", &magic) != 1) {
+			error("GMPI (abort-wait) received spurious message.");
+			close(newfd);
+			continue;
+		}
+		if (magic != job->jobid) {
+			error("GMPI (abort-wait) received bad magic number.");
+			close(newfd);
+			continue;
+		}
+		close(newfd);
+		debug("Received ABORT message from an MPI process.");
+		slurm_signal_job_step(job->jobid, job->stepid, SIGKILL);
+#if 0
+		xfree(rbuf);
+		close(jgmpi_fd);
+		gmpi_fd = -1;
+		return;
+#endif
+	}
+}
+
+
+static void *_gmpi_thr(void *arg)
+{
+	gmpi_state_t *st;
+	mpi_plugin_client_info_t *job;
+
+	st = (gmpi_state_t *) arg;
+	job = st->job;
+
+	debug3("GMPI master thread pid=%lu", (unsigned long) getpid());
+	_gmpi_establish_map(st);
+	
+	debug3("GMPI master thread is waiting for ABORT message.");
+	_gmpi_wait_abort(st);
+
+	return (void *)0;
+}
+
+static gmpi_state_t *
+gmpi_state_create(const mpi_plugin_client_info_t *job)
+{
+	gmpi_state_t *state;
+
+	state = (gmpi_state_t *)xmalloc(sizeof(gmpi_state_t));
+
+	state->tid = (pthread_t)-1;
+	state->fd  = -1;
+	state->job = (mpi_plugin_client_info_t *) job;
+
+	return state;
+}
+
+static void
+gmpi_state_destroy(gmpi_state_t *st)
+{
+	xfree(st);
+}
+
+extern gmpi_state_t *
+gmpi_thr_create(const mpi_plugin_client_info_t *job, char ***env)
+{
+	short port;
+	pthread_attr_t attr;
+	gmpi_state_t *st = NULL;
+
+	st = gmpi_state_create(job);
+
+	/*
+	 * It is possible for one to modify the mpirun command in
+	 * MPICH-GM distribution so that it calls srun, instead of
+	 * rsh, for remote process invocations.  In that case, we
+	 * should not override envs nor open the master port.
+	 */
+	if (getenv("GMPI_PORT"))
+		return st;
+
+	if (net_stream_listen (&st->fd, &port) < 0) {
+		error ("Unable to create GMPI listen port: %m");
+		gmpi_state_destroy(st);
+		return NULL;
+	}
+
+	/*
+	 * Accept in a separate thread.
+	 */
+	slurm_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	if (pthread_create(&st->tid, &attr, &_gmpi_thr, (void *)st)) {
+		slurm_attr_destroy(&attr);
+		gmpi_state_destroy(st);
+		return NULL;
+	}
+	slurm_attr_destroy(&attr);
+
+	env_array_overwrite_fmt(env, "GMPI_PORT",  "%hu", port);
+	env_array_overwrite_fmt(env, "GMPI_MAGIC", "%u", job->jobid);
+	env_array_overwrite_fmt(env, "GMPI_NP",    "%d", 
+				job->step_layout->task_cnt);
+	env_array_overwrite_fmt(env, "GMPI_SHMEM", "1");
+	/* FIXME for multi-board config. */
+	env_array_overwrite_fmt(env, "GMPI_BOARD", "-1");
+
+
+	/* For new MX version */
+	env_array_overwrite_fmt(env, "MXMPI_PORT",  "%hu", port);
+	env_array_overwrite_fmt(env, "MXMPI_MAGIC", "%u", job->jobid);
+	env_array_overwrite_fmt(env, "MXMPI_NP",    "%d",
+				job->step_layout->task_cnt);
+	/* FIXME for multi-board config. */
+	env_array_overwrite_fmt(env, "MXMPI_BOARD", "-1");
+ 
+
+	/* for MACOSX to override default malloc */
+	env_array_overwrite_fmt(env, "DYLD_FORCE_FLAT_NAMESPACE", "1");
+
+
+	debug("Started GMPI master thread (%lu)", (unsigned long) st->tid);
+
+	return st;
+}
+
+extern int gmpi_thr_destroy(gmpi_state_t *st)
+{
+	if (st != NULL) {
+		if (st->tid != (pthread_t)-1) {
+			pthread_cancel(st->tid);
+			pthread_join(st->tid, NULL);
+		}
+		gmpi_state_destroy(st);
+	}
+	return SLURM_SUCCESS;
+}
diff --git a/src/plugins/mpi/mpichmx/mpichmx.h b/src/plugins/mpi/mpichmx/mpichmx.h
new file mode 100644
index 0000000000000000000000000000000000000000..cdcade47ccee58ed6ce0c68b6ecde9a83ee1db0b
--- /dev/null
+++ b/src/plugins/mpi/mpichmx/mpichmx.h
@@ -0,0 +1,50 @@
+/*****************************************************************************\
+ **  mpichmx.h - Library routines for initiating jobs on with mpich/mx
+ **              based upon the code for mpich/gm
+ *****************************************************************************
+ *  Copyright (C) 2004 The Regents of the University of California.
+ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ *  Written by Danny Auble <da@llnl.gov>
+ *  UCRL-CODE-226842.
+ *  
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://www.llnl.gov/linux/slurm/>.
+ *  
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  In addition, as a special exception, the copyright holders give permission 
+ *  to link the code of portions of this program with the OpenSSL library under 
+ *  certain conditions as described in each individual source file, and 
+ *  distribute linked combinations including the two. You must obey the GNU 
+ *  General Public License in all respects for all of the code used other than 
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this 
+ *  exception to your version of the file(s), but you are not obligated to do 
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in 
+ *  the program, then also delete it here.
+ *  
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *  
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+#if HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "src/common/slurm_xlator.h"
+#include "src/common/mpi.h"
+#include "src/common/env.h"
+
+typedef struct gmpi_state gmpi_state_t;
+
+extern gmpi_state_t *gmpi_thr_create(const mpi_plugin_client_info_t *job,
+				     char ***env);
+extern int gmpi_thr_destroy(gmpi_state_t *state);
diff --git a/src/salloc/opt.c b/src/salloc/opt.c
index 59de3d16e2d62d2e1ed42a235fef92481d566ce9..ed20f603793cdc6e803b5c438edf321004993fde 100644
--- a/src/salloc/opt.c
+++ b/src/salloc/opt.c
@@ -1290,7 +1290,7 @@ static void _usage(void)
 "              [[-c cpus-per-node] [-r n] [-p partition] [--hold] [-t minutes]\n"
 "              [--immediate] [--no-kill]\n"
 "              [--share] [-J jobname] [--jobid=id]\n"
-"              [--verbose]\n"
+"              [--verbose] [--gid=group] [--uid=user]\n"
 "              [-W sec] [--minsockets=n] [--mincores=n] [--minthreads=n]\n"
 "              [--contiguous] [--mincpus=n] [--mem=MB] [--tmp=MB] [-C list]\n"
 "              [--account=name] [--dependency=jobid] [--comment=name]\n"
@@ -1298,7 +1298,9 @@ static void _usage(void)
 "              [--geometry=XxYxZ] [--conn-type=type] [--no-rotate] [ --reboot]\n"
 #endif
 "              [--mail-type=type] [--mail-user=user][--nice[=value]]\n"
-"              [-w hosts...] [-x hosts...] executable [args...]\n");
+"              [--bell] [--no-bell] [--kill-command[=signal]]\n"
+"              [--nodefile=file] [--nodelist=hosts] [--exclude=hosts]\n"
+"              executable [args...]\n");
 }
 
 static void _help(void)
@@ -1308,13 +1310,14 @@ static void _help(void)
 "\n"
 "Parallel run options:\n"
 "  -N, --nodes=N               number of nodes on which to run (N = min[-max])\n"
-"  -n, --procs=N               number of processors required\n"
+"  -n, --tasks=N               number of processors required\n"
 "  -c, --cpus-per-task=ncpus   number of cpus required per task\n"
 "  -p, --partition=partition   partition requested\n"
 "  -H, --hold                  submit job in held state\n"
 "  -t, --time=minutes          time limit\n"
 "  -I, --immediate             exit if resources are not immediately available\n"
 "  -k, --no-kill               do not kill job on node failure\n"
+"  -K, --kill-command[=signal] signal to send terminating job\n"
 "  -s, --share                 share nodes with other jobs\n"
 "  -J, --job-name=jobname      name of job\n"
 "      --jobid=id              specify jobid to use\n"
@@ -1329,6 +1332,10 @@ static void _help(void)
 "      --comment=name          arbitrary comment\n"
 "      --mail-type=type        notify on state change: BEGIN, END, FAIL or ALL\n"
 "      --mail-user=user        who to send email notification for job state changes\n"
+"      --bell                  ring the terminal bell when the job is allocated\n"
+"      --no-bell               do NOT ring the terminal bell\n"
+"      --gid=group_id          group ID to run job as (user root only)\n"
+"      --uid=user_id           user ID to run job as (user root only)\n"
 "\n"
 "Constraint options:\n"
 "      --mincpus=n             minimum number of cpus per node\n"
@@ -1339,6 +1346,7 @@ static void _help(void)
 "      --tmp=MB                minimum amount of temporary disk\n"
 "      --contiguous            demand a contiguous range of nodes\n"
 "  -C, --constraint=list       specify a list of constraints\n"
+"  -F, --nodefile=filename     request a specific list of hosts\n"
 "  -w, --nodelist=hosts...     request a specific list of hosts\n"
 "  -x, --exclude=hosts...      exclude a specific list of hosts\n"
 "\n"
diff --git a/src/salloc/salloc.c b/src/salloc/salloc.c
index e023f005f684451839c02e844d0dba04244d296a..cd9bc574437b4c1cbd529339ac17491d84e77342 100644
--- a/src/salloc/salloc.c
+++ b/src/salloc/salloc.c
@@ -301,8 +301,10 @@ static int fill_job_desc_from_opts(job_desc_msg_t *desc)
 
 static void ring_terminal_bell(void)
 {
-	fprintf(stdout, "\a");
-	fflush(stdout);
+        if (isatty(STDOUT_FILENO)) {
+                fprintf(stdout, "\a");
+                fflush(stdout);
+        }
 }
 
 /* returns the pid of the forked command, or <0 on error */
diff --git a/src/sbatch/opt.c b/src/sbatch/opt.c
index 9efa3680cac0c749f550e02da30231e2d66f193f..c24bbf7e7b08534d24bfc54b763a5f33e45ec162 100644
--- a/src/sbatch/opt.c
+++ b/src/sbatch/opt.c
@@ -1611,8 +1611,8 @@ static void _usage(void)
 "              [-c ncpus] [-r n] [-p partition] [--hold] [-t minutes]\n"
 "              [-D path] [--immediate] [--no-kill]\n"
 "              [--input file] [--output file] [--error file]\n"
-"              [--share] [-m dist] [-J jobname]\n"
-"              [--jobid=id] [--verbose]\n"
+"              [--workdir=directory] [--share] [-m dist] [-J jobname]\n"
+"              [--jobid=id] [--verbose] [--gid=group] [--uid=user]\n"
 "              [-W sec] [--minsockets=n] [--mincores=n] [--minthreads=n]\n"
 "              [--contiguous] [--mincpus=n] [--mem=MB] [--tmp=MB] [-C list]\n"
 "              [--account=name] [--dependency=jobid] [--comment=name]\n"
@@ -1623,7 +1623,8 @@ static void _usage(void)
 #endif
 "              [--mail-type=type] [--mail-user=user][--nice[=value]]\n"
 "              [--no-requeue] [--ntasks-per-node=n]\n"
-"              [-w hosts...] [-x hosts...] executable [args...]\n");
+"              [--nodefile=file] [--nodelist=hosts] [--exclude=hosts]\n"
+"              executable [args...]\n");
 }
 
 static void _help(void)
@@ -1651,12 +1652,15 @@ static void _help(void)
 "  -v, --verbose               verbose mode (multiple -v's increase verbosity)\n"
 "  -q, --quiet                 quiet mode (suppress informational messages)\n"
 "  -d, --dependency=jobid      defer job until specified jobid completes\n"
+"  -D, --workdir=directory     set working directory for batch script\n"
 "      --nice[=value]          decrease secheduling priority by value\n"
 "  -U, --account=name          charge job to specified account\n"
 "      --begin=time            defer job until HH:MM DD/MM/YY\n"
 "      --comment=name          arbitrary comment\n"
 "      --mail-type=type        notify on state change: BEGIN, END, FAIL or ALL\n"
 "      --mail-user=user        who to send email notification for job state changes\n"
+"      --gid=group_id          group ID to run job as (user root only)\n"
+"      --uid=user_id           user ID to run job as (user root only)\n"
 "      --get-user-env          used by Moab.  See srun man page.\n"
 "      --no-requeue            if set, do not permit the job to be requeued\n"
 "\n"
@@ -1669,6 +1673,7 @@ static void _help(void)
 "      --tmp=MB                minimum amount of temporary disk\n"
 "      --contiguous            demand a contiguous range of nodes\n"
 "  -C, --constraint=list       specify a list of constraints\n"
+"  -F, --nodefile=filename     request a specific list of hosts\n"
 "  -w, --nodelist=hosts...     request a specific list of hosts\n"
 "  -x, --exclude=hosts...      exclude a specific list of hosts\n"
 "\n"
diff --git a/src/slurmctld/agent.c b/src/slurmctld/agent.c
index 689dcd995be84a6b77afcd38691f0e3cfd618d1e..28aaa27bd190e18180fd935dcf8d54d83ec0c062 100644
--- a/src/slurmctld/agent.c
+++ b/src/slurmctld/agent.c
@@ -725,6 +725,26 @@ static inline int _comm_err(char *node_name)
 	return rc;
 }
 
+/* return a value for wihc WEXITSTATUS returns 1 */
+static int _wif_status(void)
+{
+	static int rc = 0;
+	int i;
+
+	if (rc)
+		return rc;
+
+	rc = 1;
+	for (i=0; i<64; i++) {
+		if (WEXITSTATUS(rc))
+			return rc;
+		rc = rc << 1;
+	}
+	error("Could not identify WEXITSTATUS");
+	rc = 1;
+	return rc;
+}
+
 /*
  * _thread_per_group_rpc - thread to issue an RPC for a group of nodes
  *                         sending message out to one and forwarding it to
@@ -859,7 +879,7 @@ static void *_thread_per_group_rpc(void *args)
 			thread_state = DSH_DONE;
 			ret_data_info->err = thread_state;
 			lock_slurmctld(job_write_lock);
-			job_complete(job_id, 0, false, 1);
+			job_complete(job_id, 0, false, _wif_status());
 			unlock_slurmctld(job_write_lock);
 			continue;
 		}
diff --git a/src/slurmctld/node_scheduler.c b/src/slurmctld/node_scheduler.c
index 49bf2fb753d4723c89ec4ede93386f4d61897d71..9900881a38d795616fbe14310cf54c82af63e441 100644
--- a/src/slurmctld/node_scheduler.c
+++ b/src/slurmctld/node_scheduler.c
@@ -63,7 +63,10 @@
 #include "src/slurmctld/sched_plugin.h"
 #include "src/slurmctld/slurmctld.h"
 
-#define MAX_RETRIES 10
+#define FEATURE_OP_OR  0
+#define FEATURE_OP_AND 1
+#define MAX_FEATURES  32	/* max exclusive features "[fs1|fs2]"=2 */
+#define MAX_RETRIES   10
 
 struct node_set {		/* set of nodes with same configuration */
 	uint32_t cpus_per_node;	/* NOTE: This is the minimum count,
@@ -74,7 +77,7 @@ struct node_set {		/* set of nodes with same configuration */
 	uint32_t real_memory;
 	uint32_t nodes;
 	uint32_t weight;
-	int feature;
+	bitstr_t *feature_bits;
 	bitstr_t *my_bitmap;
 };
 
@@ -104,7 +107,7 @@ static int _pick_best_nodes(struct node_set *node_set_ptr,
 			    struct part_record *part_ptr,
 			    uint32_t min_nodes, uint32_t max_nodes,
 			    uint32_t req_nodes);
-static int _valid_features(char *requested, char *available);
+static bitstr_t *_valid_features(char *requested, char *available);
 
 
 /*
@@ -499,7 +502,8 @@ _pick_best_nodes(struct node_set *node_set_ptr, int node_set_size,
 			job_ptr->details->job_max_memory = 0;
 		}
 
-                debug3("Job %u in exclusive mode? %d cr_enabled %d CR type %d num_procs %d", 
+                debug3("Job %u in exclusive mode? "
+		     "%d cr_enabled %d CR type %d num_procs %d", 
 		     job_ptr->job_id, 
 		     job_ptr->details->shared ? 0 : 1,
 		     cr_enabled,
@@ -617,21 +621,23 @@ _pick_best_nodes(struct node_set *node_set_ptr, int node_set_size,
 		total_nodes = total_cpus = 0;	/* reinitialize */
 	}
 
-	/* identify how many feature sets we have (e.g. "[fs1|fs2|fs3|fs4]" */
-	max_feature = min_feature = node_set_ptr[0].feature;
-	for (i = 1; i < node_set_size; i++) {
-		if (node_set_ptr[i].feature > max_feature)
-			max_feature = node_set_ptr[i].feature;
-		if (node_set_ptr[i].feature < min_feature)
-			min_feature = node_set_ptr[i].feature;
+	/* identify the min and max feature values for exclusive OR */
+	max_feature = -1;
+	min_feature = MAX_FEATURES;
+	for (i = 0; i < node_set_size; i++) {
+		j = bit_ffs(node_set_ptr[i].feature_bits);
+		if ((j >= 0) && (j < min_feature))
+			min_feature = j;
+		j = bit_fls(node_set_ptr[i].feature_bits);
+		if ((j >= 0) && (j > max_feature))
+			max_feature = j;
 	}
-	
+		
 	for (j = min_feature; j <= max_feature; j++) {
 		for (i = 0; i < node_set_size; i++) {
 			bool pick_light_load = false;
-			if (node_set_ptr[i].feature != j)
+			if (!bit_test(node_set_ptr[i].feature_bits, j))
 				continue;
-			
 			if (!runable_ever) {
 				int cr_disabled = 0;
 				total_mem = 0;
@@ -659,24 +665,9 @@ _pick_best_nodes(struct node_set *node_set_ptr, int node_set_size,
 			/* shared needs to be checked before cr_enabled
 			 * to make sure that CR_MEMORY works correctly. */ 
 			if (shared) {
-#ifdef HAVE_BG
-				/* If any nodes which can be used have jobs in 
-				 * COMPLETING state then do not schedule the  
-				 * job, this give time to insure Epilog 
-				 * completes before possibly scheduling another
-				 * job to the same bgblock. We also want to 
-				 * route the job to the smallest usable block*/
-				int ni;
-				bit_and(node_set_ptr[i].my_bitmap,
-					share_node_bitmap);
-				for (ni = 0; ni < node_record_count; ni++) {
-					if (node_record_table_ptr[ni].
-					    node_state & NODE_STATE_COMPLETING)
-						continue;
-				}
-#else
 				bit_and(node_set_ptr[i].my_bitmap,
 					share_node_bitmap);
+#ifndef HAVE_BG
 				pick_light_load = true;
 #endif
 			} else if (cr_enabled) {
@@ -757,13 +748,14 @@ _pick_best_nodes(struct node_set *node_set_ptr, int node_set_size,
 				FREE_NULL_BITMAP(avail_bitmap);
 				avail_bitmap = backup_bitmap;
 			}
-		}
+		} /* for (i = 0; i < node_set_size; i++) */
 
 		/* try to get req_nodes now for this feature */
-		if ((req_nodes   >  min_nodes) && 
-		    (avail_nodes >= min_nodes) &&
-		    (avail_nodes <  req_nodes) &&
-		    ((job_ptr->details->req_node_bitmap == NULL) ||
+		if (avail_bitmap
+		&&  (req_nodes   >  min_nodes) 
+		&&  (avail_nodes >= min_nodes)
+		&&  (avail_nodes <  req_nodes)
+		&&  ((job_ptr->details->req_node_bitmap == NULL) ||
 		     bit_super_set(job_ptr->details->req_node_bitmap, 
                                         avail_bitmap))) {
 			pick_code = select_g_job_test(job_ptr, avail_bitmap, 
@@ -785,12 +777,13 @@ _pick_best_nodes(struct node_set *node_set_ptr, int node_set_size,
 		/* determine if job could possibly run (if all configured 
 		 * nodes available) */
 
-		if ((!runable_ever || !runable_avail)
-		    &&  (total_nodes >= min_nodes)
-		    &&  ((slurmctld_conf.fast_schedule == 0) ||
-			 (total_cpus >= job_ptr->num_procs))
-		    &&  ((job_ptr->details->req_node_bitmap == NULL) ||
-			 (bit_super_set(job_ptr->details->req_node_bitmap, 
+		if (total_bitmap
+		&&  (!runable_ever || !runable_avail)
+		&&  (total_nodes >= min_nodes)
+		&&  ((slurmctld_conf.fast_schedule == 0) ||
+		     (total_cpus >= job_ptr->num_procs))
+		&&  ((job_ptr->details->req_node_bitmap == NULL) ||
+		     (bit_super_set(job_ptr->details->req_node_bitmap, 
 					total_bitmap)))) {
 			if (!runable_avail) {
 				FREE_NULL_BITMAP(avail_bitmap);
@@ -1169,8 +1162,10 @@ extern int select_nodes(struct job_record *job_ptr, bool test_only,
 	else
 		FREE_NULL_BITMAP(select_bitmap);
 	if (node_set_ptr) {
-		for (i = 0; i < node_set_size; i++)
+		for (i = 0; i < node_set_size; i++) {
 			FREE_NULL_BITMAP(node_set_ptr[i].my_bitmap);
+			FREE_NULL_BITMAP(node_set_ptr[i].feature_bits);
+		}
 		xfree(node_set_ptr);
 	}
 	return error_code;
@@ -1192,10 +1187,11 @@ static int _build_node_list(struct job_record *job_ptr,
 	struct config_record *config_ptr;
 	struct part_record *part_ptr = job_ptr->part_ptr;
 	ListIterator config_iterator;
-	int tmp_feature, check_node_config, config_filter = 0;
+	int check_node_config, config_filter = 0;
 	struct job_details *detail_ptr = job_ptr->details;
 	bitstr_t *exc_node_mask = NULL;
 	multi_core_data_t *mc_ptr = detail_ptr->mc_ptr;
+	bitstr_t *tmp_feature;
 
 	node_set_inx = 0;
 	node_set_ptr = (struct node_set *) 
@@ -1214,10 +1210,6 @@ static int _build_node_list(struct job_record *job_ptr,
 
 	while ((config_ptr = (struct config_record *) 
 			list_next(config_iterator))) {
-		tmp_feature = _valid_features(job_ptr->details->features,
-					      config_ptr->feature);
-		if (tmp_feature == 0)
-			continue;
 
 		config_filter = 0;
 		if ((detail_ptr->job_min_procs    > config_ptr->cpus       )
@@ -1246,32 +1238,42 @@ static int _build_node_list(struct job_record *job_ptr,
 			check_node_config = 0;
 
 		node_set_ptr[node_set_inx].my_bitmap =
-		    bit_copy(config_ptr->node_bitmap);
+			bit_copy(config_ptr->node_bitmap);
 		if (node_set_ptr[node_set_inx].my_bitmap == NULL)
 			fatal("bit_copy malloc failure");
 		bit_and(node_set_ptr[node_set_inx].my_bitmap,
 			part_ptr->node_bitmap);
-		if (exc_node_mask)
+		if (exc_node_mask) {
 			bit_and(node_set_ptr[node_set_inx].my_bitmap,
 				exc_node_mask);
+		}
 		node_set_ptr[node_set_inx].nodes =
 			bit_set_count(node_set_ptr[node_set_inx].my_bitmap);
-		if (check_node_config && 
-		    (node_set_ptr[node_set_inx].nodes != 0))
+		if (check_node_config 
+		&&  (node_set_ptr[node_set_inx].nodes != 0)) {
 			_filter_nodes_in_set(&node_set_ptr[node_set_inx], 
 					     detail_ptr);
-
+		}
 		if (node_set_ptr[node_set_inx].nodes == 0) {
 			FREE_NULL_BITMAP(node_set_ptr[node_set_inx].my_bitmap);
 			continue;
 		}
+
+		tmp_feature = _valid_features(job_ptr->details->features,
+					      config_ptr->feature);
+		if (tmp_feature == NULL) {
+			FREE_NULL_BITMAP(node_set_ptr[node_set_inx].my_bitmap);
+			continue;
+		}
+		/* NOTE: Must bit_free(tmp_feature) to avoid memory leak */
+
 		node_set_ptr[node_set_inx].cpus_per_node =
 			config_ptr->cpus;
 		node_set_ptr[node_set_inx].real_memory =
 			config_ptr->real_memory;		
 		node_set_ptr[node_set_inx].weight =
 		    config_ptr->weight;
-		node_set_ptr[node_set_inx].feature = tmp_feature;
+		node_set_ptr[node_set_inx].feature_bits = tmp_feature;
 		debug2("found %d usable nodes from config containing %s",
 		       node_set_ptr[node_set_inx].nodes, config_ptr->nodes);
 
@@ -1283,6 +1285,7 @@ static int _build_node_list(struct job_record *job_ptr,
 	list_iterator_destroy(config_iterator);
 	/* eliminate last (incomplete) node_set record */
 	FREE_NULL_BITMAP(node_set_ptr[node_set_inx].my_bitmap);
+	FREE_NULL_BITMAP(node_set_ptr[node_set_inx].feature_bits);
 	FREE_NULL_BITMAP(exc_node_mask);
 
 	if (node_set_inx == 0) {
@@ -1516,30 +1519,35 @@ extern void build_node_details(struct job_record *job_ptr)
  *	slurm administrator and user guides for details. returns 1 if 
  *	requirements are satisfied without mutually exclusive feature list.
  */
-static int _valid_features(char *requested, char *available)
+static bitstr_t *_valid_features(char *requested, char *available)
 {
 	char *tmp_requested, *str_ptr1;
-	int bracket, found, i, option, position, result;
+	int bracket, found, i, position, result;
 	int last_op;		/* last operation 0 for or, 1 for and */
 	int save_op = 0, save_result = 0;	/* for bracket support */
+	bitstr_t *result_bits = (bitstr_t *) NULL;
 
-	if (requested == NULL)
-		return 1;	/* no constraints */
-	if (available == NULL)
-		return 0;	/* no features */
+	if (requested == NULL) {		/* no constraints */
+		result_bits = bit_alloc(MAX_FEATURES);
+		bit_set(result_bits, 0);
+		return result_bits;
+	}
+	if (available == NULL)			/* no features */
+		return result_bits;
 
 	tmp_requested = xstrdup(requested);
-	bracket = option = position = 0;
+	bracket = position = 0;
 	str_ptr1 = tmp_requested;	/* start of feature name */
-	result = last_op = 1;	/* assume good for now */
-	for (i = 0;; i++) {
+	result = 1;			/* assume good for now */
+	last_op = FEATURE_OP_AND;
+	for (i=0; ; i++) {
 		if (tmp_requested[i] == (char) NULL) {
 			if (strlen(str_ptr1) == 0)
 				break;
 			found = _match_feature(str_ptr1, available);
-			if (last_op == 1)	/* and */
+			if (last_op == FEATURE_OP_AND)
 				result &= found;
-			else	/* or */
+			else	/* FEATURE_OP_OR */
 				result |= found;
 			break;
 		}
@@ -1553,53 +1561,67 @@ static int _valid_features(char *requested, char *available)
 			}
 			tmp_requested[i] = (char) NULL;
 			found = _match_feature(str_ptr1, available);
-			if (last_op == 1)	/* and */
+			if (last_op == FEATURE_OP_AND)
 				result &= found;
-			else	/* or */
+			else	/* FEATURE_OP_OR */
 				result |= found;
 			str_ptr1 = &tmp_requested[i + 1];
-			last_op = 1;	/* and */
+			last_op = FEATURE_OP_AND;
 
 		} else if (tmp_requested[i] == '|') {
 			tmp_requested[i] = (char) NULL;
 			found = _match_feature(str_ptr1, available);
 			if (bracket != 0) {
-				if (found)
-					option = position;
+				if (found) {
+					if (!result_bits)
+						result_bits = bit_alloc(MAX_FEATURES);
+					if (position < MAX_FEATURES)
+						bit_set(result_bits, (position-1));
+					else
+						error("_valid_features: overflow");
+				}
 				position++;
 			}
-			if (last_op == 1)	/* and */
+			if (last_op == FEATURE_OP_AND)
 				result &= found;
-			else	/* or */
+			else	/* FEATURE_OP_OR */
 				result |= found;
 			str_ptr1 = &tmp_requested[i + 1];
-			last_op = 0;	/* or */
+			last_op = FEATURE_OP_OR;
 
 		} else if (tmp_requested[i] == '[') {
 			bracket++;
 			position = 1;
 			save_op = last_op;
 			save_result = result;
-			last_op = result = 1;
+			last_op = FEATURE_OP_AND;
+			result = 1;
 			str_ptr1 = &tmp_requested[i + 1];
 
 		} else if (tmp_requested[i] == ']') {
 			tmp_requested[i] = (char) NULL;
 			found = _match_feature(str_ptr1, available);
-			if (found)
-				option = position;
+			if (found) {
+				if (!result_bits)
+					result_bits = bit_alloc(MAX_FEATURES);
+				if (position < MAX_FEATURES)
+					bit_set(result_bits, (position-1));
+				else
+					error("_valid_features: overflow");
+			}
+			position++;
 			result |= found;
-			if (save_op == 1)	/* and */
+			if (save_op == FEATURE_OP_AND)
 				result &= save_result;
-			else	/* or */
+			else	/* FEATURE_OP_OR */
 				result |= save_result;
 			if ((tmp_requested[i + 1] == '&')
 			    && (bracket == 1)) {
-				last_op = 1;
+				last_op = FEATURE_OP_AND;
 				str_ptr1 = &tmp_requested[i + 2];
 			} else if ((tmp_requested[i + 1] == '|')
 				   && (bracket == 1)) {
-				last_op = 0;
+				last_op = FEATURE_OP_OR;
 				str_ptr1 = &tmp_requested[i + 2];
 			} else if ((tmp_requested[i + 1] == (char) NULL)
 				   && (bracket == 1)) {
@@ -1613,11 +1635,18 @@ static int _valid_features(char *requested, char *available)
 			bracket = 0;
 		}
 	}
-
-	if (position)
-		result *= option;
 	xfree(tmp_requested);
-	return result;
+
+	if (result) {
+		if (!result_bits) {
+			result_bits = bit_alloc(MAX_FEATURES);
+			bit_set(result_bits, 0);
+		}
+	} else {
+		FREE_NULL_BITMAP(result_bits);
+	}
+
+	return result_bits;
 }
 
 /*