From cbcfbccd476f98417a179afcf7b6f654e5d5ab0b Mon Sep 17 00:00:00 2001
From: Danny Auble <da@llnl.gov>
Date: Wed, 19 Aug 2009 19:42:59 +0000
Subject: [PATCH] infrastructure in place to begin work on qos stuff

---
 src/common/assoc_mgr.c                        |  77 +++-
 src/common/pack.h                             |  32 ++
 src/common/slurm_accounting_storage.c         | 273 +++++++++++---
 src/common/slurm_accounting_storage.h         |  13 +-
 .../mysql/accounting_storage_mysql.c          | 352 ++++++------------
 src/sacctmgr/common.c                         |  41 +-
 src/sacctmgr/qos_functions.c                  |  26 +-
 src/sacctmgr/sacctmgr.c                       |   2 +-
 src/sacctmgr/sacctmgr.h                       |   2 +
 9 files changed, 474 insertions(+), 344 deletions(-)

diff --git a/src/common/assoc_mgr.c b/src/common/assoc_mgr.c
index d54dce49fdb..f2429b1d006 100644
--- a/src/common/assoc_mgr.c
+++ b/src/common/assoc_mgr.c
@@ -50,8 +50,8 @@
 #define ASSOC_USAGE_VERSION 1
 
 acct_association_rec_t *assoc_mgr_root_assoc = NULL;
-uint32_t qos_max_priority = 0;
-
+uint32_t g_qos_max_priority = 0;
+uint32_t g_qos_count = 0;
 List assoc_mgr_association_list = NULL;
 List assoc_mgr_qos_list = NULL;
 List assoc_mgr_user_list = NULL;
@@ -287,6 +287,19 @@ static int _set_assoc_parent_and_user(acct_association_rec_t *assoc,
 			assoc->uid = (uint32_t)NO_VAL;
 		else
 			assoc->uid = pw_uid;	
+
+		/* get the qos bitmap here */
+		if(g_qos_count > 0) {
+			if(!assoc->valid_qos 
+			   || (bit_size(assoc->valid_qos) != g_qos_count)) {
+				FREE_NULL_BITMAP(assoc->valid_qos);
+				assoc->valid_qos = bit_alloc(g_qos_count);
+			} else
+				bit_nclear(assoc->valid_qos, 0,
+					   (bit_size(assoc->valid_qos) - 1));
+			set_qos_bitstr_from_list(assoc->valid_qos,
+						 assoc->qos_list);
+		}
 	} else {
 		assoc->uid = (uint32_t)NO_VAL;	
 	}
@@ -304,7 +317,7 @@ static int _post_association_list(List assoc_list)
 
 	if(!assoc_list)
 		return SLURM_ERROR;
-
+	
 	itr = list_iterator_create(assoc_list);
 	//START_TIMER;
 	while((assoc = list_next(itr))) {
@@ -452,16 +465,27 @@ static int _get_assoc_mgr_qos_list(void *db_conn, int enforce)
 		ListIterator itr = list_iterator_create(assoc_mgr_qos_list);
 		acct_qos_rec_t *qos = NULL;
 		while((qos = list_next(itr))) {
-			if(qos->priority > qos_max_priority) 
-				qos_max_priority = qos->priority;
+			/* get the highest qos value to create bitmaps
+			   from */
+			if(qos->id > g_qos_count)
+				g_qos_count = qos->id;
+
+			if(qos->priority > g_qos_max_priority) 
+				g_qos_max_priority = qos->priority;
 		}
+		/* Since in the database id's don't start at 1
+		   instead of 0 we need to ignore the 0 bit and start
+		   with 1 so increase the count by 1.
+		*/
+		if(g_qos_count > 0)
+			g_qos_count++;
 
-		if(qos_max_priority) {
+		if(g_qos_max_priority) {
 			list_iterator_reset(itr);
 			
 			while((qos = list_next(itr))) {
 				qos->norm_priority = (double)qos->priority 
-					/ (double)qos_max_priority;
+					/ (double)g_qos_max_priority;
 			}
 		}
 		list_iterator_destroy(itr);
@@ -772,16 +796,17 @@ extern int assoc_mgr_init(void *db_conn, assoc_init_args_t *args)
 	if(errno == ESLURM_ACCESS_DENIED)
 		return SLURM_ERROR;
 	
+	/* get qos before association since it is used there */
+	if((!assoc_mgr_qos_list) && (cache_level & ASSOC_MGR_CACHE_QOS))
+		if(_get_assoc_mgr_qos_list(db_conn, enforce) == SLURM_ERROR)
+			return SLURM_ERROR;
+
 	if((!assoc_mgr_association_list)
 	   && (cache_level & ASSOC_MGR_CACHE_ASSOC)) 
 		if(_get_assoc_mgr_association_list(db_conn, enforce)
 		   == SLURM_ERROR)
 			return SLURM_ERROR;
 		
-	if((!assoc_mgr_qos_list) && (cache_level & ASSOC_MGR_CACHE_QOS))
-		if(_get_assoc_mgr_qos_list(db_conn, enforce) == SLURM_ERROR)
-			return SLURM_ERROR;
-
 	if((!assoc_mgr_user_list) && (cache_level & ASSOC_MGR_CACHE_USER))
 		if(_get_assoc_mgr_user_list(db_conn, enforce) == SLURM_ERROR)
 			return SLURM_ERROR;
@@ -1158,10 +1183,8 @@ extern int assoc_mgr_fill_in_qos(void *db_conn, acct_qos_rec_t *qos,
 
 	qos->norm_priority = found_qos->norm_priority;
 
-	if(!qos->preemptee_list)
-		qos->preemptee_list = found_qos->preemptee_list;
-	if(!qos->preemptor_list)
-		qos->preemptor_list = found_qos->preemptor_list;
+	if(!qos->preempt_bitstr)
+		qos->preempt_bitstr = found_qos->preempt_bitstr;
 
 	qos->priority = found_qos->priority;
 
@@ -2025,10 +2048,11 @@ extern int assoc_mgr_update_qos(acct_update_object_t *update)
 
 	acct_association_rec_t *assoc = NULL;
 	int rc = SLURM_SUCCESS;
+	bool resize_qos_bitstr = 0;
 
-	if(!assoc_mgr_qos_list)
+	if(!assoc_mgr_qos_list) 
 		return SLURM_SUCCESS;
-
+	
 	slurm_mutex_lock(&assoc_mgr_qos_lock);
 	itr = list_iterator_create(assoc_mgr_qos_list);
 	while((object = list_pop(update->objects))) {
@@ -2047,7 +2071,12 @@ extern int assoc_mgr_update_qos(acct_update_object_t *update)
 				break;
 			}
 			list_append(assoc_mgr_qos_list, object);
-			object = NULL;			
+			if(object->id+1 > g_qos_count) {
+				resize_qos_bitstr = 1;
+				g_qos_count = object->id+1;
+			}
+			object = NULL;	
+	
 			break;
 		case ACCT_MODIFY_QOS:
 			/* FIX ME: fill in here the qos changes stuff */
@@ -2088,6 +2117,18 @@ extern int assoc_mgr_update_qos(acct_update_object_t *update)
 		}
 		destroy_acct_qos_rec(object);			
 	}
+
+	if(resize_qos_bitstr) {
+		list_iterator_reset(itr);
+		while((rec = list_next(itr))) {
+			if(!object->preempt_bitstr) 
+				continue;
+
+			object->preempt_bitstr = 
+				bit_realloc(object->preempt_bitstr,
+					    g_qos_count);
+		}
+	}
 	list_iterator_destroy(itr);
 	slurm_mutex_unlock(&assoc_mgr_qos_lock);
 
diff --git a/src/common/pack.h b/src/common/pack.h
index a3980de6e22..3b16d15adcd 100644
--- a/src/common/pack.h
+++ b/src/common/pack.h
@@ -320,6 +320,38 @@ int	unpackmem_array(char *valp, uint32_t size_valp, Buf buffer);
 		packmem(_tmp_str,_size,buf);	\
 	} else						\
 		packmem(NULL,(uint32_t)0,buf);		\
+} while (0)
+				
+#define pack_bit_str(bitmap,buf) do {	\
+	assert(buf->magic == BUF_MAGIC);		\
+	if (bitmap) {					\
+		char _tmp_str[0xfffe];			\
+		uint32_t _size;				\
+		bit_fmt(_tmp_str,0xfffe,bitmap);	\
+		_size = bit_size(bitmap);               \
+		pack32(_size, buf);              	\
+		_size = strlen(_tmp_str)+1;		\
+		packmem(_tmp_str,_size,buf);	        \
+	} else						\
+		pack32(NO_VAL, buf);                 	\
+} while (0)	
+			
+#define unpack_bit_str(bitmap,buf) do {	\
+	assert(bitmap != NULL);                         \
+	assert(*bitmap == NULL);                        \
+	assert(buf->magic == BUF_MAGIC);		\
+	if (bitmap) {					\
+		char *tmp_str = NULL;      		\
+		uint32_t _size = NO_VAL;		\
+		safe_unpack32(&_size, buf);             \
+		if(_size != NO_VAL) {                   \
+			*bitmap = bit_alloc(_size);	\
+			safe_unpackstr_xmalloc(&tmp_str, &_size, buf); \
+			bit_unfmt(*bitmap, tmp_str);    \
+			xfree(tmp_str);			\
+		} else					\
+			*bitmap = NULL;                 \
+	}                                               \
 } while (0)				
 
 #define unpackstr_ptr		                        \
diff --git a/src/common/slurm_accounting_storage.c b/src/common/slurm_accounting_storage.c
index 2d5d79a4166..22287e56d54 100644
--- a/src/common/slurm_accounting_storage.c
+++ b/src/common/slurm_accounting_storage.c
@@ -553,6 +553,7 @@ extern void destroy_acct_association_rec(void *object)
 		if(acct_association->qos_list)
 			list_destroy(acct_association->qos_list);
 		xfree(acct_association->user);
+		FREE_NULL_BITMAP(acct_association->valid_qos);
 		xfree(acct_association);
 	}
 }
@@ -566,10 +567,9 @@ extern void destroy_acct_qos_rec(void *object)
 		if(acct_qos->job_list)
 			list_destroy(acct_qos->job_list);
 		xfree(acct_qos->name);
-		if(acct_qos->preemptee_list)
-			list_destroy(acct_qos->preemptee_list);
-		if(acct_qos->preemptor_list)
-			list_destroy(acct_qos->preemptor_list);
+		FREE_NULL_BITMAP(acct_qos->preempt_bitstr);
+		if(acct_qos->preempt_list)
+			list_destroy(acct_qos->preempt_list);
 		if(acct_qos->user_limit_list)
 			list_destroy(acct_qos->user_limit_list);
 		xfree(acct_qos);
@@ -2362,8 +2362,8 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer)
 	acct_qos_rec_t *object = (acct_qos_rec_t *)in;	
 	uint32_t count = NO_VAL;
 	char *tmp_info = NULL;
-
-	if(rpc_version >= 5) {
+		
+	if(rpc_version >= 6) {
 		if(!object) {
 			packnull(buffer);
 			pack32(0, buffer);
@@ -2385,7 +2385,7 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer)
 
 			packnull(buffer);
 
-			pack32(NO_VAL, buffer);
+			pack_bit_str(NULL, buffer);
 			pack32(NO_VAL, buffer);
 
 			pack32(0, buffer);
@@ -2414,34 +2414,22 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer)
 
 		packstr(object->name, buffer);	
 
-		if(object->preemptee_list)
-			count = list_count(object->preemptee_list);
-
-		pack32(count, buffer);
-
-		if(count && count != NO_VAL) {
-			itr = list_iterator_create(object->preemptee_list);
-			while((tmp_info = list_next(itr))) {
-				packstr(tmp_info, buffer);
-			}
-			list_iterator_destroy(itr);
-		}
-		count = NO_VAL;
+		pack_bit_str(object->preempt_bitstr, buffer);
 		
-		if(object->preemptor_list)
-			count = list_count(object->preemptor_list);
+		if(object->preempt_list)
+			count = list_count(object->preempt_list);
 
 		pack32(count, buffer);
 
 		if(count && count != NO_VAL) {
-			itr = list_iterator_create(object->preemptor_list);
+			itr = list_iterator_create(object->preempt_list);
 			while((tmp_info = list_next(itr))) {
 				packstr(tmp_info, buffer);
 			}
 			list_iterator_destroy(itr);
 		}
 		count = NO_VAL;
-		
+
 		pack32(object->priority, buffer);
 		
 		packdouble(object->usage_factor, buffer);
@@ -2461,7 +2449,7 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer)
 			list_iterator_destroy(itr);
 		}
 		count = NO_VAL;
-	} else if(rpc_version >= 3) {
+	} else if(rpc_version >= 5) {
 		if(!object) {
 			packnull(buffer);
 			pack32(0, buffer);
@@ -2488,6 +2476,8 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer)
 
 			pack32(0, buffer);
 
+			packdouble(NO_VAL, buffer);
+
 			pack32(NO_VAL, buffer);
 			return;
 		}
@@ -2510,33 +2500,87 @@ extern void pack_acct_qos_rec(void *in, uint16_t rpc_version, Buf buffer)
 
 		packstr(object->name, buffer);	
 
-		if(object->preemptee_list)
-			count = list_count(object->preemptee_list);
+		/* These are here for the old preemptee preemptor
+		   lists we could figure this out from the
+		   preempt_bitstr, but qos wasn't used for anything
+		   before rpc_version 6 so just send NO_VALS */
+		pack32(NO_VAL, buffer);
+		pack32(NO_VAL, buffer);
+		
+		pack32(object->priority, buffer);
+		
+		packdouble(object->usage_factor, buffer);
+
+		if(object->user_limit_list)
+			count = list_count(object->user_limit_list);
 
 		pack32(count, buffer);
 
 		if(count && count != NO_VAL) {
-			itr = list_iterator_create(object->preemptee_list);
-			while((tmp_info = list_next(itr))) {
-				packstr(tmp_info, buffer);
+			acct_used_limits_t *used_limits = NULL;
+			itr = list_iterator_create(object->user_limit_list);
+			while((used_limits = list_next(itr))) {
+				pack_acct_used_limits(used_limits,
+						      rpc_version, buffer);
 			}
 			list_iterator_destroy(itr);
 		}
 		count = NO_VAL;
-		
-		if(object->preemptor_list)
-			count = list_count(object->preemptor_list);
+	} else if(rpc_version >= 3) {
+		if(!object) {
+			packnull(buffer);
+			pack32(0, buffer);
+			packnull(buffer);
 
-		pack32(count, buffer);
+			pack64(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
 
-		if(count && count != NO_VAL) {
-			itr = list_iterator_create(object->preemptor_list);
-			while((tmp_info = list_next(itr))) {
-				packstr(tmp_info, buffer);
-			}
-			list_iterator_destroy(itr);
+			pack64(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+
+			packnull(buffer);
+
+			pack32(NO_VAL, buffer);
+			pack32(NO_VAL, buffer);
+
+			pack32(0, buffer);
+
+			pack32(NO_VAL, buffer);
+			return;
 		}
-		count = NO_VAL;
+		packstr(object->description, buffer);	
+		pack32(object->id, buffer);
+
+		pack64(object->grp_cpu_mins, buffer);
+		pack32(object->grp_cpus, buffer);
+		pack32(object->grp_jobs, buffer);
+		pack32(object->grp_nodes, buffer);
+		pack32(object->grp_submit_jobs, buffer);
+		pack32(object->grp_wall, buffer);
+
+		pack64(object->max_cpu_mins_pu, buffer);
+		pack32(object->max_cpus_pu, buffer);
+		pack32(object->max_jobs_pu, buffer);
+		pack32(object->max_nodes_pu, buffer);
+		pack32(object->max_submit_jobs_pu, buffer);
+		pack32(object->max_wall_pu, buffer);
+
+		packstr(object->name, buffer);	
+
+		/* These are here for the old preemptee preemptor
+		   lists we could figure this out from the
+		   preempt_bitstr, but qos wasn't used for anything
+		   before rpc_version 6 so just send NO_VALS */
+		pack32(NO_VAL, buffer);
+		pack32(NO_VAL, buffer);
 		
 		pack32(object->priority, buffer);
 		
@@ -2580,7 +2624,7 @@ extern int unpack_acct_qos_rec(void **object, uint16_t rpc_version, Buf buffer)
 	
 	init_acct_qos_rec(object_ptr);
 
-	if(rpc_version >= 5) {
+	if(rpc_version >= 6) {
 		safe_unpackstr_xmalloc(&object_ptr->description,
 				       &uint32_tmp, buffer);
 		safe_unpack32(&object_ptr->id, buffer);
@@ -2601,30 +2645,83 @@ extern int unpack_acct_qos_rec(void **object, uint16_t rpc_version, Buf buffer)
 
 		safe_unpackstr_xmalloc(&object_ptr->name, &uint32_tmp, buffer);
 
+		unpack_bit_str(&object_ptr->preempt_bitstr, buffer);
+
 		safe_unpack32(&count, buffer);
 		if(count != NO_VAL) {
-			object_ptr->preemptee_list = 
+			object_ptr->preempt_list = 
 				list_create(slurm_destroy_char);
 			for(i=0; i<count; i++) {
 				safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp,
 						       buffer);
-				list_append(object_ptr->preemptee_list,
+				list_append(object_ptr->preempt_list,
 					    tmp_info);
 			}
 		}
+		
+		safe_unpack32(&object_ptr->priority, buffer);
+
+		safe_unpackdouble(&object_ptr->usage_factor, buffer);
+
+		safe_unpack32(&count, buffer);
+		if(count != NO_VAL) {
+			void *used_limits = NULL;
+
+			object_ptr->user_limit_list = 
+				list_create(slurm_destroy_char);
+			for(i=0; i<count; i++) {
+				unpack_acct_used_limits(&used_limits,
+							rpc_version, buffer);
+				list_append(object_ptr->user_limit_list,
+					    used_limits);
+			}
+		}
+
+	} else if(rpc_version >= 5) {
+		safe_unpackstr_xmalloc(&object_ptr->description,
+				       &uint32_tmp, buffer);
+		safe_unpack32(&object_ptr->id, buffer);
+
+		safe_unpack64(&object_ptr->grp_cpu_mins, buffer);
+		safe_unpack32(&object_ptr->grp_cpus, buffer);
+		safe_unpack32(&object_ptr->grp_jobs, buffer);
+		safe_unpack32(&object_ptr->grp_nodes, buffer);
+		safe_unpack32(&object_ptr->grp_submit_jobs, buffer);
+		safe_unpack32(&object_ptr->grp_wall, buffer);
+
+		safe_unpack64(&object_ptr->max_cpu_mins_pu, buffer);
+		safe_unpack32(&object_ptr->max_cpus_pu, buffer);
+		safe_unpack32(&object_ptr->max_jobs_pu, buffer);
+		safe_unpack32(&object_ptr->max_nodes_pu, buffer);
+		safe_unpack32(&object_ptr->max_submit_jobs_pu, buffer);
+		safe_unpack32(&object_ptr->max_wall_pu, buffer);
+
+		safe_unpackstr_xmalloc(&object_ptr->name, &uint32_tmp, buffer);
 
 		safe_unpack32(&count, buffer);
 		if(count != NO_VAL) {
-			object_ptr->preemptor_list = 
+			object_ptr->preempt_list = 
 				list_create(slurm_destroy_char);
 			for(i=0; i<count; i++) {
 				safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp,
 						       buffer);
-				list_append(object_ptr->preemptor_list,
+				list_append(object_ptr->preempt_list,
 					    tmp_info);
 			}
 		}
 
+		/* this is here for the old preemptor list.  which was
+		   never used so just throw anything here away.
+		*/
+		safe_unpack32(&count, buffer);
+		if(count != NO_VAL) {
+			for(i=0; i<count; i++) {
+				safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp,
+						       buffer);
+				xfree(tmp_info);
+			}
+		}
+
 		safe_unpack32(&object_ptr->priority, buffer);
 
 		safe_unpackdouble(&object_ptr->usage_factor, buffer);
@@ -2666,25 +2763,25 @@ extern int unpack_acct_qos_rec(void **object, uint16_t rpc_version, Buf buffer)
 
 		safe_unpack32(&count, buffer);
 		if(count != NO_VAL) {
-			object_ptr->preemptee_list = 
+			object_ptr->preempt_list = 
 				list_create(slurm_destroy_char);
 			for(i=0; i<count; i++) {
 				safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp,
 						       buffer);
-				list_append(object_ptr->preemptee_list,
+				list_append(object_ptr->preempt_list,
 					    tmp_info);
 			}
 		}
 
+		/* this is here for the old preemptor list.  which was
+		   never used so just throw anything here away.
+		*/
 		safe_unpack32(&count, buffer);
 		if(count != NO_VAL) {
-			object_ptr->preemptor_list = 
-				list_create(slurm_destroy_char);
 			for(i=0; i<count; i++) {
 				safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp,
 						       buffer);
-				list_append(object_ptr->preemptor_list,
-					    tmp_info);
+				xfree(tmp_info);
 			}
 		}
 
@@ -7194,6 +7291,78 @@ extern char *get_tree_acct_name(char *name, char *parent, List tree_list)
 	return acct_print_tree->print_name;
 }
 
+extern int set_qos_bitstr_from_list(bitstr_t *valid_qos, List qos_list)
+{
+	ListIterator itr = NULL;
+	bitoff_t bit = 0;
+	int rc = SLURM_SUCCESS;
+	char *temp_char = NULL;
+	void (*my_function) (bitstr_t *b, bitoff_t bit);
+
+	xassert(valid_qos);
+
+	if(!qos_list)
+		return SLURM_ERROR;
+
+	itr = list_iterator_create(qos_list);
+	while((temp_char = list_next(itr))) {
+		if(temp_char[0] == '-') {
+			temp_char++;
+			my_function = bit_clear;
+		} else if(temp_char[0] == '+') {
+			temp_char++;
+			my_function = bit_set;
+		} else
+			my_function = bit_set;
+		bit = atoi(temp_char);
+		if(bit >= bit_size(valid_qos)) {
+			rc = SLURM_ERROR;
+			break;
+		}
+		(*(my_function))(valid_qos, bit);
+	}
+	list_iterator_destroy(itr);
+	
+	return rc;
+}
+
+extern char *get_qos_complete_str_bitstr(List qos_list, bitstr_t *valid_qos)
+{
+	List temp_list = NULL;
+	char *temp_char = NULL;
+	char *print_this = NULL;
+	ListIterator itr = NULL;
+	int i = 0;
+
+	if(!qos_list || !list_count(qos_list)
+	   || !valid_qos || (bit_ffs(valid_qos) == -1))
+		return xstrdup("");
+
+	temp_list = list_create(NULL);
+
+	for(i=0; i<bit_size(valid_qos); i++) {
+		if(!bit_test(valid_qos, i))
+			continue;
+		if((temp_char = acct_qos_str(qos_list, i)))
+			list_append(temp_list, temp_char);
+	}
+	list_sort(temp_list, (ListCmpF)slurm_sort_char_list_asc);
+	itr = list_iterator_create(temp_list);
+	while((temp_char = list_next(itr))) {
+		if(print_this) 
+			xstrfmtcat(print_this, ",%s", temp_char);
+		else 
+			print_this = xstrdup(temp_char);
+	}
+	list_iterator_destroy(itr);
+	list_destroy(temp_list);
+
+	if(!print_this)
+		return xstrdup("");
+
+	return print_this;
+}
+
 extern char *get_qos_complete_str(List qos_list, List num_qos_list)
 {
 	List temp_list = NULL;
diff --git a/src/common/slurm_accounting_storage.h b/src/common/slurm_accounting_storage.h
index 23b862391b7..fbe7b53a335 100644
--- a/src/common/slurm_accounting_storage.h
+++ b/src/common/slurm_accounting_storage.h
@@ -244,6 +244,8 @@ typedef struct acct_association_rec {
 				    * (DON'T PACK) */
 	
 	char *user;		/* user associated to association */
+	bitstr_t *valid_qos;    /* qos available for this association
+				 * (DON'T PACK) */	
 } acct_association_rec_t;
 
 typedef struct {
@@ -340,10 +342,8 @@ typedef struct {
 
 	char *name;
 	double norm_priority;/* normalized priority (DON'T PACK) */
-	List preemptee_list; /* list of char * list of qos's that this
-				qos can preempt */
-	List preemptor_list; /* list of char * list of qos's that this
-			      * qos is preempted by */
+	bitstr_t *preempt_bitstr; /* other qos' this qos can preempt */
+	List preempt_list; /* list of char *'s */
 	uint32_t priority;  /* ranged int needs to be a unint for
 			     * heterogeneous systems */
 	double usage_factor; /* factor to apply to usage in this qos */
@@ -553,7 +553,8 @@ typedef struct {
 			     insert of jobs since past */
 } acct_archive_rec_t;
 
-extern uint32_t qos_max_priority; /* max priority in all qos's */
+extern uint32_t g_qos_max_priority; /* max priority in all qos's */
+extern uint32_t g_qos_count; /* count used for generating qos bitstr's */
 
 extern void destroy_acct_user_rec(void *object);
 extern void destroy_acct_account_rec(void *object);
@@ -689,6 +690,8 @@ extern List get_acct_hierarchical_rec_list(List assoc_list);
 /* IN/OUT: tree_list a list of acct_print_tree_t's */ 
 extern char *get_tree_acct_name(char *name, char *parent, List tree_list);
 
+extern int set_qos_bitstr_from_list(bitstr_t *valid_qos, List qos_list);
+extern char *get_qos_complete_str_bitstr(List qos_list, bitstr_t *valid_qos);
 extern char *get_qos_complete_str(List qos_list, List num_qos_list);
 
 extern char *get_classification_str(uint16_t class);
diff --git a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c
index a01f26918fa..afff3df0fa5 100644
--- a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c
+++ b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c
@@ -161,6 +161,34 @@ extern List acct_storage_p_remove_wckeys(mysql_conn_t *mysql_conn,
 					 uint32_t uid, 
 					 acct_wckey_cond_t *wckey_cond);
 
+static int _set_qos_cnt(MYSQL *db_conn)
+{
+	MYSQL_RES *result = NULL;
+	MYSQL_ROW row;
+	char *query = xstrdup_printf("select MAX(id) from %s", qos_table);
+
+	if(!(result = mysql_db_query_ret(db_conn, query, 0))) {
+		xfree(query);
+		return SLURM_ERROR;
+	}
+	xfree(query);
+	
+	if(!(row = mysql_fetch_row(result))) {
+		mysql_free_result(result);
+		return SLURM_ERROR;
+	}
+			
+	/* Set the current qos_count on the system for
+	   generating bitstr of that length.  Since 0 isn't
+	   possible as an id we add 1 to the total to burn 0 and
+	   start at the 1 bit.
+	*/
+	g_qos_count = atoi(row[0]) + 1;
+	mysql_free_result(result);
+
+	return SLURM_SUCCESS;
+}
+
 static char *_get_cluster_from_associd(mysql_conn_t *mysql_conn,
 				       uint32_t associd)
 {
@@ -670,7 +698,7 @@ end_qos:
 
 static int _setup_qos_limits(acct_qos_rec_t *qos,
 			     char **cols, char **vals,
-			     char **extra, qos_level_t qos_level)
+			     char **extra)
 {	
 	if(!qos)
 		return SLURM_ERROR;
@@ -822,44 +850,43 @@ static int _setup_qos_limits(acct_qos_rec_t *qos,
 		xstrcat(*extra, ", max_wall_duration_per_user=NULL");
 	}
 
-	if((qos_level != QOS_LEVEL_MODIFY)
-	   && qos->preemptee_list && list_count(qos->preemptee_list)) {
-		char *qos_val = NULL;
-		char *tmp_char = NULL;
-		ListIterator qos_itr = 
-			list_iterator_create(qos->preemptee_list);
-		
-		xstrcat(*cols, ", qos");
-		
-		while((tmp_char = list_next(qos_itr))) 
-			xstrfmtcat(qos_val, ",%s", tmp_char);
+	if(qos->preempt_list && list_count(qos->preempt_list)) {
+		char *preempt_val = NULL;
+		char *tmp_char = NULL, *begin_preempt = NULL;
+		ListIterator preempt_itr = 
+			list_iterator_create(qos->preempt_list);
 		
-		list_iterator_destroy(qos_itr);
-		
-		xstrfmtcat(*vals, ", \"%s\"", qos_val); 		
-		xstrfmtcat(*extra, ", preemptees=\"%s\"", qos_val); 
-		xfree(qos_val);
-	} 
+		xstrcat(*cols, ", preempt");
+
+		begin_preempt = xstrdup("preempt");
+
+		while((tmp_char = list_next(preempt_itr))) {
+			if(tmp_char[0] == '-') {				
+				xstrfmtcat(preempt_val,
+					   "replace(%s, ',%s', '')",
+					   begin_preempt, tmp_char+1);
+				xfree(begin_preempt);
+				begin_preempt = preempt_val;
+			} else if(tmp_char[0] == '+') {
+				xstrfmtcat(preempt_val,
+					   "concat("
+					   "replace(%s, ',%s', ''), ',%s')",
+					   begin_preempt, 
+					   tmp_char+1, tmp_char+1);
+				xfree(begin_preempt);
+				begin_preempt = preempt_val;
+			} else if(tmp_char[0]) 
+				xstrfmtcat(preempt_val, ",%s", tmp_char);
+			else
+				xstrcat(preempt_val, "");
+		}
+		list_iterator_destroy(preempt_itr);
 
-	if((qos_level != QOS_LEVEL_MODIFY)
-	   && qos->preemptor_list && list_count(qos->preemptor_list)) {
-		char *qos_val = NULL;
-		char *tmp_char = NULL;
-		ListIterator qos_itr = 
-			list_iterator_create(qos->preemptor_list);
-		
-		xstrcat(*cols, ", qos");
-		
-		while((tmp_char = list_next(qos_itr))) 
-			xstrfmtcat(qos_val, ",%s", tmp_char);
-		
-		list_iterator_destroy(qos_itr);
-		
-		xstrfmtcat(*vals, ", \"%s\"", qos_val); 		
-		xstrfmtcat(*extra, ", preemptors=\"%s\"", qos_val); 
-		xfree(qos_val);
+		xstrfmtcat(*vals, ", \"%s\"", preempt_val); 		
+		xstrfmtcat(*extra, ", preempt=\"%s\"", preempt_val); 
+		xfree(preempt_val);
 	} 
-	
+
 	if(qos->job_flags) {
 		xstrcat(*cols, ", job_flags");
 		xstrfmtcat(*vals, ", \"%s\"", qos->job_flags);
@@ -2990,8 +3017,7 @@ static int _mysql_acct_check_tables(MYSQL *db_conn)
 		{ "grp_wall", "int default NULL" },
 		{ "grp_cpu_mins", "bigint default NULL" },
 		{ "job_flags", "text" },
-		{ "preemptees", "text not null default ''" },
-		{ "preemptors", "text not null default ''" },
+		{ "preempt", "text not null default ''" },
 		{ "priority", "int default 0" },
 		{ "usage_factor", "double default 1.0 not null" },
 		{ NULL, NULL}		
@@ -3296,10 +3322,15 @@ static int _mysql_acct_check_tables(MYSQL *db_conn)
 			qos_id = mysql_insert_ret_id(db_conn, query);
 			if(!qos_id)
 				fatal("problem added qos 'normal");
+			
 			xstrfmtcat(default_qos_str, ",%d", qos_id);
 			xfree(query);		
 		}
+
+		if(_set_qos_cnt(db_conn) != SLURM_SUCCESS)
+			return SLURM_ERROR;
 	}
+
 	if(mysql_db_create_table(db_conn, step_table,
 				 step_table_fields, 
 				 ", primary key (id, stepid))") == SLURM_ERROR)
@@ -3517,7 +3548,8 @@ extern int acct_storage_p_commit(mysql_conn_t *mysql_conn, bool commit)
 		slurm_msg_t resp;
 		ListIterator itr = NULL;
 		acct_update_object_t *object = NULL;
-		
+		bool get_qos_count = 0;
+
 		memset(&msg, 0, sizeof(accounting_update_msg_t));
 		msg.update_list = mysql_conn->update_list;
 		
@@ -3599,6 +3631,9 @@ extern int acct_storage_p_commit(mysql_conn_t *mysql_conn, bool commit)
 				rc = assoc_mgr_update_assocs(object);
 				break;
 			case ACCT_ADD_QOS:
+				/* we need to check the qos's here to
+				 * get the correct count */
+				get_qos_count = 1;
 			case ACCT_MODIFY_QOS:
 			case ACCT_REMOVE_QOS:
 				rc = assoc_mgr_update_qos(object);
@@ -3618,7 +3653,11 @@ extern int acct_storage_p_commit(mysql_conn_t *mysql_conn, bool commit)
 			list_delete_item(itr);
 		}
 		list_iterator_destroy(itr);
+
+		if(get_qos_count) 
+			_set_qos_cnt(mysql_conn->db_conn);
 	}
+
 	list_flush(mysql_conn->update_list);
 
 	return SLURM_SUCCESS;
@@ -4617,8 +4656,7 @@ extern int acct_storage_p_add_qos(mysql_conn_t *mysql_conn, uint32_t uid,
 			   now, now, object->name); 
 		xstrfmtcat(extra, ", mod_time=%d", now);
 
-		_setup_qos_limits(object, &cols, &vals, &extra, 
-				  QOS_LEVEL_NONE);
+		_setup_qos_limits(object, &cols, &vals, &extra);
 		xstrfmtcat(query, 
 			   "insert into %s (%s) values (%s) "
 			   "on duplicate key update deleted=0, "
@@ -5785,8 +5823,8 @@ end_it:
 }
 
 extern List acct_storage_p_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid, 
-					acct_qos_cond_t *qos_cond,
-					acct_qos_rec_t *qos)
+				      acct_qos_cond_t *qos_cond,
+				      acct_qos_rec_t *qos)
 {
 	ListIterator itr = NULL;
 	List ret_list = NULL;
@@ -5799,7 +5837,6 @@ extern List acct_storage_p_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid,
 	MYSQL_RES *result = NULL;
 	MYSQL_ROW row;
 	char *tmp_char1=NULL, *tmp_char2=NULL;
-	int replace_preemptor = 0, replace_preemptee = 0;
 
 	if(!qos_cond || !qos) {
 		error("we need something to change");
@@ -5856,85 +5893,19 @@ extern List acct_storage_p_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid,
 		xstrcat(extra, ")");
 	}
 	
-	_setup_qos_limits(qos, &tmp_char1, &tmp_char2,
-			  &vals, QOS_LEVEL_MODIFY);
+	_setup_qos_limits(qos, &tmp_char1, &tmp_char2, &vals);
 	xfree(tmp_char1);
 	xfree(tmp_char2);
 
-	if(qos->preemptee_list && list_count(qos->preemptee_list)) {
-		char *tmp_qos = NULL;
-		set = 0;
-		itr = list_iterator_create(qos->preemptee_list);
-		while((object = list_next(itr))) {
-			/* when adding we need to make sure we don't
-			 * already have it so we remove it and then add
-			 * it.
-			 */
-			if(object[0] == '-') {
-				xstrfmtcat(vals,
-					   ", preemptees="
-					   "replace(qos, ',%s', '')",
-					   object+1);
-			} else if(object[0] == '+') {
-				xstrfmtcat(vals,
-					   ", preemptees=concat_ws(',', "
-					   "replace(preemptees, ',%s', ''), "
-					   "\"%s\")",
-					   object+1, object+1);
-			} else {
-				xstrfmtcat(tmp_qos, ",%s", object);
-			}
-		}
-		list_iterator_destroy(itr);
-		if(tmp_qos) {
-			xstrfmtcat(vals, ", preemptees='%s'", tmp_qos);
-			xfree(tmp_qos);
-			replace_preemptee = 1;
-		}
-	}
-
-	if(qos->preemptor_list && list_count(qos->preemptor_list)) {
-		char *tmp_qos = NULL;
-		set = 0;
-		itr = list_iterator_create(qos->preemptor_list);
-		while((object = list_next(itr))) {
-			/* when adding we need to make sure we don't
-			 * already have it so we remove it and then add
-			 * it.
-			 */
-			if(object[0] == '-') {
-				xstrfmtcat(vals,
-					   ", preemptors="
-					   "replace(qos, ',%s', '')",
-					   object+1);
-			} else if(object[0] == '+') {
-				xstrfmtcat(vals,
-					   ", preemptors=concat_ws(',', "
-					   "replace(preemptors, ',%s', ''), "
-					   "\"%s\")",
-					   object+1, object+1);
-			} else {
-				xstrfmtcat(tmp_qos, ",%s", object);
-			}
-		}
-		list_iterator_destroy(itr);
-		if(tmp_qos) {
-			xstrfmtcat(vals, ", preemptors='%s'", tmp_qos);
-			xfree(tmp_qos);
-			replace_preemptor = 1;
-		}
-	}
-
 	if(!extra || !vals) {
 		errno = SLURM_NO_CHANGE_IN_DATA;
 		error("Nothing to change");
 		return NULL;
 	}
-	query = xstrdup_printf("select name, preemptees, preemptors "
-			       "from %s %s;", qos_table, extra);
+	query = xstrdup_printf("select name, preempt from %s %s;",
+			       qos_table, extra);
 	xfree(extra);
-	if(!(result = mysql_db_query_ret(
-		     mysql_conn->db_conn, query, 0))) {
+	if(!(result = mysql_db_query_ret(mysql_conn->db_conn, query, 0))) {
 		xfree(query);
 		return NULL;
 	}
@@ -5971,112 +5942,36 @@ extern List acct_storage_p_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid,
 
 		qos_rec->priority = qos->priority;
 
-		if(qos->preemptee_list) {
-			ListIterator new_qos_itr = 
-				list_iterator_create(qos->preemptee_list);
-			ListIterator curr_qos_itr = NULL;
-			char *new_qos = NULL, *curr_qos = NULL;
-
-			qos_rec->preemptee_list = 
-				list_create(slurm_destroy_char);
-			if(!replace_preemptee)
-				slurm_addto_char_list(qos_rec->preemptee_list,
-						      row[1]);
-			curr_qos_itr = 
-				list_iterator_create(qos_rec->preemptee_list);
-			
-			while((new_qos = list_next(new_qos_itr))) {
-				char *tmp_char = NULL;
-				if(new_qos[0] == '-') {
-					tmp_char = xstrdup(new_qos+1);
-					while((curr_qos =
-					       list_next(curr_qos_itr))) {
-						if(!strcmp(curr_qos,
-							   tmp_char)) {
-							list_delete_item(
-								curr_qos_itr);
-							break;
-						}
-					}
-					xfree(tmp_char);
-					list_iterator_reset(curr_qos_itr);
-				} else if(new_qos[0] == '+') {
-					tmp_char = xstrdup(new_qos+1);
-					while((curr_qos =
-					       list_next(curr_qos_itr))) {
-						if(!strcmp(curr_qos,
-							   tmp_char)) {
-							break;
-						}
-					}
-					if(!curr_qos)
-						list_append(
-							qos_rec->preemptee_list,
-							tmp_char);
-					else
-						xfree(tmp_char);
-					list_iterator_reset(curr_qos_itr);
+		if(qos->preempt_list) {
+			ListIterator new_preempt_itr = 
+				list_iterator_create(qos->preempt_list);
+			char *new_preempt = NULL;
+
+			qos->preempt_bitstr = bit_alloc(g_qos_count);
+			if(row[1] && row[1][0])
+				bit_unfmt(qos->preempt_bitstr, row[1]+1);
+
+			while((new_preempt = list_next(new_preempt_itr))) {
+				bool cleared = 0;
+				if(new_preempt[0] == '-') {
+					bit_clear(qos->preempt_bitstr,
+						  atoi(new_preempt+1));
+				} else if(new_preempt[0] == '+') {
+					bit_set(qos->preempt_bitstr,
+						atoi(new_preempt+1));
 				} else {
-					list_append(qos_rec->preemptee_list,
-						    xstrdup(new_qos));
-				}
-			}
-			list_iterator_destroy(curr_qos_itr);
-			list_iterator_destroy(new_qos_itr);			
-		}
-
-		if(qos->preemptor_list) {
-			ListIterator new_qos_itr = 
-				list_iterator_create(qos->preemptor_list);
-			ListIterator curr_qos_itr = NULL;
-			char *new_qos = NULL, *curr_qos = NULL;
-
-			qos_rec->preemptor_list = 
-				list_create(slurm_destroy_char);
-			if(!replace_preemptor)
-				slurm_addto_char_list(qos_rec->preemptor_list,
-						      row[2]);
-			curr_qos_itr = 
-				list_iterator_create(qos_rec->preemptor_list);
-			
-			while((new_qos = list_next(new_qos_itr))) {
-				char *tmp_char = NULL;
-				if(new_qos[0] == '-') {
-					tmp_char = xstrdup(new_qos+1);
-					while((curr_qos =
-					       list_next(curr_qos_itr))) {
-						if(!strcmp(curr_qos,
-							   tmp_char)) {
-							list_delete_item(
-								curr_qos_itr);
-							break;
-						}
-					}
-					xfree(tmp_char);
-					list_iterator_reset(curr_qos_itr);
-				} else if(new_qos[0] == '+') {
-					tmp_char = xstrdup(new_qos+1);
-					while((curr_qos =
-					       list_next(curr_qos_itr))) {
-						if(!strcmp(curr_qos,
-							   tmp_char)) {
-							break;
-						}
+					if(!cleared) {
+						cleared = 1;
+						bit_nclear(qos->preempt_bitstr,
+							   0,
+							   bit_size(qos->preempt_bitstr)-1);
 					}
-					if(!curr_qos)
-						list_append(
-							qos_rec->preemptor_list,
-							tmp_char);
-					else
-						xfree(tmp_char);
-					list_iterator_reset(curr_qos_itr);
-				} else {
-					list_append(qos_rec->preemptor_list,
-						    xstrdup(new_qos));
+
+					bit_set(qos->preempt_bitstr,
+						atoi(new_preempt));
 				}
 			}
-			list_iterator_destroy(curr_qos_itr);
-			list_iterator_destroy(new_qos_itr);			
+			list_iterator_destroy(new_preempt_itr);			
 		}
 
 		_addto_update_list(mysql_conn->update_list, ACCT_MODIFY_QOS,
@@ -8614,9 +8509,9 @@ empty:
 			list_iterator_destroy(curr_qos_itr);
 			list_flush(delta_qos_list);
 		}
-
+		
 		assoc->parent_id = parent_id;
-
+		
 		//info("parent id is %d", assoc->parent_id);
 		//log_assoc_rec(assoc);
 	}
@@ -8700,8 +8595,7 @@ extern List acct_storage_p_get_qos(mysql_conn_t *mysql_conn, uid_t uid,
 		"max_submit_jobs_per_user",
 		"max_wall_duration_per_user",
 		"job_flags",
-		"preemptees",
-		"preemptors",
+		"preempt",
 		"priority",
 		"usage_factor",
 	};
@@ -8723,7 +8617,6 @@ extern List acct_storage_p_get_qos(mysql_conn_t *mysql_conn, uid_t uid,
 		QOS_REQ_MWPU,
 		QOS_REQ_JOBF,
 		QOS_REQ_PREE,
-		QOS_REQ_PREO,
 		QOS_REQ_PRIO,
 		QOS_REQ_UF,
 		QOS_REQ_COUNT
@@ -8820,7 +8713,7 @@ empty:
 			qos->description = xstrdup(row[QOS_REQ_DESC]);
 
 		qos->id = atoi(row[QOS_REQ_ID]);
-
+		
 		if(row[QOS_REQ_NAME] && row[QOS_REQ_NAME][0])
 			qos->name =  xstrdup(row[QOS_REQ_NAME]);
 
@@ -8877,18 +8770,9 @@ empty:
 		else
 			qos->max_wall_pu = INFINITE;
 
-		if(row[QOS_REQ_PREE] && row[QOS_REQ_PREE][0]) {
-			qos->preemptee_list = list_create(slurm_destroy_char);
-			slurm_addto_char_list(qos->preemptee_list,
-					      row[QOS_REQ_PREE]+1);
-		} 
-
-		if(row[QOS_REQ_PREE] && row[QOS_REQ_PREE][0]) {
-			qos->preemptee_list = list_create(slurm_destroy_char);
-			slurm_addto_char_list(qos->preemptee_list,
-					      row[QOS_REQ_PREE]+1);
-		} 
-
+		if(row[QOS_REQ_PREE] && row[QOS_REQ_PREE][0]) 
+			bit_unfmt(qos->preempt_bitstr, row[QOS_REQ_PREE]+1);
+		
 		if(row[QOS_REQ_PRIO])
 			qos->priority = atoi(row[QOS_REQ_PRIO]);
 
diff --git a/src/sacctmgr/common.c b/src/sacctmgr/common.c
index 99819ca5693..df8dc589600 100644
--- a/src/sacctmgr/common.c
+++ b/src/sacctmgr/common.c
@@ -1060,6 +1060,31 @@ extern void sacctmgr_print_qos_list(print_field_t *field, List qos_list,
 	xfree(print_this);
 }
 
+extern void sacctmgr_print_qos_bitstr(print_field_t *field, List qos_list,
+				      bitstr_t *value, int last)
+{
+	int abs_len = abs(field->len);
+	char *print_this = NULL;
+
+	print_this = get_qos_complete_str_bitstr(qos_list, value);
+	
+	if(print_fields_parsable_print == PRINT_FIELDS_PARSABLE_NO_ENDING
+	   && last)
+		printf("%s", print_this);
+	else if(print_fields_parsable_print)
+		printf("%s|", print_this);
+	else {
+		if(strlen(print_this) > abs_len) 
+			print_this[abs_len-1] = '+';
+		
+		if(field->len == abs_len)
+			printf("%*.*s ", abs_len, abs_len, print_this);
+		else
+			printf("%-*.*s ", abs_len, abs_len, print_this);
+	}
+	xfree(print_this);
+}
+
 extern void sacctmgr_print_assoc_limits(acct_association_rec_t *assoc)
 {
 	if(!assoc)
@@ -1161,7 +1186,7 @@ extern void sacctmgr_print_qos_limits(acct_qos_rec_t *qos)
 	if(!qos)
 		return;
 
-	if(qos->preemptee_list || qos->preemptor_list)
+	if(qos->preempt_list)
 		qos_list = acct_storage_g_get_qos(db_conn, my_uid, NULL);
 
 	if(qos->job_flags)
@@ -1239,19 +1264,11 @@ extern void sacctmgr_print_qos_limits(acct_qos_rec_t *qos)
 		printf("  MaxWall        = %s\n", time_buf);
 	}
 
-	if(qos->preemptee_list) {
-		char *temp_char = get_qos_complete_str(qos_list,
-						       qos->preemptee_list);
-		if(temp_char) {		
-			printf("  Preemptable by = %s\n", temp_char);
-			xfree(temp_char);
-		}
-	}
-	if(qos->preemptor_list) {
+	if(qos->preempt_list) {
 		char *temp_char = get_qos_complete_str(qos_list,
-						       qos->preemptee_list);
+						       qos->preempt_list);
 		if(temp_char) {		
-			printf("  Can Preempt    = %s\n", temp_char);
+			printf("  Preempt        = %s\n", temp_char);
 			xfree(temp_char);
 		}
 	} 
diff --git a/src/sacctmgr/qos_functions.c b/src/sacctmgr/qos_functions.c
index a936b2dbf51..413b73c0757 100644
--- a/src/sacctmgr/qos_functions.c
+++ b/src/sacctmgr/qos_functions.c
@@ -281,38 +281,20 @@ static int _set_rec(int *start, int argc, char *argv[],
 					" Bad MaxWall time format: %s\n", 
 					argv[i]);
 			}
-		} else if (!strncasecmp (argv[i], "Preemptee", 
+		} else if (!strncasecmp (argv[i], "Preempt", 
 					 MAX(command_len, 9))) {
 			if(!qos)
 				continue;
 
-			if(!qos->preemptee_list) 
-				qos->preemptee_list = 
+			if(!qos->preempt_list) 
+				qos->preempt_list = 
 					list_create(slurm_destroy_char);
 						
 			if(!qos_list) 
 				qos_list = acct_storage_g_get_qos(
 					db_conn, my_uid, NULL);
 						
-			if(addto_qos_char_list(qos->preemptee_list,
-					       qos_list, argv[i]+end, option))
-				set = 1;
-			else
-				exit_code = 1;
-		} else if (!strncasecmp (argv[i], "Preemptor",
-					 MAX(command_len, 9))) {
-			if(!qos)
-				continue;
-
-			if(!qos->preemptor_list) 
-				qos->preemptor_list = 
-					list_create(slurm_destroy_char);
-						
-			if(!qos_list) 
-				qos_list = acct_storage_g_get_qos(
-					db_conn, my_uid, NULL);
-						
-			if(addto_qos_char_list(qos->preemptor_list,
+			if(addto_qos_char_list(qos->preempt_list,
 					       qos_list, argv[i]+end, option))
 				set = 1;
 			else
diff --git a/src/sacctmgr/sacctmgr.c b/src/sacctmgr/sacctmgr.c
index 45963780770..d7ed1517e57 100644
--- a/src/sacctmgr/sacctmgr.c
+++ b/src/sacctmgr/sacctmgr.c
@@ -838,7 +838,7 @@ sacctmgr [<OPTION>] [<COMMAND>]                                            \n\
        add qos            - Description=, GrpCPUMins=, GrpCPUs=, GrpJobs=, \n\
                             GrpNodes=, GrpSubmitJob=, GrpWall=, JobFlags=, \n\
                             MaxCPUMins=, MaxJobs=, MaxNodes=, MaxWall=,    \n\
-                            Preemptee=, Preemptor=, Priority=, and Names=  \n\
+                            Preempt=, Priority=, and Names=                \n\
        delete qos         - Descriptions=, IDs=, and Names=                \n\
                                                                            \n\
        list transactions  - Accounts=, Action=, Actor=, Clusters=, End=,   \n\
diff --git a/src/sacctmgr/sacctmgr.h b/src/sacctmgr/sacctmgr.h
index 66af91003b2..d106c74f56d 100644
--- a/src/sacctmgr/sacctmgr.h
+++ b/src/sacctmgr/sacctmgr.h
@@ -150,6 +150,8 @@ extern void sacctmgr_print_coord_list(
 	print_field_t *field, List value, int last);
 extern void sacctmgr_print_qos_list(print_field_t *field, List qos_list,
 				    List value, int last);
+extern void sacctmgr_print_qos_bitstr(print_field_t *field, List qos_list,
+				      bitstr_t *value, int last);
 
 extern void sacctmgr_print_assoc_limits(acct_association_rec_t *assoc);
 extern void sacctmgr_print_qos_limits(acct_qos_rec_t *qos);
-- 
GitLab