diff --git a/src/slurmctld/node_scheduler.c b/src/slurmctld/node_scheduler.c
index cd17c4d2d1ca6bd5d4bce3f39052efa181c22e92..3dd18a34204f65f168ac93727bca8fb02b85116d 100644
--- a/src/slurmctld/node_scheduler.c
+++ b/src/slurmctld/node_scheduler.c
@@ -26,15 +26,17 @@
 
 int Is_Key_Valid(int Key);
 int Match_Group(char *AllowGroups, char *UserGroups);
+int Match_Feature(char *Seek, char *Available);
 int Parse_Job_Specs(char *Job_Specs, char **Req_Features, char **Req_Node_List, char **Job_Name,
 	char **Req_Group, char **Req_Partition, int *Contiguous, int *Req_CPUs, 
-	int *Req_Nodes, int *Min_CPUs, int *Min_Memory, int *Min_TmpDisk, int *Key);
+	int *Req_Nodes, int *Min_CPUs, int *Min_Memory, int *Min_TmpDisk, int *Key, int *Shared);
 int ValidFeatures(char *Requested, char *Available);
 
 struct Node_Set {	/* Set of nodes with same configuration that could be allocated */
 	int CPUs_Per_Node;
 	int Nodes;
 	int Weight;
+	int Feature;
 	unsigned *My_BitMap;
 };
 
@@ -76,6 +78,19 @@ main(int argc, char * argv[]) {
 	exit(1);
     } /* if */
 
+    i = ValidFeatures("FS1&FS2","FS1");
+    if (i != 0) printf("ValidFeatures error 1\n");
+    i = ValidFeatures("FS1|FS2","FS1");
+    if (i != 1) printf("ValidFeatures error 2\n");
+    i = ValidFeatures("FS1|FS2&FS3","FS1,FS3");
+    if (i != 1) printf("ValidFeatures error 3\n");
+    i = ValidFeatures("[FS1|FS2]&FS3","FS2,FS3");
+    if (i != 2) printf("ValidFeatures error 4\n");
+    i = ValidFeatures("FS0&[FS1|FS2]&FS3","FS2,FS3");
+    if (i != 0) printf("ValidFeatures error 5\n");
+    i = ValidFeatures("FS3&[FS1|FS2]&FS3","FS2,FS3");
+    if (i != 2) printf("ValidFeatures error 6\n");
+
     Line_Num = 0;
     printf("\n");
     while (fgets(In_Line, BUF_SIZE, Command_File)) {
@@ -138,6 +153,45 @@ int Is_Key_Valid(int Key) {
 }  /* Is_Key_Valid */
 
 
+/*
+ * Match_Feature - Determine if the desired feature (Seek) is one of those available
+ * Input: Seek - Desired feature
+ *        Available - Comma separated list of features
+ * Output: Returns 1 if found, 0 otherwise
+ */
+int Match_Feature(char *Seek, char *Available) {
+    char *Tmp_Available, *str_ptr3, *str_ptr4;
+    int found;
+
+    if (Seek      == NULL) return 1;	/* Nothing to look for */
+    if (Available == NULL) return 0;	/* Nothing to find */
+
+    Tmp_Available = malloc(strlen(Available)+1);
+    if (Tmp_Available == NULL) {
+#if DEBUG_SYSTEM
+	fprintf(stderr, "Match_Feature: unable to allocate memory\n");
+#else
+	syslog(LOG_ALERT, "Match_Feature: unable to allocate memory\n");
+#endif
+	return 1; /* Assume good for now */
+    } /* if */
+    strcpy(Tmp_Available, Available);
+
+    found = 0;
+    str_ptr3 = (char *)strtok_r(Tmp_Available, ",", &str_ptr4);
+    while (str_ptr3) {
+	if (strcmp(Seek, str_ptr3) == 0) {  /* We have a match */
+	    found = 1;
+	    break;
+	} /* if */
+	str_ptr3 = (char *)strtok_r(NULL, ",", &str_ptr4);
+    } /* while (str_ptr3) */
+
+    free(Tmp_Available);
+    return found;
+} /* Match_Feature */
+
+
 /*
  * Match_Group - Determine if the user is a member of any groups permitted to use this partition
  * Input: AllowGroups - Comma delimited list of groups permitted to use the partition, 
@@ -205,12 +259,13 @@ int Match_Group(char *AllowGroups, char *UserGroups) {
  */
 int Parse_Job_Specs(char *Job_Specs, char **Req_Features, char **Req_Node_List, char **Job_Name,
 	char **Req_Group, char **Req_Partition, int *Contiguous, int *Req_CPUs, 
-	int *Req_Nodes, int *Min_CPUs, int *Min_Memory, int *Min_TmpDisk, int *Key) {
+	int *Req_Nodes, int *Min_CPUs, int *Min_Memory, int *Min_TmpDisk, int *Key, int *Shared) {
     int Bad_Index, Error_Code, i;
     char *Temp_Specs;
 
     Req_Features[0] = Req_Node_List[0] = Req_Group[0] = Req_Partition[0] = Job_Name[0] = NULL;
     *Contiguous = *Req_CPUs = *Req_Nodes = *Min_CPUs = *Min_Memory = *Min_TmpDisk = NO_VAL;
+    *Key = *Shared = NO_VAL;
 
     Temp_Specs = malloc(strlen(Job_Specs)+1);
     if (Temp_Specs == NULL) {
@@ -259,6 +314,9 @@ int Parse_Job_Specs(char *Job_Specs, char **Req_Features, char **Req_Node_List,
     Error_Code = Load_Integer (Key, "Key=", Temp_Specs);
     if (Error_Code) goto cleanup;
 
+    Error_Code = Load_Integer (Shared, "Shared=", Temp_Specs);
+    if (Error_Code) goto cleanup;
+
     Bad_Index = -1;
     for (i=0; i<strlen(Temp_Specs); i++) {
 	if (isspace((int)Temp_Specs[i]) || (Temp_Specs[i] == '\n')) continue;
@@ -307,9 +365,13 @@ cleanup:
 int Pick_Best_Nodes(struct Node_Set *Node_Set_Ptr, int Node_Set_Size, 
 	unsigned **Req_BitMap, int Req_CPUs, int  Req_Nodes, int Contiguous) {
     int Error_Code, i;
-    int Total_Nodes, Total_CPUs;
+    int Total_Nodes, Total_CPUs;	/* Total resources configured in partition */
+    int Avail_Nodes, Avail_CPUs;	/* Resources available for use now */
+    int *CPUs_Per_Node;
 
-    Error_Code = Total_Nodes = Total_CPUs = 0;
+    Error_Code = 0;
+    Total_Nodes = Total_CPUs = 0;
+    Avail_Nodes = Avail_CPUs = 0;
     if (Req_BitMap[0]) {	/* Specific nodes required */
 				/* Already confirmed nodes are up, available and contiguous */
 	if (Req_Nodes != NO_VAL) Total_Nodes=BitMapCount(Req_BitMap[0]);
@@ -319,7 +381,17 @@ int Pick_Best_Nodes(struct Node_Set *Node_Set_Ptr, int Node_Set_Size,
 printf("More work to be done here: Add nodes to given list to satisfy CPU and/or node requirements\n");
 
     } else {			/* Any nodes usable */
-printf("More work to be done here\n");
+	if (Node_Set_Size == 0) return EINVAL;
+printf("More work to be done here: Add nodes to given list to satisfy CPU and/or node requirements\n");
+	for (i=0; i<Node_Set_Size; i++) {
+	    if (i==0) 
+		Req_BitMap[0] = BitMapCopy(Node_Set_Ptr[i].My_BitMap);
+	    else
+		BitMapOR(Req_BitMap[0], Node_Set_Ptr[i].My_BitMap);
+	    Total_Nodes += Node_Set_Ptr[i].Nodes;
+	    Total_CPUs += (Node_Set_Ptr[i].Nodes * Node_Set_Ptr[i].CPUs_Per_Node);
+	    if ((Total_Nodes >= Req_Nodes) && (Total_CPUs >= Req_CPUs)) break;
+	} /* for */
     } /* else */
 
     return Error_Code;
@@ -338,7 +410,7 @@ printf("More work to be done here\n");
 int Select_Nodes(char *Job_Specs, char **Node_List) {
     char *Req_Features, *Req_Node_List, *Job_Name, *Req_Group, *Req_Partition, *Out_Line;
     int Contiguous, Req_CPUs, Req_Nodes, Min_CPUs, Min_Memory, Min_TmpDisk;
-    int Error_Code, CPU_Tally, Node_Tally, Key;
+    int Error_Code, CPU_Tally, Node_Tally, Key, Shared;
     struct Part_Record *Part_Ptr;
     unsigned *Req_BitMap, *Scratch_BitMap;
     ListIterator Config_Record_Iterator;	/* For iterating through Config_List */
@@ -349,7 +421,8 @@ int Select_Nodes(char *Job_Specs, char **Node_List) {
 
     Req_Features = Req_Node_List = Req_Group = Req_Partition = NULL;
     Req_BitMap = Scratch_BitMap = NULL;
-    Contiguous = Req_CPUs = Req_Nodes = Min_CPUs = Min_Memory = Min_TmpDisk = Key = NO_VAL;
+    Contiguous = Req_CPUs = Req_Nodes = Min_CPUs = Min_Memory = Min_TmpDisk = NO_VAL;
+    Key = Shared = NO_VAL;
     Node_Set_Ptr = NULL;
     Config_Record_Iterator = NULL;
     Node_List[0] = NULL;
@@ -357,7 +430,7 @@ int Select_Nodes(char *Job_Specs, char **Node_List) {
     /* Setup and basic parsing */
     Error_Code = Parse_Job_Specs(Job_Specs, &Req_Features, &Req_Node_List, &Job_Name, &Req_Group, 
 		&Req_Partition, &Contiguous, &Req_CPUs, &Req_Nodes, &Min_CPUs, 
-		&Min_Memory, &Min_TmpDisk, &Key);
+		&Min_Memory, &Min_TmpDisk, &Key, &Shared);
     if (Error_Code == ENOMEM) {
 	Error_Code = EAGAIN;	/* Don't want to kill the job off */
 	goto cleanup;
@@ -505,10 +578,14 @@ int Select_Nodes(char *Job_Specs, char **Node_List) {
     } /* if */
 
     while (Config_Record_Point = (struct Config_Record *)list_next(Config_Record_Iterator)) {
-	if ((Min_CPUs    != NO_VAL) && (Min_CPUs    > Config_Record_Point->CPUs))       continue;
-	if ((Min_Memory  != NO_VAL) && (Min_Memory  > Config_Record_Point->RealMemory)) continue;
-	if ((Min_TmpDisk != NO_VAL) && (Min_TmpDisk > Config_Record_Point->TmpDisk))    continue;
-	if (ValidFeatures(Req_Features,Config_Record_Point->Feature) == 0) continue;
+	int Tmp_Feature;
+/* Since nodes can register with more resources than defined in the configuration, we want   */
+/* to use those higher values for scheduling and ignore the values in the configuration file */
+/*	if ((Min_CPUs    != NO_VAL) && (Min_CPUs    > Config_Record_Point->CPUs))       continue; */
+/*	if ((Min_Memory  != NO_VAL) && (Min_Memory  > Config_Record_Point->RealMemory)) continue; */
+/*	if ((Min_TmpDisk != NO_VAL) && (Min_TmpDisk > Config_Record_Point->TmpDisk))    continue; */
+	Tmp_Feature = ValidFeatures(Req_Features, Config_Record_Point->Feature);
+	if (Tmp_Feature == 0) continue;
 
 	Node_Set_Ptr[Node_Set_Index].My_BitMap = BitMapCopy(Config_Record_Point->NodeBitMap);
 	if (Node_Set_Ptr[Node_Set_Index].My_BitMap == NULL) {
@@ -530,6 +607,7 @@ int Select_Nodes(char *Job_Specs, char **Node_List) {
 	    } /* if */
 	    Node_Set_Ptr[Node_Set_Index].CPUs_Per_Node = Config_Record_Point->CPUs;
 	    Node_Set_Ptr[Node_Set_Index].Weight = Config_Record_Point->Weight;
+	    Node_Set_Ptr[Node_Set_Index].Feature = Tmp_Feature;
 #if DEBUG_MODULE > 1
 	    printf("Found %d usable nodes from configuration with %s\n",
 		Node_Set_Ptr[Node_Set_Index].Nodes, Config_Record_Point->Nodes);
@@ -629,14 +707,17 @@ cleanup:
 /* ValidFeatures - Determine if the Requested features are satisfied by those Available
  * Input: Requested - Requested features (by a job)
  *        Available - Available features (on a node)
- * Output: Returns 0 if request is not satisfied, 1 otherwise
- * NOTE: This is only checking comma separated features (Interpretted as AND), 
- *       this should be expanded to support AND, OR, and parentheses "(&|)"
+ * Output: Returns 0 if request is not satisfied, otherwise an integer indicating 
+ *		which mutually exclusive feature is satisfied. For example
+ *		ValidFeatures("[FS1|FS2|FS3|FS4]", "FS3") returns 3. See the 
+ *		SLURM administrator and user guides for details. Returns 1 if 
+ *		requirements are satisfied without mutually exclusive feature list.
  */
 int ValidFeatures(char *Requested, char *Available) {
-    char *Tmp_Requested, *str_ptr1, *str_ptr2;
-    char *Tmp_Available, *str_ptr3, *str_ptr4;
-    int found;
+    char *Tmp_Requested, *str_ptr1;
+    int bracket, found, i, option, position, result;
+    int last_op;	/* Last operation 0 for OR, 1 for AND */
+    int save_op, save_result; /* For bracket support */
 
     if (Requested == NULL) return 1;	/* No constraints */
     if (Available == NULL) return 0;	/* No features */
@@ -652,34 +733,94 @@ int ValidFeatures(char *Requested, char *Available) {
     } /* if */
     strcpy(Tmp_Requested, Requested);
 
-    Tmp_Available = malloc(strlen(Available)+1);
-    if (Tmp_Available == NULL) {
+    bracket = option = position = 0;
+    str_ptr1 = Tmp_Requested;	/* Start of feature name */
+    result = last_op = 1;	/* Assume good for now */
+    for (i=0; ; i++) {
+printf("res:%d:last:%d:%c:\n",result,last_op,Tmp_Requested[i]);
+	if (Tmp_Requested[i] == (char)NULL) {
+	    if (strlen(str_ptr1) == 0) break;
+	    found = Match_Feature(str_ptr1, Available);
+	    if (last_op == 1)	/* AND */
+		result &= found;
+	    else		/* OR */
+		result |= found;
+	    break;
+	} /* if */
+
+	if (Tmp_Requested[i] == '&') {
+	    if (bracket != 0) {
 #if DEBUG_SYSTEM
-	fprintf(stderr, "ValidFeatures: unable to allocate memory\n");
+		fprintf(stderr, "ValidFeatures: Parsing failure 1 on %s\n", Requested);
 #else
-	syslog(LOG_ALERT, "ValidFeatures: unable to allocate memory\n");
+		syslog(LOG_NOTICE, "ValidFeatures: Parsing failure 1 on %s\n", Requested);
 #endif
-	free(Tmp_Requested);
-	return 1; /* Assume good for now */
-    } /* if */
-
-    found = 1;
-    str_ptr1 = (char *)strtok_r(Tmp_Requested, ",", &str_ptr2);
-    while (str_ptr1) {
-	found = 0;
-	strcpy(Tmp_Available, Available);
-	str_ptr3 = (char *)strtok_r(Tmp_Available, ",", &str_ptr4);
-	while (str_ptr3) {
-	    if (strcmp(str_ptr1, str_ptr3) == 0) {  /* We have a match */
-		found = 1;
+		result = 0;
 		break;
 	    } /* if */
-	    str_ptr3 = (char *)strtok_r(NULL, ",", &str_ptr4);
-	} /* while (str_ptr3) */
-	if (found == 0) break;
-	str_ptr1 = (char *)strtok_r(NULL, ",", &str_ptr2);
-    } /* while (str_ptr1) */
+	    Tmp_Requested[i] = (char)NULL;
+	    found = Match_Feature(str_ptr1, Available);
+	    if (last_op == 1)	/* AND */
+		result &= found;
+	    else		/* OR */
+		result |= found;
+	    str_ptr1 = &Tmp_Requested[i+1];
+	    last_op = 1;	/* AND */
+
+	} else if (Tmp_Requested[i] == '|') {
+	    Tmp_Requested[i] = (char)NULL;
+	    found = Match_Feature(str_ptr1, Available);
+	    if (bracket != 0) {
+		if (found) option=position;
+		position++;
+	    } 
+	    if (last_op == 1)	/* AND */
+		result &= found;
+	    else		/* OR */
+		result |= found;
+	    str_ptr1 = &Tmp_Requested[i+1];
+	    last_op = 0;	/* OR */
+
+	} else if (Tmp_Requested[i] == '[') {
+	    bracket++;
+	    position = 1;
+	    save_op = last_op;
+	    save_result = result;
+	    last_op = 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;
+	    result |= found;
+	    if (save_op == 1)	/* AND */
+		result &= save_result;
+	    else		/* OR */
+		result |= save_result;
+	    if ((Tmp_Requested[i+1] == '&') && (bracket == 1)) {
+		last_op = 1;
+		str_ptr1 = &Tmp_Requested[i+2];
+	    } else if ((Tmp_Requested[i+1] == '|') && (bracket == 1)) {
+		last_op = 0;
+		str_ptr1 = &Tmp_Requested[i+2];
+	    } else if ((Tmp_Requested[i+1] == (char)NULL) && (bracket == 1)) {
+		break;
+	    } else {
+#if DEBUG_SYSTEM
+		fprintf(stderr, "ValidFeatures: Parsing failure 2 on %s\n", Requested);
+#else
+		syslog(LOG_NOTICE, "ValidFeatures: Parsing failure 2 on %s\n", Requested);
+#endif
+		result = 0;
+		break;
+	    } /* else */
+	    bracket = 0;
+	} /* else */
+    } /* for */
+
+    if (position) result *= option;
     free(Tmp_Requested);
-    free(Tmp_Available);
-    return found;  /* No match */
+printf("Res:%d:last:%d:\n",result,last_op);
+    return result;
 } /* ValidFeatures */